Let mob_local_sound and ominous_warning_sound run with parity.py's defaults

tools/parity.py starts every harness with no arguments, and both scripts
required --binary and --work-dir, so parity-main failed them in 0 s
(argparse usage error) since #10524 and #10266. Like
hostile_sound_categories, they now build the game through net.sides and
pick a work folder under .local/ when none is given.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Horizon agentandClaude Opus 5.5 committed 2026-11-07 02:06:56 +01:00
1 parent 80947472c1
commit 88a372f808
3 files changed
+69 -7

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
"""The network sound harnesses run with no arguments, as tools/parity.py starts them."""
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
TOOLS = Path(__file__).resolve().parents[1] / 'tools'
# Runs in its own interpreter: tools/ on sys.path would shadow tests/ modules of the same name.
PROBE = '''
import sys
from pathlib import Path
sys.path.insert(0, sys.argv[1])
harness = __import__(sys.argv[2])
local = Path(sys.argv[3])
harness.net.lab.LOCAL = local
seen = {}
class Reached(Exception):
pass
def sides(name, binary=None):
seen.update(name=name, binary=binary)
raise Reached
harness.net.sides = sides
sys.argv = [sys.argv[2] + '.py', *(a.replace('{local}', str(local)) for a in sys.argv[4:])]
try:
harness.main()
except Reached:
pass
build = local / seen['name']
print(seen['binary'], '/'.join(build.relative_to(local).parts[:1]), build.is_dir())
'''
class SoundHarnessInvocationTest(unittest.TestCase):
def run_harness(self, name, *arguments):
with tempfile.TemporaryDirectory() as temporary:
local = Path(temporary).resolve()
result = subprocess.run([sys.executable, '-c', PROBE, str(TOOLS), name, str(local), *arguments],
capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stderr)
return result.stdout.split()
def test_defaults_build_the_game_in_a_scratch_folder(self):
for name, folder in [('test_mob_local_sound_parity', 'mob-local-sound'),
('test_ominous_warning_sound_parity', 'ominous-warning-sound-parity')]:
with self.subTest(harness=name):
self.assertEqual(self.run_harness(name), ['None', folder, 'True'])
def test_explicit_arguments_still_win(self):
for name in ['test_mob_local_sound_parity', 'test_ominous_warning_sound_parity']:
with self.subTest(harness=name):
self.assertEqual(self.run_harness(name, '--binary', '/bin/game', '--work-dir', '{local}/chosen'),
['/bin/game', 'chosen', 'True'])
if __name__ == '__main__':
unittest.main()
+7 -4
View File
@@ -145,17 +145,20 @@ def run(label, command, client_command, build, world, spec):
def main():
parser=argparse.ArgumentParser(description=__doc__)
parser.add_argument('--binary', type=Path, required=True)
parser.add_argument('--work-dir', type=Path, required=True)
# The parity runner passes no arguments: net.sides builds the game, and every run gets its own folder.
parser.add_argument('--binary', type=Path)
parser.add_argument('--work-dir', type=Path)
parser.add_argument('--reference-only', action='store_true')
parser.add_argument('--reference-dir', type=Path)
args=parser.parse_args()
build=args.work_dir.resolve(); build.mkdir(parents=True,exist_ok=False)
build=(args.work_dir or net.lab.LOCAL/'mob-local-sound'/f'run-{time.time_ns()}').resolve()
build.mkdir(parents=True,exist_ok=False)
spec=program(); (build/'program.json').write_text(json.dumps(spec,indent=2)+'\n')
script=Path(__file__).read_bytes()
(build/'manifest.json').write_text(json.dumps(dict(script_sha256=hashlib.sha256(script).hexdigest(),
declared_at=sound.now(), program_sha256=hashlib.sha256((build/'program.json').read_bytes()).hexdigest()),indent=2)+'\n')
_,_,java,native,client=net.sides(str(build.relative_to(net.lab.LOCAL)),args.binary.resolve())
_,_,java,native,client=net.sides(str(build.relative_to(net.lab.LOCAL)),
args.binary.resolve() if args.binary else None)
reference=args.reference_dir.resolve() if args.reference_dir else build
if not args.reference_dir:
world=sound.generate(java,build)
+4 -3
View File
@@ -176,10 +176,11 @@ def run(label, command, client_command, build, world, script):
def main():
p=argparse.ArgumentParser();p.add_argument('--binary',type=Path,required=True);p.add_argument('--work-dir',type=Path,required=True);p.add_argument('--reference-only',action='store_true');p.add_argument('--reference',type=Path);a=p.parse_args()
build=a.work_dir.resolve();build.mkdir(parents=True,exist_ok=True)
# The parity runner passes no arguments: net.sides builds the game, and the folder has a default.
p=argparse.ArgumentParser();p.add_argument('--binary',type=Path);p.add_argument('--work-dir',type=Path);p.add_argument('--reference-only',action='store_true');p.add_argument('--reference',type=Path);a=p.parse_args()
build=(a.work_dir or net.lab.LOCAL/'ominous-warning-sound-parity').resolve();build.mkdir(parents=True,exist_ok=True)
script=program();(build/'program.json').write_text(json.dumps(script,indent=2)+'\n')
name=str(build.relative_to(net.lab.LOCAL));_,_,java,native,client=net.sides(name,a.binary.resolve())
name=str(build.relative_to(net.lab.LOCAL));_,_,java,native,client=net.sides(name,a.binary.resolve() if a.binary else None)
world=generate(java,build)
reference=run('java',java,client,build,world,script)
(build/'reference.json').write_text(json.dumps(reference,indent=2)+'\n')