github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/stacks/arraystack/arraystack_test.go (about) 1 package arraystack 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 TestStackIteratorOnEmpty(t *testing.T) { 73 stack := New[int]() 74 it := stack.Iterator() 75 for it.Next() { 76 t.Errorf("Shouldn't iterate on empty stack") 77 } 78 } 79 80 func TestStackIteratorNext(t *testing.T) { 81 stack := New[string]() 82 stack.Push("a") 83 stack.Push("b") 84 stack.Push("c") 85 86 it := stack.Iterator() 87 count := 0 88 for it.Next() { 89 count++ 90 index := it.Index() 91 value := it.Value() 92 switch index { 93 case 0: 94 if actualValue, expectedValue := value, "c"; actualValue != expectedValue { 95 t.Errorf("Got %v expected %v", actualValue, expectedValue) 96 } 97 case 1: 98 if actualValue, expectedValue := value, "b"; actualValue != expectedValue { 99 t.Errorf("Got %v expected %v", actualValue, expectedValue) 100 } 101 case 2: 102 if actualValue, expectedValue := value, "a"; actualValue != expectedValue { 103 t.Errorf("Got %v expected %v", actualValue, expectedValue) 104 } 105 default: 106 t.Errorf("Too many") 107 } 108 if actualValue, expectedValue := index, count-1; actualValue != expectedValue { 109 t.Errorf("Got %v expected %v", actualValue, expectedValue) 110 } 111 } 112 if actualValue, expectedValue := count, 3; actualValue != expectedValue { 113 t.Errorf("Got %v expected %v", actualValue, expectedValue) 114 } 115 116 stack.Clear() 117 it = stack.Iterator() 118 for it.Next() { 119 t.Errorf("Shouldn't iterate on empty stack") 120 } 121 } 122 123 func TestStackIteratorPrev(t *testing.T) { 124 stack := New[string]() 125 stack.Push("a") 126 stack.Push("b") 127 stack.Push("c") 128 129 it := stack.Iterator() 130 for it.Next() { 131 } 132 count := 0 133 for it.Prev() { 134 count++ 135 index := it.Index() 136 value := it.Value() 137 switch index { 138 case 0: 139 if actualValue, expectedValue := value, "c"; actualValue != expectedValue { 140 t.Errorf("Got %v expected %v", actualValue, expectedValue) 141 } 142 case 1: 143 if actualValue, expectedValue := value, "b"; actualValue != expectedValue { 144 t.Errorf("Got %v expected %v", actualValue, expectedValue) 145 } 146 case 2: 147 if actualValue, expectedValue := value, "a"; actualValue != expectedValue { 148 t.Errorf("Got %v expected %v", actualValue, expectedValue) 149 } 150 default: 151 t.Errorf("Too many") 152 } 153 if actualValue, expectedValue := index, 3-count; actualValue != expectedValue { 154 t.Errorf("Got %v expected %v", actualValue, expectedValue) 155 } 156 } 157 if actualValue, expectedValue := count, 3; actualValue != expectedValue { 158 t.Errorf("Got %v expected %v", actualValue, expectedValue) 159 } 160 } 161 162 func TestStackIteratorBegin(t *testing.T) { 163 stack := New[string]() 164 it := stack.Iterator() 165 it.Begin() 166 stack.Push("a") 167 stack.Push("b") 168 stack.Push("c") 169 for it.Next() { 170 } 171 it.Begin() 172 it.Next() 173 if index, value := it.Index(), it.Value(); index != 0 || value != "c" { 174 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") 175 } 176 } 177 178 func TestStackIteratorEnd(t *testing.T) { 179 stack := New[string]() 180 it := stack.Iterator() 181 182 if index := it.Index(); index != -1 { 183 t.Errorf("Got %v expected %v", index, -1) 184 } 185 186 it.End() 187 if index := it.Index(); index != 0 { 188 t.Errorf("Got %v expected %v", index, 0) 189 } 190 191 stack.Push("a") 192 stack.Push("b") 193 stack.Push("c") 194 it.End() 195 if index := it.Index(); index != stack.Size() { 196 t.Errorf("Got %v expected %v", index, stack.Size()) 197 } 198 199 it.Prev() 200 if index, value := it.Index(), it.Value(); index != stack.Size()-1 || value != "a" { 201 t.Errorf("Got %v,%v expected %v,%v", index, value, stack.Size()-1, "a") 202 } 203 } 204 205 func TestStackIteratorFirst(t *testing.T) { 206 stack := New[string]() 207 it := stack.Iterator() 208 if actualValue, expectedValue := it.First(), false; actualValue != expectedValue { 209 t.Errorf("Got %v expected %v", actualValue, expectedValue) 210 } 211 stack.Push("a") 212 stack.Push("b") 213 stack.Push("c") 214 if actualValue, expectedValue := it.First(), true; actualValue != expectedValue { 215 t.Errorf("Got %v expected %v", actualValue, expectedValue) 216 } 217 if index, value := it.Index(), it.Value(); index != 0 || value != "c" { 218 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "c") 219 } 220 } 221 222 func TestStackIteratorLast(t *testing.T) { 223 stack := New[string]() 224 it := stack.Iterator() 225 if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue { 226 t.Errorf("Got %v expected %v", actualValue, expectedValue) 227 } 228 stack.Push("a") 229 stack.Push("b") 230 stack.Push("c") 231 if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue { 232 t.Errorf("Got %v expected %v", actualValue, expectedValue) 233 } 234 if index, value := it.Index(), it.Value(); index != 2 || value != "a" { 235 t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "a") 236 } 237 } 238 239 func TestStackIteratorNextTo(t *testing.T) { 240 // Sample seek function, i.e. string starting with "b" 241 seek := func(index int, value string) bool { 242 return strings.HasSuffix(value, "b") 243 } 244 245 // NextTo (empty) 246 { 247 stack := New[string]() 248 it := stack.Iterator() 249 for it.NextTo(seek) { 250 t.Errorf("Shouldn't iterate on empty stack") 251 } 252 } 253 254 // NextTo (not found) 255 { 256 stack := New[string]() 257 stack.Push("xx") 258 stack.Push("yy") 259 it := stack.Iterator() 260 for it.NextTo(seek) { 261 t.Errorf("Shouldn't iterate on empty stack") 262 } 263 } 264 265 // NextTo (found) 266 { 267 stack := New[string]() 268 stack.Push("aa") 269 stack.Push("bb") 270 stack.Push("cc") 271 it := stack.Iterator() 272 it.Begin() 273 if !it.NextTo(seek) { 274 t.Errorf("Shouldn't iterate on empty stack") 275 } 276 if index, value := it.Index(), it.Value(); index != 1 || value != "bb" { 277 t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb") 278 } 279 if !it.Next() { 280 t.Errorf("Should go to first element") 281 } 282 if index, value := it.Index(), it.Value(); index != 2 || value != "aa" { 283 t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "aa") 284 } 285 if it.Next() { 286 t.Errorf("Should not go past last element") 287 } 288 } 289 } 290 291 func TestStackIteratorPrevTo(t *testing.T) { 292 // Sample seek function, i.e. string starting with "b" 293 seek := func(index int, value string) bool { 294 return strings.HasSuffix(value, "b") 295 } 296 297 // PrevTo (empty) 298 { 299 stack := New[string]() 300 it := stack.Iterator() 301 it.End() 302 for it.PrevTo(seek) { 303 t.Errorf("Shouldn't iterate on empty stack") 304 } 305 } 306 307 // PrevTo (not found) 308 { 309 stack := New[string]() 310 stack.Push("xx") 311 stack.Push("yy") 312 it := stack.Iterator() 313 it.End() 314 for it.PrevTo(seek) { 315 t.Errorf("Shouldn't iterate on empty stack") 316 } 317 } 318 319 // PrevTo (found) 320 { 321 stack := New[string]() 322 stack.Push("aa") 323 stack.Push("bb") 324 stack.Push("cc") 325 it := stack.Iterator() 326 it.End() 327 if !it.PrevTo(seek) { 328 t.Errorf("Shouldn't iterate on empty stack") 329 } 330 if index, value := it.Index(), it.Value(); index != 1 || value != "bb" { 331 t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb") 332 } 333 if !it.Prev() { 334 t.Errorf("Should go to first element") 335 } 336 if index, value := it.Index(), it.Value(); index != 0 || value != "cc" { 337 t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "cc") 338 } 339 if it.Prev() { 340 t.Errorf("Should not go before first element") 341 } 342 } 343 } 344 345 func TestStackSerialization(t *testing.T) { 346 stack := New[string]() 347 stack.Push("a") 348 stack.Push("b") 349 stack.Push("c") 350 351 var err error 352 assert := func() { 353 if actualValue, expectedValue := stack.Values(), []string{"c", "b", "a"}; !reflect.DeepEqual(actualValue, expectedValue) { 354 t.Errorf("Got %v expected %v", actualValue, expectedValue) 355 } 356 if actualValue, expectedValue := stack.Size(), 3; actualValue != expectedValue { 357 t.Errorf("Got %v expected %v", actualValue, expectedValue) 358 } 359 if err != nil { 360 t.Errorf("Got error %v", err) 361 } 362 } 363 364 assert() 365 366 bytes, err := stack.MarshalJSON() 367 assert() 368 369 err = stack.UnmarshalJSON(bytes) 370 assert() 371 372 bytes, err = json.Marshal([]interface{}{"a", "b", "c", stack}) 373 if err != nil { 374 t.Errorf("Got error %v", err) 375 } 376 377 err = json.Unmarshal([]byte(`["1","2","3"]`), &stack) 378 if err != nil { 379 t.Errorf("Got error %v", err) 380 } 381 } 382 383 func TestStackString(t *testing.T) { 384 c := New[int]() 385 c.Push(1) 386 if !strings.HasPrefix(c.String(), "ArrayStack") { 387 t.Errorf("String should start with container name") 388 } 389 } 390 391 func benchmarkPush[E int](b *testing.B, stack *Stack[E], size int) { 392 for i := 0; i < b.N; i++ { 393 for n := 0; n < size; n++ { 394 stack.Push(E(n)) 395 } 396 } 397 } 398 399 func benchmarkPop[E int](b *testing.B, stack *Stack[E], size int) { 400 for i := 0; i < b.N; i++ { 401 for n := 0; n < size; n++ { 402 stack.Pop() 403 } 404 } 405 } 406 407 func BenchmarkArrayStackPop100(b *testing.B) { 408 b.StopTimer() 409 size := 100 410 stack := New[int]() 411 for n := 0; n < size; n++ { 412 stack.Push(n) 413 } 414 b.StartTimer() 415 benchmarkPop(b, stack, size) 416 } 417 418 func BenchmarkArrayStackPop1000(b *testing.B) { 419 b.StopTimer() 420 size := 1000 421 stack := New[int]() 422 for n := 0; n < size; n++ { 423 stack.Push(n) 424 } 425 b.StartTimer() 426 benchmarkPop(b, stack, size) 427 } 428 429 func BenchmarkArrayStackPop10000(b *testing.B) { 430 b.StopTimer() 431 size := 10000 432 stack := New[int]() 433 for n := 0; n < size; n++ { 434 stack.Push(n) 435 } 436 b.StartTimer() 437 benchmarkPop(b, stack, size) 438 } 439 440 func BenchmarkArrayStackPop100000(b *testing.B) { 441 b.StopTimer() 442 size := 100000 443 stack := New[int]() 444 for n := 0; n < size; n++ { 445 stack.Push(n) 446 } 447 b.StartTimer() 448 benchmarkPop(b, stack, size) 449 } 450 451 func BenchmarkArrayStackPush100(b *testing.B) { 452 b.StopTimer() 453 size := 100 454 stack := New[int]() 455 b.StartTimer() 456 benchmarkPush(b, stack, size) 457 } 458 459 func BenchmarkArrayStackPush1000(b *testing.B) { 460 b.StopTimer() 461 size := 1000 462 stack := New[int]() 463 for n := 0; n < size; n++ { 464 stack.Push(n) 465 } 466 b.StartTimer() 467 benchmarkPush(b, stack, size) 468 } 469 470 func BenchmarkArrayStackPush10000(b *testing.B) { 471 b.StopTimer() 472 size := 10000 473 stack := New[int]() 474 for n := 0; n < size; n++ { 475 stack.Push(n) 476 } 477 b.StartTimer() 478 benchmarkPush(b, stack, size) 479 } 480 481 func BenchmarkArrayStackPush100000(b *testing.B) { 482 b.StopTimer() 483 size := 100000 484 stack := New[int]() 485 for n := 0; n < size; n++ { 486 stack.Push(n) 487 } 488 b.StartTimer() 489 benchmarkPush(b, stack, size) 490 }