package cat import ( "testing" "time" ) // The rule that decides whether a silent-but-alive Icom network session is // tolerated or torn down. It was "always tolerate", and that is what froze the // frequency display for ever when another program took the CI-V session. // // The decision is pinned here rather than left implicit, because the two cases // it separates pull in opposite directions: a rig in standby must NOT be // reconnected every few seconds (the panel and its ON button would blink away), // while a hijacked session must recover without restarting OpsLog. func TestIcomSilenceTolerance(t *testing.T) { // tolerate mirrors the condition in ReadState. tolerate := func(alive, readerGone bool, lastGood time.Time, silentFor, grace time.Duration) bool { return alive && !readerGone && (lastGood.IsZero() || silentFor < grace) } never := time.Time{} some := time.Now() cases := []struct { name string alive bool readerGone bool lastGood time.Time silentFor time.Duration want bool }{ {"never answered since connect — rig is off, keep the panel", true, false, never, time.Hour, true}, {"brief silence during a band change", true, false, some, 2 * time.Second, true}, {"silence past the grace — reconnect", true, false, some, icomSilentGrace + time.Second, false}, {"reader goroutine gone — dead however alive the link looks", true, true, some, time.Second, false}, {"control link itself dead", false, false, some, time.Second, false}, } for _, c := range cases { got := tolerate(c.alive, c.readerGone, c.lastGood, c.silentFor, icomSilentGrace) if got != c.want { t.Errorf("%s: tolerate = %v, want %v", c.name, got, c.want) } } } // The backoff must actually converge on the ceiling: a rig left switched off is // silent for hours, and a window that stayed at 30 s would re-tear its session // about a hundred times an hour. func TestIcomSilenceBackoff(t *testing.T) { g := icomSilentGrace for i := 0; i < 20; i++ { if g < icomSilentGraceMax { g *= 2 } } if g < icomSilentGraceMax { t.Fatalf("backoff never reached the ceiling: %s < %s", g, icomSilentGraceMax) } if g > 2*icomSilentGraceMax { t.Errorf("backoff overshot the ceiling: %s", g) } }