#!/usr/bin/env python3 """Disposable checks against the actual non-test native v6/v7 executable.""" import ctypes import os from pathlib import Path import subprocess assert os.geteuid()==0 and os.environ.get('ARCHY_RADIO_ABI')=='1' binary='/opt/radio-native' libc=ctypes.CDLL(None,use_errno=True) def drop(): os.setgroups([]); os.setgid(53001); os.setuid(53001) assert libc.prctl(38,1,0,0,0)==0 cases=[ ('c01-managed-v6',(),'required Tor lifecycle FD12 missing'), ('c01-managed-v7',(),'required v7 radio FD14 missing'), ('c01-managed-v7',(14,),'required Tor lifecycle FD12 missing'), ('c01-managed-v7',(12,14),'required network settings FD11 missing'), ('c01-managed-v7',(11,12,14),'required D09 FD10 missing'), ('c01-managed-v5',(),'obsolete protected application ABI'), ] for role,slots,expected in cases: for slot in slots: fd=os.open('/dev/null',os.O_RDONLY) os.dup2(fd,slot,inheritable=True) if fd!=slot: os.close(fd) try: result=subprocess.run([binary,role],preexec_fn=drop,pass_fds=slots,capture_output=True,timeout=10) assert result.returncode!=0 and expected in result.stderr.decode(),(role,result.stderr) finally: for slot in slots: os.close(slot) print('PASS',role,expected,flush=True) result=subprocess.run([binary,'radio-owner-v1'],capture_output=True,timeout=20) assert result.returncode!=0 and b'runtime.json' in result.stderr,result.stderr print('PASS embedded fixed radio owner refuses absent external runtime appointment before device access',flush=True) Path('/run/archipelago-radio').mkdir(mode=0o700) result=subprocess.run([binary,'radio-retire-v1'],capture_output=True,timeout=20) assert result.returncode==0,result.stderr assert not list(Path('/var/lib/archipelago').iterdir()) print('PASS embedded finite retirement entry point; no app/wallet state created',flush=True)