github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/puller/frontier/heap_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package frontier 15 16 import ( 17 "math" 18 "math/rand" 19 "time" 20 21 "github.com/pingcap/check" 22 "github.com/pingcap/ticdc/pkg/util/testleak" 23 ) 24 25 type tsHeapSuite struct{} 26 27 var _ = check.Suite(&tsHeapSuite{}) 28 29 func (s *tsHeapSuite) TestInsert(c *check.C) { 30 defer testleak.AfterTest(c)() 31 var heap fibonacciHeap 32 target := uint64(15000) 33 34 for i := 0; i < 5000; i++ { 35 heap.Insert(uint64(10001) + target + 1) 36 } 37 heap.Insert(target) 38 39 c.Assert(heap.GetMinKey(), check.Equals, target) 40 } 41 42 func (s *tsHeapSuite) TestUpdateTs(c *check.C) { 43 defer testleak.AfterTest(c)() 44 seed := time.Now().Unix() 45 rand.Seed(seed) 46 var heap fibonacciHeap 47 nodes := make([]*fibonacciHeapNode, 2000) 48 expectedMin := uint64(math.MaxUint64) 49 for i := range nodes { 50 key := 10000 + uint64(rand.Intn(len(nodes)/2)) 51 nodes[i] = heap.Insert(key) 52 if expectedMin > key { 53 expectedMin = key 54 } 55 } 56 57 var key uint64 58 for i := range nodes { 59 min := heap.GetMinKey() 60 c.Assert(min, check.Equals, expectedMin, check.Commentf("seed:%d", seed)) 61 if rand.Intn(2) == 0 { 62 key = nodes[i].key + uint64(10000) 63 heap.UpdateKey(nodes[i], key) 64 } else { 65 key = nodes[i].key - uint64(10000) 66 heap.UpdateKey(nodes[i], key) 67 } 68 if expectedMin > key { 69 expectedMin = key 70 } 71 } 72 } 73 74 func (s *tsHeapSuite) TestRemoveNode(c *check.C) { 75 defer testleak.AfterTest(c)() 76 seed := time.Now().Unix() 77 rand.Seed(seed) 78 var heap fibonacciHeap 79 nodes := make([]*fibonacciHeapNode, 2000) 80 expectedMin := uint64(math.MaxUint64) 81 for i := range nodes { 82 nodes[i] = heap.Insert(10000 + uint64(rand.Intn(len(nodes)/2))) 83 if nodes[i].key < expectedMin { 84 expectedMin = nodes[i].key 85 } 86 } 87 88 preKey := expectedMin + 1 89 for i := range nodes { 90 min := heap.GetMinKey() 91 if preKey == expectedMin { 92 expectedMin = uint64(math.MaxUint64) 93 for _, n := range nodes { 94 if isRemoved(n) { 95 continue 96 } 97 if expectedMin > n.key { 98 expectedMin = n.key 99 } 100 } 101 } 102 c.Assert(min, check.Equals, expectedMin, check.Commentf("seed:%d", seed)) 103 preKey = nodes[i].key 104 heap.Remove(nodes[i]) 105 } 106 for _, n := range nodes { 107 if !isRemoved(n) { 108 c.Fatal("all of the node shoule be removed") 109 } 110 } 111 } 112 113 func isRemoved(n *fibonacciHeapNode) bool { 114 return n.left == nil && n.right == nil && n.children == nil && n.parent == nil 115 } 116 117 func (x *fibonacciHeap) Entries(fn func(n *fibonacciHeapNode) bool) { 118 heapNodeIterator(x.root, fn) 119 } 120 121 func heapNodeIterator(n *fibonacciHeapNode, fn func(n *fibonacciHeapNode) bool) { 122 firstStep := true 123 124 for next := n; next != nil && (next != n || firstStep); next = next.right { 125 firstStep = false 126 if !fn(next) { 127 return 128 } 129 if next.children != nil { 130 heapNodeIterator(next.children, fn) 131 } 132 } 133 }