#!/bin/bash set -uo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PYTHONPATH="$ROOT/lib" python3 - "$ROOT" <<'PY' import importlib.util import sys import tempfile from importlib.machinery import SourceFileLoader from pathlib import Path root = Path(sys.argv[1]) loader = SourceFileLoader("layout", str(root / "scripts/classroom-desktop-layout")) spec = importlib.util.spec_from_loader("layout", loader) module = importlib.util.module_from_spec(spec) loader.exec_module(module) passed = failed = 0 def check(label, condition, detail=""): global passed, failed if condition: print(f" ok {label}") passed += 1 else: print(f" FAIL {label}") if detail: print(f" {detail}") failed += 1 WITH = '''tasks.writeConfig("launchers", [ /* CLASSROOM-WONDERINK-LAUNCHER */ "applications:ekklesia-wonderink.desktop", "applications:google-chrome.desktop", /* CLASSROOM-DVD-LAUNCHER */ "applications:ekklesia-dvd.desktop" ].join(","));''' def dvd(text, wanted): return module.rewrite(text, module.DVD_MARKER, module.DVD_ENTRY, wanted) def ink(text, wanted): return module.rewrite( text, module.WONDERINK_MARKER, module.WONDERINK_ENTRY, wanted ) WITHOUT = WITH.replace(' /* CLASSROOM-DVD-LAUNCHER */', ' // /* CLASSROOM-DVD-LAUNCHER */') NO_INK = WITH.replace(' /* CLASSROOM-WONDERINK-LAUNCHER */', ' // /* CLASSROOM-WONDERINK-LAUNCHER */') print("1. the DVD launcher follows the hardware") check("a machine with a drive keeps it", dvd(WITH, True) == WITH) check("a machine without a drive loses it", dvd(WITH, False) == WITHOUT, dvd(WITH, False)) check("and gets it back when a drive appears", dvd(WITHOUT, True) == WITH) check("removing twice changes nothing the second time", dvd(dvd(WITH, False), False) == WITHOUT) check("adding twice changes nothing the second time", dvd(dvd(WITHOUT, True), True) == WITH) print() print("2. Wonder Ink follows the device setting") check("a device with Wonder Ink keeps it", ink(WITH, True) == WITH) check("a device without it loses the launcher", ink(WITH, False) == NO_INK, ink(WITH, False)) check("and gets it back when the setting changes", ink(NO_INK, True) == WITH) check("turning it off twice changes nothing the second time", ink(ink(WITH, False), False) == NO_INK) # The line carries a trailing comma, so a comment that stopped short of it # would leave the array with a hole in it. check("the comma goes with the line", '// /* CLASSROOM-WONDERINK-LAUNCHER */ "applications:' 'ekklesia-wonderink.desktop",' in ink(WITH, False)) check("the browser is untouched either way", "applications:google-chrome.desktop" in ink(WITH, False)) check("and so is the disc player", 'CLASSROOM-DVD-LAUNCHER */ "applications:ekklesia-dvd.desktop"' in ink(WITH, False)) print() print("3. the two settings are independent") neither = ink(dvd(WITH, False), False) check("a laptop with no drive and no Wonder Ink keeps only the browser", neither.count("// /* CLASSROOM") == 2 and "applications:google-chrome.desktop" in neither) check("and comes all the way back", ink(dvd(neither, True), True) == WITH) print() print("4. nothing else in the layout is touched") other = WITH + "\npanel.addWidget(\"org.kde.plasma.digitalclock\");\n" check("a line without the marker is left alone", dvd(other, False).endswith('digitalclock");\n')) check("the other launchers survive", "ekklesia-wonderink.desktop" in dvd(WITH, False) and "google-chrome.desktop" in dvd(WITH, False)) print() print("5. the real layout carries both markers") layout = (root / "config/plasma/lookandfeel/contents/layouts" / "org.kde.plasma.desktop-layout.js").read_text() check("exactly one DVD marker on a launcher line", layout.count(module.DVD_MARKER + ' "applications:') == 1) check("exactly one Wonder Ink marker on a launcher line", layout.count(module.WONDERINK_MARKER + ' "applications:') == 1) check("the shipped layout is one a drive-less machine can be given", dvd(layout, False) != layout) check("and one a Wonder-Ink-less device can be given", ink(layout, False) != layout) print() print("6. the setting defaults to yes") check("an unset WONDERINK_ENABLED means the room has Wonder Ink", module.enabled({}, "WONDERINK_ENABLED", default=True)) for value in ("true", "1", "yes", "on"): check(f"{value} is on", module.enabled({"WONDERINK_ENABLED": value}, "WONDERINK_ENABLED", default=True)) for value in ("false", "0", "no", "off", "banana"): check(f"{value} is off", not module.enabled({"WONDERINK_ENABLED": value}, "WONDERINK_ENABLED", default=True)) print() print("7. a missing or unmarked layout is not an error") with tempfile.TemporaryDirectory() as work: empty = Path(work) / "none.js" check("a layout that does not exist exits cleanly", module.main.__code__ is not None) unmarked = Path(work) / "plain.js" unmarked.write_text("panel.addWidget('x');\n") sys.argv = ["classroom-desktop-layout", str(unmarked)] check("an unmarked layout is left alone", module.main() == 0) check("and unchanged", unmarked.read_text() == "panel.addWidget('x');\n") sys.argv = ["classroom-desktop-layout", str(Path(work) / "missing.js")] check("a missing layout is not a failure", module.main() == 0) print() print(f"{passed} passed, {failed} failed") raise SystemExit(1 if failed else 0) PY