github.com/songzhibin97/gkit@v1.2.13/structure/lscq/lscq_test.go (about) 1 // Copyright 2021 ByteDance 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 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package lscq 16 17 import ( 18 "github.com/songzhibin97/gkit/structure/skipset" 19 "github.com/songzhibin97/gkit/sys/fastrand" 20 "sync" 21 "testing" 22 ) 23 24 func TestBoundedQueue(t *testing.T) { 25 q := newUint64SCQ() 26 s := skipset.NewUint64() 27 28 // Dequeue empty queue. 29 val, ok := q.Dequeue() 30 if ok { 31 t.Fatal(val) 32 } 33 34 // Single goroutine correctness. 35 for i := 0; i < scqsize; i++ { 36 if !q.Enqueue(uint64(i)) { 37 t.Fatal(i) 38 } 39 s.Add(uint64(i)) 40 } 41 42 if q.Enqueue(20) { // queue is full 43 t.Fatal() 44 } 45 46 s.Range(func(value uint64) bool { 47 if val, ok := q.Dequeue(); !ok || val != value { 48 t.Fatal(val, ok, value) 49 } 50 return true 51 }) 52 53 // Dequeue empty queue after previous loop. 54 val, ok = q.Dequeue() 55 if ok { 56 t.Fatal(val) 57 } 58 59 // ---------- MULTIPLE TEST BEGIN ----------. 60 for j := 0; j < 10; j++ { 61 s = skipset.NewUint64() 62 63 // Dequeue empty queue. 64 val, ok = q.Dequeue() 65 if ok { 66 t.Fatal(val) 67 } 68 69 // Single goroutine correctness. 70 for i := 0; i < scqsize; i++ { 71 if !q.Enqueue(uint64(i)) { 72 t.Fatal() 73 } 74 s.Add(uint64(i)) 75 } 76 77 if q.Enqueue(20) { // queue is full 78 t.Fatal() 79 } 80 81 s.Range(func(value uint64) bool { 82 if val, ok := q.Dequeue(); !ok || val != value { 83 t.Fatal(val, ok, value) 84 } 85 return true 86 }) 87 88 // Dequeue empty queue after previous loop. 89 val, ok = q.Dequeue() 90 if ok { 91 t.Fatal(val) 92 } 93 } 94 // ---------- MULTIPLE TEST END ----------. 95 96 // MPMC correctness. 97 var wg sync.WaitGroup 98 s1 := skipset.NewUint64() 99 s2 := skipset.NewUint64() 100 for i := 0; i < 100000; i++ { 101 wg.Add(1) 102 go func() { 103 if fastrand.Uint32n(2) == 0 { 104 r := fastrand.Uint64() 105 if q.Enqueue(r) { 106 s1.Add(r) 107 } 108 } else { 109 val, ok := q.Dequeue() 110 if ok { 111 s2.Add(uint64(val)) 112 } 113 } 114 wg.Done() 115 }() 116 } 117 wg.Wait() 118 119 for { 120 val, ok := q.Dequeue() 121 if !ok { 122 break 123 } 124 s2.Add(uint64(val)) 125 } 126 127 s1.Range(func(value uint64) bool { 128 if !s2.Contains(value) { 129 t.Fatal(value) 130 } 131 return true 132 }) 133 134 if s1.Len() != s2.Len() { 135 t.Fatal("invalid") 136 } 137 } 138 139 func TestUnboundedQueue(t *testing.T) { 140 // MPMC correctness. 141 q := NewUint64() 142 var wg sync.WaitGroup 143 s1 := skipset.NewUint64() 144 s2 := skipset.NewUint64() 145 for i := 0; i < 100000; i++ { 146 wg.Add(1) 147 go func() { 148 if fastrand.Uint32n(2) == 0 { 149 r := fastrand.Uint64() 150 if !s1.Add(r) || !q.Enqueue(r) { 151 panic("invalid") 152 } 153 } else { 154 val, ok := q.Dequeue() 155 if ok { 156 s2.Add(uint64(val)) 157 } 158 } 159 wg.Done() 160 }() 161 } 162 wg.Wait() 163 164 for { 165 val, ok := q.Dequeue() 166 if !ok { 167 break 168 } 169 s2.Add(uint64(val)) 170 } 171 172 s1.Range(func(value uint64) bool { 173 if !s2.Contains(value) { 174 t.Fatal(value) 175 } 176 return true 177 }) 178 179 if s1.Len() != s2.Len() { 180 t.Fatal("invalid") 181 } 182 }