Files

77 lines
3.1 KiB
Go

package mesh
import (
"testing"
"time"
)
func TestPeerConnectionTrackerTransitionsReadyAndDegraded(t *testing.T) {
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
tracker := NewPeerConnectionTracker(PeerCacheSnapshot{
Entries: []PeerCacheEntry{
{NodeID: "node-b", Warm: true, WarmReason: "route_adjacent", Endpoint: "quic://node-b:19443"},
},
}, now)
begin := tracker.BeginProbe(PeerCacheEntry{NodeID: "node-b", Warm: true}, now.Add(time.Second))
if begin.State != PeerConnectionConnecting {
t.Fatalf("begin state = %q, want connecting", begin.State)
}
ready := tracker.RecordSuccess("node-b", 42, now.Add(2*time.Second))
if ready.State != PeerConnectionReady || ready.ConsecutiveSuccesses != 1 || ready.ConsecutiveFailures != 0 {
t.Fatalf("ready state unexpected: %+v", ready)
}
degraded := tracker.RecordSuccess("node-b", 800, now.Add(3*time.Second))
if degraded.State != PeerConnectionDegraded || degraded.LastLatencyMs != 800 {
t.Fatalf("degraded state unexpected: %+v", degraded)
}
}
func TestPeerConnectionTrackerBackoffAfterRepeatedFailures(t *testing.T) {
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
tracker := NewPeerConnectionTracker(PeerCacheSnapshot{
Entries: []PeerCacheEntry{{NodeID: "node-b", Warm: true}},
}, now)
first := tracker.RecordFailure("node-b", "timeout", now.Add(time.Second))
if first.State != PeerConnectionDegraded {
t.Fatalf("first failure state = %q, want degraded", first.State)
}
_ = tracker.RecordFailure("node-b", "timeout", now.Add(2*time.Second))
third := tracker.RecordFailure("node-b", "timeout", now.Add(3*time.Second))
if third.State != PeerConnectionBackoff || third.BackoffUntil.IsZero() {
t.Fatalf("third failure did not enter backoff: %+v", third)
}
if tracker.ShouldProbe("node-b", now.Add(4*time.Second)) {
t.Fatal("ShouldProbe returned true during backoff")
}
if !tracker.ShouldProbe("node-b", third.BackoffUntil.Add(time.Millisecond)) {
t.Fatal("ShouldProbe returned false after backoff")
}
recovered := tracker.RecordSuccess("node-b", 12, third.BackoffUntil.Add(time.Second))
if recovered.State != PeerConnectionReady || recovered.ConsecutiveFailures != 0 || !recovered.BackoffUntil.IsZero() {
t.Fatalf("success did not recover from backoff: %+v", recovered)
}
}
func TestPeerConnectionTrackerSnapshotCountsStates(t *testing.T) {
now := time.Date(2026, 4, 28, 12, 0, 0, 0, time.UTC)
tracker := NewPeerConnectionTracker(PeerCacheSnapshot{
Entries: []PeerCacheEntry{
{NodeID: "node-a", Warm: true},
{NodeID: "node-b", Warm: true},
{NodeID: "node-c", Warm: true},
},
}, now)
tracker.RecordSuccess("node-a", 25, now.Add(time.Second))
tracker.RecordFailure("node-b", "timeout", now.Add(time.Second))
tracker.RecordFailure("node-c", "timeout", now.Add(time.Second))
tracker.RecordFailure("node-c", "timeout", now.Add(2*time.Second))
tracker.RecordFailure("node-c", "timeout", now.Add(3*time.Second))
snapshot := tracker.Snapshot()
if snapshot.Total != 3 || snapshot.Ready != 1 || snapshot.Degraded != 1 || snapshot.Backoff != 1 {
t.Fatalf("unexpected snapshot: %+v", snapshot)
}
}