github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/stacks/linkedliststack/linkedliststack_test.go (about) 1 package linkedliststack 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "strings" 7 "testing" 8 ) 9 10 func TestStackPush(t *testing.T) { 11 stack := New[int]() 12 if actualValue := stack.Empty(); actualValue != true { 13 t.Errorf("Got %v expected %v", actualValue, true) 14 } 15 stack.Push(1) 16 stack.Push(2) 17 stack.Push(3) 18 19 if actualValue := stack.Values(); actualValue[0] != 3 || actualValue[1] != 2 || actualValue[2] != 1 { 20 t.Errorf("Got %v expected %v", actualValue, "[3,2,1]") 21 } 22 if actualValue := stack.Empty(); actualValue != false { 23 t.Errorf("Got %v expected %v", actualValue, false) 24 } 25 if actualValue := stack.Size(); actualValue != 3 { 26 t.Errorf("Got %v expected %v", actualValue, 3) 27 } 28 if actualValue, ok := stack.Peek(); actualValue != 3 || !ok { 29 t.Errorf("Got %v expected %v", actualValue, 3) 30 } 31 } 32 33 func TestStackPeek(t *testing.T) { 34 stack := New[int]() 35 if actualValue, ok := stack.Peek(); actualValue != 0 || ok { 36 t.Errorf("Got %v expected %v", actualValue, nil) 37 } 38 stack.Push(1) 39 stack.Push(2) 40 stack.Push(3) 41 if actualValue, ok := stack.Peek(); actualValue != 3 || !ok { 42 t.Errorf("Got %v expected %v", actualValue, 3) 43 } 44 } 45 46 func TestStackPop(t *testing.T) { 47 stack := New[int]() 48 stack.Push(1) 49 stack.Push(2) 50 stack.Push(3) 51 stack.Pop() 52 if actualValue, ok := stack.Peek(); actualValue != 2 || !ok { 53 t.Errorf("Got %v expected %v", actualValue, 2) 54 } 55 if actualValue, ok := stack.Pop(); actualValue != 2 || !ok { 56 t.Errorf("Got %v expected %v", actualValue, 2) 57 } 58 if actualValue, ok := stack.Pop(); actualValue != 1 || !ok { 59 t.Errorf("Got %v expected %v", actualValue, 1) 60 } 61 if actualValue, ok := stack.Pop(); actualValue != 0 || ok { 62 t.Errorf("Got %v expected %v", actualValue, nil) 63 } 64 if actualValue := stack.Empty(); actualValue != true { 65 t.Errorf("Got %v expected %v", actualValue, true) 66 } 67 if actualValue := stack.Values(); len(actualValue) != 0 { 68 t.Errorf("Got %v expected %v", actualValue, "[]") 69 } 70 } 71 72 func TestStackIterator(t *testing.T) { 73 stack := New[string]() 74 stack.Push("a") 75 stack.Push("b") 76 stack.Push("c") 77 78 // Iterator 79 it := stack.Iterator() 80 count := 0 81 for it.Next() { 82 count++ 83 index := it.Index() 84 value := it.Value() 85 switch index { 86 case 0: 87 if actualValue, expectedValue := value, "c"; actualValue != expectedValue { 88 t.Errorf("Got %v expected %v", actualValue, expectedValue) 89 } 90 case 1: 91 if actualValue, expectedValue := value, "b"; actualValue != expectedValue { 92 t.Errorf("Got %v expected %v", actualValue, expectedValue) 93 } 94 case 2: 95 if actualValue, expectedValue := value, "a"; actualValue != expectedValue { 96 t.Errorf("Got %v expected %v", actualValue, expectedValue) 97 } 98 default: 99 t.Errorf("Too many") 100 } 101 if actualValue, expectedValue := index, count-1; actualValue != expectedValue { 102 t.Errorf("Got %v expected %v", actualValue, expectedValue) 103 } 104 } 105 if actualValue, expectedValue := count, 3; actualValue != expectedValue { 106 t.Errorf("Got %v expected %v", actualValue, expectedValue) 107 } 108 109 stack.Clear() 110 it = stack.Iterator() 111 for it.Next() { 112 t.Errorf("Shouldn't iterate on empty stack") 113 } 114 } 115 116 func TestStackIteratorBegin(t *testing.T) { 117 stack := New[string]() 118 it := stack.Iterator() 119 it.Begin() 120 stack.Push("a") 121 stack.Push("b") 122 stack.Push("c") 123 for it.Next() { 124 } 125 it.Begin() 126 it.Next() 127 if index, value := it.Index(), it.Value(); index != 0 || value != "c" { 128 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") 129 } 130 } 131 132 func TestStackIteratorFirst(t *testing.T) { 133 stack := New[string]() 134 it := stack.Iterator() 135 if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { 136 t.Errorf("Got %v expected %v", actualValue, expectedValue) 137 } 138 stack.Push("a") 139 stack.Push("b") 140 stack.Push("c") 141 if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { 142 t.Errorf("Got %v expected %v", actualValue, expectedValue) 143 } 144 if index, value := it.Index(), it.Value(); index != 0 || value != "c" { 145 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") 146 } 147 } 148 149 func TestStackIteratorNextTo(t *testing.T) { 150 // Sample seek function, i.e. string starting with "b" 151 seek := func(index int, value string) bool { 152 return strings.HasSuffix(value, "b") 153 } 154 155 // NextTo (empty) 156 { 157 stack := New[string]() 158 it := stack.Iterator() 159 for it.NextTo(seek) { 160 t.Errorf("Shouldn't iterate on empty stack") 161 } 162 } 163 164 // NextTo (not found) 165 { 166 stack := New[string]() 167 stack.Push("xx") 168 stack.Push("yy") 169 it := stack.Iterator() 170 for it.NextTo(seek) { 171 t.Errorf("Shouldn't iterate on empty stack") 172 } 173 } 174 175 // NextTo (found) 176 { 177 stack := New[string]() 178 stack.Push("aa") 179 stack.Push("bb") 180 stack.Push("cc") 181 it := stack.Iterator() 182 it.Begin() 183 if !it.NextTo(seek) { 184 t.Errorf("Shouldn't iterate on empty stack") 185 } 186 if index, value := it.Index(), it.Value(); index != 1 || value != "bb" { 187 t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb") 188 } 189 if !it.Next() { 190 t.Errorf("Should go to first element") 191 } 192 if index, value := it.Index(), it.Value(); index != 2 || value != "aa" { 193 t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "aa") 194 } 195 if it.Next() { 196 t.Errorf("Should not go past last element") 197 } 198 } 199 } 200 201 func TestStackSerialization(t *testing.T) { 202 stack := New[string]() 203 stack.Push("a") 204 stack.Push("b") 205 stack.Push("c") 206 207 var err error 208 assert := func() { 209 if actualValue, expectedValue := stack.Values(), []string{"c", "b", "a"}; !reflect.DeepEqual(actualValue, expectedValue) { 210 t.Errorf("Got %v expected %v", actualValue, expectedValue) 211 } 212 if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue { 213 t.Errorf("Got %v expected %v", actualValue, expectedValue) 214 } 215 if err != nil { 216 t.Errorf("Got error %v", err) 217 } 218 } 219 220 assert() 221 222 bytes, err := stack.MarshalJSON() 223 assert() 224 225 err = stack.UnmarshalJSON(bytes) 226 assert() 227 228 bytes, err = json.Marshal([]interface{}{"a", "b", "c", stack}) 229 if err != nil { 230 t.Errorf("Got error %v", err) 231 } 232 233 err = json.Unmarshal([]byte(`["1","2","3"]`), &stack) 234 if err != nil { 235 t.Errorf("Got error %v", err) 236 } 237 } 238 239 func TestStackString(t *testing.T) { 240 c := New[int]() 241 c.Push(1) 242 if !strings.HasPrefix(c.String(), "LinkedListStack") { 243 t.Errorf("String should start with container name") 244 } 245 } 246 247 func benchmarkPush[E int](b *testing.B, stack *Stack[E], size int) { 248 for i := 0; i < b.N; i++ { 249 for n := 0; n < size; n++ { 250 stack.Push(E(n)) 251 } 252 } 253 } 254 255 func benchmarkPop[E int](b *testing.B, stack *Stack[E], size int) { 256 for i := 0; i < b.N; i++ { 257 for n := 0; n < size; n++ { 258 stack.Pop() 259 } 260 } 261 } 262 263 func BenchmarkLinkedListStackPop100(b *testing.B) { 264 b.StopTimer() 265 size := 100 266 stack := New[int]() 267 for n := 0; n < size; n++ { 268 stack.Push(n) 269 } 270 b.StartTimer() 271 benchmarkPop(b, stack, size) 272 } 273 274 func BenchmarkLinkedListStackPop1000(b *testing.B) { 275 b.StopTimer() 276 size := 1000 277 stack := New[int]() 278 for n := 0; n < size; n++ { 279 stack.Push(n) 280 } 281 b.StartTimer() 282 benchmarkPop(b, stack, size) 283 } 284 285 func BenchmarkLinkedListStackPop10000(b *testing.B) { 286 b.StopTimer() 287 size := 10000 288 stack := New[int]() 289 for n := 0; n < size; n++ { 290 stack.Push(n) 291 } 292 b.StartTimer() 293 benchmarkPop(b, stack, size) 294 } 295 296 func BenchmarkLinkedListStackPop100000(b *testing.B) { 297 b.StopTimer() 298 size := 100000 299 stack := New[int]() 300 for n := 0; n < size; n++ { 301 stack.Push(n) 302 } 303 b.StartTimer() 304 benchmarkPop(b, stack, size) 305 } 306 307 func BenchmarkLinkedListStackPush100(b *testing.B) { 308 b.StopTimer() 309 size := 100 310 stack := New[int]() 311 b.StartTimer() 312 benchmarkPush(b, stack, size) 313 } 314 315 func BenchmarkLinkedListStackPush1000(b *testing.B) { 316 b.StopTimer() 317 size := 1000 318 stack := New[int]() 319 for n := 0; n < size; n++ { 320 stack.Push(n) 321 } 322 b.StartTimer() 323 benchmarkPush(b, stack, size) 324 } 325 326 func BenchmarkLinkedListStackPush10000(b *testing.B) { 327 b.StopTimer() 328 size := 10000 329 stack := New[int]() 330 for n := 0; n < size; n++ { 331 stack.Push(n) 332 } 333 b.StartTimer() 334 benchmarkPush(b, stack, size) 335 } 336 337 func BenchmarkLinkedListStackPush100000(b *testing.B) { 338 b.StopTimer() 339 size := 100000 340 stack := New[int]() 341 for n := 0; n < size; n++ { 342 stack.Push(n) 343 } 344 b.StartTimer() 345 benchmarkPush(b, stack, size) 346 }