mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-20 12:11:58 +00:00
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.
81 lines
2.5 KiB
Go
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)
|
|
}
|
|
}
|