github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/pkg/container/queue/iterator_test.go (about) 1 // Copyright 2022 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 queue 15 16 import ( 17 "math/rand" 18 "testing" 19 20 "github.com/edwingeng/deque" 21 "github.com/stretchr/testify/require" 22 ) 23 24 const ( 25 iterTestSize = 10007 26 ) 27 28 func TestChunkQueueIteratorPrevNext(t *testing.T) { 29 t.Parallel() 30 q := NewChunkQueue[int]() 31 for i := 0; i < iterTestSize; i++ { 32 q.Push(i) 33 } 34 35 var it *ChunkQueueIterator[int] 36 i := 0 37 for it = q.First(); it.Valid(); it.Next() { 38 v := it.Value() 39 require.Equal(t, i, it.Index()) 40 require.Equal(t, i, v) 41 i++ 42 } 43 i-- 44 for it = q.End(); it.Prev(); { 45 v := it.Value() 46 require.Equal(t, i, it.Index()) 47 require.Equal(t, i, v) 48 i-- 49 } 50 51 it = &ChunkQueueIterator[int]{0, nil} 52 require.False(t, it.Prev()) 53 require.False(t, it.Next()) 54 } 55 56 func BenchmarkIterate(b *testing.B) { 57 b.Run("Iterate-ChunkQueue-by-iterator", func(b *testing.B) { 58 q := NewChunkQueue[int]() 59 n := b.N 60 for i := 0; i < n; i++ { 61 q.Push(i) 62 } 63 b.ResetTimer() 64 65 i := 0 66 for it := q.First(); it.Valid(); it.Next() { 67 v := it.Value() 68 if v != i { 69 panic("not equal") 70 } 71 i++ 72 } 73 }) 74 75 b.Run("Iterate-ChunkQueue-by-Peek", func(b *testing.B) { 76 q := NewChunkQueue[int]() 77 n := b.N 78 for i := 0; i < n; i++ { 79 q.Push(i) 80 } 81 b.ResetTimer() 82 83 i := 0 84 for i = 0; i < q.Len(); i++ { 85 if q.Peek(i) != i { 86 panic(q.Peek(i)) 87 } 88 } 89 }) 90 91 b.Run("Iterate-ChunkQueue-by-Range", func(b *testing.B) { 92 q := NewChunkQueue[int]() 93 n := b.N 94 for i := 0; i < n; i++ { 95 q.Push(i) 96 } 97 b.ResetTimer() 98 99 q.RangeWithIndex(func(idx int, val int) bool { 100 if val != idx { 101 panic("not equal") 102 } 103 return true 104 }) 105 }) 106 107 b.Run("Iterate-Slice-byLoop", func(b *testing.B) { 108 n := b.N 109 q := make([]int, n) 110 for i := 0; i < n; i++ { 111 q[i] = i 112 } 113 b.ResetTimer() 114 115 for i := 0; i < len(q); i++ { 116 if q[i] != i { 117 panic("error") 118 } 119 } 120 }) 121 122 b.Run("Iterate-3rdPartyDeque-byRange", func(b *testing.B) { 123 q := deque.NewDeque() 124 n := b.N 125 126 for i := 0; i < n; i++ { 127 q.Enqueue(i) 128 } 129 b.ResetTimer() 130 131 q.Range(func(idx int, val deque.Elem) bool { 132 if val.(int) != idx { 133 panic("not equal") 134 } 135 return true 136 }) 137 }) 138 139 b.Run("Iterate-3rdPartyDeque-byPeek", func(b *testing.B) { 140 q := deque.NewDeque() 141 n := b.N 142 143 for i := 0; i < n; i++ { 144 q.Enqueue(i) 145 } 146 b.ResetTimer() 147 148 for i := 0; i < n; i++ { 149 val := q.Peek(i) 150 if val != i { 151 panic("not equal") 152 } 153 } 154 }) 155 } 156 157 func TestChunkQueueGetIterator(t *testing.T) { 158 t.Parallel() 159 160 q := NewChunkQueue[int]() 161 q.PushMany(0, 1) 162 var it *ChunkQueueIterator[int] 163 it = q.GetIterator(-1) 164 require.Nil(t, it) 165 it = q.GetIterator(2) 166 require.Nil(t, it) 167 oldIt := q.GetIterator(1) 168 q.PopMany(2) 169 require.False(t, oldIt.Valid(), oldIt.Prev()) 170 require.True(t, q.Empty()) 171 172 for i := 0; i < iterTestSize; i++ { 173 q.Push(i) 174 } 175 require.True(t, q.End().Index() < 0) 176 require.False(t, q.Begin().Prev()) 177 require.Panics(t, func() { 178 q.End().Set(1) 179 }) 180 181 require.NotPanics(t, func() { 182 for i := 0; i < iterTestSize; i++ { 183 it = q.GetIterator(i) 184 require.Equal(t, i, it.Index(), it.Value(), q.Peek(i)) 185 } 186 }) 187 188 cnt := 0 189 for !q.Empty() { 190 n := rand.Intn(q.Len()) 191 if n == 0 { 192 n = testCaseSize/20 + 1 193 } 194 it := q.Begin() 195 require.True(t, it.Valid()) 196 197 q.PopMany(n) 198 require.Equal(t, -1, it.Index()) 199 require.False(t, it.Valid()) 200 201 require.Nil(t, q.Begin().chunk.prev) 202 cnt += n 203 v := q.Begin().Value() 204 if cnt >= iterTestSize { 205 require.True(t, !it.Valid()) 206 } else { 207 require.Equal(t, cnt, v) 208 } 209 } 210 }