mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
package session
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/samosvalishe/free-turn-proxy/internal/config"
|
|
)
|
|
|
|
func newWakeSession(t *testing.T, window time.Duration) *Session {
|
|
t.Helper()
|
|
s, err := New(&config.Client{}, Deps{
|
|
Options: Options{Traffic: true, WakeProbeWindow: window},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("New: %v", err)
|
|
}
|
|
return s
|
|
}
|
|
|
|
// Пробуждение при живом канале не должно стоить рецикла: аллокация переживает сон, а её
|
|
// пересоздание тянет за собой поход в VK и капчу.
|
|
func TestWakeSkipsRecycleWhenTrafficFlows(t *testing.T) {
|
|
t.Parallel()
|
|
// Окно с запасом: пакет обязан лечь между снимком счётчика и концом окна, а не
|
|
// проиграть гранулярности таймера.
|
|
s := newWakeSession(t, 2*time.Second)
|
|
s.connected.Store(1)
|
|
|
|
done := make(chan bool, 1)
|
|
go func() { done <- s.wakeNeedsRecycle(context.Background()) }()
|
|
|
|
// Имитируем keepalive туннеля, идущий через relay.
|
|
time.Sleep(50 * time.Millisecond)
|
|
s.traffic.stats.AddRx(64)
|
|
|
|
select {
|
|
case need := <-done:
|
|
if need {
|
|
t.Fatal("recycle requested while traffic was flowing")
|
|
}
|
|
case <-time.After(10 * time.Second):
|
|
t.Fatal("wakeNeedsRecycle did not finish")
|
|
}
|
|
}
|
|
|
|
func TestWakeRecyclesOnSilence(t *testing.T) {
|
|
t.Parallel()
|
|
s := newWakeSession(t, 50*time.Millisecond)
|
|
s.connected.Store(1)
|
|
|
|
if !s.wakeNeedsRecycle(context.Background()) {
|
|
t.Fatal("silent channel must be recycled")
|
|
}
|
|
}
|
|
|
|
// Пробуждение во время подъёма сессии отменило бы перебор реквизитов и решение капчи.
|
|
func TestWakeSkipsRecycleWhileConnecting(t *testing.T) {
|
|
t.Parallel()
|
|
s := newWakeSession(t, 50*time.Millisecond)
|
|
|
|
start := time.Now()
|
|
if s.wakeNeedsRecycle(context.Background()) {
|
|
t.Fatal("recycle requested while session was still connecting")
|
|
}
|
|
if elapsed := time.Since(start); elapsed > 40*time.Millisecond {
|
|
t.Fatalf("probe window was waited unnecessarily (%s)", elapsed)
|
|
}
|
|
}
|
|
|
|
// Гэп-детектор ядра и пинок с платформы приходят почти одновременно: второй сигнал
|
|
// про тот же сон не должен давать второй рецикл.
|
|
func TestWakeCollapsesBurst(t *testing.T) {
|
|
t.Parallel()
|
|
s := newWakeSession(t, 50*time.Millisecond)
|
|
s.connected.Store(1)
|
|
|
|
go s.watchWake(t.Context())
|
|
|
|
s.Wake()
|
|
s.Wake()
|
|
|
|
select {
|
|
case <-s.reconnectCh:
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("no recycle after wake on a silent channel")
|
|
}
|
|
|
|
select {
|
|
case <-s.reconnectCh:
|
|
t.Fatal("burst produced a second recycle")
|
|
case <-time.After(200 * time.Millisecond):
|
|
}
|
|
}
|