package main import "testing" // sent is the sender's frontier: sequence numbers at or above it were never put // on the wire. func newWindow(sent uint64) *lossWindow { tx := &txStats{} tx.sent.Store(sent) w := newLossWindows([]*txStats{tx}) return &w[0] } func TestLossWindowContiguousLosesNothing(t *testing.T) { w := newWindow(lossSlots + 1000) for seq := uint64(0); seq < lossSlots+1000; seq++ { w.observe(seq, false) } if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d, want 0", got) } if got := w.late.Load(); got != 0 { t.Errorf("late = %d, want 0", got) } } func TestLossWindowCountsGapOnceEvicted(t *testing.T) { w := newWindow(lossSlots + 1000) for seq := uint64(0); seq < lossSlots+1000; seq++ { if seq == 100 { continue } w.observe(seq, false) } if got := w.lost.Load(); got != 1 { t.Errorf("lost = %d, want 1", got) } } // Arriving out of order inside the window is not loss: a sequence is only // judged once it falls out the far end. func TestLossWindowOutOfOrderIsNotLoss(t *testing.T) { w := newWindow(lossSlots + 1000) for seq := uint64(99); ; seq-- { w.observe(seq, false) if seq == 0 { break } } for seq := uint64(100); seq < lossSlots+1000; seq++ { w.observe(seq, false) } if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d, want 0", got) } } // The other branch of evict: a jump past a whole window writes off everything // the window held plus the sequences that never landed in it at all. func TestLossWindowJumpBeyondWindow(t *testing.T) { w := newWindow(200001) w.observe(0, false) w.observe(200000, false) // Everything below the new base except the one sequence that was seen. want := uint64(200000 - lossSlots + 1 - 1) if got := w.lost.Load(); got != want { t.Errorf("lost = %d, want %d", got, want) } if got := w.late.Load(); got != 0 { t.Errorf("late = %d, want 0", got) } } func TestLossWindowBelowBaseIsLate(t *testing.T) { w := newWindow(100001) w.observe(100000, false) w.observe(1000, false) if got := w.late.Load(); got != 1 { t.Errorf("late = %d, want 1", got) } if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d, want 0", got) } } // The first sequence seen starts the window half a span below it, so frames // another worker is still holding land inside rather than arriving late. func TestLossWindowStartsHalfAWindowBack(t *testing.T) { w := newWindow(100001) w.observe(100000, false) if w.base != 100000-lossSlots/2 { t.Errorf("base = %d, want %d", w.base, 100000-lossSlots/2) } } // The failure this guard exists for. A sequence number the sender never reached // used to drag the base up to it, write off the span in between as lost, and // leave every real frame after it below the base and counted late for the rest // of the run. It has to be refused outright, and the stream has to go on // counting as if it had never arrived. func TestLossWindowRefusesUnsentSeq(t *testing.T) { const first = 100000 w := newWindow(first + 2000) for seq := uint64(first); seq < first+1000; seq++ { w.observe(seq, false) } base := w.base if w.observe(1<<62, false) { t.Error("a sequence number far past the sender's frontier was accepted") } if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d after one impossible sequence number, want 0", got) } if w.base != base { t.Errorf("base moved to %d, want it left at %d where the real traffic put it", w.base, base) } // Still tracking the real traffic, rather than reporting every frame late // against a base that ran away. for seq := uint64(first + 1000); seq < first+2000; seq++ { w.observe(seq, false) } if got := w.late.Load(); got != 0 { t.Errorf("late = %d, want 0", got) } if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d, want 0", got) } } // A gap written off while quiet — a cable measure's own link blip — charges // nothing, however the eviction timing falls: even the gap's tail still // inside the window when the measure ends is presumed delivered. Counting // resumes seamlessly and later real gaps are still caught. func TestLossWindowQuietSlidesWithoutCharging(t *testing.T) { w := newWindow(4 * lossSlots) for seq := uint64(0); seq < 100; seq++ { w.observe(seq, false) } // The blip: a huge jump arriving during the measure. w.observe(2*lossSlots, true) if got := w.lost.Load(); got != 0 { t.Errorf("lost = %d after a quiet write-off, want 0", got) } // The measure ends immediately — the worst case, with the gap's tail // still in-window — and a single real gap follows. for seq := uint64(2*lossSlots + 1); seq < 4*lossSlots-100; seq++ { if seq == 2*lossSlots+500 { continue } w.observe(seq, false) } if got := w.lost.Load(); got != 1 { t.Errorf("lost = %d, want exactly the one real post-measure gap", got) } } // The sender's own frontier is the bound, so the sequence one past it is // refused while the one below it is not. func TestLossWindowBoundIsExclusive(t *testing.T) { w := newWindow(500) if !w.observe(499, false) { t.Error("the last sequence the sender put on the wire was refused") } if w.observe(500, false) { t.Error("a sequence the sender had not reached was accepted") } }