github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/util/interval/btree_based_interval_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  	"encoding/binary"
    16  	"flag"
    17  	"fmt"
    18  	"math/rand"
    19  	"reflect"
    20  	"sort"
    21  	"testing"
    22  
    23  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    24  	"golang.org/x/sync/errgroup"
    25  )
    26  
    27  var btreeMinDegree = flag.Int("btree_min_degree", DefaultBTreeMinimumDegree, "B-Tree minimum degree")
    28  
    29  func init() {
    30  	seed := timeutil.Now().Unix()
    31  	rand.Seed(seed)
    32  }
    33  
    34  // perm returns a random permutation of intervals whose range start is in the
    35  // range [0, n).
    36  func perm(n uint32) (out items) {
    37  	for _, i := range rand.Perm(int(n)) {
    38  		u := uint32(i)
    39  		iv := makeMultiByteInterval(u, u+1, u)
    40  		out = append(out, iv)
    41  	}
    42  	return
    43  }
    44  
    45  // rang returns an ordered list of intervals in the range [m, n].
    46  func rang(m, n uint32) (out items) {
    47  	for u := m; u <= n; u++ {
    48  		iv := makeMultiByteInterval(u, u+1, u)
    49  		out = append(out, iv)
    50  	}
    51  	return
    52  }
    53  
    54  // all extracts all items from a tree in order as a slice.
    55  func all(t *btree) (out items) {
    56  	t.Do(func(a Interface) bool {
    57  		out = append(out, a)
    58  		return false
    59  	})
    60  	return
    61  }
    62  
    63  func makeMultiByteInterval(start, end, id uint32) *Interval {
    64  	return &Interval{Range{toBytes(start), toBytes(end)}, uintptr(id)}
    65  }
    66  
    67  func toBytes(n uint32) Comparable {
    68  	buf := new(bytes.Buffer)
    69  	if err := binary.Write(buf, binary.BigEndian, n); err != nil {
    70  		panic(fmt.Sprintf("binary.Write error: %s", err))
    71  	}
    72  	return Comparable(buf.Bytes())
    73  }
    74  
    75  type Interval struct {
    76  	r  Range
    77  	id uintptr
    78  }
    79  
    80  func (iv *Interval) Range() Range {
    81  	return iv.r
    82  }
    83  
    84  func (iv *Interval) ID() uintptr {
    85  	return iv.id
    86  }
    87  
    88  func (iv *Interval) String() string {
    89  	return fmt.Sprintf("%v-%d", iv.Range(), iv.ID())
    90  }
    91  
    92  func (items items) Len() int {
    93  	return len(items)
    94  }
    95  
    96  func (items items) Less(i, j int) bool {
    97  	return Compare(items[i], items[j]) <= 0
    98  }
    99  
   100  func (items items) Swap(i, j int) {
   101  	items[i], items[j] = items[j], items[i]
   102  }
   103  
   104  func (children children) Len() int {
   105  	return len(children)
   106  }
   107  
   108  func (children children) Less(i, j int) bool {
   109  	return children[i].Range.Start.Compare(children[j].Range.Start) <= 0
   110  }
   111  
   112  func (children children) Swap(i, j int) {
   113  	children[i], children[j] = children[j], children[i]
   114  }
   115  
   116  // describe returns a string description of the tree. The format is similar to
   117  // https://en.wikipedia.org/wiki/Newick_format
   118  func (tree *btree) describe() string {
   119  	if tree.isEmpty() {
   120  		return ";"
   121  	}
   122  	return tree.root.String()
   123  }
   124  
   125  var _ = (*btree).describe
   126  
   127  func (n node) String() string {
   128  	var buf bytes.Buffer
   129  	n.describe(&buf)
   130  	return buf.String()
   131  }
   132  
   133  func (n *node) describe(buf *bytes.Buffer) {
   134  	if len(n.children) == 0 {
   135  		for idx, i := range n.items {
   136  			if idx != 0 {
   137  				buf.WriteString(",")
   138  			}
   139  			buf.WriteString(i.(*Interval).String())
   140  		}
   141  	}
   142  	for i, c := range n.children {
   143  		buf.WriteString("(")
   144  		c.describe(buf)
   145  		buf.WriteString(fmt.Sprintf(":%s", c.Range))
   146  		buf.WriteString(")")
   147  		if i < len(n.children)-1 {
   148  			buf.WriteString(n.items[i].(*Interval).String())
   149  		}
   150  	}
   151  }
   152  
   153  func (n *node) isKeyInRange(t *testing.T, min, max Comparable) bool {
   154  	for _, i := range n.items {
   155  		start := i.Range().Start
   156  		if min != nil && start.Compare(min) < 0 {
   157  			return false
   158  		}
   159  		if max != nil && start.Compare(max) > 0 {
   160  			return false
   161  		}
   162  	}
   163  	oldMin, oldMax := min, max
   164  	for i, c := range n.children {
   165  		min, max := oldMin, oldMax
   166  		if i != 0 {
   167  			min = n.items[i-1].Range().Start
   168  		}
   169  		if i != len(n.children)-1 {
   170  			max = n.items[i].Range().Start
   171  		}
   172  		if !c.isKeyInRange(t, min, max) {
   173  			return false
   174  		}
   175  	}
   176  	return true
   177  }
   178  
   179  func (n *node) isSorted(t *testing.T) bool {
   180  	for _, c := range n.children {
   181  		if !c.isSorted(t) {
   182  			return false
   183  		}
   184  	}
   185  	if !sort.IsSorted(n.items) {
   186  		return false
   187  	}
   188  	if !sort.IsSorted(n.children) {
   189  		return false
   190  	}
   191  	return true
   192  }
   193  
   194  func (tree *btree) computeHeight() (h int) {
   195  	h = -1
   196  	for node := tree.root; ; {
   197  		h++
   198  		if len(node.children) == 0 {
   199  			break
   200  		}
   201  		node = node.children[0]
   202  	}
   203  	return
   204  }
   205  
   206  func (n *node) isDepthEqualToHeight(t *testing.T, depth, height int) bool {
   207  	if len(n.children) == 0 {
   208  		return depth == height
   209  	}
   210  	for _, c := range n.children {
   211  		if !c.isDepthEqualToHeight(t, depth+1, height) {
   212  			return false
   213  		}
   214  	}
   215  	return true
   216  }
   217  
   218  func (n *node) isCountAllowed(t *testing.T, minItems, maxItems int, root bool) bool {
   219  	iLen := len(n.items)
   220  	cLen := len(n.children)
   221  	if !root {
   222  		iAllowed := minItems <= iLen && iLen <= maxItems
   223  		if !iAllowed {
   224  			return false
   225  		}
   226  	}
   227  	if cLen > 0 {
   228  		cAllowed := cLen == iLen+1
   229  		if !cAllowed {
   230  			return false
   231  		}
   232  		for _, c := range n.children {
   233  			allowed := c.isCountAllowed(t, minItems, maxItems, false)
   234  			if !allowed {
   235  				return false
   236  			}
   237  		}
   238  	}
   239  	return true
   240  }
   241  
   242  func (n *node) isIntervalInRange(t *testing.T) bool {
   243  	for _, c := range n.children {
   244  		if !c.isIntervalInRange(t) {
   245  			return false
   246  		}
   247  	}
   248  	r := n.bound()
   249  	if !n.Range.Equal(r) {
   250  		t.Errorf("%v expected range %v, got %v", n, r, n.Range)
   251  		return false
   252  	}
   253  	return true
   254  }
   255  
   256  func (r *Range) combine(other Range) {
   257  	if r.Start.Compare(other.Start) > 0 {
   258  		r.Start = other.Start
   259  	}
   260  	if r.End.Compare(other.End) < 0 {
   261  		r.End = other.End
   262  	}
   263  }
   264  
   265  func (n *node) bound() Range {
   266  	r := n.items[0].Range()
   267  	ptr := &r
   268  	for _, e := range n.items[1:] {
   269  		ptr.combine(e.Range())
   270  	}
   271  	for _, c := range n.children {
   272  		ptr.combine(c.Range)
   273  	}
   274  	return r
   275  }
   276  
   277  func checkWithLen(t *testing.T, tree *btree, l int) {
   278  	if tree.Len() != l {
   279  		t.Errorf("expected tree length %d, got %d", l, tree.Len())
   280  	}
   281  	check(t, tree)
   282  }
   283  
   284  func check(t *testing.T, tree *btree) {
   285  	if !tree.isLeafSameDepth(t) {
   286  		t.Error("Not all the leaves have the same depth as the tree height")
   287  	}
   288  	if !tree.isCountAllowed(t) {
   289  		t.Error("Not all the nodes have allowed key count and child node count")
   290  	}
   291  	if !tree.isIntervalInRange(t) {
   292  		t.Error("Not all the nodes bound all the intervals in its subtree with its Range field")
   293  	}
   294  	if !tree.isSorted(t) {
   295  		t.Error("Not all the nodes have its items and children fields sorted")
   296  	}
   297  	if !tree.isKeyInRange(t) {
   298  		t.Error("not all the nodes keep node keys (range.start) in range")
   299  	}
   300  }
   301  
   302  func (tree *btree) isLeafSameDepth(t *testing.T) bool {
   303  	if tree.isEmpty() {
   304  		return true
   305  	}
   306  	h := tree.computeHeight()
   307  	t.Logf("tree height: %d", h)
   308  	return tree.root.isDepthEqualToHeight(t, 0, h)
   309  }
   310  
   311  func (tree *btree) isCountAllowed(t *testing.T) bool {
   312  	if tree.isEmpty() {
   313  		return true
   314  	}
   315  	return tree.root.isCountAllowed(t, tree.minItems(), tree.maxItems(), true)
   316  }
   317  
   318  // Does every node correctly annotate the range of its children.
   319  func (tree *btree) isIntervalInRange(t *testing.T) bool {
   320  	if tree.isEmpty() {
   321  		return true
   322  	}
   323  	return tree.root.isIntervalInRange(t)
   324  }
   325  
   326  func (tree *btree) isSorted(t *testing.T) bool {
   327  	if tree.isEmpty() {
   328  		return true
   329  	}
   330  	return tree.root.isSorted(t)
   331  }
   332  
   333  func (tree *btree) isKeyInRange(t *testing.T) bool {
   334  	if tree.isEmpty() {
   335  		return true
   336  	}
   337  	return tree.root.isKeyInRange(t, nil, nil)
   338  }
   339  
   340  func checkEqualIntervals(t *testing.T, actual, expected items) {
   341  	for i := 0; i < len(actual)-1; i++ {
   342  		if actual[i].Range().Start.Compare(actual[i+1].Range().Start) > 0 {
   343  			t.Fatalf("interval slice is not sorted: %v", actual)
   344  			break
   345  		}
   346  	}
   347  	itemsLen := len(expected)
   348  	sortedExpected := make(items, itemsLen)
   349  	copy(sortedExpected, expected)
   350  	sort.Sort(sortedExpected)
   351  	if !reflect.DeepEqual(actual, sortedExpected) {
   352  		t.Errorf("expected intervals %v, got %v", expected, actual)
   353  	}
   354  }
   355  
   356  func checkTraversal(t *testing.T, tree *btree, ivs items) {
   357  	// Get, GetWithOverlapper
   358  	r := Range{Comparable{0x0}, Comparable{0x1}}
   359  	expectedIntervals := items{ivs[0], ivs[2], ivs[4]}
   360  	checkEqualIntervals(t, tree.Get(r), expectedIntervals)
   361  	checkEqualIntervals(t, tree.GetWithOverlapper(r, ExclusiveOverlapper), items{ivs[0]})
   362  
   363  	// DoMatching
   364  	var overlapped items
   365  	tree.DoMatching(func(e Interface) bool {
   366  		overlapped = append(overlapped, e)
   367  		return false
   368  	}, r)
   369  	checkEqualIntervals(t, overlapped, expectedIntervals)
   370  
   371  	// Do
   372  	var all items
   373  	tree.Do(func(e Interface) bool {
   374  		all = append(all, e)
   375  		return false
   376  	})
   377  	checkEqualIntervals(t, all, ivs)
   378  }
   379  
   380  func checkIterator(t *testing.T, tree *btree, ivs items) {
   381  	var actual items
   382  	it := tree.Iterator()
   383  	for r, ok := it.Next(); ok; r, ok = it.Next() {
   384  		actual = append(actual, r)
   385  	}
   386  	checkEqualIntervals(t, actual, ivs)
   387  }
   388  
   389  func checkFastDelete(t *testing.T, tree *btree, ivs items, deleteCount int) {
   390  	for i, iv := range ivs[:deleteCount] {
   391  		if err := tree.Delete(iv, true); err != nil {
   392  			t.Fatalf("delete error: %s", err)
   393  		}
   394  		// Unlike fast insert, AdjustRanges must be called after each fast delete.
   395  		// Otherwise, the following fast deletes may go wrong.
   396  		tree.AdjustRanges()
   397  		checkWithLen(t, tree, len(ivs)-i-1)
   398  	}
   399  }
   400  
   401  func makeIntervals() items {
   402  	ivs := items{
   403  		&Interval{Range{Comparable{0}, Comparable{2}}, 0},
   404  		&Interval{Range{Comparable{2}, Comparable{4}}, 0},
   405  		&Interval{Range{Comparable{1}, Comparable{6}}, 0},
   406  		&Interval{Range{Comparable{3}, Comparable{4}}, 0},
   407  		&Interval{Range{Comparable{1}, Comparable{3}}, 0},
   408  		&Interval{Range{Comparable{4}, Comparable{6}}, 0},
   409  		&Interval{Range{Comparable{5}, Comparable{8}}, 0},
   410  		&Interval{Range{Comparable{6}, Comparable{8}}, 0},
   411  		&Interval{Range{Comparable{5}, Comparable{9}}, 0},
   412  		&Interval{Range{Comparable{0x11}, Comparable{0x13}}, 0},
   413  		&Interval{Range{Comparable{0x14}, Comparable{0x16}}, 0},
   414  		&Interval{Range{Comparable{0x15}, Comparable{0x18}}, 0},
   415  		&Interval{Range{Comparable{0x10}, Comparable{0x12}}, 0},
   416  		&Interval{Range{Comparable{0x20}, Comparable{0x62}}, 0},
   417  		&Interval{Range{Comparable{0x24}, Comparable{0xA0}}, 0},
   418  		&Interval{Range{Comparable{0x31}, Comparable{0x63}}, 0},
   419  		&Interval{Range{Comparable{0x44}, Comparable{0x56}}, 0},
   420  		&Interval{Range{Comparable{0x45}, Comparable{0x68}}, 0},
   421  		&Interval{Range{Comparable{0x30}, Comparable{0x72}}, 0},
   422  		&Interval{Range{Comparable{0x30}, Comparable{0x52}}, 0},
   423  		&Interval{Range{Comparable{0x44}, Comparable{0xB0}}, 0},
   424  	}
   425  	for i, iv := range ivs {
   426  		iv.(*Interval).id = uintptr(i)
   427  	}
   428  	return ivs
   429  }
   430  
   431  // TestBTree is based on https://github.com/google/btree/blob/master/btree_test.go.
   432  func TestBTree(t *testing.T) {
   433  	tree := newBTreeWithDegree(InclusiveOverlapper, *btreeMinDegree)
   434  	const treeSize = 10000
   435  	for i := 0; i < 10; i++ {
   436  		for _, iv := range perm(treeSize) {
   437  			if x := tree.Insert(iv, false); x != nil {
   438  				t.Fatalf("insert found interval %v", x)
   439  			}
   440  		}
   441  
   442  		for _, iv := range perm(treeSize) {
   443  			if x := tree.Insert(iv, false); x != nil {
   444  				t.Fatalf("insert didn't find interval %v", x)
   445  			}
   446  		}
   447  
   448  		var all items
   449  		tree.DoMatching(func(e Interface) bool {
   450  			all = append(all, e)
   451  			return false
   452  		}, Range{toBytes(0), toBytes(treeSize)})
   453  		if expected := rang(0, treeSize-1); !reflect.DeepEqual(all, expected) {
   454  			t.Fatalf("expected intervals %v, got %v", expected, all)
   455  		}
   456  
   457  		var slice items
   458  		min := uint32(10)
   459  		max := uint32(20)
   460  		tree.DoMatching(func(e Interface) bool {
   461  			slice = append(slice, e)
   462  			return false
   463  		}, Range{toBytes(min + 1), toBytes(max)})
   464  		if expected := rang(min, max); !reflect.DeepEqual(slice, expected) {
   465  			t.Fatalf("expected intervals %v, got %v", expected, slice)
   466  		}
   467  
   468  		var halfSlice items
   469  		half := uint32(15)
   470  		tree.DoMatching(func(e Interface) bool {
   471  			if e.Range().Start.Compare(toBytes(half)) > 0 {
   472  				return true
   473  			}
   474  			halfSlice = append(halfSlice, e)
   475  			return false
   476  		}, Range{toBytes(min + 1), toBytes(max)})
   477  		if expected := rang(min, half); !reflect.DeepEqual(halfSlice, expected) {
   478  			t.Fatalf("expected intervals %v, got %v", expected, halfSlice)
   479  		}
   480  
   481  		for _, item := range perm(treeSize) {
   482  			if err := tree.Delete(item, false); err != nil {
   483  				t.Fatalf("delete error: %s", err)
   484  			}
   485  		}
   486  
   487  		if len := tree.Len(); len > 0 {
   488  			t.Fatalf("expected 0 item, got %d items", len)
   489  		}
   490  	}
   491  }
   492  
   493  // TestDeleteAfterRootNodeMerge verifies that delete from a leaf node works
   494  // correctly after a merge which involves the root node. During the delete of a
   495  // Interface from a leaf node, if the root node has only one Interface and takes
   496  // part of a merge, the root does have any Interface after the merge. The
   497  // subsequent adjustment of node range should take this into account.
   498  func TestDeleteAfterRootNodeMerge(t *testing.T) {
   499  	tree := newBTreeWithDegree(InclusiveOverlapper, 2)
   500  	ivs := items{
   501  		&Interval{Range{Comparable{1}, Comparable{8}}, 0},
   502  		&Interval{Range{Comparable{2}, Comparable{3}}, 1},
   503  		&Interval{Range{Comparable{3}, Comparable{4}}, 2},
   504  		&Interval{Range{Comparable{4}, Comparable{5}}, 3},
   505  	}
   506  
   507  	//
   508  	//             +------+
   509  	//             | id-1 |
   510  	//             +------+
   511  	//              /    \
   512  	//             v      v
   513  	//       +------+    +-----------+
   514  	//       | id-0 |    | id-2 id-3 |
   515  	//       +------+    +-----------+
   516  	//
   517  	for i := 0; i < len(ivs); i++ {
   518  		if err := tree.Insert(ivs[i], false); err != nil {
   519  			t.Fatalf("insert error: %s", err)
   520  		}
   521  	}
   522  
   523  	//
   524  	//             +------+
   525  	//             | id-1 |
   526  	//             +------+
   527  	//              /    \
   528  	//             v      v
   529  	//       +------+    +------+
   530  	//       | id-0 |    | id-3 |
   531  	//       +------+    +------+
   532  	//
   533  	if err := tree.Delete(ivs[2], false); err != nil {
   534  		t.Fatalf("delete error: %s", err)
   535  	}
   536  
   537  	// Delete id-0
   538  	if err := tree.Delete(ivs[0], false); err != nil {
   539  		t.Fatalf("delete error: %s", err)
   540  	}
   541  }
   542  
   543  func TestSmallTree(t *testing.T) {
   544  	tree := newBTreeWithDegree(InclusiveOverlapper, 2)
   545  	ivs := makeIntervals()
   546  
   547  	// Insert
   548  	for i, iv := range ivs {
   549  		if err := tree.Insert(iv, false); err != nil {
   550  			t.Fatalf("insert error: %s", err)
   551  		}
   552  		checkWithLen(t, tree, i+1)
   553  	}
   554  
   555  	checkTraversal(t, tree, ivs)
   556  	checkIterator(t, tree, ivs)
   557  
   558  	// Delete
   559  	l := tree.Len()
   560  	for i, iv := range ivs {
   561  		if err := tree.Delete(iv, false); err != nil {
   562  			t.Fatalf("delete error: %s", err)
   563  		}
   564  		checkWithLen(t, tree, l-i-1)
   565  	}
   566  }
   567  
   568  func TestSmallTreeWithFastOperations(t *testing.T) {
   569  	tree := newBTreeWithDegree(InclusiveOverlapper, 2)
   570  	ivs := makeIntervals()
   571  
   572  	// Fast insert
   573  	for _, iv := range ivs {
   574  		if err := tree.Insert(iv, true); err != nil {
   575  			t.Fatalf("insert error: %s", err)
   576  		}
   577  	}
   578  	tree.AdjustRanges()
   579  	checkWithLen(t, tree, len(ivs))
   580  
   581  	checkTraversal(t, tree, ivs)
   582  	checkIterator(t, tree, ivs)
   583  	checkFastDelete(t, tree, ivs, tree.Len())
   584  }
   585  
   586  func TestLargeTree(t *testing.T) {
   587  	var ivs items
   588  
   589  	const treeSize = 40000
   590  	for i := uint32(0); i < treeSize; i++ {
   591  		iv := makeMultiByteInterval(i, i+1, i)
   592  		ivs = append(ivs, iv)
   593  	}
   594  
   595  	tree := newBTreeWithDegree(ExclusiveOverlapper, *btreeMinDegree)
   596  	for _, iv := range ivs {
   597  		if err := tree.Insert(iv, true); err != nil {
   598  			t.Fatalf("fast insert error: %s", err)
   599  		}
   600  	}
   601  	tree.AdjustRanges()
   602  	checkWithLen(t, tree, treeSize)
   603  	checkFastDelete(t, tree, ivs, 10)
   604  }
   605  
   606  const cloneTestSize = 10000
   607  
   608  func cloneTest(
   609  	t *testing.T, b *btree, start int, p items, g *errgroup.Group, treeC chan *btree,
   610  ) error {
   611  	t.Logf("Starting new clone at %v", start)
   612  	treeC <- b
   613  	for i := start; i < cloneTestSize; i++ {
   614  		if err := b.Insert(p[i], false); err != nil {
   615  			return err
   616  		}
   617  		if i%(cloneTestSize/5) == 0 {
   618  			i := i
   619  			c := b.cloneInternal()
   620  			g.Go(func() error {
   621  				return cloneTest(t, c, i+1, p, g, treeC)
   622  			})
   623  		}
   624  	}
   625  	return nil
   626  }
   627  
   628  func TestCloneConcurrentOperations(t *testing.T) {
   629  	var trees []*btree
   630  	treeC, treeDone := make(chan *btree), make(chan struct{})
   631  	go func() {
   632  		for b := range treeC {
   633  			trees = append(trees, b)
   634  		}
   635  		close(treeDone)
   636  	}()
   637  
   638  	var g errgroup.Group
   639  	b := newBTree(InclusiveOverlapper)
   640  	p := perm(cloneTestSize)
   641  	g.Go(func() error {
   642  		return cloneTest(t, b, 0, p, &g, treeC)
   643  	})
   644  	if err := g.Wait(); err != nil {
   645  		t.Fatal(err)
   646  	}
   647  	close(treeC)
   648  	<-treeDone
   649  
   650  	want := rang(0, cloneTestSize-1)
   651  	t.Logf("Starting equality checks on %d trees", len(trees))
   652  	for i, tree := range trees {
   653  		if !reflect.DeepEqual(want, all(tree)) {
   654  			t.Errorf("tree %v mismatch", i)
   655  		}
   656  	}
   657  
   658  	t.Log("Removing half from first half")
   659  	toRemove := want[cloneTestSize/2:]
   660  	for i := 0; i < len(trees)/2; i++ {
   661  		tree := trees[i]
   662  		g.Go(func() error {
   663  			for _, item := range toRemove {
   664  				if err := tree.Delete(item, false); err != nil {
   665  					return err
   666  				}
   667  			}
   668  			return nil
   669  		})
   670  	}
   671  	if err := g.Wait(); err != nil {
   672  		t.Fatal(err)
   673  	}
   674  
   675  	t.Log("Checking all values again")
   676  	for i, tree := range trees {
   677  		var wantpart items
   678  		if i < len(trees)/2 {
   679  			wantpart = want[:cloneTestSize/2]
   680  		} else {
   681  			wantpart = want
   682  		}
   683  		if got := all(tree); !reflect.DeepEqual(wantpart, got) {
   684  			t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
   685  		}
   686  	}
   687  }
   688  
   689  func TestIterator(t *testing.T) {
   690  	var ivs items
   691  	const treeSize = 400
   692  	for i := uint32(0); i < treeSize; i++ {
   693  		iv := makeMultiByteInterval(i, i+1, i)
   694  		ivs = append(ivs, iv)
   695  	}
   696  	tree := newBTreeWithDegree(InclusiveOverlapper, 4)
   697  	for _, iv := range ivs {
   698  		if err := tree.Insert(iv, true); err != nil {
   699  			t.Fatalf("fast insert error: %s", err)
   700  		}
   701  	}
   702  	tree.AdjustRanges()
   703  	checkIterator(t, tree, ivs)
   704  }
   705  
   706  func forBenchmarkSizes(b *testing.B, f func(b *testing.B, count int)) {
   707  	for _, count := range []int{16, 128, 1024, 8192, 65536} {
   708  		b.Run(fmt.Sprintf("count=%d", count), func(b *testing.B) {
   709  			f(b, count)
   710  		})
   711  	}
   712  }
   713  
   714  func BenchmarkBTreeInsert(b *testing.B) {
   715  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   716  		insertP := perm(uint32(count))
   717  		b.ResetTimer()
   718  		i := 0
   719  		for i < b.N {
   720  			tr := newBTree(InclusiveOverlapper)
   721  			for _, item := range insertP {
   722  				if err := tr.Insert(item, false); err != nil {
   723  					b.Fatal(err)
   724  				}
   725  				i++
   726  				if i >= b.N {
   727  					return
   728  				}
   729  			}
   730  		}
   731  	})
   732  }
   733  
   734  func BenchmarkBTreeDelete(b *testing.B) {
   735  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   736  		insertP, removeP := perm(uint32(count)), perm(uint32(count))
   737  		b.ResetTimer()
   738  		i := 0
   739  		for i < b.N {
   740  			b.StopTimer()
   741  			tr := newBTree(InclusiveOverlapper)
   742  			for _, item := range insertP {
   743  				if err := tr.Insert(item, false); err != nil {
   744  					b.Fatal(err)
   745  				}
   746  			}
   747  			b.StartTimer()
   748  			for _, item := range removeP {
   749  				if err := tr.Delete(item, false); err != nil {
   750  					b.Fatal(err)
   751  				}
   752  				i++
   753  				if i >= b.N {
   754  					return
   755  				}
   756  			}
   757  			if tr.Len() > 0 {
   758  				panic(tr.Len())
   759  			}
   760  		}
   761  	})
   762  }
   763  
   764  func BenchmarkBTreeDeleteInsert(b *testing.B) {
   765  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   766  		insertP := perm(uint32(count))
   767  		tr := newBTree(InclusiveOverlapper)
   768  		for _, item := range insertP {
   769  			if err := tr.Insert(item, false); err != nil {
   770  				b.Fatal(err)
   771  			}
   772  		}
   773  		b.ResetTimer()
   774  		for i := 0; i < b.N; i++ {
   775  			if err := tr.Delete(insertP[i%count], false); err != nil {
   776  				b.Fatal(err)
   777  			}
   778  			if err := tr.Insert(insertP[i%count], false); err != nil {
   779  				b.Fatal(err)
   780  			}
   781  		}
   782  	})
   783  }
   784  
   785  func BenchmarkBTreeDeleteInsertCloneOnce(b *testing.B) {
   786  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   787  		insertP := perm(uint32(count))
   788  		tr := newBTree(InclusiveOverlapper)
   789  		for _, item := range insertP {
   790  			if err := tr.Insert(item, false); err != nil {
   791  				b.Fatal(err)
   792  			}
   793  		}
   794  		tr = tr.cloneInternal()
   795  		b.ResetTimer()
   796  		for i := 0; i < b.N; i++ {
   797  			if err := tr.Delete(insertP[i%count], false); err != nil {
   798  				b.Fatal(err)
   799  			}
   800  			if err := tr.Insert(insertP[i%count], false); err != nil {
   801  				b.Fatal(err)
   802  			}
   803  		}
   804  	})
   805  }
   806  
   807  func BenchmarkBTreeDeleteInsertCloneEachTime(b *testing.B) {
   808  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   809  		insertP := perm(uint32(count))
   810  		tr := newBTree(InclusiveOverlapper)
   811  		for _, item := range insertP {
   812  			if err := tr.Insert(item, false); err != nil {
   813  				b.Fatal(err)
   814  			}
   815  		}
   816  		b.ResetTimer()
   817  		for i := 0; i < b.N; i++ {
   818  			tr = tr.cloneInternal()
   819  			if err := tr.Delete(insertP[i%count], false); err != nil {
   820  				b.Fatal(err)
   821  			}
   822  			if err := tr.Insert(insertP[i%count], false); err != nil {
   823  				b.Fatal(err)
   824  			}
   825  		}
   826  	})
   827  }
   828  
   829  func BenchmarkBTreeGet(b *testing.B) {
   830  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   831  		insertP := perm(uint32(count))
   832  		removeP := perm(uint32(count))
   833  		b.ResetTimer()
   834  		i := 0
   835  		for i < b.N {
   836  			b.StopTimer()
   837  			tr := newBTree(InclusiveOverlapper)
   838  			for _, item := range insertP {
   839  				if err := tr.Insert(item, false); err != nil {
   840  					b.Fatal(err)
   841  				}
   842  			}
   843  			b.StartTimer()
   844  			for _, item := range removeP {
   845  				tr.Get(item.Range())
   846  				i++
   847  				if i >= b.N {
   848  					return
   849  				}
   850  			}
   851  		}
   852  	})
   853  }
   854  
   855  func BenchmarkBTreeGetCloneEachTime(b *testing.B) {
   856  	forBenchmarkSizes(b, func(b *testing.B, count int) {
   857  		insertP := perm(uint32(count))
   858  		removeP := perm(uint32(count))
   859  		b.ResetTimer()
   860  		i := 0
   861  		for i < b.N {
   862  			b.StopTimer()
   863  			tr := newBTree(InclusiveOverlapper)
   864  			for _, v := range insertP {
   865  				if err := tr.Insert(v, false); err != nil {
   866  					b.Fatal(err)
   867  				}
   868  			}
   869  			b.StartTimer()
   870  			for _, item := range removeP {
   871  				tr = tr.cloneInternal()
   872  				tr.Get(item.Range())
   873  				i++
   874  				if i >= b.N {
   875  					return
   876  				}
   877  			}
   878  		}
   879  	})
   880  }
   881  
   882  func key(i int) Comparable {
   883  	return []byte(fmt.Sprintf("%04d", i))
   884  }
   885  
   886  func rangeWithEnd(start, end int) Range {
   887  	return Range{Start: key(start), End: key(end)}
   888  }
   889  
   890  func randomRange(rng *rand.Rand, n int) Range {
   891  	start := rng.Intn(n)
   892  	end := rng.Intn(n + 1)
   893  	if end < start {
   894  		start, end = end, start
   895  	}
   896  	return rangeWithEnd(start, end)
   897  }
   898  
   899  func BenchmarkBTreeOverlapScan(b *testing.B) {
   900  	tr := newBTree(InclusiveOverlapper)
   901  	rng := rand.New(rand.NewSource(timeutil.Now().UnixNano()))
   902  
   903  	const count = 8 << 10
   904  	const size = 2 * 31
   905  	for i := 0; i < count; i++ {
   906  		iv := &Interval{rangeWithEnd(i, i+size+1), uintptr(i)}
   907  		if err := tr.Insert(iv, false); err != nil {
   908  			b.Fatal(err)
   909  		}
   910  	}
   911  
   912  	b.ResetTimer()
   913  	for i := 0; i < b.N; i++ {
   914  		cmd := randomRange(rng, count)
   915  		tr.DoMatching(func(e Interface) bool {
   916  			return false
   917  		}, cmd)
   918  	}
   919  }