"""Synthetic files test no-launch planning; never execute a server or client.""" import json from pathlib import Path import sys import tempfile import unittest from unittest.mock import patch sys.path.insert(0, str(Path(__file__).resolve().parents[1]/'tools')) import dedicated_preflight as tool class DedicatedPreflightTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.addCleanup(self.tmp.cleanup) root = Path(self.tmp.name) self.source, self.runtime = root/'source', root/'runtime' self.runtime.mkdir() for project, header in tool.HEADERS.items(): addon = self.source/'addons/core' path = addon/header path.parent.mkdir(parents=True, exist_ok=True) (addon/'addon.gproj').write_text('GameProject { GUID "2528466DE220D91C" }') path.write_text('SCR_MissionHeader { World "'+tool.WORLD+'" SystemsConfig "'+tool.SYSTEMS+'" }') path.with_suffix('.conf.meta').write_text('MetaFileClass { Name "{AD62322D5213C440}'+header+'" }') (self.runtime/'runtime-origin.json').write_text(json.dumps({'app_id':1874900,'purpose':'private anonymous Reforger dedicated server preparation; no server launched'})) def plan(self, **kwargs): return tool.build_plan(self.source,self.runtime,**kwargs) def installed(self, app='1874900', architecture=62): directory=self.runtime/'server';directory.mkdir(exist_ok=True) binary=directory/'ArmaReforgerServer' data=bytearray(20);data[:6]=b'\x7fELF\x02\x01';data[18:20]=architecture.to_bytes(2,'little') binary.write_bytes(data);binary.chmod(0o700) manifests=directory/'steamapps';manifests.mkdir(exist_ok=True) (manifests/'appmanifest_1874900.acf').write_text('"AppState" { "appid" "'+app+'" "buildid" "synthetic-build" "StateFlags" "4" }') return binary def test_missing_runtime_still_prepares_strict_loopback_review(self): result,config,_=self.plan() self.assertFalse(result['launch_allowed']);self.assertFalse(result['multiplayer_passed']) self.assertEqual(result['genuine_clients_verified'],0) self.assertIn('missing or incomplete',result['blockers'][0]) self.assertEqual(config['bindAddress'],'127.0.0.1') self.assertEqual(config['publicAddress'],'127.0.0.1') self.assertFalse(config['game']['visible']) self.assertTrue(config['game']['gameProperties']['fastValidation']) self.assertTrue(config['game']['gameProperties']['battlEye']) self.assertTrue(config['operating']['disableCrashReporter']) self.assertNotIn('rcon',config);self.assertNotIn('a2s',config) def test_binary_is_inspected_never_executed_and_cannot_establish_mp(self): self.installed() with patch('subprocess.run',side_effect=AssertionError('must not run')),patch('subprocess.Popen',side_effect=AssertionError('must not spawn')): result,_,_=self.plan() runtime=result['runtime'] self.assertTrue(runtime['binary_elf_x86_64']);self.assertTrue(runtime['install_complete']) self.assertEqual(runtime['steam_build_id'],'synthetic-build') self.assertIsNone(runtime['engine_version']);self.assertFalse(runtime['native_runtime_executed']) self.assertFalse(result['launch_allowed']);self.assertTrue(result['blockers']) def test_wrong_app_rejected_wrong_arch_incomplete(self): self.installed(app='1890870') with self.assertRaisesRegex(ValueError,'stable dedicated'):self.plan() self.installed(architecture=183) result,_,_=self.plan();self.assertFalse(result['runtime']['binary_elf_x86_64']) self.assertIn('missing or incomplete',result['blockers'][0]) def test_symlink_to_existing_server_rejected(self): binary=self.installed();target=self.runtime/'other-server';binary.rename(target);binary.symlink_to(target) with self.assertRaisesRegex(ValueError,'symlink'):self.plan() def test_header_and_port_validation(self): for port in (0,1023,65536): with self.assertRaisesRegex(ValueError,'unprivileged'):self.plan(port=port) header=self.source/'addons/core'/tool.HEADERS['core'] header.write_text(header.read_text().replace(tool.SYSTEMS,'wrong')) with self.assertRaisesRegex(ValueError,'SystemsConfig'):self.plan() def test_project_selection_and_source_snapshot_change(self): before,config,_=self.plan(project='chat') self.assertEqual(before['scenario']['project'],'chat') self.assertTrue(config['game']['scenarioId'].endswith(tool.HEADERS['chat'])) (self.source/'addons/core/new.c').write_text('// independent new source') after,_,_=self.plan(project='chat') self.assertNotEqual(before['source_manifest_sha256'],after['source_manifest_sha256']) def test_write_new_private_review_only_preserves_existing_evidence(self): result,config,manifest=self.plan();destination=self.runtime/'review' tool.write_plan(destination,result,config,manifest) self.assertEqual(json.loads((destination/'server-config.review.json').read_text()),config) self.assertFalse(json.loads((destination/'preflight.json').read_text())['listener_started']) self.assertEqual(tool.digest(destination/'source-manifest.json'),result['source_manifest_sha256']) with self.assertRaisesRegex(ValueError,'never overwritten'):tool.write_plan(destination,result,config,manifest) with self.assertRaisesRegex(ValueError,'direct child'):tool.write_plan(self.source/'review',result,config,manifest) def test_unmarked_runtime_and_source_overlap_refused(self): result,config,manifest=self.plan();(self.runtime/'runtime-origin.json').unlink() with self.assertRaisesRegex(ValueError,'origin marker'):tool.write_plan(self.runtime/'review',result,config,manifest) with self.assertRaisesRegex(ValueError,'separate'):tool.build_plan(self.source,self.source/'runtime') if __name__=='__main__':unittest.main()