Files
MrAlders0n 876d99704f feat(ws): opt-in includeRepeats streams later hearings over new paths (#178)
Duplicate observations are dropped before the hub today, so a live map only sees each packet's first hearing per observer. Clients that configure includeRepeats also get later hearings whose path is new; nothing is stored, repeats skip the count query, and they are dropped first when the broadcast channel is half full.
2026-09-27 20:38:49 -04:00

81 lines
2.5 KiB
Go

// Copyright 2026 Beacon Contributors
// SPDX-License-Identifier: AGPL-3.0-or-later
package ingest
import (
"context"
"encoding/json"
"strings"
"testing"
"time"
"github.com/MeshCore-Beacon/beacon-server/internal/api"
"github.com/MeshCore-Beacon/beacon-server/internal/hub"
)
func TestBroadcastPacketObservation_ObserverKeyOptIn(t *testing.T) {
const key = "ab01020304050607080910111213141516171819202122232425262728293031"
w, _ := newTestWorker()
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
go w.hub.Run()
client := w.hub.NewClient()
defer w.hub.Remove(client)
w.hub.AddScope(client, "all", hub.Scope{Events: []hub.EventType{hub.EventPacketObservation, hub.EventObserverStatus}})
waitForSummarySubscriber(t, ctx, w.hub, client)
broadcast := func() hub.Event {
t.Helper()
w.broadcastPacketObservation("YVR", 4, packetObservationEvent{}, []api.ResolvedHop{{}}, key, false)
for {
select {
case evt := <-client.Send:
if evt.Type == hub.EventPacketObservation {
return evt
}
case <-ctx.Done():
t.Fatal("packetObservation not delivered")
}
}
}
observation := func(raw json.RawMessage) map[string]json.RawMessage {
t.Helper()
var evt struct {
Observation map[string]json.RawMessage `json:"observation"`
}
if err := json.Unmarshal(raw, &evt); err != nil {
t.Fatal(err)
}
return evt.Observation
}
evt := broadcast()
if evt.PayloadWithKey != nil || evt.PayloadResolvedWithKey != nil {
t.Fatal("key variants built with no opted-in client")
}
if strings.Contains(string(evt.Payload)+string(evt.PayloadResolved), "observerPublicKey") {
t.Fatal("default payloads must not carry observerPublicKey")
}
// client stays plain so its Payload is still the base variant.
keyed := w.hub.NewClient()
defer w.hub.Remove(keyed)
w.hub.Configure(keyed, hub.ClientOptions{IncludeObserverKey: true})
for !w.hub.ObserverKeyWanted() {
time.Sleep(time.Millisecond)
}
evt = broadcast()
if _, ok := observation(evt.Payload)["observerPublicKey"]; ok {
t.Fatal("base payload must not carry observerPublicKey")
}
withKey := observation(evt.PayloadWithKey)
if string(withKey["observerPublicKey"]) != `"`+key+`"` || string(withKey["resolvedPath"]) != "null" {
t.Fatalf("key variant = %v", withKey)
}
both := observation(evt.PayloadResolvedWithKey)
if string(both["observerPublicKey"]) != `"`+key+`"` || string(both["resolvedPath"]) == "null" {
t.Fatalf("resolved key variant = %v", both)
}
}