Files
status-indicators/tests/test_builders.py
T
christianandClaude Fable 5.1 a33e344cae Steps 4-6: the jobs, the set-up tab with generated scripts, Install the staged folder, site bundles and the campus template
- Overview jobs: Change the playlist, Add or remove a HyperDeck, Add a MIDI link, Add a computer,
  Make a PC program startable; 'Add a key for it' on unwatched Companion connections.
- Computers > Setup: steps with a [how] each and the set-up scripts generated per computer by
  settings/scripts.py from the templates in remote-access/ (no site-shaped value left in them);
  Remove this computer drops the fixes and checks that used it.
- Site setup > Site: the running and staged code, Install the staged folder (a one-shot launchd job
  running install.sh --keep-config, refused while live), Export site bundle (zip), New campus from a
  bundle (this campus's site block stays; every copied computer is flagged until touched).
- sites/: na -> the repo config, _template = the empty campus; install.sh --site <id>.
- Review reads appended checks as 'added'; tests for all of it.
- Deployed page-only to NA Ingest. (config.json, status_panel.py and readiness.py are left to the
  READY-page work in progress in the same tree.)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-14 14:53:08 -04:00

127 lines
7.6 KiB
Python

"""Fix and check builders: every one of today's fixes regenerates from its fields exactly, values are
quoted or refused, a start builder never closes a running program, and this Mac becomes a local fix."""
import json
import os
import sys
import unittest
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, ROOT)
import schema # noqa: E402
from settings import builders as b # noqa: E402
CFG = json.load(open(os.path.join(ROOT, "config.json")))
class TestTodaysFixes(unittest.TestCase):
def test_every_fix_has_a_builder_and_regenerates_exactly(self):
known = {t.get("kind") or "ssh" for t in b.TEMPLATES.values()} | {"local"}
n = 0
for fid, fix in CFG["fixes"].items():
if (fix.get("kind") or "ssh") not in known: # a kind the builders do not make yet (another feature's)
continue
self.assertTrue(fix.get("template"), fid)
built = b.build(CFG, fix)
for k in ("run", "kind", "host"):
self.assertEqual(built.get(k), fix.get(k), "%s %s" % (fid, k))
n += 1
self.assertEqual(b.mismatches(CFG), [])
self.assertGreaterEqual(n, 27)
def test_todays_remote_checks_regenerate(self):
n = 0
for t in CFG["tiles"]:
for c in t.get("checks", []):
if c.get("template"):
self.assertEqual(b.build_check(CFG, c)["cmd"], c["cmd"])
n += 1
self.assertEqual(n, 5)
def test_a_changed_command_is_refused_by_validate(self):
cfg = json.loads(json.dumps(CFG))
cfg["fixes"]["vista"]["run"] = "shutdown /s"
errors, _ = schema.validate(cfg)
self.assertTrue(any("vista" in e and "no longer matches" in e for e in errors), errors)
cfg["fixes"]["vista"]["template"] = "custom" # a hand-typed command is allowed when it says so
self.assertEqual([e for e in schema.validate(cfg)[0] if "vista" in e], [])
def test_exact_strings_of_the_shapes_that_matter(self):
vista = b.build(CFG, {"template": "win_start", "params": {"host": "lighting", "task": "Start Vista", "exe": "Vista.exe"}})
self.assertEqual(vista["run"], 'tasklist /NH /FI "IMAGENAME eq Vista.exe" | find /I "Vista.exe" >nul || (schtasks /Run /TN "\\StatusPanel\\Start Vista" >nul '
'&& ping -n 9 127.0.0.1 >nul && tasklist /NH /FI "IMAGENAME eq Vista.exe" | find /I "Vista.exe" >nul)')
self.assertEqual((vista["kind"], vista["host"]), ("ssh", "lighting"))
self.assertNotIn("%ERRORLEVEL%", vista["run"])
caps = b.build(CFG, {"template": "helpers", "params": {"labels": ["a.b", "c.d"]}})
self.assertEqual(caps["run"], "s=0; { launchctl kickstart -k gui/$(id -u)/a.b || launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/a.b.plist; } || s=1; "
"{ launchctl kickstart -k gui/$(id -u)/c.d || launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/c.d.plist; } || s=1; exit $s")
self.assertEqual(caps["kind"], "local")
class TestQuotingAndGuards(unittest.TestCase):
def test_mac_names_are_quoted(self):
f = b.build(CFG, {"template": "mac_start", "params": {"host": "tracks", "process": "Ableton Live 11 Suite", "app": "Rob's App"}})
self.assertEqual(f["run"], "pgrep -xq 'Ableton Live 11 Suite' || open -a 'Rob'\"'\"'s App'")
f = b.build(CFG, {"template": "mac_restart", "params": {"host": "tracks", "process": "x; rm -rf /", "app": "X"}})
self.assertIn("pkill -TERM -x 'x; rm -rf /'", f["run"])
def test_windows_values_are_checked(self):
for bad in ("Vista & del", "Start!Vista", 'a"b', "x%y", "a^b"):
with self.assertRaises(ValueError):
b.build(CFG, {"template": "win_start", "params": {"host": "lighting", "task": bad, "exe": "Vista.exe"}})
ok = b.build(CFG, {"template": "win_restart", "params": {"host": "bibletv", "task": "Start BibleApp", "exe": "Bible App.exe"}})
self.assertEqual(ok["run"], CFG["fixes"]["bibleapp"]["run"])
def test_helper_labels_and_folders_are_checked(self):
with self.assertRaises(ValueError):
b.build(CFG, {"template": "helpers", "params": {"labels": ["org.x; rm"]}})
cfg = json.loads(json.dumps(CFG))
cfg["site"]["solo_dir"] = '~/Library/"x"'
with self.assertRaises(ValueError):
b.build(cfg, {"template": "solo_afl", "params": {"host": "studiob"}})
cfg["site"]["solo_dir"] = "~/Library/Application Support/status-panel/"
self.assertEqual(b.build(cfg, {"template": "solo_afl", "params": {"host": "studiob"}})["run"], CFG["fixes"]["solo_afl"]["run"])
def test_start_builders_never_close_a_running_program(self):
for name, t in b.TEMPLATES.items():
if t.get("start_only") and t.get("render"):
params = {p[0]: (p[4] if p[4] is not None else {"host": "lighting" if t.get("os") == "windows" else "tracks"}.get(p[0], "Thing.exe" if t.get("os") == "windows" else "Thing"))
for p in t["params"]}
run = b.build(CFG, {"template": name, "params": params})["run"]
self.assertFalse(any(w in run for w in ("pkill", "taskkill", "killall", "kill ")), (name, run))
self.assertTrue("||" in run, (name, run)) # only if not already running
def test_this_mac_becomes_a_local_fix_and_the_wrong_os_is_refused(self):
f = b.build(CFG, {"template": "mac_restart", "params": {"host": "ingest", "process": "ProdDash", "app": "/Applications/ProdDash.app"}})
self.assertEqual((f["kind"], f.get("host")), ("local", None))
with self.assertRaises(ValueError):
b.build(CFG, {"template": "win_start", "params": {"host": "tracks", "task": "Start X", "exe": "X.exe"}})
with self.assertRaises(ValueError):
b.build(CFG, {"template": "mac_start", "params": {"host": "lighting", "process": "x", "app": "x"}})
with self.assertRaises(ValueError):
b.build(CFG, {"template": "mac_start", "params": {"host": "nowhere", "process": "x", "app": "x"}})
def test_missing_fields_and_suggested_words(self):
with self.assertRaises(ValueError) as cm:
b.build(CFG, {"template": "mac_start", "params": {"host": "tracks"}})
self.assertIn("process name is needed", str(cm.exception))
self.assertEqual(b.suggest_label(CFG, {"template": "spotify"}), "play the Christian EDM 2026 playlist in Spotify on NA Ingest (opens Spotify if it is closed)")
self.assertEqual(b.suggest_label(CFG, {"template": "win_start", "params": {"task": "Start OBS", "exe": "obs64.exe"}}), "start obs64 if it is not running")
names = {t["name"] for t in b.template_list(CFG)}
self.assertEqual(names, set(b.TEMPLATES))
def test_check_builders(self):
c = b.build_check(CFG, {"type": "remote", "template": "mac_program", "params": {"host": "prop", "process": "Pro Tools"}, "msg": "PT NOT RUNNING", "fix": "x"})
self.assertEqual((c["cmd"], c["host"], c["fix"], c["msg"]), ("pgrep -xq 'Pro Tools'", "prop", "x", "PT NOT RUNNING"))
with self.assertRaises(ValueError):
b.build_check(CFG, {"template": "mac_program", "params": {"host": "ingest", "process": "x"}})
cfg = json.loads(json.dumps(CFG))
for t in cfg["tiles"]:
for ch in t.get("checks", []):
if ch.get("template") == "mac_program":
ch["cmd"] = "true"
self.assertTrue(any("no longer matches" in e for e in schema.validate(cfg)[0]))
if __name__ == "__main__":
unittest.main()