github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/tm2/pkg/clist/clist_test.go (about) 1 package clist 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/gnolang/gno/tm2/pkg/random" 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestPanicOnMaxLength(t *testing.T) { 13 t.Parallel() 14 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 t.Parallel() 28 29 l := New() 30 el1 := l.PushBack(1) 31 el2 := l.PushBack(2) 32 el3 := l.PushBack(3) 33 if l.Len() != 3 { 34 t.Error("Expected len 3, got ", l.Len()) 35 } 36 37 // fmt.Printf("%p %v\n", el1, el1) 38 // fmt.Printf("%p %v\n", el2, el2) 39 // fmt.Printf("%p %v\n", el3, el3) 40 41 r1 := l.Remove(el1) 42 43 // fmt.Printf("%p %v\n", el1, el1) 44 // fmt.Printf("%p %v\n", el2, el2) 45 // fmt.Printf("%p %v\n", el3, el3) 46 47 r2 := l.Remove(el2) 48 49 // fmt.Printf("%p %v\n", el1, el1) 50 // fmt.Printf("%p %v\n", el2, el2) 51 // fmt.Printf("%p %v\n", el3, el3) 52 53 r3 := l.Remove(el3) 54 55 if r1 != 1 { 56 t.Error("Expected 1, got ", r1) 57 } 58 if r2 != 2 { 59 t.Error("Expected 2, got ", r2) 60 } 61 if r3 != 3 { 62 t.Error("Expected 3, got ", r3) 63 } 64 if l.Len() != 0 { 65 t.Error("Expected len 0, got ", l.Len()) 66 } 67 } 68 69 func TestScanRightDeleteRandom(t *testing.T) { 70 t.Parallel() 71 72 const numElements = 1000 73 const numTimes = 100 74 const numScanners = 10 75 76 l := New() 77 stop := make(chan struct{}) 78 79 els := make([]*CElement, numElements) 80 for i := 0; i < numElements; i++ { 81 el := l.PushBack(i) 82 els[i] = el 83 } 84 85 // Launch scanner routines that will rapidly iterate over elements. 86 for i := 0; i < numScanners; i++ { 87 go func(scannerID int) { 88 var el *CElement 89 restartCounter := 0 90 counter := 0 91 FOR_LOOP: 92 for { 93 select { 94 case <-stop: 95 fmt.Println("stopped") 96 break FOR_LOOP 97 default: 98 } 99 if el == nil { 100 el = l.FrontWait() 101 restartCounter++ 102 } 103 el = el.Next() 104 counter++ 105 } 106 fmt.Printf("Scanner %v restartCounter: %v counter: %v\n", scannerID, restartCounter, counter) 107 }(i) 108 } 109 110 // Remove an element, push back an element. 111 for i := 0; i < numTimes; i++ { 112 // Pick an element to remove 113 rmElIdx := random.RandIntn(len(els)) 114 rmEl := els[rmElIdx] 115 116 // Remove it 117 l.Remove(rmEl) 118 // fmt.Print(".") 119 120 // Insert a new element 121 newEl := l.PushBack(-1*i - 1) 122 els[rmElIdx] = newEl 123 124 if i%100000 == 0 { 125 fmt.Printf("Pushed %vK elements so far...\n", i/1000) 126 } 127 } 128 129 // Stop scanners 130 close(stop) 131 // time.Sleep(time.Second * 1) 132 133 // And remove all the elements. 134 for el := l.Front(); el != nil; el = el.Next() { 135 l.Remove(el) 136 } 137 if l.Len() != 0 { 138 t.Fatal("Failed to remove all elements from CList") 139 } 140 } 141 142 func TestWaitChan(t *testing.T) { 143 t.Parallel() 144 145 l := New() 146 ch := l.WaitChan() 147 148 // 1) add one element to an empty list 149 go l.PushBack(1) 150 <-ch 151 152 // 2) and remove it 153 el := l.Front() 154 v := l.Remove(el) 155 if v != 1 { 156 t.Fatal("where is 1 coming from?") 157 } 158 159 // 3) test iterating forward and waiting for Next (NextWaitChan and Next) 160 el = l.PushBack(0) 161 162 done := make(chan struct{}) 163 pushed := 0 164 go func() { 165 for i := 1; i < 100; i++ { 166 l.PushBack(i) 167 pushed++ 168 time.Sleep(time.Duration(random.RandIntn(25)) * time.Millisecond) 169 } 170 // apply a deterministic pause so the counter has time to catch up 171 time.Sleep(25 * time.Millisecond) 172 close(done) 173 }() 174 175 next := el 176 seen := 0 177 FOR_LOOP: 178 for { 179 select { 180 case <-next.NextWaitChan(): 181 next = next.Next() 182 seen++ 183 if next == nil { 184 t.Fatal("Next should not be nil when waiting on NextWaitChan") 185 } 186 case <-done: 187 break FOR_LOOP 188 case <-time.After(10 * time.Second): 189 t.Fatal("max execution time") 190 } 191 } 192 193 if pushed != seen { 194 t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen) 195 } 196 197 // 4) test iterating backwards (PrevWaitChan and Prev) 198 prev := next 199 seen = 0 200 FOR_LOOP2: 201 for { 202 select { 203 case <-prev.PrevWaitChan(): 204 prev = prev.Prev() 205 seen++ 206 if prev == nil { 207 t.Fatal("expected PrevWaitChan to block forever on nil when reached first elem") 208 } 209 case <-time.After(3 * time.Second): 210 break FOR_LOOP2 211 } 212 } 213 214 if pushed != seen { 215 t.Fatalf("number of pushed items (%d) not equal to number of seen items (%d)", pushed, seen) 216 } 217 }