aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/src/meshbay_cli/selftest.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-cli/src/meshbay_cli/selftest.py')
-rw-r--r--packages/meshbay-cli/src/meshbay_cli/selftest.py61
1 files changed, 61 insertions, 0 deletions
diff --git a/packages/meshbay-cli/src/meshbay_cli/selftest.py b/packages/meshbay-cli/src/meshbay_cli/selftest.py
new file mode 100644
index 0000000..81453c4
--- /dev/null
+++ b/packages/meshbay-cli/src/meshbay_cli/selftest.py
@@ -0,0 +1,61 @@
+"""
+What a frozen build must be able to load, checked with no hub and no node.
+
+A PyInstaller build carries only the modules its analysis found, and a module
+it missed fails at run time only — in the interactive mode, or the first time
+the store asks for the system's key storage. The Windows build runs this
+(`MESHBAY_CLI_SELFTEST=1 meshbay-cli`, see packaging/win/build-node-runtime.ps1)
+on the frozen executable; nothing here is reachable through the command line.
+"""
+
+import asyncio
+import os
+import sys
+import tempfile
+
+
+async def _interactive() -> None:
+ """The sign-in screen, drawn off-screen: Textual's widgets, CSS and Rich."""
+ from .__main__ import build_parser
+ from .commands.context import Context
+ from .tui.app import MeshBayApp
+ from .tui.screens import SignInScreen
+
+ app = MeshBayApp(Context(build_parser().parse_args(["--hub", "http://127.0.0.1:1"])))
+ async with app.run_test(size=(100, 30)) as pilot:
+ for _ in range(100):
+ if isinstance(app.screen, SignInScreen):
+ break
+ await pilot.pause(0.05)
+ else:
+ raise RuntimeError("the sign-in screen never showed")
+ app.screen.query_one("#user")
+
+
+async def _webrtc() -> None:
+ from aiortc import RTCPeerConnection
+ pc = RTCPeerConnection()
+ pc.createDataChannel("selftest")
+ await pc.setLocalDescription(await pc.createOffer())
+ await pc.close()
+
+
+def run() -> int:
+ with tempfile.TemporaryDirectory() as home:
+ os.environ["MESHBAY_CLI_HOME"] = home # nothing stored: the sign-in screen
+ # keyring finds its backends through its own entry points: without its
+ # metadata in the build, Windows Credential Manager is simply not
+ # there and the store falls back to a key file on every machine.
+ import keyring.backend
+ backends = [type(b).__module__ for b in keyring.backend.get_all_keyring()]
+ if sys.platform == "win32" and "keyring.backends.Windows" not in backends:
+ raise RuntimeError(f"no Windows Credential Manager backend in {backends}")
+
+ from argon2.low_level import Type, hash_secret_raw
+ hash_secret_raw(b"x", b"saltsalt", 1, 8, 1, 16, Type.ID)
+
+ from .__main__ import loop_factory
+ asyncio.run(_webrtc(), loop_factory=loop_factory())
+ asyncio.run(_interactive(), loop_factory=loop_factory())
+ print(f"self-test ok (keyring: {', '.join(backends)})")
+ return 0