From 32b289e04ea315ffbd082eb787ecb197ba189170 Mon Sep 17 00:00:00 2001 From: Eli Mallon Date: Tue, 13 Oct 2026 19:12:13 -0700 Subject: [PATCH] e2e: give the upstream local and Desktop nodes their own MoQ ports MoQ now listens on UDP :38443 by default, and the upstream harness's local node and the Desktop spec's node run beside the harness's other nodes, so the second to start failed to bind. --- js/e2e-web/flows/desktop-upstream-station.spec.ts | 12 ++++++++++++ pkg/cmd/e2e_upstream.go | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/js/e2e-web/flows/desktop-upstream-station.spec.ts b/js/e2e-web/flows/desktop-upstream-station.spec.ts index a8416efa..cbd93d4c 100644 --- a/js/e2e-web/flows/desktop-upstream-station.spec.ts +++ b/js/e2e-web/flows/desktop-upstream-station.spec.ts @@ -4,6 +4,7 @@ import { test, type ElectronApplication, } from "@playwright/test"; +import { createSocket } from "node:dgram"; import { mkdtemp, rm } from "node:fs/promises"; import { createRequire } from "node:module"; import { createServer } from "node:net"; @@ -31,6 +32,16 @@ async function freePort(): Promise { return port; } +// Every node binds MoQ on UDP :38443 by default, and the upstream harness's +// local node is already running beside this one. +async function freeUDPPort(): Promise { + const socket = createSocket("udp4"); + await new Promise((done) => socket.bind(0, "127.0.0.1", done)); + const port = socket.address().port; + await new Promise((done) => socket.close(done)); + return port; +} + // Exercise the actual Electron entry point and its bundled-node launcher, not a // copied spawn configuration. Mobile counterparts live in upstream-station.yaml. test("desktop-upstream-station: login and writes survive closing Desktop", async () => { @@ -54,6 +65,7 @@ test("desktop-upstream-station: login and writes survive closing Desktop", async SP_HTTP_ADDR: localHost, SP_HTTP_INTERNAL_ADDR: `127.0.0.1:${await freePort()}`, SP_RTMP_ADDR: `127.0.0.1:${await freePort()}`, + SP_MOQ_ADDR: `127.0.0.1:${await freeUDPPort()}`, SP_DATA_DIR: join(state, "node"), SP_BROADCASTER_HOST: localHost, SP_DEV_FRONTEND_PROXY: "", diff --git a/pkg/cmd/e2e_upstream.go b/pkg/cmd/e2e_upstream.go index 3b1d655f..d5f4bf8e 100644 --- a/pkg/cmd/e2e_upstream.go +++ b/pkg/cmd/e2e_upstream.go @@ -211,6 +211,12 @@ func startE2ELocalNode(ctx context.Context, self string, tlsEnv *e2eHTTPS, env e } ports[i] = port } + // Every node binds MoQ on UDP :38443 by default, and the harness runs + // several on this host. + moqPort, err := freeUDPPort() + if err != nil { + return nil, err + } proxyURL, err := tlsEnv.StartLocalProxy(ctx, env.PDSURL) if err != nil { return nil, fmt.Errorf("start local PDS observer: %w", err) @@ -225,6 +231,7 @@ func startE2ELocalNode(ctx context.Context, self string, tlsEnv *e2eHTTPS, env e "SP_HTTP_ADDR="+n.addr, fmt.Sprintf("SP_HTTP_INTERNAL_ADDR=127.0.0.1:%d", ports[1]), fmt.Sprintf("SP_RTMP_ADDR=127.0.0.1:%d", ports[2]), + fmt.Sprintf("SP_MOQ_ADDR=127.0.0.1:%d", moqPort), "SP_DATA_DIR="+dir, "SP_BROADCASTER_HOST="+n.addr, "SP_WEBSOCKET_URL=ws://"+n.addr, -- 2.51.2