All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
113 lines
2.8 KiB
Go
113 lines
2.8 KiB
Go
package cluster
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"switchboard-core/store"
|
|
)
|
|
|
|
// mockClusterStore implements store.ClusterStore for unit tests.
|
|
type mockClusterStore struct {
|
|
nodes []store.ClusterNode
|
|
heartbeatRows int64
|
|
heartbeatErr error
|
|
sweepCalled bool
|
|
registerCalled bool
|
|
lastStats json.RawMessage
|
|
}
|
|
|
|
func (m *mockClusterStore) Register(_ context.Context, nodeID, endpoint string) error {
|
|
m.registerCalled = true
|
|
return nil
|
|
}
|
|
|
|
func (m *mockClusterStore) Heartbeat(_ context.Context, nodeID string, stats json.RawMessage) (int64, error) {
|
|
m.lastStats = stats
|
|
return m.heartbeatRows, m.heartbeatErr
|
|
}
|
|
|
|
func (m *mockClusterStore) SweepStale(_ context.Context, _ time.Duration) (int64, error) {
|
|
m.sweepCalled = true
|
|
return 0, nil
|
|
}
|
|
|
|
func (m *mockClusterStore) ListNodes(_ context.Context) ([]store.ClusterNode, error) {
|
|
return m.nodes, nil
|
|
}
|
|
|
|
func (m *mockClusterStore) Deregister(_ context.Context, _ string) error {
|
|
return nil
|
|
}
|
|
|
|
// mockHub implements ConnCounter.
|
|
type mockHub struct{ count int }
|
|
|
|
func (h *mockHub) ConnCount() int { return h.count }
|
|
|
|
func TestCollectStats(t *testing.T) {
|
|
hub := &mockHub{count: 5}
|
|
reg := NewRegistry("test-node", "http://localhost:8080", nil, hub, RegistryConfig{
|
|
HeartbeatInterval: 10 * time.Second,
|
|
StaleThreshold: 30 * time.Second,
|
|
})
|
|
|
|
data := reg.collectStats()
|
|
|
|
var stats map[string]any
|
|
if err := json.Unmarshal(data, &stats); err != nil {
|
|
t.Fatalf("collectStats returned invalid JSON: %v", err)
|
|
}
|
|
|
|
// Verify expected keys
|
|
expectedKeys := []string{"goroutines", "heap_alloc", "heap_sys", "gc_cycles", "gc_pause_ns", "uptime_sec", "ws_clients"}
|
|
for _, key := range expectedKeys {
|
|
if _, ok := stats[key]; !ok {
|
|
t.Errorf("missing expected stats key: %s", key)
|
|
}
|
|
}
|
|
|
|
// ws_clients should reflect hub count
|
|
if ws, ok := stats["ws_clients"].(float64); !ok || int(ws) != 5 {
|
|
t.Errorf("ws_clients = %v, want 5", stats["ws_clients"])
|
|
}
|
|
}
|
|
|
|
func TestRegistryStartStop(t *testing.T) {
|
|
ms := &mockClusterStore{heartbeatRows: 1}
|
|
hub := &mockHub{count: 0}
|
|
|
|
reg := NewRegistry("test-node", "", ms, hub, RegistryConfig{
|
|
HeartbeatInterval: 50 * time.Millisecond,
|
|
StaleThreshold: 150 * time.Millisecond,
|
|
})
|
|
|
|
if err := reg.Start(); err != nil {
|
|
t.Fatalf("Start() error: %v", err)
|
|
}
|
|
if !ms.registerCalled {
|
|
t.Error("Register was not called on Start")
|
|
}
|
|
|
|
// Let at least one tick fire
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
reg.Stop()
|
|
|
|
if !ms.sweepCalled {
|
|
t.Error("SweepStale was never called during tick")
|
|
}
|
|
if ms.lastStats == nil {
|
|
t.Error("Heartbeat was never called with stats")
|
|
}
|
|
}
|
|
|
|
func TestNodeID(t *testing.T) {
|
|
reg := NewRegistry("my-node-123", "", nil, &mockHub{}, RegistryConfig{})
|
|
if got := reg.NodeID(); got != "my-node-123" {
|
|
t.Errorf("NodeID() = %q, want %q", got, "my-node-123")
|
|
}
|
|
}
|