github.com/supragya/TendermintConnector@v0.0.0-20210619045051-113e32b84fb1/_deprecated_chains/irisnet/libs/clist/clist_test.go (about) 1 package clist 2 3 import ( 4 "fmt" 5 "runtime" 6 "sync/atomic" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 cmn "github.com/tendermint/tendermint/libs/common" 12 ) 13 14 func TestPanicOnMaxLength(t *testing.T) { 15 maxLength := 1000 16 17 l := newWithMax(maxLength) 18 for i := 0; i < maxLength; i++ { 19 l.PushBack(1) 20 } 21 assert.Panics(t, func() { 22 l.PushBack(1) 23 }) 24 } 25 26 func TestSmall(t *testing.T) { 27 l := New() 28 el1 := l.PushBack(1) 29 el2 := l.PushBack(2) 30 el3 := l.PushBack(3) 31 if l.Len() != 3 { 32 t.Error("Expected len 3, got ", l.Len()) 33 } 34 35 //fmt.Printf("%p %v\n", el1, el1) 36 //fmt.Printf("%p %v\n", el2, el2) 37 //fmt.Printf("%p %v\n", el3, el3) 38 39 r1 := l.Remove(el1) 40 41 //fmt.Printf("%p %v\n", el1, el1) 42 //fmt.Printf("%p %v\n", el2, el2) 43 //fmt.Printf("%p %v\n", el3, el3) 44 45 r2 := l.Remove(el2) 46 47 //fmt.Printf("%p %v\n", el1, el1) 48 //fmt.Printf("%p %v\n", el2, el2) 49 //fmt.Printf("%p %v\n", el3, el3) 50 51 r3 := l.Remove(el3) 52 53 if r1 != 1 { 54 t.Error("Expected 1, got ", r1) 55 } 56 if r2 != 2 { 57 t.Error("Expected 2, got ", r2) 58 } 59 if r3 != 3 { 60 t.Error("Expected 3, got ", r3) 61 } 62 if l.Len() != 0 { 63 t.Error("Expected len 0, got ", l.Len()) 64 } 65 66 } 67 68 /* 69 This test is quite hacky because it relies on SetFinalizer 70 which isn't guaranteed to run at all. 71 */ 72 // nolint: megacheck 73 func _TestGCFifo(t *testing.T) { 74 75 const numElements = 1000000 76 l := New() 77 gcCount := new(uint64) 78 79 // SetFinalizer doesn't work well with circular structures, 80 // so we construct a trivial non-circular structure to 81 // track. 82 type value struct { 83 Int int 84 } 85 done := make(chan struct{}) 86 87 for i := 0; i < numElements; i++ { 88 v := new(value) 89 v.Int = i 90 l.PushBack(v) 91 runtime.SetFinalizer(v, func(v *value) { 92 atomic.AddUint64(gcCount, 1) 93 }) 94 } 95 96 for el := l.Front(); el != nil; { 97 l.Remove(el) 98 //oldEl := el 99 el = el.Next() 100 //oldEl.DetachPrev() 101 //oldEl.DetachNext() 102 } 103 104 runtime.GC() 105 time.Sleep(time.Second * 3) 106 runtime.GC() 107 time.Sleep(time.Second * 3) 108 _ = done 109 110 if *gcCount != numElements { 111 t.Errorf("Expected gcCount to be %v, got %v", numElements, 112 *gcCount) 113 } 114 } 115 116 /* 117 This test is quite hacky because it relies on SetFinalizer 118 which isn't guaranteed to run at all. 119 */ 120 // nolint: megacheck 121 func _TestGCRandom(t *testing.T) { 122 123 const numElements = 1000000 124 l := New() 125 gcCount := 0 126 127 // SetFinalizer doesn't work well with circular structures, 128 // so we construct a trivial non-circular structure to 129 // track. 130 type value struct { 131 Int int 132 } 133 134 for i := 0; i < numElements; i++ { 135 v := new(value) 136 v.Int = i 137 l.PushBack(v) 138 runtime.SetFinalizer(v, func(v *value) { 139 gcCount++ 140 }) 141 } 142 143 els := make([]*CElement, 0, numElements) 144 for el := l.Front(); el != nil; el = el.Next() { 145 els = append(els, el) 146 } 147 148 for _, i := range cmn.RandPerm(numElements) { 149 el := els[i] 150 l.Remove(el) 151 _ = el.Next() 152 } 153 154 runtime.GC() 155 time.Sleep(time.Second * 3) 156 157 if gcCount != numElements { 158 t.Errorf("Expected gcCount to be %v, got %v", numElements, 159 gcCount) 160 } 161 } 162 163 func TestScanRightDeleteRandom(t *testing.T) { 164 165 const numElements = 1000 166 const numTimes = 100 167 const numScanners = 10 168 169 l := New() 170 stop := make(chan struct{}) 171 172 els := make([]*CElement, numElements) 173 for i := 0; i < numElements; i++ { 174 el := l.PushBack(i) 175 els[i] = el 176 } 177 178 // Launch scanner routines that will rapidly iterate over elements. 179 for i := 0; i < numScanners; i++ { 180 go func(scannerID int) { 181 var el *CElement 182 restartCounter := 0 183 counter := 0 184 FOR_LOOP: 185 for { 186 select { 187 case <-stop: 188 fmt.Println("stopped") 189 break FOR_LOOP 190 default: 191 } 192 if el == nil { 193 el = l.FrontWait() 194 restartCounter++ 195 } 196 el = el.Next() 197 counter++ 198 } 199 fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter) 200 }(i) 201 } 202 203 // Remove an element, push back an element. 204 for i := 0; i < numTimes; i++ { 205 // Pick an element to remove 206 rmElIdx := cmn.RandIntn(len(els)) 207 rmEl := els[rmElIdx] 208 209 // Remove it 210 l.Remove(rmEl) 211 //fmt.Print(".") 212 213 // Insert a new element 214 newEl := l.PushBack(-1*i - 1) 215 els[rmElIdx] = newEl 216 217 if i%100000 == 0 { 218 fmt.Printf("Pushed %vK elements so far...\n", i/1000) 219 } 220 221 } 222 223 // Stop scanners 224 close(stop) 225 // time.Sleep(time.Second * 1) 226 227 // And remove all the elements. 228 for el := l.Front(); el != nil; el = el.Next() { 229 l.Remove(el) 230 } 231 if l.Len() != 0 { 232 t.Fatal("Failed to remove all elements from CList") 233 } 234 } 235 236 func TestWaitChan(t *testing.T) { 237 l := New() 238 ch := l.WaitChan() 239 240 // 1) add one element to an empty list 241 go l.PushBack(1) 242 <-ch 243 244 // 2) and remove it 245 el := l.Front() 246 v := l.Remove(el) 247 if v != 1 { 248 t.Fatal("where is 1 coming from?") 249 } 250 251 // 3) test iterating forward and waiting for Next (NextWaitChan and Next) 252 el = l.PushBack(0) 253 254 done := make(chan struct{}) 255 pushed := 0 256 go func() { 257 for i := 1; i < 100; i++ { 258 l.PushBack(i) 259 pushed++ 260 time.Sleep(time.Duration(cmn.RandIntn(25)) * time.Millisecond) 261 } 262 close(done) 263 }() 264 265 next := el 266 seen := 0 267 FOR_LOOP: 268 for { 269 select { 270 case <-next.NextWaitChan(): 271 next = next.Next() 272 seen++ 273 if next == nil { 274 continue 275 } 276 case <-done: 277 break FOR_LOOP 278 case <-time.After(10 * time.Second): 279 t.Fatal("max execution time") 280 } 281 } 282 283 if pushed != seen { 284 t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen) 285 } 286 287 // 4) test iterating backwards (PrevWaitChan and Prev) 288 prev := next 289 seen = 0 290 FOR_LOOP2: 291 for { 292 select { 293 case <-prev.PrevWaitChan(): 294 prev = prev.Prev() 295 seen++ 296 if prev == nil { 297 t.Fatal("expected PrevWaitChan to block forever on nil when reached first elem") 298 } 299 case <-time.After(3 * time.Second): 300 break FOR_LOOP2 301 } 302 } 303 304 if pushed != seen { 305 t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen) 306 } 307 }