package tunnel import ( "testing" "time" ) // TestBackoffValues 驗證退避函式輸出。 // // 這組測試的核心動機是 POC 的 backoff bug:math.Min 單位 mix 造成 attempt>=1 // 永遠回 30s。修復後應該是純指數退避,clamp 在 [base, cap]。 func TestBackoffValues(t *testing.T) { cases := []struct { attempt int want time.Duration }{ {attempt: 0, want: backoffBase}, // 不應發生,但定義行為 {attempt: 1, want: 1 * time.Second}, // base × 2^0 = 1s {attempt: 2, want: 2 * time.Second}, // base × 2^1 = 2s {attempt: 3, want: 4 * time.Second}, {attempt: 4, want: 8 * time.Second}, {attempt: 5, want: 16 * time.Second}, {attempt: 6, want: backoffCap}, // 32s > 30s → cap {attempt: 7, want: backoffCap}, {attempt: 10, want: backoffCap}, {attempt: 30, want: backoffCap}, {attempt: 100, want: backoffCap}, // 極大 attempt 應不 overflow } for _, tc := range cases { got := backoff(tc.attempt) if got != tc.want { t.Errorf("backoff(%d) = %v, want %v", tc.attempt, got, tc.want) } } } // TestBackoffMonotonicUntilCap 驗證退避在 cap 之前是遞增的。 // 這是 POC bug 會失敗的測試(POC 從 attempt=1 起就固定 30s,根本不遞增)。 func TestBackoffMonotonicUntilCap(t *testing.T) { var prev time.Duration for attempt := 1; attempt <= 5; attempt++ { got := backoff(attempt) if got <= prev { t.Errorf("backoff not monotonically increasing: backoff(%d)=%v, backoff(%d)=%v", attempt-1, prev, attempt, got) } if got > backoffCap { t.Errorf("backoff(%d)=%v exceeds cap %v", attempt, got, backoffCap) } prev = got } } // TestKeepAliveIntervalDefault 固定住 10s 預設值,避免未來不小心改回 POC 的 30s。 // 10s 是 tunnel.md §4.2 M-5 統一的心跳週期。 func TestKeepAliveIntervalDefault(t *testing.T) { if KeepAliveInterval != 10*time.Second { t.Errorf("KeepAliveInterval = %v, want 10s (tunnel.md §4.2 M-5)", KeepAliveInterval) } }