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