98 lines
4.2 KiB
Python
98 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Exercise the shipped router scripts with a disposable router filesystem."""
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
|
|
REPO = Path(__file__).resolve().parents[2]
|
|
SCRIPTS = REPO / "core/openwrt/src/tollgate"
|
|
|
|
|
|
def run(scenario, prepare=False):
|
|
with tempfile.TemporaryDirectory(prefix="archy-nds-") as directory:
|
|
root = Path(directory)
|
|
for name in ("etc/config", "etc/init.d", "lib/functions", "tmp/etc", "proc", "bin"):
|
|
(root / name).mkdir(parents=True)
|
|
def write(name, content):
|
|
path = root / name
|
|
path.write_text(content)
|
|
path.chmod(0o755)
|
|
# Shell paths alone are redirected; guard logic is the production file.
|
|
def redirect(script):
|
|
return re.sub(r"/(?:etc|lib|tmp|proc|usr/bin)/", lambda m: str(root) + m[0], script)
|
|
write("lib/functions.sh", '''
|
|
config_load() { :; }
|
|
config_foreach() {
|
|
if [ "$SCENARIO" = prepare ]; then "$1" stock; "$1" custom;
|
|
elif [ "$SCENARIO" = extra ]; then "$1" rogue;
|
|
else "$1" main; fi
|
|
}
|
|
config_get_bool() { enabled=1; }
|
|
''')
|
|
write("lib/functions/network.sh", "# fixture network functions\n")
|
|
write("bin/uci", '''#!/bin/sh
|
|
echo "uci $*" >> "$FIXTURE/log"
|
|
case "$*" in
|
|
'get nodogsplash.main.enabled') echo 1;;
|
|
'get nodogsplash.main.gatewayinterface') echo br-tollgate;;
|
|
esac
|
|
''')
|
|
write("bin/sleep", "#!/bin/sh\nexit 0\n")
|
|
write("etc/init.d/nodogsplash", redirect('''#!/bin/sh
|
|
generate_uci_config() {
|
|
case "$SCENARIO" in
|
|
bad) echo 'GatewayInterface br-lan';;
|
|
duplicate) printf 'GatewayInterface br-tollgate\\nGatewayInterface br-lan\\n';;
|
|
matching-duplicate) printf 'GatewayInterface br-tollgate\\ngatewayinterface br-tollgate\\n';;
|
|
conflicting-lowercase) printf 'GatewayInterface br-tollgate\\ngatewayinterface br-lan\\n';;
|
|
missing) echo '# no gateway';;
|
|
*) echo 'GatewayInterface br-tollgate';;
|
|
esac > /tmp/etc/nodogsplash_main.conf
|
|
}
|
|
case "${1:-}" in
|
|
restart)
|
|
echo restart >> "$FIXTURE/log"
|
|
if [ "$SCENARIO" != absent ]; then
|
|
mkdir -p /proc/42
|
|
ln -s /usr/bin/nodogsplash /proc/42/exe
|
|
if [ "$SCENARIO" = wrongpath ]; then conf=/tmp/etc/other.conf
|
|
else conf=/tmp/etc/nodogsplash_main.conf; fi
|
|
printf '/usr/bin/nodogsplash\\000-c\\000%s\\000-f\\000' "$conf" > /proc/42/cmdline
|
|
fi;;
|
|
stop|disable|enable) echo "$1" >> "$FIXTURE/log";;
|
|
esac
|
|
'''))
|
|
previous = "preserve existing router configuration\n"
|
|
(root / "etc/config/nodogsplash").write_text(previous)
|
|
source = SCRIPTS / ("nds-prepare.sh" if prepare else "nds-restart.sh")
|
|
write("guard.sh", redirect(source.read_text()))
|
|
env = dict(os.environ, SCENARIO=scenario, FIXTURE=str(root),
|
|
PATH=str(root / "bin") + ":/usr/bin:/bin")
|
|
result = subprocess.run(["/bin/sh", str(root / "guard.sh")], env=env,
|
|
capture_output=True, text=True, timeout=5)
|
|
log = (root / "log").read_text() if (root / "log").exists() else ""
|
|
if prepare:
|
|
assert result.returncode == 0, result.stderr
|
|
backups = list((root / "etc/config").glob(".archy-nodogsplash-backup.*"))
|
|
assert len(backups) == 1 and backups[0].read_text() == previous
|
|
for section in ("stock", "custom", "main"):
|
|
assert f"uci set nodogsplash.{section}.enabled=0" in log
|
|
assert log.index("uci commit nodogsplash") < log.index("\nstop")
|
|
elif scenario in ("good", "matching-duplicate"):
|
|
assert result.returncode == 0, result.stderr
|
|
assert log.endswith("restart\nenable\n"), log
|
|
else:
|
|
assert result.returncode != 0, scenario
|
|
assert log.endswith("stop\ndisable\n"), log
|
|
assert "\nenable\n" not in log
|
|
if scenario in ("bad", "duplicate", "conflicting-lowercase", "missing", "extra"):
|
|
assert "restart\n" not in log, log
|
|
|
|
|
|
run("prepare", prepare=True)
|
|
for case in ("good", "matching-duplicate", "bad", "duplicate", "conflicting-lowercase", "missing", "extra", "wrongpath", "absent"):
|
|
run(case)
|
|
print("PASS: disabled install defaults, preserved configuration, render/start guards and failure cleanup")
|