github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/segment/test/segment_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package segment
    16  
    17  import (
    18  	"fmt"
    19  	"math/rand"
    20  	"reflect"
    21  	"testing"
    22  )
    23  
    24  const (
    25  	// testSize is the baseline number of elements inserted into sets under
    26  	// test, and is chosen to be large enough to ensure interesting amounts of
    27  	// tree rebalancing.
    28  	//
    29  	// Note that because checkSet is called between each insertion/removal in
    30  	// some tests that use it, tests may be quadratic in testSize.
    31  	testSize = 8000
    32  
    33  	// valueOffset is the difference between the value and start of test
    34  	// segments.
    35  	valueOffset = 100000
    36  
    37  	// intervalLength is the interval used by random gap tests.
    38  	intervalLength = 10
    39  )
    40  
    41  func shuffle(xs []int) {
    42  	rand.Shuffle(len(xs), func(i, j int) { xs[i], xs[j] = xs[j], xs[i] })
    43  }
    44  
    45  func randIntervalPermutation(size int) []int {
    46  	p := make([]int, size)
    47  	for i := range p {
    48  		p[i] = intervalLength * i
    49  	}
    50  	shuffle(p)
    51  	return p
    52  }
    53  
    54  // validate can be passed to Check.
    55  func validate(nr int, r Range, v int) error {
    56  	if got, want := v, r.Start+valueOffset; got != want {
    57  		return fmt.Errorf("segment %d has key %d, value %d (expected %d)", nr, r.Start, got, want)
    58  	}
    59  	return nil
    60  }
    61  
    62  // checkSetMaxGap returns an error if maxGap inside all nodes of s is not well
    63  // maintained.
    64  func checkSetMaxGap(s *gapSet) error {
    65  	n := s.root
    66  	return checkNodeMaxGap(&n)
    67  }
    68  
    69  // checkNodeMaxGap returns an error if maxGap inside the subtree rooted by n is
    70  // not well maintained.
    71  func checkNodeMaxGap(n *gapnode) error {
    72  	var max int
    73  	if !n.hasChildren {
    74  		max = n.calculateMaxGapLeaf()
    75  	} else {
    76  		for i := 0; i <= n.nrSegments; i++ {
    77  			child := n.children[i]
    78  			if err := checkNodeMaxGap(child); err != nil {
    79  				return err
    80  			}
    81  			if temp := child.maxGap.Get(); i == 0 || temp > max {
    82  				max = temp
    83  			}
    84  		}
    85  	}
    86  	if max != n.maxGap.Get() {
    87  		return fmt.Errorf("maxGap wrong in node\n%vexpected: %d got: %d", n, max, n.maxGap)
    88  	}
    89  	return nil
    90  }
    91  
    92  func TestAddRandom(t *testing.T) {
    93  	var s Set
    94  	order := rand.Perm(testSize)
    95  	var nrInsertions int
    96  	for i, j := range order {
    97  		if !s.AddWithoutMerging(Range{j, j + 1}, j+valueOffset) {
    98  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
    99  			break
   100  		}
   101  		nrInsertions++
   102  		if err := s.segmentTestCheck(nrInsertions, validate); err != nil {
   103  			t.Errorf("Iteration %d: %v", i, err)
   104  			break
   105  		}
   106  	}
   107  	if got, want := s.countSegments(), nrInsertions; got != want {
   108  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   109  	}
   110  	if t.Failed() {
   111  		t.Logf("Insertion order: %v", order[:nrInsertions])
   112  		t.Logf("Set contents:\n%v", &s)
   113  	}
   114  }
   115  
   116  func TestRemoveRandom(t *testing.T) {
   117  	var s Set
   118  	for i := 0; i < testSize; i++ {
   119  		if !s.AddWithoutMerging(Range{i, i + 1}, i+valueOffset) {
   120  			t.Fatalf("Failed to insert segment %d", i)
   121  		}
   122  	}
   123  	order := rand.Perm(testSize)
   124  	var nrRemovals int
   125  	for i, j := range order {
   126  		seg := s.FindSegment(j)
   127  		if !seg.Ok() {
   128  			t.Errorf("Iteration %d: failed to find segment with key %d", i, j)
   129  			break
   130  		}
   131  		s.Remove(seg)
   132  		nrRemovals++
   133  		if err := s.segmentTestCheck(testSize-nrRemovals, validate); err != nil {
   134  			t.Errorf("Iteration %d: %v", i, err)
   135  			break
   136  		}
   137  	}
   138  	if got, want := s.countSegments(), testSize-nrRemovals; got != want {
   139  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   140  	}
   141  	if t.Failed() {
   142  		t.Logf("Removal order: %v", order[:nrRemovals])
   143  		t.Logf("Set contents:\n%v", &s)
   144  		t.FailNow()
   145  	}
   146  }
   147  
   148  func TestMaxGapAddRandom(t *testing.T) {
   149  	var s gapSet
   150  	order := rand.Perm(testSize)
   151  	var nrInsertions int
   152  	for i, j := range order {
   153  		if !s.AddWithoutMerging(Range{j, j + 1}, j+valueOffset) {
   154  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   155  			break
   156  		}
   157  		nrInsertions++
   158  		if err := s.segmentTestCheck(nrInsertions, validate); err != nil {
   159  			t.Errorf("Iteration %d: %v", i, err)
   160  			break
   161  		}
   162  		if err := checkSetMaxGap(&s); err != nil {
   163  			t.Errorf("When inserting %d: %v", j, err)
   164  			break
   165  		}
   166  	}
   167  	if got, want := s.countSegments(), nrInsertions; got != want {
   168  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   169  	}
   170  	if t.Failed() {
   171  		t.Logf("Insertion order: %v", order[:nrInsertions])
   172  		t.Logf("Set contents:\n%v", &s)
   173  	}
   174  }
   175  
   176  func TestMaxGapAddRandomWithRandomInterval(t *testing.T) {
   177  	var s gapSet
   178  	order := randIntervalPermutation(testSize)
   179  	var nrInsertions int
   180  	for i, j := range order {
   181  		if !s.AddWithoutMerging(Range{j, j + rand.Intn(intervalLength-1) + 1}, j+valueOffset) {
   182  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   183  			break
   184  		}
   185  		nrInsertions++
   186  		if err := s.segmentTestCheck(nrInsertions, validate); err != nil {
   187  			t.Errorf("Iteration %d: %v", i, err)
   188  			break
   189  		}
   190  		if err := checkSetMaxGap(&s); err != nil {
   191  			t.Errorf("When inserting %d: %v", j, err)
   192  			break
   193  		}
   194  	}
   195  	if got, want := s.countSegments(), nrInsertions; got != want {
   196  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   197  	}
   198  	if t.Failed() {
   199  		t.Logf("Insertion order: %v", order[:nrInsertions])
   200  		t.Logf("Set contents:\n%v", &s)
   201  	}
   202  }
   203  
   204  func TestMaxGapAddRandomWithMerge(t *testing.T) {
   205  	var s gapSet
   206  	order := randIntervalPermutation(testSize)
   207  	nrInsertions := 1
   208  	for i, j := range order {
   209  		if !s.Add(Range{j, j + intervalLength}, j+valueOffset) {
   210  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   211  			break
   212  		}
   213  		if err := checkSetMaxGap(&s); err != nil {
   214  			t.Errorf("When inserting %d: %v", j, err)
   215  			break
   216  		}
   217  	}
   218  	if got, want := s.countSegments(), nrInsertions; got != want {
   219  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   220  	}
   221  	if t.Failed() {
   222  		t.Logf("Insertion order: %v", order)
   223  		t.Logf("Set contents:\n%v", &s)
   224  	}
   225  }
   226  
   227  func TestMaxGapRemoveRandom(t *testing.T) {
   228  	var s gapSet
   229  	for i := 0; i < testSize; i++ {
   230  		if !s.AddWithoutMerging(Range{i, i + 1}, i+valueOffset) {
   231  			t.Fatalf("Failed to insert segment %d", i)
   232  		}
   233  	}
   234  	order := rand.Perm(testSize)
   235  	var nrRemovals int
   236  	for i, j := range order {
   237  		seg := s.FindSegment(j)
   238  		if !seg.Ok() {
   239  			t.Errorf("Iteration %d: failed to find segment with key %d", i, j)
   240  			break
   241  		}
   242  		temprange := seg.Range()
   243  		s.Remove(seg)
   244  		nrRemovals++
   245  		if err := s.segmentTestCheck(testSize-nrRemovals, validate); err != nil {
   246  			t.Errorf("Iteration %d: %v", i, err)
   247  			break
   248  		}
   249  		if err := checkSetMaxGap(&s); err != nil {
   250  			t.Errorf("When removing %v: %v", temprange, err)
   251  			break
   252  		}
   253  	}
   254  	if got, want := s.countSegments(), testSize-nrRemovals; got != want {
   255  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   256  	}
   257  	if t.Failed() {
   258  		t.Logf("Removal order: %v", order[:nrRemovals])
   259  		t.Logf("Set contents:\n%v", &s)
   260  		t.FailNow()
   261  	}
   262  }
   263  
   264  func TestMaxGapRemoveHalfRandom(t *testing.T) {
   265  	var s gapSet
   266  	for i := 0; i < testSize; i++ {
   267  		if !s.AddWithoutMerging(Range{intervalLength * i, intervalLength*i + rand.Intn(intervalLength-1) + 1}, intervalLength*i+valueOffset) {
   268  			t.Fatalf("Failed to insert segment %d", i)
   269  		}
   270  	}
   271  	order := randIntervalPermutation(testSize)
   272  	order = order[:testSize/2]
   273  	var nrRemovals int
   274  	for i, j := range order {
   275  		seg := s.FindSegment(j)
   276  		if !seg.Ok() {
   277  			t.Errorf("Iteration %d: failed to find segment with key %d", i, j)
   278  			break
   279  		}
   280  		temprange := seg.Range()
   281  		s.Remove(seg)
   282  		nrRemovals++
   283  		if err := s.segmentTestCheck(testSize-nrRemovals, validate); err != nil {
   284  			t.Errorf("Iteration %d: %v", i, err)
   285  			break
   286  		}
   287  		if err := checkSetMaxGap(&s); err != nil {
   288  			t.Errorf("When removing %v: %v", temprange, err)
   289  			break
   290  		}
   291  	}
   292  	if got, want := s.countSegments(), testSize-nrRemovals; got != want {
   293  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   294  	}
   295  	if t.Failed() {
   296  		t.Logf("Removal order: %v", order[:nrRemovals])
   297  		t.Logf("Set contents:\n%v", &s)
   298  		t.FailNow()
   299  	}
   300  }
   301  
   302  func TestMaxGapAddRandomRemoveRandomHalfWithMerge(t *testing.T) {
   303  	var s gapSet
   304  	order := randIntervalPermutation(testSize * 2)
   305  	order = order[:testSize]
   306  	for i, j := range order {
   307  		if !s.Add(Range{j, j + intervalLength}, j+valueOffset) {
   308  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   309  			break
   310  		}
   311  		if err := checkSetMaxGap(&s); err != nil {
   312  			t.Errorf("When inserting %d: %v", j, err)
   313  			break
   314  		}
   315  	}
   316  	shuffle(order)
   317  	var nrRemovals int
   318  	for _, j := range order {
   319  		seg := s.FindSegment(j)
   320  		if !seg.Ok() {
   321  			continue
   322  		}
   323  		temprange := seg.Range()
   324  		s.Remove(seg)
   325  		nrRemovals++
   326  		if err := checkSetMaxGap(&s); err != nil {
   327  			t.Errorf("When removing %v: %v", temprange, err)
   328  			break
   329  		}
   330  	}
   331  	if t.Failed() {
   332  		t.Logf("Removal order: %v", order[:nrRemovals])
   333  		t.Logf("Set contents:\n%v", &s)
   334  		t.FailNow()
   335  	}
   336  }
   337  
   338  func TestNextLargeEnoughGap(t *testing.T) {
   339  	var s gapSet
   340  	order := randIntervalPermutation(testSize * 2)
   341  	order = order[:testSize]
   342  	for i, j := range order {
   343  		if !s.Add(Range{j, j + rand.Intn(intervalLength-1) + 1}, j+valueOffset) {
   344  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   345  			break
   346  		}
   347  		if err := checkSetMaxGap(&s); err != nil {
   348  			t.Errorf("When inserting %d: %v", j, err)
   349  			break
   350  		}
   351  	}
   352  	shuffle(order)
   353  	order = order[:testSize/2]
   354  	for _, j := range order {
   355  		seg := s.FindSegment(j)
   356  		if !seg.Ok() {
   357  			continue
   358  		}
   359  		temprange := seg.Range()
   360  		s.Remove(seg)
   361  		if err := checkSetMaxGap(&s); err != nil {
   362  			t.Errorf("When removing %v: %v", temprange, err)
   363  			break
   364  		}
   365  	}
   366  	minSize := 7
   367  	var gapArr1 []int
   368  	for gap := s.LowerBoundGap(0).NextLargeEnoughGap(minSize); gap.Ok(); gap = gap.NextLargeEnoughGap(minSize) {
   369  		if gap.Range().Length() < minSize {
   370  			t.Errorf("NextLargeEnoughGap wrong, gap %v has length %d, wanted %d", gap.Range(), gap.Range().Length(), minSize)
   371  		} else {
   372  			gapArr1 = append(gapArr1, gap.Range().Start)
   373  		}
   374  	}
   375  	var gapArr2 []int
   376  	for gap := s.LowerBoundGap(0).NextGap(); gap.Ok(); gap = gap.NextGap() {
   377  		if gap.Range().Length() >= minSize {
   378  			gapArr2 = append(gapArr2, gap.Range().Start)
   379  		}
   380  	}
   381  
   382  	if !reflect.DeepEqual(gapArr2, gapArr1) {
   383  		t.Errorf("Search result not correct, got: %v, wanted: %v", gapArr1, gapArr2)
   384  	}
   385  	if t.Failed() {
   386  		t.Logf("Set contents:\n%v", &s)
   387  		t.FailNow()
   388  	}
   389  }
   390  
   391  func TestPrevLargeEnoughGap(t *testing.T) {
   392  	var s gapSet
   393  	order := randIntervalPermutation(testSize * 2)
   394  	order = order[:testSize]
   395  	for i, j := range order {
   396  		if !s.Add(Range{j, j + rand.Intn(intervalLength-1) + 1}, j+valueOffset) {
   397  			t.Errorf("Iteration %d: failed to insert segment with key %d", i, j)
   398  			break
   399  		}
   400  		if err := checkSetMaxGap(&s); err != nil {
   401  			t.Errorf("When inserting %d: %v", j, err)
   402  			break
   403  		}
   404  	}
   405  	end := s.LastSegment().End()
   406  	shuffle(order)
   407  	order = order[:testSize/2]
   408  	for _, j := range order {
   409  		seg := s.FindSegment(j)
   410  		if !seg.Ok() {
   411  			continue
   412  		}
   413  		temprange := seg.Range()
   414  		s.Remove(seg)
   415  		if err := checkSetMaxGap(&s); err != nil {
   416  			t.Errorf("When removing %v: %v", temprange, err)
   417  			break
   418  		}
   419  	}
   420  	minSize := 7
   421  	var gapArr1 []int
   422  	for gap := s.UpperBoundGap(end + intervalLength).PrevLargeEnoughGap(minSize); gap.Ok(); gap = gap.PrevLargeEnoughGap(minSize) {
   423  		if gap.Range().Length() < minSize {
   424  			t.Errorf("PrevLargeEnoughGap wrong, gap length %d, wanted %d", gap.Range().Length(), minSize)
   425  		} else {
   426  			gapArr1 = append(gapArr1, gap.Range().Start)
   427  		}
   428  	}
   429  	var gapArr2 []int
   430  	for gap := s.UpperBoundGap(end + intervalLength).PrevGap(); gap.Ok(); gap = gap.PrevGap() {
   431  		if gap.Range().Length() >= minSize {
   432  			gapArr2 = append(gapArr2, gap.Range().Start)
   433  		}
   434  	}
   435  	if !reflect.DeepEqual(gapArr2, gapArr1) {
   436  		t.Errorf("Search result not correct, got: %v, wanted: %v", gapArr1, gapArr2)
   437  	}
   438  	if t.Failed() {
   439  		t.Logf("Set contents:\n%v", &s)
   440  		t.FailNow()
   441  	}
   442  }
   443  
   444  func TestAddSequentialAdjacent(t *testing.T) {
   445  	var s Set
   446  	var nrInsertions int
   447  	for i := 0; i < testSize; i++ {
   448  		if !s.AddWithoutMerging(Range{i, i + 1}, i+valueOffset) {
   449  			t.Fatalf("Failed to insert segment %d", i)
   450  		}
   451  		nrInsertions++
   452  		if err := s.segmentTestCheck(nrInsertions, validate); err != nil {
   453  			t.Errorf("Iteration %d: %v", i, err)
   454  			break
   455  		}
   456  	}
   457  	if got, want := s.countSegments(), nrInsertions; got != want {
   458  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   459  	}
   460  	if t.Failed() {
   461  		t.Logf("Set contents:\n%v", &s)
   462  	}
   463  
   464  	first := s.FirstSegment()
   465  	gotSeg, gotGap := first.PrevNonEmpty()
   466  	if wantGap := s.FirstGap(); gotSeg.Ok() || gotGap != wantGap {
   467  		t.Errorf("FirstSegment().PrevNonEmpty(): got (%v, %v), wanted (<terminal iterator>, %v)", gotSeg, gotGap, wantGap)
   468  	}
   469  	gotSeg, gotGap = first.NextNonEmpty()
   470  	if wantSeg := first.NextSegment(); gotSeg != wantSeg || gotGap.Ok() {
   471  		t.Errorf("FirstSegment().NextNonEmpty(): got (%v, %v), wanted (%v, <terminal iterator>)", gotSeg, gotGap, wantSeg)
   472  	}
   473  
   474  	last := s.LastSegment()
   475  	gotSeg, gotGap = last.PrevNonEmpty()
   476  	if wantSeg := last.PrevSegment(); gotSeg != wantSeg || gotGap.Ok() {
   477  		t.Errorf("LastSegment().PrevNonEmpty(): got (%v, %v), wanted (%v, <terminal iterator>)", gotSeg, gotGap, wantSeg)
   478  	}
   479  	gotSeg, gotGap = last.NextNonEmpty()
   480  	if wantGap := s.LastGap(); gotSeg.Ok() || gotGap != wantGap {
   481  		t.Errorf("LastSegment().NextNonEmpty(): got (%v, %v), wanted (<terminal iterator>, %v)", gotSeg, gotGap, wantGap)
   482  	}
   483  
   484  	for seg := first.NextSegment(); seg != last; seg = seg.NextSegment() {
   485  		gotSeg, gotGap = seg.PrevNonEmpty()
   486  		if wantSeg := seg.PrevSegment(); gotSeg != wantSeg || gotGap.Ok() {
   487  			t.Errorf("%v.PrevNonEmpty(): got (%v, %v), wanted (%v, <terminal iterator>)", seg, gotSeg, gotGap, wantSeg)
   488  		}
   489  		gotSeg, gotGap = seg.NextNonEmpty()
   490  		if wantSeg := seg.NextSegment(); gotSeg != wantSeg || gotGap.Ok() {
   491  			t.Errorf("%v.NextNonEmpty(): got (%v, %v), wanted (%v, <terminal iterator>)", seg, gotSeg, gotGap, wantSeg)
   492  		}
   493  	}
   494  }
   495  
   496  func TestAddSequentialNonAdjacent(t *testing.T) {
   497  	var s Set
   498  	var nrInsertions int
   499  	for i := 0; i < testSize; i++ {
   500  		// The range here differs from TestAddSequentialAdjacent so that
   501  		// consecutive segments are not adjacent.
   502  		if !s.AddWithoutMerging(Range{2 * i, 2*i + 1}, 2*i+valueOffset) {
   503  			t.Fatalf("Failed to insert segment %d", i)
   504  		}
   505  		nrInsertions++
   506  		if err := s.segmentTestCheck(nrInsertions, validate); err != nil {
   507  			t.Errorf("Iteration %d: %v", i, err)
   508  			break
   509  		}
   510  	}
   511  	if got, want := s.countSegments(), nrInsertions; got != want {
   512  		t.Errorf("Wrong final number of segments: got %d, wanted %d", got, want)
   513  	}
   514  	if t.Failed() {
   515  		t.Logf("Set contents:\n%v", &s)
   516  	}
   517  
   518  	for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
   519  		gotSeg, gotGap := seg.PrevNonEmpty()
   520  		if wantGap := seg.PrevGap(); gotSeg.Ok() || gotGap != wantGap {
   521  			t.Errorf("%v.PrevNonEmpty(): got (%v, %v), wanted (<terminal iterator>, %v)", seg, gotSeg, gotGap, wantGap)
   522  		}
   523  		gotSeg, gotGap = seg.NextNonEmpty()
   524  		if wantGap := seg.NextGap(); gotSeg.Ok() || gotGap != wantGap {
   525  			t.Errorf("%v.NextNonEmpty(): got (%v, %v), wanted (<terminal iterator>, %v)", seg, gotSeg, gotGap, wantGap)
   526  		}
   527  	}
   528  }
   529  
   530  func TestMergeSplit(t *testing.T) {
   531  	tests := []struct {
   532  		name      string
   533  		initial   []Range
   534  		split     bool
   535  		splitAddr int
   536  		final     []Range
   537  	}{
   538  		{
   539  			name:    "Add merges after existing segment",
   540  			initial: []Range{{1000, 1100}, {1100, 1200}},
   541  			final:   []Range{{1000, 1200}},
   542  		},
   543  		{
   544  			name:    "Add merges before existing segment",
   545  			initial: []Range{{1100, 1200}, {1000, 1100}},
   546  			final:   []Range{{1000, 1200}},
   547  		},
   548  		{
   549  			name:    "Add merges between existing segments",
   550  			initial: []Range{{1000, 1100}, {1200, 1300}, {1100, 1200}},
   551  			final:   []Range{{1000, 1300}},
   552  		},
   553  		{
   554  			name:      "SplitAt does nothing at a free address",
   555  			initial:   []Range{{100, 200}},
   556  			split:     true,
   557  			splitAddr: 300,
   558  			final:     []Range{{100, 200}},
   559  		},
   560  		{
   561  			name:      "SplitAt does nothing at the beginning of a segment",
   562  			initial:   []Range{{100, 200}},
   563  			split:     true,
   564  			splitAddr: 100,
   565  			final:     []Range{{100, 200}},
   566  		},
   567  		{
   568  			name:      "SplitAt does nothing at the end of a segment",
   569  			initial:   []Range{{100, 200}},
   570  			split:     true,
   571  			splitAddr: 200,
   572  			final:     []Range{{100, 200}},
   573  		},
   574  		{
   575  			name:      "SplitAt splits in the middle of a segment",
   576  			initial:   []Range{{100, 200}},
   577  			split:     true,
   578  			splitAddr: 150,
   579  			final:     []Range{{100, 150}, {150, 200}},
   580  		},
   581  	}
   582  Tests:
   583  	for _, test := range tests {
   584  		var s Set
   585  		for _, r := range test.initial {
   586  			if !s.Add(r, 0) {
   587  				t.Errorf("%s: Add(%v) failed; set contents:\n%v", test.name, r, &s)
   588  				continue Tests
   589  			}
   590  		}
   591  		if test.split {
   592  			s.SplitAt(test.splitAddr)
   593  		}
   594  		var i int
   595  		for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
   596  			if i > len(test.final) {
   597  				t.Errorf("%s: Incorrect number of segments: got %d, wanted %d; set contents:\n%v", test.name, s.countSegments(), len(test.final), &s)
   598  				continue Tests
   599  			}
   600  			if got, want := seg.Range(), test.final[i]; got != want {
   601  				t.Errorf("%s: Segment %d mismatch: got %v, wanted %v; set contents:\n%v", test.name, i, got, want, &s)
   602  				continue Tests
   603  			}
   604  			i++
   605  		}
   606  		if i < len(test.final) {
   607  			t.Errorf("%s: Incorrect number of segments: got %d, wanted %d; set contents:\n%v", test.name, i, len(test.final), &s)
   608  		}
   609  	}
   610  }
   611  
   612  func TestIsolate(t *testing.T) {
   613  	tests := []struct {
   614  		name    string
   615  		initial Range
   616  		bounds  Range
   617  		final   []Range
   618  	}{
   619  		{
   620  			name:    "Isolate does not split a segment that falls inside bounds",
   621  			initial: Range{100, 200},
   622  			bounds:  Range{100, 200},
   623  			final:   []Range{{100, 200}},
   624  		},
   625  		{
   626  			name:    "Isolate splits at beginning of segment",
   627  			initial: Range{50, 200},
   628  			bounds:  Range{100, 200},
   629  			final:   []Range{{50, 100}, {100, 200}},
   630  		},
   631  		{
   632  			name:    "Isolate splits at end of segment",
   633  			initial: Range{100, 250},
   634  			bounds:  Range{100, 200},
   635  			final:   []Range{{100, 200}, {200, 250}},
   636  		},
   637  		{
   638  			name:    "Isolate splits at beginning and end of segment",
   639  			initial: Range{50, 250},
   640  			bounds:  Range{100, 200},
   641  			final:   []Range{{50, 100}, {100, 200}, {200, 250}},
   642  		},
   643  	}
   644  Tests:
   645  	for _, test := range tests {
   646  		var s Set
   647  		seg := s.Insert(s.FirstGap(), test.initial, 0)
   648  		seg = s.Isolate(seg, test.bounds)
   649  		if !test.bounds.IsSupersetOf(seg.Range()) {
   650  			t.Errorf("%s: Isolated segment %v lies outside bounds %v; set contents:\n%v", test.name, seg.Range(), test.bounds, &s)
   651  		}
   652  		var i int
   653  		for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
   654  			if i > len(test.final) {
   655  				t.Errorf("%s: Incorrect number of segments: got %d, wanted %d; set contents:\n%v", test.name, s.countSegments(), len(test.final), &s)
   656  				continue Tests
   657  			}
   658  			if got, want := seg.Range(), test.final[i]; got != want {
   659  				t.Errorf("%s: Segment %d mismatch: got %v, wanted %v; set contents:\n%v", test.name, i, got, want, &s)
   660  				continue Tests
   661  			}
   662  			i++
   663  		}
   664  		if i < len(test.final) {
   665  			t.Errorf("%s: Incorrect number of segments: got %d, wanted %d; set contents:\n%v", test.name, i, len(test.final), &s)
   666  		}
   667  	}
   668  }
   669  
   670  func benchmarkAddSequential(b *testing.B, size int) {
   671  	for n := 0; n < b.N; n++ {
   672  		var s Set
   673  		for i := 0; i < size; i++ {
   674  			if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   675  				b.Fatalf("Failed to insert segment %d", i)
   676  			}
   677  		}
   678  	}
   679  }
   680  
   681  func benchmarkAddRandom(b *testing.B, size int) {
   682  	order := rand.Perm(size)
   683  
   684  	b.ResetTimer()
   685  	for n := 0; n < b.N; n++ {
   686  		var s Set
   687  		for _, i := range order {
   688  			if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   689  				b.Fatalf("Failed to insert segment %d", i)
   690  			}
   691  		}
   692  	}
   693  }
   694  
   695  func benchmarkFindSequential(b *testing.B, size int) {
   696  	var s Set
   697  	for i := 0; i < size; i++ {
   698  		if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   699  			b.Fatalf("Failed to insert segment %d", i)
   700  		}
   701  	}
   702  
   703  	b.ResetTimer()
   704  	for n := 0; n < b.N; n++ {
   705  		for i := 0; i < size; i++ {
   706  			if seg := s.FindSegment(i); !seg.Ok() {
   707  				b.Fatalf("Failed to find segment %d", i)
   708  			}
   709  		}
   710  	}
   711  }
   712  
   713  func benchmarkFindRandom(b *testing.B, size int) {
   714  	var s Set
   715  	for i := 0; i < size; i++ {
   716  		if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   717  			b.Fatalf("Failed to insert segment %d", i)
   718  		}
   719  	}
   720  	order := rand.Perm(size)
   721  
   722  	b.ResetTimer()
   723  	for n := 0; n < b.N; n++ {
   724  		for _, i := range order {
   725  			if si := s.FindSegment(i); !si.Ok() {
   726  				b.Fatalf("Failed to find segment %d", i)
   727  			}
   728  		}
   729  	}
   730  }
   731  
   732  func benchmarkIteration(b *testing.B, size int) {
   733  	var s Set
   734  	for i := 0; i < size; i++ {
   735  		if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   736  			b.Fatalf("Failed to insert segment %d", i)
   737  		}
   738  	}
   739  
   740  	b.ResetTimer()
   741  	var count uint64
   742  	for n := 0; n < b.N; n++ {
   743  		for seg := s.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
   744  			count++
   745  		}
   746  	}
   747  	if got, want := count, uint64(size)*uint64(b.N); got != want {
   748  		b.Fatalf("Iterated wrong number of segments: got %d, wanted %d", got, want)
   749  	}
   750  }
   751  
   752  func benchmarkAddFindRemoveSequential(b *testing.B, size int) {
   753  	for n := 0; n < b.N; n++ {
   754  		var s Set
   755  		for i := 0; i < size; i++ {
   756  			if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   757  				b.Fatalf("Failed to insert segment %d", i)
   758  			}
   759  		}
   760  		for i := 0; i < size; i++ {
   761  			seg := s.FindSegment(i)
   762  			if !seg.Ok() {
   763  				b.Fatalf("Failed to find segment %d", i)
   764  			}
   765  			s.Remove(seg)
   766  		}
   767  		if !s.IsEmpty() {
   768  			b.Fatalf("Set not empty after all removals:\n%v", &s)
   769  		}
   770  	}
   771  }
   772  
   773  func benchmarkAddFindRemoveRandom(b *testing.B, size int) {
   774  	order := rand.Perm(size)
   775  
   776  	b.ResetTimer()
   777  	for n := 0; n < b.N; n++ {
   778  		var s Set
   779  		for _, i := range order {
   780  			if !s.AddWithoutMerging(Range{i, i + 1}, i) {
   781  				b.Fatalf("Failed to insert segment %d", i)
   782  			}
   783  		}
   784  		for _, i := range order {
   785  			seg := s.FindSegment(i)
   786  			if !seg.Ok() {
   787  				b.Fatalf("Failed to find segment %d", i)
   788  			}
   789  			s.Remove(seg)
   790  		}
   791  		if !s.IsEmpty() {
   792  			b.Fatalf("Set not empty after all removals:\n%v", &s)
   793  		}
   794  	}
   795  }
   796  
   797  // Although we don't generally expect our segment sets to get this big, they're
   798  // useful for emulating the effect of cache pressure.
   799  var testSizes = []struct {
   800  	desc string
   801  	size int
   802  }{
   803  	{"64", 1 << 6},
   804  	{"256", 1 << 8},
   805  	{"1K", 1 << 10},
   806  	{"4K", 1 << 12},
   807  	{"16K", 1 << 14},
   808  	{"64K", 1 << 16},
   809  }
   810  
   811  func BenchmarkAddSequential(b *testing.B) {
   812  	for _, test := range testSizes {
   813  		b.Run(test.desc, func(b *testing.B) {
   814  			benchmarkAddSequential(b, test.size)
   815  		})
   816  	}
   817  }
   818  
   819  func BenchmarkAddRandom(b *testing.B) {
   820  	for _, test := range testSizes {
   821  		b.Run(test.desc, func(b *testing.B) {
   822  			benchmarkAddRandom(b, test.size)
   823  		})
   824  	}
   825  }
   826  
   827  func BenchmarkFindSequential(b *testing.B) {
   828  	for _, test := range testSizes {
   829  		b.Run(test.desc, func(b *testing.B) {
   830  			benchmarkFindSequential(b, test.size)
   831  		})
   832  	}
   833  }
   834  
   835  func BenchmarkFindRandom(b *testing.B) {
   836  	for _, test := range testSizes {
   837  		b.Run(test.desc, func(b *testing.B) {
   838  			benchmarkFindRandom(b, test.size)
   839  		})
   840  	}
   841  }
   842  
   843  func BenchmarkIteration(b *testing.B) {
   844  	for _, test := range testSizes {
   845  		b.Run(test.desc, func(b *testing.B) {
   846  			benchmarkIteration(b, test.size)
   847  		})
   848  	}
   849  }
   850  
   851  func BenchmarkAddFindRemoveSequential(b *testing.B) {
   852  	for _, test := range testSizes {
   853  		b.Run(test.desc, func(b *testing.B) {
   854  			benchmarkAddFindRemoveSequential(b, test.size)
   855  		})
   856  	}
   857  }
   858  
   859  func BenchmarkAddFindRemoveRandom(b *testing.B) {
   860  	for _, test := range testSizes {
   861  		b.Run(test.desc, func(b *testing.B) {
   862  			benchmarkAddFindRemoveRandom(b, test.size)
   863  		})
   864  	}
   865  }