github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/queues/lscq/point_test.go (about) 1 package lscq 2 3 import ( 4 "sync" 5 "testing" 6 7 "github.com/songzhibin97/go-baseutils/base/bcomparator" 8 "github.com/songzhibin97/go-baseutils/structure/sets/skipset" 9 "github.com/songzhibin97/go-baseutils/sys/fastrand" 10 ) 11 12 func TestBoundedQueue(t *testing.T) { 13 q := newUint64SCQ() 14 s := skipset.New[uint64](bcomparator.Uint64Comparator()) 15 16 // Dequeue empty queue. 17 val, ok := q.Dequeue() 18 if ok { 19 t.Fatal(val) 20 } 21 22 // Single goroutine correctness. 23 for i := 0; i < scqsize; i++ { 24 if !q.Enqueue(uint64(i)) { 25 t.Fatal(i) 26 } 27 s.Add(uint64(i)) 28 } 29 30 if q.Enqueue(20) { // queue is full 31 t.Fatal() 32 } 33 34 s.Range(func(value uint64) bool { 35 if val, ok := q.Dequeue(); !ok || val != value { 36 t.Fatal(val, ok, value) 37 } 38 return true 39 }) 40 41 // Dequeue empty queue after previous loop. 42 val, ok = q.Dequeue() 43 if ok { 44 t.Fatal(val) 45 } 46 47 // ---------- MULTIPLE TEST BEGIN ----------. 48 for j := 0; j < 10; j++ { 49 s = skipset.New[uint64](bcomparator.Uint64Comparator()) 50 51 // Dequeue empty queue. 52 val, ok = q.Dequeue() 53 if ok { 54 t.Fatal(val) 55 } 56 57 // Single goroutine correctness. 58 for i := 0; i < scqsize; i++ { 59 if !q.Enqueue(uint64(i)) { 60 t.Fatal() 61 } 62 s.Add(uint64(i)) 63 } 64 65 if q.Enqueue(20) { // queue is full 66 t.Fatal() 67 } 68 69 s.Range(func(value uint64) bool { 70 if val, ok := q.Dequeue(); !ok || val != value { 71 t.Fatal(val, ok, value) 72 } 73 return true 74 }) 75 76 // Dequeue empty queue after previous loop. 77 val, ok = q.Dequeue() 78 if ok { 79 t.Fatal(val) 80 } 81 } 82 // ---------- MULTIPLE TEST END ----------. 83 84 // MPMC correctness. 85 var wg sync.WaitGroup 86 s1 := skipset.New[uint64](bcomparator.Uint64Comparator()) 87 s2 := skipset.New[uint64](bcomparator.Uint64Comparator()) 88 for i := 0; i < 100000; i++ { 89 wg.Add(1) 90 go func() { 91 if fastrand.Uint32n(2) == 0 { 92 r := fastrand.Uint64() 93 if q.Enqueue(r) { 94 s1.Add(r) 95 } 96 } else { 97 val, ok := q.Dequeue() 98 if ok { 99 s2.Add(uint64(val)) 100 } 101 } 102 wg.Done() 103 }() 104 } 105 wg.Wait() 106 107 for { 108 val, ok := q.Dequeue() 109 if !ok { 110 break 111 } 112 s2.Add(uint64(val)) 113 } 114 115 s1.Range(func(value uint64) bool { 116 if !s2.Contains(value) { 117 t.Fatal(value) 118 } 119 return true 120 }) 121 122 if s1.Len() != s2.Len() { 123 t.Fatal("invalid") 124 } 125 } 126 127 func TestUnboundedQueue(t *testing.T) { 128 // MPMC correctness. 129 q := NewUint64() 130 var wg sync.WaitGroup 131 s1 := skipset.New[uint64](bcomparator.Uint64Comparator()) 132 s2 := skipset.New[uint64](bcomparator.Uint64Comparator()) 133 for i := 0; i < 100000; i++ { 134 wg.Add(1) 135 go func() { 136 if fastrand.Uint32n(2) == 0 { 137 r := fastrand.Uint64() 138 if !s1.AddB(r) || !q.Enqueue(r) { 139 panic("invalid") 140 } 141 } else { 142 val, ok := q.Dequeue() 143 if ok { 144 s2.Add(uint64(val)) 145 } 146 } 147 wg.Done() 148 }() 149 } 150 wg.Wait() 151 152 for { 153 val, ok := q.Dequeue() 154 if !ok { 155 break 156 } 157 s2.Add(uint64(val)) 158 } 159 160 s1.Range(func(value uint64) bool { 161 if !s2.Contains(value) { 162 t.Fatal(value) 163 } 164 return true 165 }) 166 167 if s1.Len() != s2.Len() { 168 t.Fatal("invalid") 169 } 170 }