77 lines
3.1 KiB
Go
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: "http://node-b:19000"},
|
|
},
|
|
}, 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)
|
|
}
|
|
}
|