package auth import ( "testing" "time" ) // TestCodeReplayRejectsReuseInWindow 同一个码在窗口内只能用一次。 func TestCodeReplayRejectsReuseInWindow(t *testing.T) { r := NewCodeReplay() base := time.Date(2026, 9, 21, 10, 0, 0, 0, time.UTC) r.now = func() time.Time { return base } if !r.Consume(7, "123456") { t.Fatal("首次使用应当通过") } if r.Consume(7, "123456") { t.Error("同一个码被重放了") } // 换个用户号的同一个数字码不受影响 if !r.Consume(8, "123456") { t.Error("不同用户的同一个码不该互相影响") } } // TestCodeReplayExpiresAfterWindow 条目只活过一个接受窗口(±1 步 = 90 秒), // 过期后同一个码可以再被收下——否则条目会越攒越多,且数字复用会误伤。 func TestCodeReplayExpiresAfterWindow(t *testing.T) { r := NewCodeReplay() now := time.Date(2026, 9, 21, 10, 0, 0, 0, time.UTC) r.now = func() time.Time { return now } if !r.Consume(7, "123456") { t.Fatal("首次使用应当通过") } now = now.Add(replayTTL - time.Second) if r.Consume(7, "123456") { t.Error("窗口内不该放行") } now = now.Add(2 * time.Second) // 越过 replayTTL if !r.Consume(7, "123456") { t.Error("过期后应当放行") } if n := len(r.used); n != 1 { t.Errorf("过期条目没被清掉,还剩 %d 条", n) } }