github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/queue/stack_test.go (about) 1 package queue 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 "time" 8 ) 9 10 func TestStackClose(t *testing.T) { 11 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 12 s, err := OpenStack(file) 13 if err != nil { 14 t.Error(err) 15 } 16 defer s.Drop() 17 18 if _, err = s.PushString("value"); err != nil { 19 t.Error(err) 20 } 21 22 if s.Length() != 1 { 23 t.Errorf("Expected stack length of 1, got %d", s.Length()) 24 } 25 26 s.Close() 27 28 if _, err = s.Pop(); err != ErrDBClosed { 29 t.Errorf("Expected to get database closed error, got %s", err.Error()) 30 } 31 32 if s.Length() != 0 { 33 t.Errorf("Expected stack length of 0, got %d", s.Length()) 34 } 35 } 36 37 func TestStackDrop(t *testing.T) { 38 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 39 s, err := OpenStack(file) 40 if err != nil { 41 t.Error(err) 42 } 43 44 if _, err = os.Stat(file); os.IsNotExist(err) { 45 t.Error(err) 46 } 47 48 s.Drop() 49 50 if _, err = os.Stat(file); err == nil { 51 t.Error("Expected directory for test database to have been deleted") 52 } 53 } 54 55 func TestStackIncompatibleType(t *testing.T) { 56 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 57 pq, err := OpenPriorityQueue(file, ASC) 58 if err != nil { 59 t.Error(err) 60 } 61 defer pq.Drop() 62 pq.Close() 63 64 if _, err = OpenStack(file); err != ErrIncompatibleType { 65 t.Error("Expected stack to return ErrIncompatibleTypes when opening queuePriorityQueue") 66 } 67 } 68 69 func TestStackPush(t *testing.T) { 70 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 71 s, err := OpenStack(file) 72 if err != nil { 73 t.Error(err) 74 } 75 defer s.Drop() 76 77 for i := 1; i <= 10; i++ { 78 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 79 t.Error(err) 80 } 81 } 82 83 if s.Length() != 10 { 84 t.Errorf("Expected stack size of 10, got %d", s.Length()) 85 } 86 } 87 88 func TestStackPop(t *testing.T) { 89 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 90 s, err := OpenStack(file) 91 if err != nil { 92 t.Error(err) 93 } 94 defer s.Drop() 95 96 for i := 1; i <= 10; i++ { 97 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 98 t.Error(err) 99 } 100 } 101 102 if s.Length() != 10 { 103 t.Errorf("Expected stack length of 10, got %d", s.Length()) 104 } 105 106 popItem, err := s.Pop() 107 if err != nil { 108 t.Error(err) 109 } 110 111 if s.Length() != 9 { 112 t.Errorf("Expected stack length of 9, got %d", s.Length()) 113 } 114 115 compStr := "value for item 10" 116 117 if popItem.ToString() != compStr { 118 t.Errorf("Expected string to be '%s', got '%s'", compStr, popItem.ToString()) 119 } 120 } 121 122 func TestStackPushPopPointerJSON(t *testing.T) { 123 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 124 q, err := OpenStack(file) 125 if err != nil { 126 t.Error(err) 127 } 128 defer q.Drop() 129 130 type subObject struct { 131 Value *int 132 } 133 134 type object struct { 135 Value int 136 SubObject subObject 137 } 138 139 val := 0 140 obj := object{ 141 Value: 0, 142 SubObject: subObject{ 143 Value: &val, 144 }, 145 } 146 147 if _, err = q.PushObjectAsJSON(obj); err != nil { 148 t.Error(err) 149 } 150 151 item, err := q.Pop() 152 if err != nil { 153 t.Error(err) 154 } 155 156 var itemObj object 157 if err := item.ToObjectFromJSON(&itemObj); err != nil { 158 t.Error(err) 159 } 160 161 if *itemObj.SubObject.Value != 0 { 162 t.Errorf("Expected object subobject value to be '0', got '%v'", *itemObj.SubObject.Value) 163 } 164 } 165 166 func TestStackPeek(t *testing.T) { 167 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 168 s, err := OpenStack(file) 169 if err != nil { 170 t.Error(err) 171 } 172 defer s.Drop() 173 174 compStr := "value for item" 175 176 if _, err = s.PushString(compStr); err != nil { 177 t.Error(err) 178 } 179 180 peekItem, err := s.Peek() 181 if err != nil { 182 t.Error(err) 183 } 184 185 if peekItem.ToString() != compStr { 186 t.Errorf("Expected string to be '%s', got '%s'", compStr, peekItem.ToString()) 187 } 188 189 if s.Length() != 1 { 190 t.Errorf("Expected stack length of 1, got %d", s.Length()) 191 } 192 } 193 194 func TestStackPeekByOffset(t *testing.T) { 195 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 196 s, err := OpenStack(file) 197 if err != nil { 198 t.Error(err) 199 } 200 defer s.Drop() 201 202 for i := 1; i <= 10; i++ { 203 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 204 t.Error(err) 205 } 206 } 207 208 compStrFirst := "value for item 10" 209 compStrLast := "value for item 1" 210 compStr := "value for item 7" 211 212 peekFirstItem, err := s.PeekByOffset(0) 213 if err != nil { 214 t.Error(err) 215 } 216 217 if peekFirstItem.ToString() != compStrFirst { 218 t.Errorf("Expected string to be '%s', got '%s'", compStrFirst, peekFirstItem.ToString()) 219 } 220 221 peekLastItem, err := s.PeekByOffset(9) 222 if err != nil { 223 t.Error(err) 224 } 225 226 if peekLastItem.ToString() != compStrLast { 227 t.Errorf("Expected string to be '%s', got '%s'", compStrLast, peekLastItem.ToString()) 228 } 229 230 peekItem, err := s.PeekByOffset(3) 231 if err != nil { 232 t.Error(err) 233 } 234 235 if peekItem.ToString() != compStr { 236 t.Errorf("Expected string to be '%s', got '%s'", compStr, peekItem.ToString()) 237 } 238 239 if s.Length() != 10 { 240 t.Errorf("Expected stack length of 10, got %d", s.Length()) 241 } 242 } 243 244 func TestStackPeekByID(t *testing.T) { 245 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 246 s, err := OpenStack(file) 247 if err != nil { 248 t.Error(err) 249 } 250 defer s.Drop() 251 252 for i := 1; i <= 10; i++ { 253 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 254 t.Error(err) 255 } 256 } 257 258 compStr := "value for item 3" 259 260 peekItem, err := s.PeekByID(3) 261 if err != nil { 262 t.Error(err) 263 } 264 265 if peekItem.ToString() != compStr { 266 t.Errorf("Expected string to be '%s', got '%s'", compStr, peekItem.ToString()) 267 } 268 269 if s.Length() != 10 { 270 t.Errorf("Expected stack length of 10, got %d", s.Length()) 271 } 272 } 273 274 func TestStackUpdate(t *testing.T) { 275 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 276 s, err := OpenStack(file) 277 if err != nil { 278 t.Error(err) 279 } 280 defer s.Drop() 281 282 for i := 1; i <= 10; i++ { 283 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 284 t.Error(err) 285 } 286 } 287 288 item, err := s.PeekByID(3) 289 if err != nil { 290 t.Error(err) 291 } 292 293 oldCompStr := "value for item 3" 294 newCompStr := "new value for item 3" 295 296 if item.ToString() != oldCompStr { 297 t.Errorf("Expected string to be '%s', got '%s'", oldCompStr, item.ToString()) 298 } 299 300 updatedItem, err := s.Update(item.ID, []byte(newCompStr)) 301 if err != nil { 302 t.Error(err) 303 } 304 305 if updatedItem.ToString() != newCompStr { 306 t.Errorf("Expected current item value to be '%s', got '%s'", newCompStr, item.ToString()) 307 } 308 309 newItem, err := s.PeekByID(3) 310 if err != nil { 311 t.Error(err) 312 } 313 314 if newItem.ToString() != newCompStr { 315 t.Errorf("Expected new item value to be '%s', got '%s'", newCompStr, item.ToString()) 316 } 317 } 318 319 func TestStackUpdateString(t *testing.T) { 320 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 321 s, err := OpenStack(file) 322 if err != nil { 323 t.Error(err) 324 } 325 defer s.Drop() 326 327 for i := 1; i <= 10; i++ { 328 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 329 t.Error(err) 330 } 331 } 332 333 item, err := s.PeekByID(3) 334 if err != nil { 335 t.Error(err) 336 } 337 338 oldCompStr := "value for item 3" 339 newCompStr := "new value for item 3" 340 341 if item.ToString() != oldCompStr { 342 t.Errorf("Expected string to be '%s', got '%s'", oldCompStr, item.ToString()) 343 } 344 345 updatedItem, err := s.UpdateString(item.ID, newCompStr) 346 if err != nil { 347 t.Error(err) 348 } 349 350 if updatedItem.ToString() != newCompStr { 351 t.Errorf("Expected current item value to be '%s', got '%s'", newCompStr, item.ToString()) 352 } 353 354 newItem, err := s.PeekByID(3) 355 if err != nil { 356 t.Error(err) 357 } 358 359 if newItem.ToString() != newCompStr { 360 t.Errorf("Expected new item value to be '%s', got '%s'", newCompStr, item.ToString()) 361 } 362 } 363 364 func TestStackUpdateObject(t *testing.T) { 365 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 366 s, err := OpenStack(file) 367 if err != nil { 368 t.Error(err) 369 } 370 defer s.Drop() 371 372 type object struct { 373 Value int 374 } 375 376 for i := 1; i <= 10; i++ { 377 if _, err = s.PushObject(object{i}); err != nil { 378 t.Error(err) 379 } 380 } 381 382 item, err := s.PeekByID(3) 383 if err != nil { 384 t.Error(err) 385 } 386 387 oldCompObj := object{3} 388 newCompObj := object{33} 389 390 var obj object 391 if err := item.ToObject(&obj); err != nil { 392 t.Error(err) 393 } 394 395 if obj != oldCompObj { 396 t.Errorf("Expected object to be '%+v', got '%+v'", oldCompObj, obj) 397 } 398 399 updatedItem, err := s.UpdateObject(item.ID, newCompObj) 400 if err != nil { 401 t.Error(err) 402 } 403 404 if err := updatedItem.ToObject(&obj); err != nil { 405 t.Error(err) 406 } 407 408 if obj != newCompObj { 409 t.Errorf("Expected current object to be '%+v', got '%+v'", newCompObj, obj) 410 } 411 412 newItem, err := s.PeekByID(3) 413 if err != nil { 414 t.Error(err) 415 } 416 417 if err := newItem.ToObject(&obj); err != nil { 418 t.Error(err) 419 } 420 421 if obj != newCompObj { 422 t.Errorf("Expected new object to be '%+v', got '%+v'", newCompObj, obj) 423 } 424 } 425 426 func TestStackUpdateObjectAsJSON(t *testing.T) { 427 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 428 s, err := OpenStack(file) 429 if err != nil { 430 t.Error(err) 431 } 432 defer s.Drop() 433 434 type subObject struct { 435 Value *int 436 } 437 438 type object struct { 439 Value int 440 SubObject subObject 441 } 442 443 for i := 1; i <= 10; i++ { 444 obj := object{ 445 Value: i, 446 SubObject: subObject{ 447 Value: &i, 448 }, 449 } 450 451 if _, err = s.PushObjectAsJSON(obj); err != nil { 452 t.Error(err) 453 } 454 } 455 456 item, err := s.PeekByID(3) 457 if err != nil { 458 t.Error(err) 459 } 460 461 oldCompObjVal := 3 462 oldCompObj := object{ 463 Value: 3, 464 SubObject: subObject{ 465 Value: &oldCompObjVal, 466 }, 467 } 468 newCompObjVal := 33 469 newCompObj := object{ 470 Value: 33, 471 SubObject: subObject{ 472 Value: &newCompObjVal, 473 }, 474 } 475 476 var obj object 477 if err := item.ToObjectFromJSON(&obj); err != nil { 478 t.Error(err) 479 } 480 481 if *obj.SubObject.Value != *oldCompObj.SubObject.Value { 482 t.Errorf("Expected object subobject value to be '%+v', got '%+v'", *oldCompObj.SubObject.Value, *obj.SubObject.Value) 483 } 484 485 updatedItem, err := s.UpdateObjectAsJSON(item.ID, newCompObj) 486 if err != nil { 487 t.Error(err) 488 } 489 490 if err := updatedItem.ToObjectFromJSON(&obj); err != nil { 491 t.Error(err) 492 } 493 494 if *obj.SubObject.Value != *newCompObj.SubObject.Value { 495 t.Errorf("Expected current object subobject value to be '%+v', got '%+v'", *newCompObj.SubObject.Value, *obj.SubObject.Value) 496 } 497 498 newItem, err := s.PeekByID(3) 499 if err != nil { 500 t.Error(err) 501 } 502 503 if err := newItem.ToObjectFromJSON(&obj); err != nil { 504 t.Error(err) 505 } 506 507 if *obj.SubObject.Value != *newCompObj.SubObject.Value { 508 t.Errorf("Expected current object subobject value to be '%+v', got '%+v'", *newCompObj.SubObject.Value, *obj.SubObject.Value) 509 } 510 } 511 512 func TestStackUpdateOutOfBounds(t *testing.T) { 513 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 514 s, err := OpenStack(file) 515 if err != nil { 516 t.Error(err) 517 } 518 defer s.Drop() 519 520 for i := 1; i <= 10; i++ { 521 if _, err = s.PushString(fmt.Sprintf("value for item %d", i)); err != nil { 522 t.Error(err) 523 } 524 } 525 526 if s.Length() != 10 { 527 t.Errorf("Expected stack length of 10, got %d", s.Length()) 528 } 529 530 popItem, err := s.Pop() 531 if err != nil { 532 t.Error(err) 533 } 534 535 if s.Length() != 9 { 536 t.Errorf("Expected stack length of 9, got %d", s.Length()) 537 } 538 539 if _, err = s.Update(popItem.ID, []byte(`new value`)); err != ErrOutOfBounds { 540 t.Errorf("Expected to get stack out of bounds error, got %s", err.Error()) 541 } 542 543 if _, err = s.Update(popItem.ID-1, []byte(`new value`)); err != nil { 544 t.Error(err) 545 } 546 } 547 548 func TestStackEmpty(t *testing.T) { 549 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 550 s, err := OpenStack(file) 551 if err != nil { 552 t.Error(err) 553 } 554 defer s.Drop() 555 556 _, err = s.PushString("value for item") 557 if err != nil { 558 t.Error(err) 559 } 560 561 _, err = s.Pop() 562 if err != nil { 563 t.Error(err) 564 } 565 566 _, err = s.Pop() 567 if err != ErrEmpty { 568 t.Errorf("Expected to get empty error, got %s", err.Error()) 569 } 570 } 571 572 func TestStackOutOfBounds(t *testing.T) { 573 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 574 s, err := OpenStack(file) 575 if err != nil { 576 t.Error(err) 577 } 578 defer s.Drop() 579 580 _, err = s.PushString("value for item") 581 if err != nil { 582 t.Error(err) 583 } 584 585 _, err = s.PeekByOffset(2) 586 if err != ErrOutOfBounds { 587 t.Errorf("Expected to get stack out of bounds error, got %s", err.Error()) 588 } 589 } 590 591 func BenchmarkStackPush(b *testing.B) { 592 // Open test database 593 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 594 s, err := OpenStack(file) 595 if err != nil { 596 b.Error(err) 597 } 598 defer s.Drop() 599 600 b.ResetTimer() 601 b.ReportAllocs() 602 603 for n := 0; n < b.N; n++ { 604 _, _ = s.PushString("value") 605 } 606 } 607 608 func BenchmarkStackPop(b *testing.B) { 609 // Open test database 610 file := fmt.Sprintf("test_db_%d", time.Now().UnixNano()) 611 s, err := OpenStack(file) 612 if err != nil { 613 b.Error(err) 614 } 615 defer s.Drop() 616 617 // Fill with dummy data 618 for n := 0; n < b.N; n++ { 619 if _, err = s.PushString("value"); err != nil { 620 b.Error(err) 621 } 622 } 623 624 // Start benchmark 625 b.ResetTimer() 626 b.ReportAllocs() 627 628 for n := 0; n < b.N; n++ { 629 _, _ = s.Pop() 630 } 631 }