github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/interval/range_group_test.go (about)

     1  // Copyright 2016 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package interval
    12  
    13  import (
    14  	"bytes"
    15  	"crypto/rand"
    16  	"reflect"
    17  	"testing"
    18  
    19  	_ "github.com/cockroachdb/cockroach/pkg/util/log" // for flags
    20  	"github.com/cockroachdb/errors"
    21  )
    22  
    23  func forEachRangeGroupImpl(t *testing.T, fn func(t *testing.T, rg RangeGroup)) {
    24  	for _, constr := range []func() RangeGroup{
    25  		NewRangeList,
    26  		NewRangeTree,
    27  	} {
    28  		rg := constr()
    29  		name := reflect.TypeOf(rg).Elem().Name()
    30  		t.Run(name, func(t *testing.T) {
    31  			fn(t, rg)
    32  		})
    33  	}
    34  }
    35  
    36  func TestRangeGroupAddSingleRangeAndClear(t *testing.T) {
    37  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
    38  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added {
    39  			t.Errorf("added new range to range group, wanted true added flag; got false")
    40  		}
    41  
    42  		if l := rg.Len(); l != 1 {
    43  			t.Errorf("added 1 range to range group, wanted len = 1; got len = %d", l)
    44  		}
    45  
    46  		rg.Clear()
    47  		if l := rg.Len(); l != 0 {
    48  			t.Errorf("cleared range group, wanted len = 0; got len = %d", l)
    49  		}
    50  	})
    51  }
    52  
    53  func TestRangeGroupAddTwoRangesBefore(t *testing.T) {
    54  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
    55  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
    56  			t.Errorf("added new range to range group, wanted true added flag; got false")
    57  		}
    58  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added {
    59  			t.Errorf("added new range to range group, wanted true added flag; got false")
    60  		}
    61  
    62  		if l := rg.Len(); l != 2 {
    63  			t.Errorf("added 2 disjoint ranges to range group, wanted len = 2; got len = %d", l)
    64  		}
    65  	})
    66  }
    67  
    68  func TestRangeGroupAddTwoRangesAfter(t *testing.T) {
    69  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
    70  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added {
    71  			t.Errorf("added new range to range group, wanted true added flag; got false")
    72  		}
    73  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
    74  			t.Errorf("added new range to range group, wanted true added flag; got false")
    75  		}
    76  
    77  		if l := rg.Len(); l != 2 {
    78  			t.Errorf("added 2 disjoint ranges to range group, wanted len = 2; got len = %d", l)
    79  		}
    80  	})
    81  }
    82  
    83  func TestRangeGroupAddTwoRangesMergeForward(t *testing.T) {
    84  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
    85  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added {
    86  			t.Errorf("added new range to range group, wanted true added flag; got false")
    87  		}
    88  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
    89  			t.Errorf("added new range to range group, wanted true added flag; got false")
    90  		}
    91  
    92  		if l := rg.Len(); l != 1 {
    93  			t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l)
    94  		}
    95  	})
    96  }
    97  
    98  func TestRangeGroupAddTwoRangesMergeBackwards(t *testing.T) {
    99  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   100  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
   101  			t.Errorf("added new range to range group, wanted true added flag; got false")
   102  		}
   103  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added {
   104  			t.Errorf("added new range to range group, wanted true added flag; got false")
   105  		}
   106  
   107  		if l := rg.Len(); l != 1 {
   108  			t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l)
   109  		}
   110  	})
   111  }
   112  
   113  func TestRangeGroupAddTwoRangesWithin(t *testing.T) {
   114  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   115  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x04}}); !added {
   116  			t.Errorf("added new range to range group, wanted true added flag; got false")
   117  		}
   118  		if added := rg.Add(Range{Start: []byte{0x02}, End: []byte{0x03}}); added {
   119  			t.Errorf("added fully contained range to range group, wanted false added flag; got true")
   120  		}
   121  
   122  		if l := rg.Len(); l != 1 {
   123  			t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l)
   124  		}
   125  	})
   126  }
   127  
   128  func TestRangeGroupAddTwoRangesSurround(t *testing.T) {
   129  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   130  		if added := rg.Add(Range{Start: []byte{0x02}, End: []byte{0x03}}); !added {
   131  			t.Errorf("added new range to range group, wanted true added flag; got false")
   132  		}
   133  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x04}}); !added {
   134  			t.Errorf("added new range to range group, wanted true added flag; got false")
   135  		}
   136  
   137  		if l := rg.Len(); l != 1 {
   138  			t.Errorf("added 2 overlapping ranges to range group, wanted len = 1; got len = %d", l)
   139  		}
   140  	})
   141  }
   142  
   143  func TestRangeGroupAddThreeRangesMergeInOrder(t *testing.T) {
   144  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   145  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added {
   146  			t.Errorf("added new range to range group, wanted true added flag; got false")
   147  		}
   148  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
   149  			t.Errorf("added new range to range group, wanted true added flag; got false")
   150  		}
   151  		if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added {
   152  			t.Errorf("added new range to range group, wanted true added flag; got false")
   153  		}
   154  
   155  		if l := rg.Len(); l != 1 {
   156  			t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l)
   157  		}
   158  	})
   159  }
   160  
   161  func TestRangeGroupAddThreeRangesMergeOutOfOrder(t *testing.T) {
   162  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   163  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added {
   164  			t.Errorf("added new range to range group, wanted true added flag; got false")
   165  		}
   166  		if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added {
   167  			t.Errorf("added new range to range group, wanted true added flag; got false")
   168  		}
   169  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
   170  			t.Errorf("added new range to range group, wanted true added flag; got false")
   171  		}
   172  
   173  		if l := rg.Len(); l != 1 {
   174  			t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l)
   175  		}
   176  	})
   177  }
   178  
   179  func TestRangeGroupAddThreeRangesMergeReverseOrder(t *testing.T) {
   180  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   181  		if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added {
   182  			t.Errorf("added new range to range group, wanted true added flag; got false")
   183  		}
   184  		if added := rg.Add(Range{Start: []byte{0x03}, End: []byte{0x04}}); !added {
   185  			t.Errorf("added new range to range group, wanted true added flag; got false")
   186  		}
   187  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x03}}); !added {
   188  			t.Errorf("added new range to range group, wanted true added flag; got false")
   189  		}
   190  
   191  		if l := rg.Len(); l != 1 {
   192  			t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l)
   193  		}
   194  	})
   195  }
   196  
   197  func TestRangeGroupAddThreeRangesSuperset(t *testing.T) {
   198  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   199  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}}); !added {
   200  			t.Errorf("added new range to range group, wanted true added flag; got false")
   201  		}
   202  		if added := rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}}); !added {
   203  			t.Errorf("added new range to range group, wanted true added flag; got false")
   204  		}
   205  		if added := rg.Add(Range{Start: []byte{0x01}, End: []byte{0x06}}); !added {
   206  			t.Errorf("added new range to range group, wanted true added flag; got false")
   207  		}
   208  
   209  		if l := rg.Len(); l != 1 {
   210  			t.Errorf("added three overlapping ranges to range group, wanted len = 1; got len = %d", l)
   211  		}
   212  	})
   213  }
   214  
   215  func TestRangeGroupSubRanges(t *testing.T) {
   216  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   217  		oneRange := []Range{{Start: []byte{0x01}, End: []byte{0x05}}}
   218  		twoRanges := []Range{
   219  			{Start: []byte{0x01}, End: []byte{0x05}},
   220  			{Start: []byte{0x07}, End: []byte{0x0f}},
   221  		}
   222  
   223  		tests := []struct {
   224  			add []Range
   225  			sub Range
   226  			rem bool
   227  			res []Range
   228  		}{
   229  			{
   230  				add: []Range{},
   231  				sub: Range{Start: []byte{0x10}, End: []byte{0x11}},
   232  				rem: false,
   233  				res: []Range{},
   234  			},
   235  			{
   236  				add: oneRange,
   237  				sub: Range{Start: []byte{0x10}, End: []byte{0x11}},
   238  				rem: false,
   239  				res: []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   240  			},
   241  			{
   242  				add: oneRange,
   243  				sub: Range{Start: []byte{0x01}, End: []byte{0x05}},
   244  				rem: true,
   245  				res: []Range{},
   246  			},
   247  			{
   248  				add: oneRange,
   249  				sub: Range{Start: []byte{0x00}, End: []byte{0x06}},
   250  				rem: true,
   251  				res: []Range{},
   252  			},
   253  			{
   254  				add: oneRange,
   255  				sub: Range{Start: []byte{0x04}, End: []byte{0x06}},
   256  				rem: true,
   257  				res: []Range{{Start: []byte{0x01}, End: []byte{0x04}}},
   258  			},
   259  			{
   260  				add: oneRange,
   261  				sub: Range{Start: []byte{0x05}, End: []byte{0x06}},
   262  				rem: false,
   263  				res: []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   264  			},
   265  			{
   266  				add: oneRange,
   267  				sub: Range{Start: []byte{0x01}, End: []byte{0x03}},
   268  				rem: true,
   269  				res: []Range{{Start: []byte{0x03}, End: []byte{0x05}}},
   270  			},
   271  			{
   272  				add: oneRange,
   273  				sub: Range{Start: []byte{0x02}, End: []byte{0x04}},
   274  				rem: true,
   275  				res: []Range{
   276  					{Start: []byte{0x01}, End: []byte{0x02}},
   277  					{Start: []byte{0x04}, End: []byte{0x05}},
   278  				},
   279  			},
   280  			{
   281  				add: twoRanges,
   282  				sub: Range{Start: []byte{0x10}, End: []byte{0x11}},
   283  				rem: false,
   284  				res: []Range{
   285  					{Start: []byte{0x01}, End: []byte{0x05}},
   286  					{Start: []byte{0x07}, End: []byte{0x0f}},
   287  				},
   288  			},
   289  			{
   290  				add: twoRanges,
   291  				sub: Range{Start: []byte{0x01}, End: []byte{0x04}},
   292  				rem: true,
   293  				res: []Range{
   294  					{Start: []byte{0x04}, End: []byte{0x05}},
   295  					{Start: []byte{0x07}, End: []byte{0x0f}},
   296  				},
   297  			},
   298  			{
   299  				add: twoRanges,
   300  				sub: Range{Start: []byte{0x01}, End: []byte{0x05}},
   301  				rem: true,
   302  				res: []Range{{Start: []byte{0x07}, End: []byte{0x0f}}},
   303  			},
   304  			{
   305  				add: twoRanges,
   306  				sub: Range{Start: []byte{0x03}, End: []byte{0x09}},
   307  				rem: true,
   308  				res: []Range{
   309  					{Start: []byte{0x01}, End: []byte{0x03}},
   310  					{Start: []byte{0x09}, End: []byte{0x0f}},
   311  				},
   312  			},
   313  			{
   314  				add: twoRanges,
   315  				sub: Range{Start: []byte{0x03}, End: []byte{0xff}},
   316  				rem: true,
   317  				res: []Range{
   318  					{Start: []byte{0x01}, End: []byte{0x03}},
   319  				},
   320  			},
   321  			{
   322  				add: twoRanges,
   323  				sub: Range{Start: []byte{0x00}, End: []byte{0x09}},
   324  				rem: true,
   325  				res: []Range{
   326  					{Start: []byte{0x09}, End: []byte{0x0f}},
   327  				},
   328  			},
   329  		}
   330  
   331  		for _, test := range tests {
   332  			rg.Clear()
   333  
   334  			for _, r := range test.add {
   335  				if added := rg.Add(r); !added {
   336  					t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r)
   337  				}
   338  			}
   339  			str := rg.String()
   340  
   341  			if rem := rg.Sub(test.sub); rem != test.rem {
   342  				t.Errorf("subtracted %v from range group %s, wanted %t removed flag; got %t", test.sub, str, test.rem, rem)
   343  			}
   344  
   345  			if l, el := rg.Len(), len(test.res); l != el {
   346  				t.Errorf("subtracted %v from range group %s, wanted %b remaining ranges; got %b", test.sub, str, el, l)
   347  			} else {
   348  				ranges := make([]Range, 0, l)
   349  				if err := rg.ForEach(func(r Range) error {
   350  					ranges = append(ranges, r)
   351  					return nil
   352  				}); err != nil {
   353  					t.Fatal(err)
   354  				}
   355  
   356  				if !reflect.DeepEqual(ranges, test.res) {
   357  					t.Errorf("subtracted %v from range group %s, wanted the remaining ranges %v; got %v", test.sub, str, test.res, ranges)
   358  				}
   359  			}
   360  		}
   361  	})
   362  }
   363  
   364  func TestRangeGroupOverlapsRange(t *testing.T) {
   365  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   366  		for _, r := range []Range{
   367  			{Start: []byte{0x01}, End: []byte{0x05}},
   368  			{Start: []byte{0x07}, End: []byte{0x0f}},
   369  		} {
   370  			if added := rg.Add(r); !added {
   371  				t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r)
   372  			}
   373  		}
   374  
   375  		tests := []struct {
   376  			r    Range
   377  			want bool
   378  		}{
   379  			{
   380  				r:    Range{Start: []byte{0x0a}, End: []byte{0x0b}},
   381  				want: true,
   382  			},
   383  			{
   384  				r:    Range{Start: []byte{0x01}, End: []byte{0x04}},
   385  				want: true,
   386  			},
   387  			{
   388  				r:    Range{Start: []byte{0x04}, End: []byte{0x07}},
   389  				want: true,
   390  			},
   391  			{
   392  				r:    Range{Start: []byte{0x06}, End: []byte{0x07}},
   393  				want: false,
   394  			},
   395  			{
   396  				r:    Range{Start: []byte{0x05}, End: []byte{0x07}},
   397  				want: false,
   398  			},
   399  			{
   400  				r:    Range{Start: []byte{0x05}, End: []byte{0x06}},
   401  				want: false,
   402  			},
   403  			{
   404  				r:    Range{Start: []byte{0x05}, End: []byte{0x08}},
   405  				want: true,
   406  			},
   407  			{
   408  				r:    Range{Start: []byte{0x01}, End: []byte{0x0f}},
   409  				want: true,
   410  			},
   411  			{
   412  				r:    Range{Start: []byte{0x10}, End: []byte{0x11}},
   413  				want: false,
   414  			},
   415  		}
   416  
   417  		for _, test := range tests {
   418  			if enc := rg.Overlaps(test.r); enc != test.want {
   419  				t.Errorf("testing if range group %v overlaps range %v, wanted %t; got %t", rg, test.r, test.want, enc)
   420  			}
   421  		}
   422  	})
   423  }
   424  
   425  func TestRangeGroupEnclosesRange(t *testing.T) {
   426  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   427  		for _, r := range []Range{
   428  			{Start: []byte{0x01}, End: []byte{0x05}},
   429  			{Start: []byte{0x07}, End: []byte{0x0f}},
   430  		} {
   431  			if added := rg.Add(r); !added {
   432  				t.Errorf("added new range %v to empty range group, wanted true added flag; got false", r)
   433  			}
   434  		}
   435  
   436  		tests := []struct {
   437  			r    Range
   438  			want bool
   439  		}{
   440  			{
   441  				r:    Range{Start: []byte{0x10}, End: []byte{0x11}},
   442  				want: false,
   443  			},
   444  			{
   445  				r:    Range{Start: []byte{0x01}, End: []byte{0x04}},
   446  				want: true,
   447  			},
   448  			{
   449  				r:    Range{Start: []byte{0x01}, End: []byte{0x05}},
   450  				want: true,
   451  			},
   452  			{
   453  				r:    Range{Start: []byte{0x01}, End: []byte{0x0f}},
   454  				want: false,
   455  			},
   456  			{
   457  				r:    Range{Start: []byte{0x07}, End: []byte{0x0f}},
   458  				want: true,
   459  			},
   460  		}
   461  
   462  		for _, test := range tests {
   463  			if enc := rg.Encloses(test.r); enc != test.want {
   464  				t.Errorf("testing if range group %v encloses range %v, wanted %t; got %t", rg, test.r, test.want, enc)
   465  			}
   466  		}
   467  	})
   468  }
   469  
   470  func TestRangeGroupForEach(t *testing.T) {
   471  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   472  		errToThrow := errors.New("this error should be thrown")
   473  		dontErr := -1
   474  		tests := []struct {
   475  			rngs     []Range
   476  			errAfter int // after this many iterations, throw error. -1 to ignore.
   477  		}{
   478  			{
   479  				rngs:     []Range{},
   480  				errAfter: dontErr,
   481  			},
   482  			{
   483  				rngs:     []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   484  				errAfter: dontErr,
   485  			},
   486  			{
   487  				rngs: []Range{
   488  					{Start: []byte{0x01}, End: []byte{0x05}},
   489  					{Start: []byte{0x09}, End: []byte{0xff}},
   490  				},
   491  				errAfter: dontErr,
   492  			},
   493  			{
   494  				rngs: []Range{
   495  					{Start: []byte{0x01}, End: []byte{0x05}},
   496  					{Start: []byte{0x09}, End: []byte{0x10}},
   497  					{Start: []byte{0x1a}, End: []byte{0x1c}},
   498  					{Start: []byte{0x44}, End: []byte{0xf0}},
   499  					{Start: []byte{0xf1}, End: []byte{0xff}},
   500  				},
   501  				errAfter: dontErr,
   502  			},
   503  			{
   504  				rngs: []Range{
   505  					{Start: []byte{0x01}, End: []byte{0x05}},
   506  					{Start: []byte{0x09}, End: []byte{0x10}},
   507  					{Start: []byte{0x1a}, End: []byte{0x1c}},
   508  					{Start: []byte{0x44}, End: []byte{0xf0}},
   509  					{Start: []byte{0xf1}, End: []byte{0xff}},
   510  				},
   511  				errAfter: 1,
   512  			},
   513  		}
   514  
   515  		for _, test := range tests {
   516  			rg.Clear()
   517  			for _, r := range test.rngs {
   518  				rg.Add(r)
   519  			}
   520  
   521  			n := 0
   522  			acc := []Range{}
   523  			throwingErr := test.errAfter != -1
   524  			errSaw := rg.ForEach(func(r Range) error {
   525  				if throwingErr && n >= test.errAfter {
   526  					return errToThrow
   527  				}
   528  				n++
   529  				acc = append(acc, r)
   530  				return nil
   531  			})
   532  
   533  			expRngs := test.rngs
   534  			if throwingErr {
   535  				expRngs = test.rngs[:test.errAfter]
   536  				if !errors.Is(errSaw, errToThrow) {
   537  					t.Errorf("expected error %v from RangeGroup.ForEach, found %v", errToThrow, errSaw)
   538  				}
   539  			} else {
   540  				if errSaw != nil {
   541  					t.Errorf("no error expected from RangeGroup.ForEach, found %v", errSaw)
   542  				}
   543  			}
   544  			if !reflect.DeepEqual(acc, expRngs) {
   545  				t.Errorf("expected to accumulate Ranges %v, found %v", expRngs, acc)
   546  			}
   547  		}
   548  	})
   549  }
   550  
   551  func TestRangeGroupIterator(t *testing.T) {
   552  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   553  		tests := []struct {
   554  			rngs []Range
   555  		}{
   556  			{
   557  				rngs: []Range{},
   558  			},
   559  			{
   560  				rngs: []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   561  			},
   562  			{
   563  				rngs: []Range{
   564  					{Start: []byte{0x01}, End: []byte{0x05}},
   565  					{Start: []byte{0x09}, End: []byte{0xff}},
   566  				},
   567  			},
   568  			{
   569  				rngs: []Range{
   570  					{Start: []byte{0x01}, End: []byte{0x05}},
   571  					{Start: []byte{0x09}, End: []byte{0x10}},
   572  					{Start: []byte{0x1a}, End: []byte{0x1c}},
   573  					{Start: []byte{0x44}, End: []byte{0xf0}},
   574  					{Start: []byte{0xf1}, End: []byte{0xff}},
   575  				},
   576  			},
   577  		}
   578  
   579  		for _, test := range tests {
   580  			rg.Clear()
   581  			for _, r := range test.rngs {
   582  				rg.Add(r)
   583  			}
   584  
   585  			acc := []Range{}
   586  			it := rg.Iterator()
   587  			for r, ok := it.Next(); ok; r, ok = it.Next() {
   588  				acc = append(acc, r)
   589  			}
   590  
   591  			if !reflect.DeepEqual(acc, test.rngs) {
   592  				t.Errorf("expected to accumulate Ranges %v, found %v", test.rngs, acc)
   593  			}
   594  		}
   595  	})
   596  }
   597  
   598  func TestRangeGroupStringer(t *testing.T) {
   599  	forEachRangeGroupImpl(t, func(t *testing.T, rg RangeGroup) {
   600  		tests := []struct {
   601  			rngs []Range
   602  			str  string
   603  		}{
   604  			{
   605  				rngs: []Range{},
   606  				str:  "[]",
   607  			},
   608  			{
   609  				rngs: []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   610  				str:  "[{01-05}]",
   611  			},
   612  			{
   613  				rngs: []Range{
   614  					{Start: []byte{0x01}, End: []byte{0x05}},
   615  					{Start: []byte{0x09}, End: []byte{0xff}},
   616  				},
   617  				str: "[{01-05} {09-ff}]",
   618  			},
   619  			{
   620  				rngs: []Range{
   621  					{Start: []byte{0x01}, End: []byte{0x05}},
   622  					{Start: []byte{0x09}, End: []byte{0xf0}},
   623  					{Start: []byte{0xf1}, End: []byte{0xff}},
   624  				},
   625  				str: "[{01-05} {09-f0} {f1-ff}]",
   626  			},
   627  		}
   628  
   629  		for _, test := range tests {
   630  			rg.Clear()
   631  			for _, r := range test.rngs {
   632  				rg.Add(r)
   633  			}
   634  			if str := rg.String(); str != test.str {
   635  				t.Errorf("added new ranges %v to range group, wanted string value %s; got %s", test.rngs, test.str, str)
   636  			}
   637  		}
   638  	})
   639  }
   640  
   641  func TestRangeGroupsOverlap(t *testing.T) {
   642  	forEachRangeGroupImpl(t, func(t *testing.T, rg1 RangeGroup) {
   643  		forEachRangeGroupImpl(t, func(t *testing.T, rg2 RangeGroup) {
   644  			tests := []struct {
   645  				rngs1   []Range
   646  				rngs2   []Range
   647  				overlap bool
   648  			}{
   649  				{
   650  					rngs1:   []Range{},
   651  					rngs2:   []Range{},
   652  					overlap: false,
   653  				},
   654  				{
   655  					rngs1:   []Range{},
   656  					rngs2:   []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   657  					overlap: false,
   658  				},
   659  				{
   660  					rngs1:   []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   661  					rngs2:   []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   662  					overlap: true,
   663  				},
   664  				{
   665  					rngs1:   []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   666  					rngs2:   []Range{{Start: []byte{0x05}, End: []byte{0x08}}},
   667  					overlap: false,
   668  				},
   669  				{
   670  					rngs1:   []Range{{Start: []byte{0x01}, End: []byte{0x05}}},
   671  					rngs2:   []Range{{Start: []byte{0x04}, End: []byte{0x08}}},
   672  					overlap: true,
   673  				},
   674  				{
   675  					rngs1: []Range{
   676  						{Start: []byte{0x01}, End: []byte{0x05}},
   677  						{Start: []byte{0x09}, End: []byte{0xf0}},
   678  					},
   679  					rngs2:   []Range{{Start: []byte{0xf1}, End: []byte{0xff}}},
   680  					overlap: false,
   681  				},
   682  				{
   683  					rngs1: []Range{
   684  						{Start: []byte{0x01}, End: []byte{0x05}},
   685  						{Start: []byte{0x09}, End: []byte{0xf0}},
   686  					},
   687  					rngs2:   []Range{{Start: []byte{0xe0}, End: []byte{0xff}}},
   688  					overlap: true,
   689  				},
   690  				{
   691  					rngs1: []Range{
   692  						{Start: []byte{0x01}, End: []byte{0x05}},
   693  						{Start: []byte{0x09}, End: []byte{0x10}},
   694  						{Start: []byte{0x1a}, End: []byte{0x1c}},
   695  						{Start: []byte{0x44}, End: []byte{0xf0}},
   696  						{Start: []byte{0xf1}, End: []byte{0xff}},
   697  					},
   698  					rngs2:   []Range{{Start: []byte{0x11}, End: []byte{0x19}}},
   699  					overlap: false,
   700  				},
   701  				{
   702  					rngs1: []Range{
   703  						{Start: []byte{0x01}, End: []byte{0x05}},
   704  						{Start: []byte{0x09}, End: []byte{0x10}},
   705  						{Start: []byte{0x1a}, End: []byte{0x1c}},
   706  						{Start: []byte{0x44}, End: []byte{0xf0}},
   707  						{Start: []byte{0xf1}, End: []byte{0xff}},
   708  					},
   709  					rngs2:   []Range{{Start: []byte{0x11}, End: []byte{0xff}}},
   710  					overlap: true,
   711  				},
   712  			}
   713  
   714  			for _, test := range tests {
   715  				for _, swap := range []bool{false, true} {
   716  					rg1.Clear()
   717  					rg2.Clear()
   718  
   719  					rngs1, rngs2 := test.rngs1, test.rngs2
   720  					if swap {
   721  						rngs1, rngs2 = rngs2, rngs1
   722  					}
   723  
   724  					for _, r := range rngs1 {
   725  						rg1.Add(r)
   726  					}
   727  					for _, r := range rngs2 {
   728  						rg2.Add(r)
   729  					}
   730  
   731  					overlap := RangeGroupsOverlap(rg1, rg2)
   732  					if e, a := test.overlap, overlap; a != e {
   733  						t.Errorf("expected RangeGroupsOverlap(%s, %s) = %t, found %t", rg1, rg2, e, a)
   734  					}
   735  				}
   736  			}
   737  		})
   738  	})
   739  }
   740  
   741  func TestRangeListAndRangeGroupIdentical(t *testing.T) {
   742  	const trials = 5
   743  	for tr := 0; tr < trials; tr++ {
   744  		rl := NewRangeList()
   745  		rt := NewRangeTree()
   746  
   747  		const iters = 50
   748  		const nBytes = 2
   749  		for i := 0; i < iters; i++ {
   750  			lStr := rl.String()
   751  			tStr := rt.String()
   752  			if lStr != tStr {
   753  				t.Errorf("expected string value for RangeList and RangeTree to be the same; got %s for RangeList and %s for RangeTree", lStr, tStr)
   754  			}
   755  
   756  			ar := getRandomRange(t, nBytes)
   757  			listAdded := rl.Add(ar)
   758  			treeAdded := rt.Add(ar)
   759  			if listAdded != treeAdded {
   760  				t.Errorf("expected adding %s to RangeList %v and RangeTree %v to produce the same result; got %t from RangeList and %t from RangeTree", ar, rl, rt, listAdded, treeAdded)
   761  			}
   762  
   763  			sr := getRandomRange(t, nBytes)
   764  			listSubtracted := rl.Sub(sr)
   765  			treeSubtracted := rt.Sub(sr)
   766  			if listSubtracted != treeSubtracted {
   767  				t.Errorf("expected subtracting %s from RangeList %v and RangeTree %v to produce the same result; got %t from RangeList and %t from RangeTree", sr, rl, rt, listSubtracted, treeSubtracted)
   768  			}
   769  
   770  			or := getRandomRange(t, nBytes)
   771  			listOverlaps := rl.Overlaps(or)
   772  			treeOverlaps := rt.Overlaps(or)
   773  			if listOverlaps != treeOverlaps {
   774  				t.Errorf("expected RangeList %v and RangeTree %v to return the same overlapping state for %v; got %t from RangeList and %t from RangeTree", rl, rt, or, listOverlaps, treeOverlaps)
   775  			}
   776  
   777  			er := getRandomRange(t, nBytes)
   778  			listEncloses := rl.Encloses(er)
   779  			treeEncloses := rt.Encloses(er)
   780  			if listEncloses != treeEncloses {
   781  				t.Errorf("expected RangeList %v and RangeTree %v to return the same enclosing state for %v; got %t from RangeList and %t from RangeTree", rl, rt, er, listEncloses, treeEncloses)
   782  			}
   783  
   784  			listLen := rl.Len()
   785  			treeLen := rt.Len()
   786  			if listLen != treeLen {
   787  				t.Fatalf("expected RangeList and RangeTree to have the same length; got %d from RangeList and %d from RangeTree", listLen, treeLen)
   788  			}
   789  
   790  			listRngs := make([]Range, 0, rl.Len())
   791  			treeRngs := make([]Range, 0, rt.Len())
   792  			if err := rl.ForEach(func(r Range) error {
   793  				listRngs = append(listRngs, r)
   794  				return nil
   795  			}); err != nil {
   796  				t.Fatal(err)
   797  			}
   798  			if err := rt.ForEach(func(r Range) error {
   799  				treeRngs = append(treeRngs, r)
   800  				return nil
   801  			}); err != nil {
   802  				t.Fatal(err)
   803  			}
   804  
   805  			if !reflect.DeepEqual(listRngs, treeRngs) {
   806  				t.Fatalf("expected RangeList and RangeTree to contain the same ranges:\nstarted with %s\nadded %v\nsubtracted %v\n\ngot:\nRangeList: %v\nRangeTree: %v", lStr, ar, sr, rl, rt)
   807  			}
   808  		}
   809  	}
   810  }
   811  
   812  func getRandomRange(t *testing.T, n int) Range {
   813  	s1 := getRandomByteSlice(t, n)
   814  	s2 := getRandomByteSlice(t, n)
   815  	cmp := bytes.Compare(s1, s2)
   816  	for cmp == 0 {
   817  		s2 = getRandomByteSlice(t, n)
   818  		cmp = bytes.Compare(s1, s2)
   819  	}
   820  	if cmp < 0 {
   821  		return Range{Start: s1, End: s2}
   822  	}
   823  	return Range{Start: s2, End: s1}
   824  }
   825  
   826  func getRandomByteSlice(t *testing.T, n int) []byte {
   827  	s := make([]byte, n)
   828  	_, err := rand.Read(s)
   829  	if err != nil {
   830  		t.Fatalf("could not create random byte slice: %v", err)
   831  	}
   832  	return s
   833  }
   834  
   835  func BenchmarkRangeList(b *testing.B) {
   836  	benchmarkRangeGroup(b, NewRangeList())
   837  }
   838  
   839  func BenchmarkRangeTree(b *testing.B) {
   840  	benchmarkRangeGroup(b, NewRangeTree())
   841  }
   842  
   843  func benchmarkRangeGroup(b *testing.B, rg RangeGroup) {
   844  	for i := 0; i < b.N; i++ {
   845  		rg.Add(Range{Start: []byte{0x01}, End: []byte{0x02}})
   846  		rg.Add(Range{Start: []byte{0x04}, End: []byte{0x06}})
   847  		rg.Add(Range{Start: []byte{0x00}, End: []byte{0x02}})
   848  		rg.Add(Range{Start: []byte{0x01}, End: []byte{0x06}})
   849  		rg.Add(Range{Start: []byte{0x05}, End: []byte{0x15}})
   850  		rg.Add(Range{Start: []byte{0x25}, End: []byte{0x30}})
   851  		rg.Clear()
   852  	}
   853  }