Files
cabletest/loss_test.go
T

108 lines
2.8 KiB
Go
Raw Normal View History

package main
import (
"testing"
"time"
)
// 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 TestLossContiguousLosesNothing(t *testing.T) {
w := newWindow(10000)
for seq := uint64(0); seq < 10000; seq++ {
w.observe(seq)
}
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)
}
}
// An arrival is the judgment: the gap between it and the previous arrival is
// lost the moment it lands, not when some window slides.
func TestLossGapChargesOnArrival(t *testing.T) {
w := newWindow(10000)
for seq := uint64(0); seq < 100; seq++ {
w.observe(seq)
}
w.observe(105)
if got := w.lost.Load(); got != 5 {
t.Errorf("lost = %d, want 5 the moment the gap's far edge arrived", got)
}
}
// No tolerance of reordering: the newer frame writes the span off, and the
// older one arriving after it is late, not a repair.
func TestLossReorderChargesAndCountsLate(t *testing.T) {
w := newWindow(10000)
for seq := uint64(0); seq < 6; seq++ {
w.observe(seq)
}
w.observe(7)
if got := w.lost.Load(); got != 1 {
t.Errorf("lost = %d after the skip, want 1", got)
}
w.observe(6)
if got := w.late.Load(); got != 1 {
t.Errorf("late = %d, want 1", got)
}
if got := w.lost.Load(); got != 1 {
t.Errorf("lost = %d after the late arrival, want still 1", got)
}
}
// A silent wire is charged by the judge within one deadline: everything the
// frontier covered a deadline ago and nothing has delivered since is lost.
func TestLossJudgeChargesSilentWire(t *testing.T) {
w := newWindow(1000)
t0 := time.Now()
w.judge(t0)
w.judge(t0.Add(lossDeadline / 2))
if got := w.lost.Load(); got != 0 {
t.Errorf("lost = %d before the deadline, want 0", got)
}
w.judge(t0.Add(lossDeadline))
if got := w.lost.Load(); got != 1000 {
t.Errorf("lost = %d after the deadline, want the whole silent frontier, 1000", got)
}
}
// Arrivals move next past the old frontier, so the judge has nothing to add.
func TestLossJudgeSkipsDelivered(t *testing.T) {
w := newWindow(1000)
t0 := time.Now()
w.judge(t0)
for seq := uint64(0); seq < 1000; seq++ {
w.observe(seq)
}
w.judge(t0.Add(lossDeadline))
if got := w.lost.Load(); got != 0 {
t.Errorf("lost = %d, want 0", got)
}
}
// A frame the judge already wrote off arriving afterwards is late, and the
// charge is not repaired.
func TestLossJudgedFrameArrivingIsLate(t *testing.T) {
w := newWindow(1000)
t0 := time.Now()
w.judge(t0)
w.judge(t0.Add(lossDeadline))
w.observe(500)
if got := w.late.Load(); got != 1 {
t.Errorf("late = %d, want 1", got)
}
if got := w.lost.Load(); got != 1000 {
t.Errorf("lost = %d, want unchanged 1000", got)
}
}