// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build go1.21 package quic import ( "reflect" "testing" ) func TestRangeSize(t *testing.T) { for _, test := range []struct { r i64range[int64] want int64 }{{ r: i64range[int64]{0, 100}, want: 100, }, { r: i64range[int64]{10, 20}, want: 10, }} { if got := test.r.size(); got != test.want { t.Errorf("%+v.size = %v, want %v", test.r, got, test.want) } } } func TestRangeContains(t *testing.T) { r := i64range[int64]{5, 10} for _, i := range []int64{0, 4, 10, 15} { if r.contains(i) { t.Errorf("%v.contains(%v) = true, want false", r, i) } } for _, i := range []int64{5, 6, 7, 8, 9} { if !r.contains(i) { t.Errorf("%v.contains(%v) = false, want true", r, i) } } } func TestRangesetAdd(t *testing.T) { for _, test := range []struct { desc string set rangeset[int64] add i64range[int64] want rangeset[int64] }{{ desc: "add to empty set", set: rangeset[int64]{}, add: i64range[int64]{0, 100}, want: rangeset[int64]{{0, 100}}, }, { desc: "add empty range", set: rangeset[int64]{}, add: i64range[int64]{100, 100}, want: rangeset[int64]{}, }, { desc: "append nonadjacent range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{300, 400}, want: rangeset[int64]{{100, 200}, {300, 400}}, }, { desc: "prepend nonadjacent range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{0, 50}, want: rangeset[int64]{{0, 50}, {100, 200}}, }, { desc: "insert nonadjacent range", set: rangeset[int64]{{100, 200}, {500, 600}}, add: i64range[int64]{300, 400}, want: rangeset[int64]{{100, 200}, {300, 400}, {500, 600}}, }, { desc: "prepend adjacent range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{50, 100}, want: rangeset[int64]{{50, 200}}, }, { desc: "append adjacent range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{200, 250}, want: rangeset[int64]{{100, 250}}, }, { desc: "prepend overlapping range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{50, 150}, want: rangeset[int64]{{50, 200}}, }, { desc: "append overlapping range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{150, 250}, want: rangeset[int64]{{100, 250}}, }, { desc: "replace range", set: rangeset[int64]{{100, 200}}, add: i64range[int64]{50, 250}, want: rangeset[int64]{{50, 250}}, }, { desc: "prepend and combine", set: rangeset[int64]{{100, 200}, {300, 400}, {500, 600}}, add: i64range[int64]{50, 300}, want: rangeset[int64]{{50, 400}, {500, 600}}, }, { desc: "combine several ranges", set: rangeset[int64]{{100, 200}, {300, 400}, {500, 600}, {700, 800}, {900, 1000}}, add: i64range[int64]{300, 850}, want: rangeset[int64]{{100, 200}, {300, 850}, {900, 1000}}, }} { test := test t.Run(test.desc, func(t *testing.T) { got := test.set got.add(test.add.start, test.add.end) if !reflect.DeepEqual(got, test.want) { t.Errorf("add [%v,%v) to %v", test.add.start, test.add.end, test.set) t.Errorf(" got: %v", got) t.Errorf(" want: %v", test.want) } }) } } func TestRangesetSub(t *testing.T) { for _, test := range []struct { desc string set rangeset[int64] sub i64range[int64] want rangeset[int64] }{{ desc: "subtract from empty set", set: rangeset[int64]{}, sub: i64range[int64]{0, 100}, want: rangeset[int64]{}, }, { desc: "subtract empty range", set: rangeset[int64]{{0, 100}}, sub: i64range[int64]{0, 0}, want: rangeset[int64]{{0, 100}}, }, { desc: "subtract not present in set", set: rangeset[int64]{{0, 100}, {200, 300}}, sub: i64range[int64]{100, 200}, want: rangeset[int64]{{0, 100}, {200, 300}}, }, { desc: "subtract prefix", set: rangeset[int64]{{100, 200}}, sub: i64range[int64]{0, 150}, want: rangeset[int64]{{150, 200}}, }, { desc: "subtract suffix", set: rangeset[int64]{{100, 200}}, sub: i64range[int64]{150, 300}, want: rangeset[int64]{{100, 150}}, }, { desc: "subtract middle", set: rangeset[int64]{{0, 100}}, sub: i64range[int64]{40, 60}, want: rangeset[int64]{{0, 40}, {60, 100}}, }, { desc: "subtract from two ranges", set: rangeset[int64]{{0, 100}, {200, 300}}, sub: i64range[int64]{50, 250}, want: rangeset[int64]{{0, 50}, {250, 300}}, }, { desc: "subtract removes range", set: rangeset[int64]{{0, 100}, {200, 300}, {400, 500}}, sub: i64range[int64]{200, 300}, want: rangeset[int64]{{0, 100}, {400, 500}}, }, { desc: "subtract removes multiple ranges", set: rangeset[int64]{{0, 100}, {200, 300}, {400, 500}, {600, 700}}, sub: i64range[int64]{50, 650}, want: rangeset[int64]{{0, 50}, {650, 700}}, }, { desc: "subtract only range", set: rangeset[int64]{{0, 100}}, sub: i64range[int64]{0, 100}, want: rangeset[int64]{}, }} { test := test t.Run(test.desc, func(t *testing.T) { got := test.set got.sub(test.sub.start, test.sub.end) if !reflect.DeepEqual(got, test.want) { t.Errorf("sub [%v,%v) from %v", test.sub.start, test.sub.end, test.set) t.Errorf(" got: %v", got) t.Errorf(" want: %v", test.want) } }) } } func TestRangesetContains(t *testing.T) { var s rangeset[int64] s.add(10, 20) s.add(30, 40) for i := int64(0); i < 50; i++ { want := (i >= 10 && i < 20) || (i >= 30 && i < 40) if got := s.contains(i); got != want { t.Errorf("%v.contains(%v) = %v, want %v", s, i, got, want) } } } func TestRangesetRangeContaining(t *testing.T) { var s rangeset[int64] s.add(10, 20) s.add(30, 40) for _, test := range []struct { v int64 want i64range[int64] }{ {0, i64range[int64]{0, 0}}, {9, i64range[int64]{0, 0}}, {10, i64range[int64]{10, 20}}, {15, i64range[int64]{10, 20}}, {19, i64range[int64]{10, 20}}, {20, i64range[int64]{0, 0}}, {29, i64range[int64]{0, 0}}, {30, i64range[int64]{30, 40}}, {39, i64range[int64]{30, 40}}, {40, i64range[int64]{0, 0}}, } { got := s.rangeContaining(test.v) if got != test.want { t.Errorf("%v.rangeContaining(%v) = %v, want %v", s, test.v, got, test.want) } } } func TestRangesetLimits(t *testing.T) { for _, test := range []struct { s rangeset[int64] wantMin int64 wantMax int64 wantEnd int64 }{{ s: rangeset[int64]{}, wantMin: 0, wantMax: 0, wantEnd: 0, }, { s: rangeset[int64]{{10, 20}}, wantMin: 10, wantMax: 19, wantEnd: 20, }, { s: rangeset[int64]{{10, 20}, {30, 40}, {50, 60}}, wantMin: 10, wantMax: 59, wantEnd: 60, }} { if got, want := test.s.min(), test.wantMin; got != want { t.Errorf("%+v.min() = %v, want %v", test.s, got, want) } if got, want := test.s.max(), test.wantMax; got != want { t.Errorf("%+v.max() = %v, want %v", test.s, got, want) } if got, want := test.s.end(), test.wantEnd; got != want { t.Errorf("%+v.end() = %v, want %v", test.s, got, want) } } } func TestRangesetIsRange(t *testing.T) { for _, test := range []struct { s rangeset[int64] r i64range[int64] want bool }{{ s: rangeset[int64]{{0, 100}}, r: i64range[int64]{0, 100}, want: true, }, { s: rangeset[int64]{{0, 100}}, r: i64range[int64]{0, 101}, want: false, }, { s: rangeset[int64]{{0, 10}, {11, 100}}, r: i64range[int64]{0, 100}, want: false, }, { s: rangeset[int64]{}, r: i64range[int64]{0, 0}, want: true, }, { s: rangeset[int64]{}, r: i64range[int64]{0, 1}, want: false, }} { if got := test.s.isrange(test.r.start, test.r.end); got != test.want { t.Errorf("%+v.isrange(%v, %v) = %v, want %v", test.s, test.r.start, test.r.end, got, test.want) } } } func TestRangesetNumRanges(t *testing.T) { for _, test := range []struct { s rangeset[int64] want int }{{ s: rangeset[int64]{}, want: 0, }, { s: rangeset[int64]{{0, 100}}, want: 1, }, { s: rangeset[int64]{{0, 100}, {200, 300}}, want: 2, }} { if got, want := test.s.numRanges(), test.want; got != want { t.Errorf("%+v.numRanges() = %v, want %v", test.s, got, want) } } }