package main import "testing" func TestAdaptiveSizerRecoversFromMinimum(t *testing.T) { opts := chunkClientOptions{ startSize: 64, minSize: 32, maxSize: 1024, adaptive: true, adaptSuccesses: 2, } s := newAdaptiveSizer("test", 64, opts) _, next := s.Failure(64) if next != 32 { t.Fatalf("failure should reduce 64 -> 32, got %d", next) } for i := 0; i < 16; i++ { s.Success(32) } if got := s.Current(); got <= 32 { t.Fatalf("adaptive controller remained stuck at minimum: %d", got) } } func newTestConn(min, max int) *chunkConn { return &chunkConn{pipeline: max, minPipeline: min, maxPipeline: max} } func TestPinnedBatchNeverAdapts(t *testing.T) { c := newTestConn(5, 5) if got := c.batchCount(1400); got != 5 { t.Fatalf("pinned batch should request 5 records, got %d", got) } for i := 0; i < 10; i++ { if _, _, shrank := c.shrinkPipeline(); shrank { t.Fatal("pinned batch shrank on transport failure") } c.growPipeline() } if c.pipeline != 5 { t.Fatalf("pinned batch drifted to %d", c.pipeline) } if got := c.batchCount(1400); got != 5 { t.Fatalf("pinned batch should still request 5 records, got %d", got) } } func TestPinnedBatchSurvivesOneMiBCap(t *testing.T) { // 8 x 1 MiB records exceed the ~1 MiB useful-data cap. A pinned depth must // win anyway, otherwise a path that needs exactly 8 records is broken by // an unrelated size heuristic. c := newTestConn(8, 8) if got := c.batchCount(1024 * 1024); got != 8 { t.Fatalf("pinned batch should ignore the 1 MiB cap, got %d", got) } // An unpinned batch is still capped. c = newTestConn(1, 8) if got := c.batchCount(1024 * 1024); got != 1 { t.Fatalf("unpinned batch should be capped to 1, got %d", got) } } func TestAdaptiveBatchStopsAtFloor(t *testing.T) { c := newTestConn(4, 32) seen := map[int]bool{} for i := 0; i < 12; i++ { _, next, _ := c.shrinkPipeline() seen[next] = true } if c.pipeline != 4 { t.Fatalf("batch fell to %d, want the floor 4", c.pipeline) } if !seen[16] || !seen[8] { t.Fatalf("expected halving through 16 and 8, saw %v", seen) } for i := 0; i < 100; i++ { c.growPipeline() } if c.pipeline != 32 { t.Fatalf("batch grew to %d, want the ceiling 32", c.pipeline) } } func TestSingleBatchIsFixed(t *testing.T) { c := newTestConn(1, 1) if !c.pinnedBatch() { t.Fatal("a 1..1 batch must be treated as pinned") } c.growPipeline() if c.pipeline != 1 { t.Fatalf("batch of 1 grew to %d", c.pipeline) } } func TestReconnectZeroMeansPersistent(t *testing.T) { lane := newRequestLane("127.0.0.1:1", 0, 0, 0) if lane.reconnectEvery != 0 { t.Fatalf("reconnectEvery=%d, want 0", lane.reconnectEvery) } }