github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/containers/slice_queue_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 containers 15 16 import ( 17 "sync" 18 "testing" 19 20 "github.com/stretchr/testify/require" 21 ) 22 23 func TestSliceQueueBasics(t *testing.T) { 24 q := NewSliceQueue[int]() 25 26 require.False(t, checkSignal(q.C)) 27 require.Equal(t, 0, q.Size()) 28 q.Push(1) 29 require.Equal(t, 1, q.Size()) 30 q.Push(2) 31 require.Equal(t, 2, q.Size()) 32 q.Push(3) 33 require.Equal(t, 3, q.Size()) 34 35 val, ok := q.Peek() 36 require.True(t, ok) 37 require.Equal(t, 1, val) 38 39 require.True(t, checkSignal(q.C)) 40 val, ok = q.Pop() 41 require.True(t, ok) 42 require.Equal(t, 1, val) 43 44 val, ok = q.Peek() 45 require.True(t, ok) 46 require.Equal(t, 2, val) 47 48 require.True(t, checkSignal(q.C)) 49 val, ok = q.Pop() 50 require.True(t, ok) 51 require.Equal(t, 2, val) 52 53 val, ok = q.Peek() 54 require.True(t, ok) 55 require.Equal(t, 3, val) 56 57 require.True(t, checkSignal(q.C)) 58 val, ok = q.Pop() 59 require.True(t, ok) 60 require.Equal(t, 3, val) 61 62 require.False(t, checkSignal(q.C)) 63 _, ok = q.Pop() 64 require.False(t, ok) 65 66 _, ok = q.Peek() 67 require.False(t, ok) 68 } 69 70 func TestSliceQueueManyElements(t *testing.T) { 71 const numElems = 10000 72 73 q := NewSliceQueue[int]() 74 for i := 0; i < numElems; i++ { 75 q.Push(i) 76 } 77 require.Equal(t, numElems, q.Size()) 78 79 for i := 0; i < numElems; i++ { 80 val, ok := q.Pop() 81 require.True(t, ok) 82 require.Equal(t, i, val) 83 } 84 require.Equal(t, 0, q.Size()) 85 86 // Repeat the test 87 for i := 0; i < numElems; i++ { 88 q.Push(i) 89 } 90 require.Equal(t, numElems, q.Size()) 91 92 for i := 0; i < numElems; i++ { 93 val, ok := q.Pop() 94 require.True(t, ok) 95 require.Equal(t, i, val) 96 } 97 require.Equal(t, 0, q.Size()) 98 } 99 100 func TestSliceQueueConcurrentWriteAndRead(t *testing.T) { 101 const numElems = 1000000 102 103 q := NewSliceQueue[int]() 104 var wg sync.WaitGroup 105 wg.Add(1) 106 go func() { 107 defer wg.Done() 108 109 for i := 0; i < numElems; i++ { 110 q.Push(i) 111 } 112 }() 113 114 wg.Add(1) 115 go func() { 116 defer wg.Done() 117 118 counter := 0 119 for { 120 <-q.C 121 122 for { 123 val, ok := q.Pop() 124 if !ok { 125 break 126 } 127 require.Equal(t, counter, val) 128 counter++ 129 if counter == numElems { 130 return 131 } 132 } 133 } 134 }() 135 136 wg.Wait() 137 require.Equal(t, 0, q.Size()) 138 } 139 140 func checkSignal(ch <-chan struct{}) bool { 141 select { 142 case <-ch: 143 return true 144 default: 145 return false 146 } 147 }