open-standards/wai/wai-rs/tests/fixtures/dev-stack/fake-stack.py
Transaction Science 6f3e31923d
Some checks failed
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 12s
joule-code conformance gate / joule-moq-relay, its own energy on a counter (macos) (push) Successful in 1m2s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Failing after 59s
joule-code conformance gate / Build + round-trip C1-C4 vectors (push) Successful in 1m59s
joule-moq-remote host agent / joule-moq-remote · does this change touch it (push) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (linux-arm64) (push) Has been cancelled
joule-moq-remote host agent / joule-moq-remote, every target (macos) (push) Has been cancelled
joule-moq-room room service / joule-moq-room · does this change touch it (push) Has been cancelled
joule-moq-room room service / joule-moq-room, every target (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · does this change touch it (push) Has been cancelled
joule-moq-web browser client / joule-moq-web · browser end-to-end (macos) (push) Has been cancelled
wai-app and Create / wai-app · does this change touch it (push) Has been cancelled
wai-app and Create / wai-app · tests, clippy, the line language's verifier (linux) (push) Has been cancelled
wai-app and Create / wai-app · Create, browser end-to-end (macos) (push) Has been cancelled
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Has been cancelled
wai-audit collector and player integration / does this change touch it (push) Has been cancelled
wai-audit collector and player integration / collector · linux (push) Has been cancelled
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Has been cancelled
WAI operation catalogue / does this change touch it (push) Has been cancelled
WAI operation catalogue / the catalogue and every door · linux (push) Has been cancelled
wai-fleet service / does this change touch it (push) Has been cancelled
wai-fleet service / service · linux (push) Has been cancelled
wai-fleet service / service · macos (push) Has been cancelled
wai-ledger service / does this change touch it (push) Has been cancelled
wai-ledger service / service · linux (push) Has been cancelled
wai-ledger service / service · macos (push) Has been cancelled
wai-quantum for JavaScript / does this change touch it (push) Has been cancelled
wai-quantum for JavaScript / javascript · linux (push) Has been cancelled
wai-quantum studio and desktop / does this change touch it (push) Has been cancelled
wai-quantum studio and desktop / studio · browser (push) Has been cancelled
wai-quantum studio and desktop / desktop app · macos (push) Has been cancelled
wai-quantum studio and desktop / desktop app · linux (push) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (push) Has been cancelled
wai-sink-android native sink library / does this change touch it (push) Has been cancelled
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Has been cancelled
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Has been cancelled
wai-sink-swift native sink package / does this change touch it (push) Has been cancelled
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Has been cancelled
WAI Studio / does this change touch it (push) Has been cancelled
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Has been cancelled
WAI Studio / Studio in Chromium and Firefox · macos (push) Has been cancelled
WAI Studio / Studio in WebKit · linux (push) Has been cancelled
joule-code conformance gate / joule-moq-relay, every target (push) Successful in 4m3s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 4m48s
joule-code conformance gate / joule-moq-ingest, every target (push) Successful in 6m43s
wai: wai dev is the one local stack, driven by control lines, with synthetic participants, room test and load, and --impair
wai mcp's development tools drive `wai dev --control`: the relay and the room service as a
deployment runs them, the relay holding each publisher's media to its receipts. Synthetic
participants (`wai-room participant`) join, leave, publish receipted objects and show the session
through control lines; `wai room test` and `wai room load` run them on the stack wai dev records;
`--impair` puts them on the relay's QUIC binding through joule-contrib's lossy path. A program of
another toolchain is refused as a stale stack. `wai-room dev` becomes the crate's test fixture.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 10:54:12 -05:00

101 lines
3.7 KiB
Python
Executable file

#!/usr/bin/env python3
"""A stand-in for the relay and the room service, for tests/cli_studio.rs: what `wai dev`
asks of each, and nothing more.
fake-stack.py keygen|relay-lines <keys.toml> prints relay lines (comments here)
fake-stack.py --config <relay.toml|room.toml> listens where the configuration says
fake-stack.py --version --json the toolchain envelope `wai dev` asks for:
the program is this file's name less `.py`
(a copy named wai-relay.py answers as the
relay), the toolchain $FAKE_STACK_TOOLCHAIN
A relay's configuration names `websocket_listen`; it accepts connections and closes them. A
room service's names `listen`; it answers GET /health as a service whose clock is on the
relay, and GET /room with an empty room. Either exits when the process that started it is
gone. Standard library only.
"""
import http.server
import json
import os
import re
import socket
import socketserver
import sys
import threading
import time
def watch_parent():
parent = os.getppid()
while True:
time.sleep(0.5)
if os.getppid() != parent:
os._exit(0)
def listen_addr(config, key):
text = open(config, encoding="utf-8").read()
m = re.search(r'^%s\s*=\s*"([^"]+)"' % key, text, re.M)
host, port = m.group(1).rsplit(":", 1)
return host, int(port)
class Room(http.server.BaseHTTPRequestHandler):
def do_GET(self):
if self.path.startswith("/health"):
body = {"ok": True, "relay": True, "room": "00" * 32}
elif self.path.startswith("/room"):
body = {"room": "00" * 32, "t0_us": 0, "descriptor": "", "grants": []}
else:
self.send_error(404)
return
b = json.dumps(body).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(b)))
self.end_headers()
self.wfile.write(b)
def log_message(self, *args):
pass
class Server(http.server.ThreadingHTTPServer):
"""HTTPServer looks up a name for its address before it listens, and nothing here reads the
name. On some hosts that lookup takes 35 s, past what `wai dev` waits for a service."""
def server_bind(self):
socketserver.TCPServer.server_bind(self)
def main(argv):
if argv == ["--version", "--json"]:
program = os.path.basename(sys.argv[0])
if program.endswith(".py"):
program = program[:-3]
data = {"program": program, "version": "0.1.0", "toolchain": os.environ.get("FAKE_STACK_TOOLCHAIN", "")}
print(json.dumps({"wai": "envelope/1", "op": "toolchain.show", "ok": True, "data": data}))
return 0
if argv[:1] in (["keygen"], ["relay-lines"]):
open(argv[1], "a").close()
print("# authority %s\n# clock %s" % ("11" * 32, "22" * 32))
return 0
if argv[:1] != ["--config"]:
print("fake-stack.py: keygen|relay-lines <keys> or --config <file>", file=sys.stderr)
return 2
threading.Thread(target=watch_parent, daemon=True).start()
config = argv[1]
if "websocket_listen" in open(config, encoding="utf-8").read():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(listen_addr(config, "websocket_listen"))
s.listen(16)
while True:
c, _ = s.accept()
c.close()
Server(listen_addr(config, "listen"), Room).serve_forever()
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1:]))