93 lines
5.4 KiB
Python
Executable File
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')
|