Files
beacon-server/internal/ingest/channel_scope_test.go
n30nex a9b8c60a97 feat: stage current preview on dev for dev1 evaluation
Port the qualified server preview at 84ac3c8781 onto
org dev c7209b7043. Preserve upstream changes and
branch policies; keep the independent private Collector service separate.

Preview-Version: 2.2.0-n30nex.1
Preview-Revision: 84ac3c8781
2026-10-04 16:31:48 -04:00

110 lines
4.0 KiB
Go

// Copyright 2026 Beacon Contributors
// SPDX-License-Identifier: AGPL-3.0-or-later
package ingest
import (
"context"
"encoding/hex"
"encoding/json"
"testing"
"time"
"github.com/MeshCore-Beacon/beacon-server/internal/api"
"github.com/MeshCore-Beacon/beacon-server/internal/hub"
"github.com/MeshCore-Beacon/beacon-server/internal/keystore"
"github.com/meshcore-go/meshcore-go"
)
type scopeMessageDB struct {
*stubDB
next *InsertedChannelMessage
}
func (s *scopeMessageDB) InsertChannelMessage(context.Context, InsertChannelMessageParams) (*InsertedChannelMessage, error) {
value := s.next
s.next = nil
return value, nil
}
func TestChannelMessageScopeLive(t *testing.T) {
for _, status := range []string{"matched", "unscoped", "unknown", "unavailable"} {
t.Run(status, func(t *testing.T) {
w, base := newTestWorker()
stored := &InsertedChannelMessage{ID: 42, ScopeStatus: api.ChannelScopeStatus(status)}
name := "#stored"
if status == "matched" {
stored.Scope = &name
}
w.db = &scopeMessageDB{stubDB: base, next: stored}
psk := make([]byte, 16)
w.keys = &mapKeys{entries: map[byte][]keystore.Entry{0x11: {{Key: psk, Fingerprint: []byte{1}, Name: "fixture"}}}}
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, "scope", hub.Scope{Events: []hub.EventType{hub.EventChannelMessage, hub.EventObserverStatus}})
waitForSummarySubscriber(t, ctx, w.hub, client)
packet := &meshcore.Packet{Header: meshcore.MakeHeader(meshcore.RouteTypeTransportFlood, meshcore.PayloadTypeGrpTxt, 0), Payload: encryptedGroupText(t, 0x11, psk, "Fixture", "test")}
latest := "#different-later-reception"
w.handlePayloadTypeSideEffects(ctx, packet, "YOW", []byte{1}, RadioSettings{}, nil, &latest, nil, 0)
select {
case event := <-client.Send:
var got channelMessageEvent
if err := json.Unmarshal(event.Payload, &got); err != nil {
t.Fatal(err)
}
if got.ID != 42 || got.ScopeStatus != stored.ScopeStatus || (got.Scope == nil) != (stored.Scope == nil) || (got.Scope != nil && *got.Scope != name) {
t.Fatal("live scope did not use stored evidence", got)
}
case <-ctx.Done():
t.Fatal("no live message")
}
w.handlePayloadTypeSideEffects(ctx, packet, "YOW", []byte{1}, RadioSettings{}, nil, &latest, nil, 0)
w.hub.Broadcast(hub.Event{Type: hub.EventObserverStatus})
select {
case event := <-client.Send:
if event.Type == hub.EventChannelMessage {
t.Fatal("duplicate broadcast")
}
case <-ctx.Done():
t.Fatal("no barrier")
}
})
}
}
func TestChannelPublicMarkerUsesDecryptionKey(t *testing.T) {
for _, public := range []bool{false, true} {
w, base := newTestWorker()
w.db = &scopeMessageDB{stubDB: base, next: &InsertedChannelMessage{ID: 1}}
key := make([]byte, 16)
if public {
key, _ = hex.DecodeString("8b3387e9c5cdea6ac9e5edbaa115cd72")
}
w.keys = &mapKeys{entries: map[byte][]keystore.Entry{0x11: {{Key: key, Name: "Public"}}}}
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, "public-marker", hub.Scope{Events: []hub.EventType{hub.EventChannelMessage, hub.EventObserverStatus}})
waitForSummarySubscriber(t, ctx, w.hub, client)
packet := &meshcore.Packet{Header: meshcore.MakeHeader(meshcore.RouteTypeFlood, meshcore.PayloadTypeGrpTxt, 0), Payload: encryptedGroupText(t, 0x11, key, "Fixture", "test")}
w.handlePayloadTypeSideEffects(ctx, packet, "YKF", []byte{1}, RadioSettings{}, nil, nil, nil, 0)
select {
case event := <-client.Send:
var got channelMessageEvent
if err := json.Unmarshal(event.Payload, &got); err != nil {
t.Fatal(err)
}
if got.IsPublic != public {
t.Fatal("channel name/hash used instead of actual decryption key")
}
case <-ctx.Done():
t.Fatal("no channel event")
}
}
}