a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
91 lines
2.8 KiB
Go
91 lines
2.8 KiB
Go
package mcp
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func TestGraphInvalidated_SubscribeUnsubscribe(t *testing.T) {
|
|
b := newGraphInvalidatedBroadcaster(&fakeSpecificSender{}, zap.NewNop())
|
|
if b.subscriberCount() != 0 {
|
|
t.Fatalf("fresh broadcaster has %d subscribers", b.subscriberCount())
|
|
}
|
|
b.subscribe("s1")
|
|
b.subscribe("s2")
|
|
b.subscribe("s1") // idempotent
|
|
if b.subscriberCount() != 2 {
|
|
t.Errorf("subscriberCount = %d, want 2", b.subscriberCount())
|
|
}
|
|
b.subscribe("") // empty id ignored
|
|
if b.subscriberCount() != 2 {
|
|
t.Errorf("empty session id must be ignored, count = %d", b.subscriberCount())
|
|
}
|
|
b.unsubscribe("s1")
|
|
if b.subscriberCount() != 1 {
|
|
t.Errorf("after unsubscribe count = %d, want 1", b.subscriberCount())
|
|
}
|
|
b.unsubscribe("s1") // idempotent
|
|
if b.subscriberCount() != 1 {
|
|
t.Errorf("double unsubscribe count = %d, want 1", b.subscriberCount())
|
|
}
|
|
}
|
|
|
|
func TestGraphInvalidated_BroadcastToSubscribers(t *testing.T) {
|
|
sender := &fakeSpecificSender{}
|
|
b := newGraphInvalidatedBroadcaster(sender, zap.NewNop())
|
|
b.subscribe("s1")
|
|
b.subscribe("s2")
|
|
|
|
b.broadcast(120, 480, "reanalysis")
|
|
|
|
targeted := sender.sessionsTargeted()
|
|
if targeted["s1"] != 1 || targeted["s2"] != 1 {
|
|
t.Fatalf("expected one delivery per subscriber, got %v", targeted)
|
|
}
|
|
calls := sender.snapshot()
|
|
for _, c := range calls {
|
|
if c.method != "notifications/graph_invalidated" {
|
|
t.Errorf("method = %q, want notifications/graph_invalidated", c.method)
|
|
}
|
|
if c.params["node_count"] != 120 || c.params["edge_count"] != 480 {
|
|
t.Errorf("payload counts wrong: %v", c.params)
|
|
}
|
|
if c.params["reason"] != "reanalysis" {
|
|
t.Errorf("reason = %v, want reanalysis", c.params["reason"])
|
|
}
|
|
if _, ok := c.params["ts"].(string); !ok {
|
|
t.Errorf("payload missing ts: %v", c.params)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGraphInvalidated_NoSubscribersNoSend(t *testing.T) {
|
|
sender := &fakeSpecificSender{}
|
|
b := newGraphInvalidatedBroadcaster(sender, zap.NewNop())
|
|
b.broadcast(1, 2, "reanalysis")
|
|
if got := len(sender.snapshot()); got != 0 {
|
|
t.Errorf("broadcast with no subscribers sent %d notifications, want 0", got)
|
|
}
|
|
}
|
|
|
|
// TestGraphInvalidated_RunAnalysisFires proves the broadcaster is
|
|
// wired into the real RunAnalysis path.
|
|
func TestGraphInvalidated_RunAnalysisFires(t *testing.T) {
|
|
srv := newFullTestServer(t)
|
|
sender := &fakeSpecificSender{}
|
|
// Swap in a recording sender so the broadcast is observable.
|
|
srv.graphInvalidatedBroadcaster = newGraphInvalidatedBroadcaster(sender, zap.NewNop())
|
|
srv.graphInvalidatedBroadcaster.subscribe("watcher-session")
|
|
|
|
srv.RunAnalysis()
|
|
|
|
calls := sender.snapshot()
|
|
if len(calls) != 1 {
|
|
t.Fatalf("RunAnalysis produced %d graph_invalidated notifications, want 1", len(calls))
|
|
}
|
|
if calls[0].method != "notifications/graph_invalidated" || calls[0].sessionID != "watcher-session" {
|
|
t.Errorf("unexpected notification: %+v", calls[0])
|
|
}
|
|
}
|