github.com/biogo/store@v0.0.0-20201120204734-aad293a2328f/llrb/llrb_test.go (about)

     1  // Copyright ©2012 The bíogo Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package llrb
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"math/rand"
    11  	"os"
    12  	"sort"
    13  	"strings"
    14  	"testing"
    15  	"unsafe"
    16  
    17  	"gopkg.in/check.v1"
    18  )
    19  
    20  var (
    21  	printTree = flag.Bool("trees", false, "Print failing tree in Newick format.")
    22  	genDot    = flag.Bool("dot", false, "Generate dot code for failing trees.")
    23  	dotLimit  = flag.Int("dotmax", 100, "Maximum size for tree output for dot format.")
    24  )
    25  
    26  // Integrity checks - translated from http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java
    27  
    28  // Is this tree a BST?
    29  func (t *Tree) isBST() bool {
    30  	if t == nil {
    31  		return true
    32  	}
    33  	return t.Root.isBST(t.Min(), t.Max())
    34  }
    35  
    36  // Are all the values in the BST rooted at x between min and max,
    37  // and does the same property hold for both subtrees?
    38  func (n *Node) isBST(min, max Comparable) bool {
    39  	if n == nil {
    40  		return true
    41  	}
    42  	if n.Elem.Compare(min) < 0 || n.Elem.Compare(max) > 0 {
    43  		return false
    44  	}
    45  	return n.Left.isBST(min, n.Elem) && n.Right.isBST(n.Elem, max)
    46  }
    47  
    48  // Test BU and TD234 invariants.
    49  func (t *Tree) is23_234() bool {
    50  	if t == nil {
    51  		return true
    52  	}
    53  	return t.Root.is23_234()
    54  }
    55  func (n *Node) is23_234() bool {
    56  	if n == nil {
    57  		return true
    58  	}
    59  	if Mode == BU23 {
    60  		// If the node has two children, only one of them may be red.
    61  		// The other must be black...
    62  		if (n.Left != nil) && (n.Right != nil) {
    63  			if n.Left.color() == Red && n.Right.color() == Red {
    64  				return false
    65  			}
    66  		}
    67  		// and the red node should really should be the left one.
    68  		if n.Right.color() == Red {
    69  			return false
    70  		}
    71  	} else if Mode == TD234 {
    72  		// This test is altered from that shown in the java since the trees
    73  		// shown in the paper do not conform to the test as it existed and the
    74  		// current situation does not break the 2-3-4 definition of the LLRB.
    75  		if n.Right.color() == Red && n.Left.color() == Black {
    76  			return false
    77  		}
    78  	} else {
    79  		panic("cannot reach")
    80  	}
    81  	if n.color() == Red && n.Left.color() == Red {
    82  		return false
    83  	}
    84  	return n.Left.is23_234() && n.Right.is23_234()
    85  }
    86  
    87  // Do all paths from root to leaf have same number of black edges?
    88  func (t *Tree) isBalanced() bool {
    89  	if t == nil {
    90  		return true
    91  	}
    92  	var black int // number of black links on path from root to min
    93  	for x := t.Root; x != nil; x = x.Left {
    94  		if x.color() == Black {
    95  			black++
    96  		}
    97  	}
    98  	return t.Root.isBalanced(black)
    99  }
   100  
   101  // Does every path from the root to a leaf have the given number
   102  // of black links?
   103  func (n *Node) isBalanced(black int) bool {
   104  	if n == nil && black == 0 {
   105  		return true
   106  	} else if n == nil && black != 0 {
   107  		return false
   108  	}
   109  	if n.color() == Black {
   110  		black--
   111  	}
   112  	return n.Left.isBalanced(black) && n.Right.isBalanced(black)
   113  }
   114  
   115  // Test helpers
   116  
   117  type compRune rune
   118  
   119  func (cr compRune) Compare(r Comparable) int {
   120  	return int(cr) - int(r.(compRune))
   121  }
   122  
   123  type compInt int
   124  
   125  func (ci compInt) Compare(i Comparable) (c int) {
   126  	switch i := i.(type) {
   127  	case compIntUpper:
   128  		c = int(ci) - int(i)
   129  	case compInt:
   130  		c = int(ci) - int(i)
   131  	}
   132  	return c
   133  }
   134  
   135  type compIntUpper int
   136  
   137  func (ci compIntUpper) Compare(i Comparable) (c int) {
   138  	switch i := i.(type) {
   139  	case compIntUpper:
   140  		c = int(ci) - int(i)
   141  	case compInt:
   142  		c = int(ci) - int(i)
   143  	}
   144  	if c == 0 {
   145  		return 1
   146  	}
   147  	return c
   148  }
   149  
   150  type Reverse struct {
   151  	sort.Interface
   152  }
   153  
   154  func (r Reverse) Less(i, j int) bool { return r.Interface.Less(j, i) }
   155  
   156  type compInts []compInt
   157  
   158  func (c compInts) Len() int           { return len(c) }
   159  func (c compInts) Less(i, j int) bool { return c[i].Compare(c[j]) < 0 }
   160  func (c compInts) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
   161  
   162  // Build a tree from a simplified Newick format returning the root node.
   163  // Single letter node names only, no error checking and all nodes are full or leaf.
   164  func makeTree(desc string) (n *Node) {
   165  	var build func([]rune) (*Node, int)
   166  	build = func(desc []rune) (cn *Node, i int) {
   167  		if len(desc) == 0 || desc[0] == ';' {
   168  			return nil, 0
   169  		}
   170  
   171  		var c int
   172  		cn = &Node{}
   173  		for {
   174  			b := desc[i]
   175  			i++
   176  			if b == '(' {
   177  				cn.Left, c = build(desc[i:])
   178  				i += c
   179  				continue
   180  			}
   181  			if b == ',' {
   182  				cn.Right, c = build(desc[i:])
   183  				i += c
   184  				continue
   185  			}
   186  			if b == ')' {
   187  				if cn.Left == nil && cn.Right == nil {
   188  					return nil, i
   189  				}
   190  				continue
   191  			}
   192  			if b != ';' {
   193  				cn.Elem = compRune(b)
   194  			}
   195  			return cn, i
   196  		}
   197  
   198  		panic("cannot reach")
   199  	}
   200  
   201  	n, _ = build([]rune(desc))
   202  	if n.Left == nil && n.Right == nil {
   203  		n = nil
   204  	}
   205  
   206  	return
   207  }
   208  
   209  // Return a Newick format description of a tree defined by a node
   210  func describeTree(n *Node, char, color bool) string {
   211  	s := []rune(nil)
   212  
   213  	var follow func(*Node)
   214  	follow = func(n *Node) {
   215  		children := n.Left != nil || n.Right != nil
   216  		if children {
   217  			s = append(s, '(')
   218  		}
   219  		if n.Left != nil {
   220  			follow(n.Left)
   221  		}
   222  		if children {
   223  			s = append(s, ',')
   224  		}
   225  		if n.Right != nil {
   226  			follow(n.Right)
   227  		}
   228  		if children {
   229  			s = append(s, ')')
   230  		}
   231  		if n.Elem != nil {
   232  			if char {
   233  				s = append(s, rune(n.Elem.(compRune)))
   234  			} else {
   235  				s = append(s, []rune(fmt.Sprintf("%d", n.Elem))...)
   236  			}
   237  			if color {
   238  				s = append(s, []rune(fmt.Sprintf(" %v", n.color()))...)
   239  			}
   240  		}
   241  	}
   242  	if n == nil {
   243  		s = []rune("()")
   244  	} else {
   245  		follow(n)
   246  	}
   247  	s = append(s, ';')
   248  
   249  	return string(s)
   250  }
   251  
   252  // Tests
   253  func Test(t *testing.T) { check.TestingT(t) }
   254  
   255  type S struct{}
   256  
   257  var _ = check.Suite(&S{})
   258  
   259  func (s *S) SetUpSuite(c *check.C) {
   260  	mode := []string{TD234: "Top-Down 2-3-4", BU23: "Bottom-Up 2-3"}
   261  	fmt.Printf("Testing %s Left-Leaning Red Black Tree package.\n", mode[Mode])
   262  }
   263  
   264  func (s *S) TestMakeAndDescribeTree(c *check.C) {
   265  	c.Check(describeTree((*Node)(nil), true, false), check.Equals, "();")
   266  	for _, desc := range []string{
   267  		"();",
   268  		"((a,c)b,(e,g)f)d;",
   269  	} {
   270  		t := makeTree(desc)
   271  		c.Check(describeTree(t, true, false), check.Equals, desc)
   272  	}
   273  }
   274  
   275  // ((a,c)b,(e,g)f)d -rotL-> (((a,c)b,e)d,g)f
   276  func (s *S) TestRotateLeft(c *check.C) {
   277  	orig := "((a,c)b,(e,g)f)d;"
   278  	rot := "(((a,c)b,e)d,g)f;"
   279  
   280  	tree := makeTree(orig)
   281  
   282  	tree = tree.rotateLeft()
   283  	c.Check(describeTree(tree, true, false), check.Equals, rot)
   284  
   285  	rotTree := makeTree(rot)
   286  	c.Check(tree, check.DeepEquals, rotTree)
   287  }
   288  
   289  // ((a,c)b,(e,g)f)d -rotR-> (a,(c,(e,g)f)d)b
   290  func (s *S) TestRotateRight(c *check.C) {
   291  	orig := "((a,c)b,(e,g)f)d;"
   292  	rot := "(a,(c,(e,g)f)d)b;"
   293  
   294  	tree := makeTree(orig)
   295  
   296  	tree = tree.rotateRight()
   297  	c.Check(describeTree(tree, true, false), check.Equals, rot)
   298  
   299  	rotTree := makeTree(rot)
   300  	c.Check(tree, check.DeepEquals, rotTree)
   301  }
   302  
   303  func (s *S) TestNilOperations(c *check.C) {
   304  	t := &Tree{}
   305  	c.Check(t.Min(), check.Equals, nil)
   306  	c.Check(t.Max(), check.Equals, nil)
   307  	if Mode == TD234 {
   308  		return
   309  	}
   310  	t.DeleteMin()
   311  	c.Check(*t, check.Equals, Tree{})
   312  	t.DeleteMax()
   313  	c.Check(*t, check.Equals, Tree{})
   314  }
   315  
   316  func (s *S) TestInsertion(c *check.C) {
   317  	min, max := compRune(0), compRune(1000)
   318  	t := &Tree{}
   319  	for i := min; i <= max; i++ {
   320  		t.Insert(i)
   321  		c.Check(t.Len(), check.Equals, int(i+1))
   322  		failed := false
   323  		failed = failed || !c.Check(t.isBST(), check.Equals, true)
   324  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   325  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   326  		if failed {
   327  			if *printTree {
   328  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   329  			}
   330  			if *genDot && t.Len() <= *dotLimit {
   331  				err := dotFile(t, fmt.Sprintf("TestInsertion_after_ins_%d", i), "")
   332  				if err != nil {
   333  					c.Errorf("Dot file write failed: %v", err)
   334  				}
   335  			}
   336  			c.Fatal("Cannot continue test: invariant contradiction")
   337  		}
   338  	}
   339  	c.Check(t.Min(), check.Equals, compRune(min))
   340  	c.Check(t.Max(), check.Equals, compRune(max))
   341  }
   342  
   343  func (s *S) TestDeletion(c *check.C) {
   344  	min, max := compRune(0), compRune(10000)
   345  	e := int(max-min) + 1
   346  	t := &Tree{}
   347  	for i := min; i <= max; i++ {
   348  		t.Insert(i)
   349  	}
   350  	for i := min; i <= max; i++ {
   351  		var dotString string
   352  		if t.Get(i) != nil {
   353  			e--
   354  		}
   355  		if *genDot && t.Len() <= *dotLimit {
   356  			dotString = dot(t, fmt.Sprintf("TestDeletion_before_%d", i))
   357  		}
   358  		t.Delete(i)
   359  		c.Check(t.Len(), check.Equals, e)
   360  		if i < max {
   361  			failed := false
   362  			failed = failed || !c.Check(t.isBST(), check.Equals, true)
   363  			failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   364  			failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   365  			if failed {
   366  				if *printTree {
   367  					c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   368  				}
   369  				if *genDot && t.Len() < *dotLimit {
   370  					var err error
   371  					err = dotFile(nil, fmt.Sprintf("TestDeletion_before_del_%d", i), dotString)
   372  					if err != nil {
   373  						c.Errorf("Dot file write failed: %v", err)
   374  					}
   375  					err = dotFile(t, fmt.Sprintf("TestDeletion_after_del_%d", i), "")
   376  					if err != nil {
   377  						c.Errorf("Dot file write failed: %v", err)
   378  					}
   379  				}
   380  				c.Fatal("Cannot continue test: invariant contradiction")
   381  			}
   382  		}
   383  	}
   384  	c.Check(*t, check.Equals, Tree{})
   385  }
   386  
   387  func (s *S) TestGet(c *check.C) {
   388  	min, max := compRune(0), compRune(100000)
   389  	t := &Tree{}
   390  	for i := min; i <= max; i++ {
   391  		if i&1 == 0 {
   392  			t.Insert(i)
   393  		}
   394  	}
   395  	for i := min; i <= max; i++ {
   396  		if i&1 == 0 {
   397  			c.Check(t.Get(i), check.Equals, compRune(i)) // Check inserted elements are present.
   398  		} else {
   399  			c.Check(t.Get(i), check.Equals, Comparable(nil)) // Check inserted elements are absent.
   400  		}
   401  	}
   402  }
   403  
   404  func (s *S) TestFloor(c *check.C) {
   405  	min, max := compRune(0), compRune(100000)
   406  	t := &Tree{}
   407  	for i := min; i <= max; i++ {
   408  		if i&1 == 0 { // Insert even numbers only.
   409  			t.Insert(i)
   410  		}
   411  	}
   412  	for i := min; i <= max; i++ {
   413  		if i&1 == 0 {
   414  			c.Check(t.Floor(i), check.Equals, compRune(i)) // Check even Floors are themselves.
   415  		} else {
   416  			c.Check(t.Floor(i), check.Equals, compRune(i-1)) // Check odd Floors are the previous number.
   417  		}
   418  	}
   419  	c.Check(t.Floor(min-1), check.Equals, Comparable(nil))
   420  }
   421  
   422  func (s *S) TestCeil(c *check.C) {
   423  	min, max := compRune(0), compRune(100000)
   424  	t := &Tree{}
   425  	for i := min; i <= max; i++ {
   426  		if i&1 == 1 { // Insert odd numbers only.
   427  			t.Insert(i)
   428  		}
   429  	}
   430  	for i := min; i < max; i++ {
   431  		if i&1 == 1 {
   432  			c.Check(t.Ceil(i), check.Equals, compRune(i)) // Check odd Ceils are themselves.
   433  		} else {
   434  			c.Check(t.Ceil(i), check.Equals, compRune(i+1)) // Check even Ceils are the next number.
   435  		}
   436  	}
   437  	c.Check(t.Ceil(max+1), check.Equals, Comparable(nil))
   438  }
   439  
   440  func (s *S) TestUpper(c *check.C) {
   441  	min, max := compInt(0), compInt(100000)
   442  	t := &Tree{}
   443  	for i := min; i <= max; i++ {
   444  		if i&1 == 1 { // Insert odd numbers only.
   445  			t.Insert(i)
   446  		}
   447  	}
   448  	for i := min; i < max-1; i++ {
   449  		if i&1 == 1 {
   450  			c.Check(t.Ceil(compIntUpper(i)), check.Equals, compInt(i+2)) // Check odd Uppers are the next odd.
   451  		} else {
   452  			c.Check(t.Ceil(compIntUpper(i)), check.Equals, compInt(i+1)) // Check even Uppers are the next number.
   453  		}
   454  	}
   455  	c.Check(t.Ceil(compIntUpper(max+1)), check.Equals, Comparable(nil))
   456  }
   457  
   458  func (s *S) TestRandomlyInsertedGet(c *check.C) {
   459  	count, max := 100000, 1000
   460  	t := &Tree{}
   461  	verify := map[rune]struct{}{}
   462  	for i := 0; i < count; i++ {
   463  		v := compRune(rand.Intn(max))
   464  		t.Insert(v)
   465  		verify[rune(v)] = struct{}{}
   466  	}
   467  	// Random fetch order - check only those inserted.
   468  	for v := range verify {
   469  		c.Check(t.Get(compRune(v)), check.Equals, compRune(v)) // Check inserted elements are present.
   470  	}
   471  	// Check all possible insertions.
   472  	for i := compRune(0); i <= compRune(max); i++ {
   473  		if _, ok := verify[rune(i)]; ok {
   474  			c.Check(t.Get(i), check.Equals, compRune(i)) // Check inserted elements are present.
   475  		} else {
   476  			c.Check(t.Get(i), check.Equals, Comparable(nil)) // Check inserted elements are absent.
   477  		}
   478  	}
   479  }
   480  
   481  func (s *S) TestRandomInsertion(c *check.C) {
   482  	count, max := 100000, 1000
   483  	t := &Tree{}
   484  	for i := 0; i < count; i++ {
   485  		r := rand.Intn(max)
   486  		t.Insert(compRune(r))
   487  		failed := false
   488  		failed = failed || !c.Check(t.isBST(), check.Equals, true)
   489  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   490  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   491  		if failed {
   492  			if *printTree {
   493  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   494  			}
   495  			if *genDot && t.Len() <= *dotLimit {
   496  				err := dotFile(t, fmt.Sprintf("TestRandomInsertion_after_ins_%d", r), "")
   497  				if err != nil {
   498  					c.Errorf("Dot file write failed: %v", err)
   499  				}
   500  			}
   501  			c.Fatal("Cannot continue test: invariant contradiction")
   502  		}
   503  	}
   504  }
   505  
   506  func (s *S) TestRandomDeletion(c *check.C) {
   507  	var (
   508  		count, max = 100000, 1000
   509  		r          = make([]compRune, count)
   510  		t          = &Tree{}
   511  	)
   512  	for i := range r {
   513  		r[i] = compRune(rand.Intn(max))
   514  		t.Insert(r[i])
   515  	}
   516  	for _, v := range r {
   517  		t.Delete(v)
   518  		if t != nil {
   519  			failed := false
   520  			failed = failed || !c.Check(t.isBST(), check.Equals, true)
   521  			failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   522  			failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   523  			if failed {
   524  				if *printTree {
   525  					c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   526  				}
   527  				if *genDot && t.Len() <= *dotLimit {
   528  					err := dotFile(t, fmt.Sprintf("TestRandomDeletion_after_del_%d", v), "")
   529  					if err != nil {
   530  						c.Errorf("Dot file write failed: %v", err)
   531  					}
   532  				}
   533  				c.Fatal("Cannot continue test: invariant contradiction")
   534  			}
   535  		}
   536  	}
   537  	c.Check(*t, check.Equals, Tree{})
   538  }
   539  
   540  type compStructUpper struct {
   541  	key int
   542  	val byte
   543  }
   544  
   545  func (cs compStructUpper) Compare(s Comparable) (c int) {
   546  	c = cs.key - s.(compStructUpper).key
   547  	if c == 0 {
   548  		c = int(cs.val) - int(s.(compStructUpper).val)
   549  	}
   550  	return c
   551  }
   552  func (cs compStructUpper) String() string { return fmt.Sprintf("[%d:%c]", cs.key, cs.val) }
   553  
   554  func (s *S) TestNonUniqueDeletion(c *check.C) {
   555  	var (
   556  		r = []compStructUpper{{1, 'a'}, {1, 'b'}, {1, 'c'}, {0, 'd'}}
   557  		t = &Tree{}
   558  	)
   559  	for i, v := range r {
   560  		t.Insert(v)
   561  		c.Check(t.Len(), check.Equals, i+1)
   562  	}
   563  	for _, v := range r {
   564  		var dotString string
   565  		if *genDot && t.Len() <= *dotLimit {
   566  			dotString = dot(t, "TestNonUniqueDeletion_before_del")
   567  		}
   568  		t.Delete(v)
   569  		if t != nil {
   570  			failed := false
   571  			failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   572  			failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   573  			if failed {
   574  				if *printTree {
   575  					c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   576  				}
   577  				if *genDot && t.Len() <= *dotLimit {
   578  					var err error
   579  					err = dotFile(nil, "TestNonUniqueDeletion_before_del", dotString)
   580  					if err != nil {
   581  						c.Errorf("Dot file write failed: %v", err)
   582  					}
   583  					err = dotFile(t, "TestNonUniqueDeletion_after_del", "")
   584  					if err != nil {
   585  						c.Errorf("Dot file write failed: %v", err)
   586  					}
   587  				}
   588  				c.Fatal("Cannot continue test: invariant contradiction")
   589  			}
   590  		}
   591  	}
   592  	c.Check(*t, check.Equals, Tree{})
   593  }
   594  
   595  func (s *S) TestDeleteMinMax(c *check.C) {
   596  	var (
   597  		min, max = compRune(0), compRune(10)
   598  		t        = &Tree{}
   599  		dI       int
   600  	)
   601  	for i := min; i <= max; i++ {
   602  		t.Insert(i)
   603  		dI = t.Len()
   604  	}
   605  	c.Check(dI, check.Equals, int(max-min+1))
   606  	for i, m := 0, int(max); i < m/2; i++ {
   607  		var failed bool
   608  		t.DeleteMin()
   609  		dI--
   610  		c.Check(t.Len(), check.Equals, dI)
   611  		min++
   612  		failed = !c.Check(t.Min(), check.Equals, min)
   613  		failed = failed || !c.Check(t.isBST(), check.Equals, true)
   614  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   615  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   616  		if failed {
   617  			if *printTree {
   618  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   619  			}
   620  			if *genDot && t.Len() <= *dotLimit {
   621  				err := dotFile(t, fmt.Sprintf("TestDeleteMinMax_after_delmin_%d", i), "")
   622  				if err != nil {
   623  					c.Errorf("Dot file write failed: %v", err)
   624  				}
   625  			}
   626  			c.Fatal("Cannot continue test: invariant contradiction")
   627  		}
   628  		t.DeleteMax()
   629  		dI--
   630  		c.Check(t.Len(), check.Equals, dI)
   631  		max--
   632  		failed = !c.Check(t.Max(), check.Equals, max)
   633  		failed = failed || !c.Check(t.isBST(), check.Equals, true)
   634  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   635  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   636  		if failed {
   637  			if *printTree {
   638  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   639  			}
   640  			if *genDot && t.Len() <= *dotLimit {
   641  				err := dotFile(t, fmt.Sprintf("TestDeleteMinMax_after_delmax_%d", i), "")
   642  				if err != nil {
   643  					c.Errorf("Dot file write failed: %v", err)
   644  				}
   645  			}
   646  			c.Fatal("Cannot continue test: invariant contradiction")
   647  		}
   648  	}
   649  }
   650  
   651  func (s *S) TestRandomInsertionDeletion(c *check.C) {
   652  	var (
   653  		count, max = 100000, 1000
   654  		t          = &Tree{}
   655  		verify     = map[int]struct{}{}
   656  	)
   657  	for i := 0; i < count; i++ {
   658  		var (
   659  			failed    bool
   660  			rI, rD    int
   661  			dotString string
   662  		)
   663  		if rand.Float64() < 0.5 {
   664  			rI = rand.Intn(max)
   665  			t.Insert(compRune(rI))
   666  			verify[rI] = struct{}{}
   667  			c.Check(t.Len(), check.Equals, len(verify))
   668  		}
   669  		failed = !c.Check(t.isBST(), check.Equals, true)
   670  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   671  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   672  		if *genDot && t.Len() <= *dotLimit {
   673  			dotString = dot(t, fmt.Sprintf("TestRandomInsertionDeletion_after_ins_%d_%d", i, rI))
   674  		}
   675  		if failed {
   676  			if *printTree {
   677  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   678  			}
   679  			if *genDot && t.Len() <= *dotLimit {
   680  				err := dotFile(nil, fmt.Sprintf("TestRandomInsertionDeletion_after_ins_%d_%d", i, rI), dotString)
   681  				if err != nil {
   682  					c.Errorf("Dot file write failed: %v", err)
   683  				}
   684  			}
   685  			c.Fatal("Cannot continue test: invariant contradiction")
   686  		}
   687  		if rand.Float64() < 0.5 {
   688  			rD = rand.Intn(max)
   689  			t.Delete(compRune(rD))
   690  			delete(verify, rD)
   691  			c.Check(t.Len(), check.Equals, len(verify))
   692  		} else {
   693  			continue
   694  		}
   695  		failed = !c.Check(t.isBST(), check.Equals, true)
   696  		failed = failed || !c.Check(t.is23_234(), check.Equals, true)
   697  		failed = failed || !c.Check(t.isBalanced(), check.Equals, true)
   698  		if failed {
   699  			if *printTree {
   700  				c.Logf("Failing tree: %s\n\n", describeTree(t.Root, false, true))
   701  			}
   702  			if *genDot && t.Len() <= *dotLimit {
   703  				var err error
   704  				err = dotFile(nil, fmt.Sprintf("TestRandomInsertionDeletion_after_ins_%d_%d", i, rI), dotString)
   705  				if err != nil {
   706  					c.Errorf("Dot file write failed: %v", err)
   707  				}
   708  				err = dotFile(t, fmt.Sprintf("TestRandomInsertionDeletion_after_del_%d_%d", i, rD), "")
   709  				if err != nil {
   710  					c.Errorf("Dot file write failed: %v", err)
   711  				}
   712  			}
   713  			c.Fatal("Cannot continue test: invariant contradiction")
   714  		}
   715  	}
   716  }
   717  
   718  func (s *S) TestDeleteRight(c *check.C) {
   719  	type target struct {
   720  		min, max, target compRune
   721  	}
   722  	for _, r := range []target{
   723  		{0, 14, -1},
   724  		{0, 14, 14},
   725  		{0, 14, 15},
   726  		{0, 15, -1},
   727  		{0, 15, 15},
   728  		{0, 15, 16},
   729  		{0, 16, -1},
   730  		{0, 16, 15},
   731  		{0, 16, 16},
   732  		{0, 16, 17},
   733  		{0, 17, -1},
   734  		{0, 17, 16},
   735  		{0, 17, 17},
   736  		{0, 17, 18},
   737  	} {
   738  		var format, dotString string
   739  		t := &Tree{}
   740  		for i := r.min; i <= r.max; i++ {
   741  			t.Insert(i)
   742  		}
   743  		before := describeTree(t.Root, false, true)
   744  		format = "Before deletion: %#v %s"
   745  		ok := checkTree(t, c, format, r, before)
   746  		if !ok {
   747  			c.Fatal("Cannot continue test: invariant contradiction")
   748  		}
   749  		if *genDot && t.Len() <= *dotLimit {
   750  			dotString = dot(t, strings.Replace(
   751  				fmt.Sprintf("TestDeleteRight_%s_before_del_%d_%d_%d", modeName[Mode], r.min, r.max, r.target),
   752  				"-", "_", -1))
   753  		}
   754  		t.Delete(r.target)
   755  		if r.min <= r.target && r.target <= r.max {
   756  			c.Check(t.Len(), check.Equals, int(r.max-r.min)) // Key in tree.
   757  		} else {
   758  			c.Check(t.Len(), check.Equals, int(r.max-r.min)+1) // Key not in tree.
   759  		}
   760  		format = "%#v\nBefore deletion: %s\nAfter deletion:  %s"
   761  		ok = checkTree(t, c, format, r, before, describeTree(t.Root, false, true))
   762  		if !ok && *genDot && t.Len() < *dotLimit {
   763  			var err error
   764  			err = dotFile(nil, strings.Replace(
   765  				fmt.Sprintf("TestDeleteRight_%s_before_del_%d_%d_%d", modeName[Mode], r.min, r.max, r.target),
   766  				"-", "_", -1), dotString)
   767  			if err != nil {
   768  				c.Errorf("Dot file write failed: %v", err)
   769  			}
   770  			err = dotFile(t, strings.Replace(
   771  				fmt.Sprintf("TestDeleteRight_%s_after_del_%d_%d_%d", modeName[Mode], r.min, r.max, r.target),
   772  				"-", "_", -1), "")
   773  			if err != nil {
   774  				c.Errorf("Dot file write failed: %v", err)
   775  			}
   776  		}
   777  	}
   778  }
   779  
   780  func checkTree(t *Tree, c *check.C, f string, i ...interface{}) (ok bool) {
   781  	comm := check.Commentf(f, i...)
   782  	ok = true
   783  	ok = ok && c.Check(t.isBST(), check.Equals, true, comm)
   784  	ok = ok && c.Check(t.is23_234(), check.Equals, true, comm)
   785  	ok = ok && c.Check(t.isBalanced(), check.Equals, true, comm)
   786  	return
   787  }
   788  
   789  var (
   790  	modeName = []string{TD234: "TD234", BU23: "BU23"}
   791  	arrows   = map[Color]string{Red: "none", Black: "normal"}
   792  )
   793  
   794  func dot(t *Tree, label string) string {
   795  	if t == nil {
   796  		return ""
   797  	}
   798  	var (
   799  		s      []string
   800  		follow func(*Node)
   801  	)
   802  	follow = func(n *Node) {
   803  		id := uintptr(unsafe.Pointer(n))
   804  		c := fmt.Sprintf("%d[label = \"<Left> |<Elem> %v|<Right>\"];", id, n.Elem)
   805  		if n.Left != nil {
   806  			c += fmt.Sprintf("\n\t\tedge [color=%v,arrowhead=%s]; \"%d\":Left -> \"%d\":Elem;",
   807  				n.Left.color(), arrows[n.Left.color()], id, uintptr(unsafe.Pointer(n.Left)))
   808  			follow(n.Left)
   809  		}
   810  		if n.Right != nil {
   811  			c += fmt.Sprintf("\n\t\tedge [color=%v,arrowhead=%s]; \"%d\":Right -> \"%d\":Elem;",
   812  				n.Right.color(), arrows[n.Right.color()], id, uintptr(unsafe.Pointer(n.Right)))
   813  			follow(n.Right)
   814  		}
   815  		s = append(s, c)
   816  	}
   817  	if t.Root != nil {
   818  		follow(t.Root)
   819  	}
   820  	return fmt.Sprintf("digraph %s {\n\tnode [shape=record,height=0.1];\n\t%s\n}\n",
   821  		label,
   822  		strings.Join(s, "\n\t"),
   823  	)
   824  }
   825  
   826  func dotFile(t *Tree, label, dotString string) (err error) {
   827  	if t == nil && dotString == "" {
   828  		return
   829  	}
   830  	f, err := os.Create(label + ".dot")
   831  	if err != nil {
   832  		return
   833  	}
   834  	defer f.Close()
   835  	if dotString == "" {
   836  		fmt.Fprintf(f, dot(t, label))
   837  	} else {
   838  		fmt.Fprintf(f, dotString)
   839  	}
   840  	return
   841  }
   842  
   843  // Test values for range methods.
   844  var values = compInts{-10, -32, 100, 46, 239, 2349, 101, 0, 1}
   845  
   846  func (s *S) TestDo(c *check.C) {
   847  	values := append(compInts(nil), values...)
   848  	t := &Tree{}
   849  	for _, v := range values {
   850  		t.Insert(v)
   851  	}
   852  	var result compInts
   853  	f := func(c Comparable) (done bool) {
   854  		result = append(result, c.(compInt))
   855  		return
   856  	}
   857  	killed := t.Do(f)
   858  	sort.Sort(values)
   859  	c.Check(result, check.DeepEquals, values)
   860  	c.Check(killed, check.Equals, false)
   861  }
   862  
   863  func (s *S) TestDoShortCircuit(c *check.C) {
   864  	values := append(compInts(nil), values...)
   865  	elem := 3
   866  	t := &Tree{}
   867  	for _, v := range values {
   868  		t.Insert(v)
   869  	}
   870  	sort.Sort(values)
   871  	target := values[elem]
   872  	var result compInts
   873  	f := func(c Comparable) (done bool) {
   874  		result = append(result, c.(compInt))
   875  		if target.Compare(c) == 0 {
   876  			done = true
   877  		}
   878  		return
   879  	}
   880  	killed := t.Do(f)
   881  	c.Check(result, check.DeepEquals, values[:elem+1])
   882  	c.Check(killed, check.Equals, true)
   883  }
   884  
   885  func (s *S) TestDoReverse(c *check.C) {
   886  	values := append(compInts(nil), values...)
   887  	t := &Tree{}
   888  	for _, v := range values {
   889  		t.Insert(v)
   890  	}
   891  	var result compInts
   892  	f := func(c Comparable) (done bool) {
   893  		result = append(result, c.(compInt))
   894  		return
   895  	}
   896  	killed := t.DoReverse(f)
   897  	sort.Sort(Reverse{values})
   898  	c.Check(result, check.DeepEquals, values)
   899  	c.Check(killed, check.Equals, false)
   900  }
   901  
   902  func (s *S) TestDoRange(c *check.C) {
   903  	values := append(compInts(nil), values...)
   904  	lo, hi := compInt(0), compInt(100)
   905  	var limValues compInts
   906  	t := &Tree{}
   907  	for _, v := range values {
   908  		t.Insert(v)
   909  		if v >= lo && v < hi {
   910  			limValues = append(limValues, v)
   911  		}
   912  	}
   913  	var result compInts
   914  	f := func(c Comparable) (done bool) {
   915  		result = append(result, c.(compInt))
   916  		return
   917  	}
   918  	killed := t.DoRange(f, lo, hi)
   919  	sort.Sort(limValues)
   920  	c.Check(result, check.DeepEquals, limValues)
   921  	c.Check(killed, check.Equals, false)
   922  }
   923  
   924  func (s *S) TestDoRangeReverse(c *check.C) {
   925  	values := append(compInts(nil), values...)
   926  	lo, hi := compInt(0), compInt(100)
   927  	var limValues compInts
   928  	t := &Tree{}
   929  	for _, v := range values {
   930  		t.Insert(v)
   931  		if v >= lo && v < hi {
   932  			limValues = append(limValues, v)
   933  		}
   934  	}
   935  	var result compInts
   936  	f := func(c Comparable) (done bool) {
   937  		result = append(result, c.(compInt))
   938  		return
   939  	}
   940  	killed := t.DoRangeReverse(f, hi, lo)
   941  	sort.Sort(Reverse{limValues})
   942  	c.Check(result, check.DeepEquals, limValues)
   943  	c.Check(killed, check.Equals, false)
   944  }
   945  
   946  func (s *S) TestDoMatch(c *check.C) {
   947  	values := append(compInts(nil), values...)
   948  	elem := 3
   949  	t := &Tree{}
   950  	for _, v := range values {
   951  		t.Insert(v)
   952  	}
   953  	sort.Sort(values)
   954  	target := values[elem]
   955  	f := func(r Comparable) (done bool) {
   956  		c.Check(r, check.Equals, target)
   957  		return
   958  	}
   959  	killed := t.DoMatching(f, target)
   960  	c.Check(killed, check.Equals, false)
   961  }
   962  
   963  // Benchmarks
   964  
   965  func BenchmarkInsert(b *testing.B) {
   966  	t := &Tree{}
   967  	for i := 0; i < b.N; i++ {
   968  		t.Insert(compInt(b.N - i))
   969  	}
   970  }
   971  
   972  func BenchmarkInsertNoRep(b *testing.B) {
   973  	t := &Tree{}
   974  	for i := 0; i < b.N; i++ {
   975  		t.Insert(compIntUpper(b.N - i))
   976  	}
   977  }
   978  
   979  func BenchmarkGet(b *testing.B) {
   980  	b.StopTimer()
   981  	t := &Tree{}
   982  	for i := 0; i < b.N; i++ {
   983  		t.Insert(compInt(b.N - i))
   984  	}
   985  	b.StartTimer()
   986  	for i := 0; i < b.N; i++ {
   987  		t.Get(compInt(i))
   988  	}
   989  }
   990  
   991  func BenchmarkMin(b *testing.B) {
   992  	b.StopTimer()
   993  	t := &Tree{}
   994  	for i := 0; i < 1e5; i++ {
   995  		t.Insert(compInt(i))
   996  	}
   997  	b.StartTimer()
   998  	var m Comparable
   999  	for i := 0; i < b.N; i++ {
  1000  		m = t.Min()
  1001  	}
  1002  	_ = m
  1003  }
  1004  
  1005  func BenchmarkMax(b *testing.B) {
  1006  	b.StopTimer()
  1007  	t := &Tree{}
  1008  	for i := 0; i < 1e5; i++ {
  1009  		t.Insert(compInt(i))
  1010  	}
  1011  	b.StartTimer()
  1012  	var m Comparable
  1013  	for i := 0; i < b.N; i++ {
  1014  		m = t.Max()
  1015  	}
  1016  	_ = m
  1017  }
  1018  
  1019  func BenchmarkDelete(b *testing.B) {
  1020  	b.StopTimer()
  1021  	t := &Tree{}
  1022  	for i := 0; i < b.N; i++ {
  1023  		t.Insert(compInt(b.N - i))
  1024  	}
  1025  	b.StartTimer()
  1026  	for i := 0; i < b.N; i++ {
  1027  		t.Delete(compInt(i))
  1028  	}
  1029  }
  1030  
  1031  func BenchmarkDeleteMin(b *testing.B) {
  1032  	b.StopTimer()
  1033  	t := &Tree{}
  1034  	for i := 0; i < b.N; i++ {
  1035  		t.Insert(compInt(b.N - i))
  1036  	}
  1037  	b.StartTimer()
  1038  	for i := 0; i < b.N; i++ {
  1039  		t.DeleteMin()
  1040  	}
  1041  }
  1042  
  1043  // Benchmarks for comparison to the built-in type.
  1044  
  1045  func BenchmarkInsertMap(b *testing.B) {
  1046  	var m = map[int]struct{}{}
  1047  	for i := 0; i < b.N; i++ {
  1048  		m[i] = struct{}{}
  1049  	}
  1050  }
  1051  
  1052  func BenchmarkGetMap(b *testing.B) {
  1053  	b.StopTimer()
  1054  	var m = map[int]struct{}{}
  1055  	for i := 0; i < b.N; i++ {
  1056  		m[i] = struct{}{}
  1057  	}
  1058  	b.StartTimer()
  1059  	var r struct{}
  1060  	for i := 0; i < b.N; i++ {
  1061  		r = m[i]
  1062  	}
  1063  	_ = r
  1064  }
  1065  
  1066  func BenchmarkDeleteMap(b *testing.B) {
  1067  	b.StopTimer()
  1068  	var m = map[int]struct{}{}
  1069  	for i := 0; i < b.N; i++ {
  1070  		m[i] = struct{}{}
  1071  	}
  1072  	b.StartTimer()
  1073  	for i := 0; i < b.N; i++ {
  1074  		delete(m, i)
  1075  	}
  1076  }