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  }