Files

93 lines
5.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""Run the actual ARM programs against disposable metadata and sysfs fixtures."""
import json
from pathlib import Path
import subprocess
import tempfile
project = Path(__file__).resolve().parents[2]
version = subprocess.check_output([str(project/'tools/version')], text=True).strip()
def run(binary, *args, ok=True):
result = subprocess.run([str(project/'tools/in-void'), 'qemu-aarch64',
str(project/'out'/binary), *map(str, args)],
capture_output=True, text=True, timeout=20)
assert (result.returncode == 0) == ok, (args, result.returncode, result.stdout, result.stderr)
return result.stdout
with tempfile.TemporaryDirectory(prefix='m3-', dir=project/'out') as directory:
work = Path(directory)
sysfs = work/'sys'
blocks = sysfs/'class/block'
blocks.mkdir(parents=True)
for helper in ['fds', 'fds-burn', 'fds-inspect', 'fds-eject', 'fds-power',
'fds-stage0', 'fds-boottrace', 'fds-cartridged', 'fds-profile', 'fds-release']:
assert f'Usage: {helper}' in run(helper, '--help')
assert version in run(helper, '--version')
assert 'activate windowmaker' in run('fds-profile', '--help')
run('fds-profile', 'activate', 'windowmaker', ok=False)
assert version in run('fds', '--version')
assert version in run('fds-stage0', '--version')
run('fds-stage0', ok=False) # Must refuse root-switch operations outside PID 1.
assert json.loads(run('fds', '--json', 'info'))['target'] == 'aarch64 static-musl'
fixture = project/'tests/fixtures/manifests/windowmaker.toml'
assert json.loads(run('fds', '--json', 'inspect', fixture))['activation']['profile'] == 'windowmaker'
assert json.loads(run('fds-inspect', fixture, '--json'))['activation']['profile'] == 'windowmaker'
assert json.loads(run('fds', 'inspect', fixture, '--json'))['activation']['profile'] == 'windowmaker'
assert 'BAY' in run('fds', 'format', 'data', '--help')
assert 'TOKEN' in run('fds', 'recovery', 'repair', '--help')
# Parse the legacy image form with global options in both positions. The
# deliberately absent regular file reaches the operation's filesystem check.
for binary, arguments in [
('fds', ['inspect', '--json', 'image']),
('fds-inspect', ['--json', 'image']),
('fds-inspect', ['image', '--json']),
]:
result = subprocess.run([str(project/'tools/in-void'), 'qemu-aarch64',
str(project/'out'/binary), *arguments, str(work/'absent.img')],
capture_output=True, text=True, timeout=20)
assert result.returncode == 2 and result.stderr.startswith('fds: No such file'), result
for binary, arguments in [
('fds', ['run', '1', '/bin/app']),
('fds', ['recovery', 'repair', '1', '--confirm']),
('fds', ['format', 'system', 'root', '1', '--label', 'wrong']),
('fds-burn', ['data', '1', '--label', 'one', '--label', 'two']),
('fds-burn', ['--worker', '--unknown']),
('fds-cartridged', ['--notify', '--topology', '/sys']),
('fds-stage0', ['--probe', '/sys', '--check-cmdline', 'cmdline']),
('fds-profile', ['--session', 'activate', 'cli']),
('fds-power', ['--record-final', 'invalid']),
('fds-release', ['sign', 'directory']),
]:
result = subprocess.run([str(project/'tools/in-void'), 'qemu-aarch64',
str(project/'out'/binary), *arguments],
capture_output=True, text=True, timeout=20)
assert result.returncode == 2, (binary, arguments, result)
assert 'error:' in result.stderr and '--help' in result.stderr, result
malformed = work/'bad.toml'
malformed.write_text(fixture.read_text().replace('profile = "windowmaker"', 'run = "/FDS/autorun.sh"'))
run('fds', 'inspect', malformed, ok=False)
malformed.write_bytes(b' ' * 65537)
run('fds', 'inspect', malformed, ok=False)
run('fds', 'eject', '99', ok=False)
assert json.loads(run('fds-stage0', '--probe', sysfs))['state'] == 'missing'
for name, major, minor in [('sdz1', 8, 241), ('nvme0n1p2', 259, 2)]:
path = blocks/name
path.mkdir()
(path/'uevent').write_text(f'DEVTYPE=partition\nDEVNAME={name}\nMAJOR={major}\nMINOR={minor}\nPARTNAME=FDS_SYSTEM\n')
result = json.loads(run('fds-stage0', '--probe', sysfs))
assert result['state'] == ('unique' if name == 'sdz1' else 'ambiguous')
# A path escape must not turn a kernel identity into an arbitrary device path.
(blocks/'sdz1/uevent').write_text('DEVTYPE=partition\nDEVNAME=../../etc/shadow\nMAJOR=8\nMINOR=241\nPARTNAME=FDS_SYSTEM\n')
run('fds-stage0', '--probe', sysfs, ok=False)
cmdline = work/'cmdline'
cmdline.write_text('console=ttyAMA0 fds.boot=recovery fds.debug=1\n')
assert json.loads(run('fds-stage0', '--check-cmdline', cmdline)) == {'mode': 'recovery', 'debug': True, 'emulator': False}
cmdline.write_text('fds.emulator=1')
assert json.loads(run('fds-stage0', '--check-cmdline', cmdline)) == {'mode': 'normal', 'debug': False, 'emulator': True}
cmdline.write_text('fds.emulator=2')
run('fds-stage0', '--check-cmdline', cmdline, ok=False)
cmdline.write_text('fds.boot=normal fds.boot=recovery')
run('fds-stage0', '--check-cmdline', cmdline, ok=False)
print('PASS: real ARM CLI, bounded/strict manifests, missing/unique/ambiguous discovery and boot options')