github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/cdc/puller/frontier/list_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 "bytes" 18 "math/rand" 19 20 "github.com/pingcap/check" 21 "github.com/pingcap/ticdc/pkg/util/testleak" 22 ) 23 24 type spanListSuite struct{} 25 26 var _ = check.Suite(&spanListSuite{}) 27 28 func (s *spanListSuite) insertIntoList(l *skipList, keys ...[]byte) { 29 for _, k := range keys { 30 l.Insert(k, nil) 31 } 32 } 33 34 func (s *spanListSuite) TestInsertAndRemove(c *check.C) { 35 defer testleak.AfterTest(c)() 36 list := newSpanList() 37 var keys [][]byte 38 for i := 0; i < 100000; i++ { 39 key := make([]byte, rand.Intn(128)+1) 40 rand.Read(key) 41 keys = append(keys, key) 42 list.Insert(key, nil) 43 } 44 45 // check all the keys are exist in list 46 for _, k := range keys { 47 a := list.Seek(k).Node().Key() 48 cmp := bytes.Compare(a, k) 49 c.Assert(cmp, check.Equals, 0) 50 } 51 checkList(c, list) 52 53 for i := 0; i < 10000; i++ { 54 indexToRemove := rand.Intn(10000) 55 seekRes := list.Seek(keys[indexToRemove]) 56 if seekRes.Node().Next() == nil { 57 break 58 } 59 removedKey := seekRes.Node().Next().Key() 60 list.Remove(seekRes, seekRes.Node().Next()) 61 62 // check the node is already removed 63 a := list.Seek(removedKey).Node().Key() 64 cmp := bytes.Compare(a, removedKey) 65 c.Assert(cmp, check.LessEqual, 0) 66 } 67 checkList(c, list) 68 } 69 70 func checkList(c *check.C, list *skipList) { 71 // check the order of the keys in list 72 var lastKey []byte 73 var nodeNum int 74 for node := list.First(); node != nil; node = node.Next() { 75 if len(lastKey) != 0 { 76 cmp := bytes.Compare(lastKey, node.Key()) 77 c.Assert(cmp, check.LessEqual, 0) 78 } 79 lastKey = node.Key() 80 nodeNum++ 81 } 82 83 // check all the pointers are valid 84 prevs := make([]*skipListNode, list.height) 85 for i := range prevs { 86 prevs[i] = list.head.nexts[i] 87 } 88 89 for node := list.First(); node != nil; node = node.Next() { 90 for i := 0; i < len(node.nexts); i++ { 91 c.Assert(prevs[i], check.Equals, node) 92 prevs[i] = node.nexts[i] 93 } 94 } 95 } 96 97 func (s *spanListSuite) TestSeek(c *check.C) { 98 defer testleak.AfterTest(c)() 99 key1 := []byte("15") 100 keyA := []byte("a5") 101 keyB := []byte("b5") 102 keyC := []byte("c5") 103 keyD := []byte("d5") 104 keyE := []byte("e5") 105 keyF := []byte("f5") 106 keyG := []byte("g5") 107 keyH := []byte("h5") 108 keyZ := []byte("z5") 109 110 list := newSpanList() 111 112 c.Assert(list.Seek(keyA).Node(), check.IsNil) 113 114 // insert keyA to keyH 115 s.insertIntoList(list, keyC, keyF, keyE, keyH, keyG, keyD, keyA, keyB) 116 117 // Point to the first node, if seek key is smaller than the first key in list. 118 c.Assert(list.Seek(key1).Node().Key(), check.IsNil) 119 120 // Point to the last node with key smaller than seek key. 121 c.Assert(list.Seek(keyH).Node().key, check.BytesEquals, keyH) 122 123 // Point to itself. 124 c.Assert(list.Seek(keyG).Node().key, check.BytesEquals, keyG) 125 126 // Ensure there is no problem to seek a larger key. 127 c.Assert(list.Seek(keyZ).Node().key, check.BytesEquals, keyH) 128 129 c.Assert(list.Seek([]byte("b0")).Node().key, check.BytesEquals, keyA) 130 c.Assert(list.Seek([]byte("c0")).Node().key, check.BytesEquals, keyB) 131 c.Assert(list.Seek([]byte("d0")).Node().key, check.BytesEquals, keyC) 132 c.Assert(list.Seek([]byte("e0")).Node().key, check.BytesEquals, keyD) 133 c.Assert(list.Seek([]byte("f0")).Node().key, check.BytesEquals, keyE) 134 c.Assert(list.Seek([]byte("g0")).Node().key, check.BytesEquals, keyF) 135 c.Assert(list.Seek([]byte("h0")).Node().key, check.BytesEquals, keyG) 136 c.Assert(list.Seek([]byte("i0")).Node().key, check.BytesEquals, keyH) 137 c.Assert(list.String(), check.Equals, "[a5] [b5] [c5] [d5] [e5] [f5] [g5] [h5] ") 138 checkList(c, list) 139 140 // remove c5 141 seekRes := list.Seek([]byte("c0")) 142 list.Remove(seekRes, seekRes.Node().Next()) 143 c.Assert(list.Seek([]byte("c0")).Node().key, check.BytesEquals, keyB) 144 c.Assert(list.Seek([]byte("d0")).Node().key, check.BytesEquals, keyB) 145 c.Assert(list.Seek([]byte("e0")).Node().key, check.BytesEquals, keyD) 146 c.Assert(list.String(), check.Equals, "[a5] [b5] [d5] [e5] [f5] [g5] [h5] ") 147 checkList(c, list) 148 149 // remove d5 150 list.Remove(seekRes, seekRes.Node().Next()) 151 c.Assert(list.Seek([]byte("d0")).Node().key, check.BytesEquals, keyB) 152 c.Assert(list.Seek([]byte("e0")).Node().key, check.BytesEquals, keyB) 153 c.Assert(list.Seek([]byte("f0")).Node().key, check.BytesEquals, keyE) 154 c.Assert(list.String(), check.Equals, "[a5] [b5] [e5] [f5] [g5] [h5] ") 155 checkList(c, list) 156 157 // remove the first node 158 seekRes = list.Seek([]byte("10")) 159 list.Remove(seekRes, seekRes.Node().Next()) 160 c.Assert(list.String(), check.Equals, "[b5] [e5] [f5] [g5] [h5] ") 161 checkList(c, list) 162 }