#31: WebRTC signaling paritesi — engine relay testi

Sinyalleşme (offer/answer/ICE) ayrı bir engine kavramı değil; SDK bunları
{type:':rtcpack:', payload} olarak pack/to üzerinden tüneller (Node ile aynı,
sunucuda RTC handler'ı yok). Engine bu paketleri her iki yönde de payload'ı
incelemeden aynen taşır. Test: TestWebRTCSignalingRelay.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
abdussamedulutas 2026-06-17 08:13:22 +03:00
parent 91ebbeffb2
commit 63680fac19
1 changed files with 45 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import (
"testing" "testing"
"git.saqut.com/saqut/mwse/internal/testutil" "git.saqut.com/saqut/mwse/internal/testutil"
"git.saqut.com/saqut/mwse/internal/ws"
) )
// findReply scans the captured frames for a [payload, id] frame whose id slot is // findReply scans the captured frames for a [payload, id] frame whose id slot is
@ -100,6 +101,50 @@ func TestTunnelLargePayloadIntact(t *testing.T) {
} }
} }
// TestWebRTCSignalingRelay is the #31 parity test. WebRTC signaling is not a
// distinct engine concept: the SDK tunnels offer/answer/ICE as opaque
// {type:":rtcpack:", payload:{...}} packs over pack/to. The engine must carry
// them through unchanged, in both directions, without inspecting the RTC payload.
func TestWebRTCSignalingRelay(t *testing.T) {
hub := newHub()
a, fa := connect(hub, "a")
b, fb := connect(hub, "b")
signal := func(from *ws.Client, to string, rtc map[string]any) {
hub.Handle(from, msg("pack/to", "to", to,
"pack", map[string]any{"type": ":rtcpack:", "payload": rtc}))
}
// A → B: SDP offer.
signal(a, "b", map[string]any{"type": "offer", "value": map[string]any{"sdp": "v=0...offer"}})
offerPack := asMap(t, waitSignal(t, fb, "pack")["pack"])
if offerPack["type"] != ":rtcpack:" {
t.Fatalf("offer relayed as %v, want :rtcpack:", offerPack["type"])
}
if rtc := asMap(t, offerPack["payload"]); rtc["type"] != "offer" {
t.Fatalf("inner signaling type = %v, want offer", rtc["type"])
}
// B → A: SDP answer.
signal(b, "a", map[string]any{"type": "answer", "value": map[string]any{"sdp": "v=0...answer"}})
answerPack := asMap(t, waitSignal(t, fa, "pack")["pack"])
if rtc := asMap(t, answerPack["payload"]); rtc["type"] != "answer" {
t.Fatalf("inner signaling type = %v, want answer", rtc["type"])
}
// A → B: ICE candidate — payload carried verbatim.
cand := map[string]any{"candidate": "candidate:842163049 1 udp ...", "sdpMLineIndex": float64(0)}
signal(a, "b", map[string]any{"type": "icecandidate", "value": cand})
waitFor(t, func() bool {
for _, raw := range fb.Writes() {
if strings.Contains(string(raw), "icecandidate") {
return true
}
}
return false
})
}
// assertNoAddressLeak fails if a relayed payload exposes anything resembling the // assertNoAddressLeak fails if a relayed payload exposes anything resembling the
// sender's real network identity. // sender's real network identity.
func assertNoAddressLeak(t *testing.T, payload map[string]any) { func assertNoAddressLeak(t *testing.T, payload map[string]any) {