github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bdb/bucket_test.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bdb_test 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "errors" 21 "fmt" 22 "log" 23 "math/rand" 24 "os" 25 "strconv" 26 "strings" 27 "testing" 28 "testing/quick" 29 30 "github.com/zuoyebang/bitalosdb/bitree/bdb" 31 ) 32 33 func TestBucket_Get_NonExistent(t *testing.T) { 34 db := MustOpenDB() 35 defer db.MustClose() 36 37 if err := db.Update(func(tx *bdb.Tx) error { 38 b, err := tx.CreateBucket([]byte("widgets")) 39 if err != nil { 40 t.Fatal(err) 41 } 42 if v := b.Get([]byte("foo")); v != nil { 43 t.Fatal("expected nil value") 44 } 45 return nil 46 }); err != nil { 47 t.Fatal(err) 48 } 49 } 50 51 func TestBucket_Get_FromNode(t *testing.T) { 52 db := MustOpenDB() 53 defer db.MustClose() 54 55 if err := db.Update(func(tx *bdb.Tx) error { 56 b, err := tx.CreateBucket([]byte("widgets")) 57 if err != nil { 58 t.Fatal(err) 59 } 60 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 61 t.Fatal(err) 62 } 63 if v := b.Get([]byte("foo")); !bytes.Equal(v, []byte("bar")) { 64 t.Fatalf("unexpected value: %v", v) 65 } 66 return nil 67 }); err != nil { 68 t.Fatal(err) 69 } 70 } 71 72 func TestBucket_Get_IncompatibleValue(t *testing.T) { 73 db := MustOpenDB() 74 defer db.MustClose() 75 if err := db.Update(func(tx *bdb.Tx) error { 76 _, err := tx.CreateBucket([]byte("widgets")) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { 82 t.Fatal(err) 83 } 84 85 if tx.Bucket([]byte("widgets")).Get([]byte("foo")) != nil { 86 t.Fatal("expected nil value") 87 } 88 return nil 89 }); err != nil { 90 t.Fatal(err) 91 } 92 } 93 94 func TestBucket_Get_Capacity(t *testing.T) { 95 db := MustOpenDB() 96 defer db.MustClose() 97 98 if err := db.Update(func(tx *bdb.Tx) error { 99 b, err := tx.CreateBucket([]byte("bucket")) 100 if err != nil { 101 return err 102 } 103 return b.Put([]byte("key"), []byte("val")) 104 }); err != nil { 105 t.Fatal(err) 106 } 107 108 if err := db.Update(func(tx *bdb.Tx) error { 109 k, v := tx.Bucket([]byte("bucket")).Cursor().First() 110 111 if len(k) != cap(k) { 112 t.Fatalf("unexpected key slice capacity: %d", cap(k)) 113 } else if len(v) != cap(v) { 114 t.Fatalf("unexpected value slice capacity: %d", cap(v)) 115 } 116 117 k = append(k, []byte("123")...) 118 v = append(v, []byte("123")...) 119 _, _ = k, v 120 121 return nil 122 }); err != nil { 123 t.Fatal(err) 124 } 125 } 126 127 func TestBucket_Put(t *testing.T) { 128 db := MustOpenDB() 129 defer db.MustClose() 130 if err := db.Update(func(tx *bdb.Tx) error { 131 b, err := tx.CreateBucket([]byte("widgets")) 132 if err != nil { 133 t.Fatal(err) 134 } 135 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 136 t.Fatal(err) 137 } 138 139 v := tx.Bucket([]byte("widgets")).Get([]byte("foo")) 140 if !bytes.Equal([]byte("bar"), v) { 141 t.Fatalf("unexpected value: %v", v) 142 } 143 return nil 144 }); err != nil { 145 t.Fatal(err) 146 } 147 } 148 149 func TestBucket_Put_Repeat(t *testing.T) { 150 db := MustOpenDB() 151 defer db.MustClose() 152 if err := db.Update(func(tx *bdb.Tx) error { 153 b, err := tx.CreateBucket([]byte("widgets")) 154 if err != nil { 155 t.Fatal(err) 156 } 157 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 158 t.Fatal(err) 159 } 160 if err := b.Put([]byte("foo"), []byte("baz")); err != nil { 161 t.Fatal(err) 162 } 163 164 value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) 165 if !bytes.Equal([]byte("baz"), value) { 166 t.Fatalf("unexpected value: %v", value) 167 } 168 return nil 169 }); err != nil { 170 t.Fatal(err) 171 } 172 } 173 174 func TestBucket_Put_Large(t *testing.T) { 175 db := MustOpenDB() 176 defer db.MustClose() 177 178 count, factor := 100, 200 179 if err := db.Update(func(tx *bdb.Tx) error { 180 b, err := tx.CreateBucket([]byte("widgets")) 181 if err != nil { 182 t.Fatal(err) 183 } 184 for i := 1; i < count; i++ { 185 if err := b.Put([]byte(strings.Repeat("0", i*factor)), []byte(strings.Repeat("X", (count-i)*factor))); err != nil { 186 t.Fatal(err) 187 } 188 } 189 return nil 190 }); err != nil { 191 t.Fatal(err) 192 } 193 194 if err := db.View(func(tx *bdb.Tx) error { 195 b := tx.Bucket([]byte("widgets")) 196 for i := 1; i < count; i++ { 197 value := b.Get([]byte(strings.Repeat("0", i*factor))) 198 if !bytes.Equal(value, []byte(strings.Repeat("X", (count-i)*factor))) { 199 t.Fatalf("unexpected value: %v", value) 200 } 201 } 202 return nil 203 }); err != nil { 204 t.Fatal(err) 205 } 206 } 207 208 func TestDB_Put_VeryLarge(t *testing.T) { 209 if testing.Short() { 210 t.Skip("skipping test in short mode.") 211 } 212 213 n, batchN := 400000, 200000 214 ksize, vsize := 8, 500 215 216 db := MustOpenDB() 217 defer db.MustClose() 218 219 for i := 0; i < n; i += batchN { 220 if err := db.Update(func(tx *bdb.Tx) error { 221 b, err := tx.CreateBucketIfNotExists([]byte("widgets")) 222 if err != nil { 223 t.Fatal(err) 224 } 225 for j := 0; j < batchN; j++ { 226 k, v := make([]byte, ksize), make([]byte, vsize) 227 binary.BigEndian.PutUint32(k, uint32(i+j)) 228 if err := b.Put(k, v); err != nil { 229 t.Fatal(err) 230 } 231 } 232 return nil 233 }); err != nil { 234 t.Fatal(err) 235 } 236 } 237 } 238 239 func TestBucket_Put_IncompatibleValue(t *testing.T) { 240 db := MustOpenDB() 241 defer db.MustClose() 242 243 if err := db.Update(func(tx *bdb.Tx) error { 244 b0, err := tx.CreateBucket([]byte("widgets")) 245 if err != nil { 246 t.Fatal(err) 247 } 248 249 if _, err := tx.Bucket([]byte("widgets")).CreateBucket([]byte("foo")); err != nil { 250 t.Fatal(err) 251 } 252 if err := b0.Put([]byte("foo"), []byte("bar")); err != bdb.ErrIncompatibleValue { 253 t.Fatalf("unexpected error: %s", err) 254 } 255 return nil 256 }); err != nil { 257 t.Fatal(err) 258 } 259 } 260 261 func TestBucket_Put_Closed(t *testing.T) { 262 db := MustOpenDB() 263 defer db.MustClose() 264 tx, err := db.Begin(true) 265 if err != nil { 266 t.Fatal(err) 267 } 268 269 b, err := tx.CreateBucket([]byte("widgets")) 270 if err != nil { 271 t.Fatal(err) 272 } 273 274 if err := tx.Rollback(); err != nil { 275 t.Fatal(err) 276 } 277 278 if err := b.Put([]byte("foo"), []byte("bar")); err != bdb.ErrTxClosed { 279 t.Fatalf("unexpected error: %s", err) 280 } 281 } 282 283 func TestBucket_Put_ReadOnly(t *testing.T) { 284 db := MustOpenDB() 285 defer db.MustClose() 286 287 if err := db.Update(func(tx *bdb.Tx) error { 288 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 289 t.Fatal(err) 290 } 291 return nil 292 }); err != nil { 293 t.Fatal(err) 294 } 295 296 if err := db.View(func(tx *bdb.Tx) error { 297 b := tx.Bucket([]byte("widgets")) 298 if err := b.Put([]byte("foo"), []byte("bar")); err != bdb.ErrTxNotWritable { 299 t.Fatalf("unexpected error: %s", err) 300 } 301 return nil 302 }); err != nil { 303 t.Fatal(err) 304 } 305 } 306 307 func TestBucket_Delete(t *testing.T) { 308 db := MustOpenDB() 309 defer db.MustClose() 310 311 if err := db.Update(func(tx *bdb.Tx) error { 312 b, err := tx.CreateBucket([]byte("widgets")) 313 if err != nil { 314 t.Fatal(err) 315 } 316 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 317 t.Fatal(err) 318 } 319 if err := b.Delete([]byte("foo")); err != nil { 320 t.Fatal(err) 321 } 322 if v := b.Get([]byte("foo")); v != nil { 323 t.Fatalf("unexpected value: %v", v) 324 } 325 return nil 326 }); err != nil { 327 t.Fatal(err) 328 } 329 } 330 331 func TestBucket_Delete_Large(t *testing.T) { 332 db := MustOpenDB() 333 defer db.MustClose() 334 335 if err := db.Update(func(tx *bdb.Tx) error { 336 b, err := tx.CreateBucket([]byte("widgets")) 337 if err != nil { 338 t.Fatal(err) 339 } 340 341 for i := 0; i < 100; i++ { 342 if err := b.Put([]byte(strconv.Itoa(i)), []byte(strings.Repeat("*", 1024))); err != nil { 343 t.Fatal(err) 344 } 345 } 346 347 return nil 348 }); err != nil { 349 t.Fatal(err) 350 } 351 352 if err := db.Update(func(tx *bdb.Tx) error { 353 b := tx.Bucket([]byte("widgets")) 354 for i := 0; i < 100; i++ { 355 if err := b.Delete([]byte(strconv.Itoa(i))); err != nil { 356 t.Fatal(err) 357 } 358 } 359 return nil 360 }); err != nil { 361 t.Fatal(err) 362 } 363 364 if err := db.View(func(tx *bdb.Tx) error { 365 b := tx.Bucket([]byte("widgets")) 366 for i := 0; i < 100; i++ { 367 if v := b.Get([]byte(strconv.Itoa(i))); v != nil { 368 t.Fatalf("unexpected value: %v, i=%d", v, i) 369 } 370 } 371 return nil 372 }); err != nil { 373 t.Fatal(err) 374 } 375 } 376 377 func TestBucket_Delete_FreelistOverflow(t *testing.T) { 378 if testing.Short() { 379 t.Skip("skipping test in short mode.") 380 } 381 382 db := MustOpenDB() 383 defer db.MustClose() 384 385 k := make([]byte, 16) 386 for i := uint64(0); i < 10000; i++ { 387 if err := db.Update(func(tx *bdb.Tx) error { 388 b, err := tx.CreateBucketIfNotExists([]byte("0")) 389 if err != nil { 390 t.Fatalf("bucket error: %s", err) 391 } 392 393 for j := uint64(0); j < 1000; j++ { 394 binary.BigEndian.PutUint64(k[:8], i) 395 binary.BigEndian.PutUint64(k[8:], j) 396 if err := b.Put(k, nil); err != nil { 397 t.Fatalf("put error: %s", err) 398 } 399 } 400 401 return nil 402 }); err != nil { 403 t.Fatal(err) 404 } 405 } 406 407 if err := db.Update(func(tx *bdb.Tx) error { 408 b := tx.Bucket([]byte("0")) 409 c := b.Cursor() 410 for k, _ := c.First(); k != nil; k, _ = c.Next() { 411 if err := c.Delete(); err != nil { 412 t.Fatal(err) 413 } 414 } 415 return nil 416 }); err != nil { 417 t.Fatal(err) 418 } 419 420 stats := db.Stats() 421 freePages := stats.FreePageN + stats.PendingPageN 422 if freePages <= 0xFFFF { 423 t.Fatalf("expected more than 0xFFFF free pages, got %v", freePages) 424 } 425 426 if err := db.DB.Close(); err != nil { 427 t.Fatal(err) 428 } 429 db.MustReopen() 430 if reopenFreePages := db.Stats().FreePageN; freePages != reopenFreePages { 431 t.Fatalf("expected %d free pages, got %+v", freePages, db.Stats()) 432 } 433 } 434 435 func TestBucket_Delete_NonExisting(t *testing.T) { 436 db := MustOpenDB() 437 defer db.MustClose() 438 439 if err := db.Update(func(tx *bdb.Tx) error { 440 b, err := tx.CreateBucket([]byte("widgets")) 441 if err != nil { 442 t.Fatal(err) 443 } 444 445 if _, err = b.CreateBucket([]byte("nested")); err != nil { 446 t.Fatal(err) 447 } 448 return nil 449 }); err != nil { 450 t.Fatal(err) 451 } 452 453 if err := db.Update(func(tx *bdb.Tx) error { 454 b := tx.Bucket([]byte("widgets")) 455 if err := b.Delete([]byte("foo")); err != nil { 456 t.Fatal(err) 457 } 458 if b.Bucket([]byte("nested")) == nil { 459 t.Fatal("nested bucket has been deleted") 460 } 461 return nil 462 }); err != nil { 463 t.Fatal(err) 464 } 465 } 466 467 func TestBucket_Nested(t *testing.T) { 468 db := MustOpenDB() 469 defer db.MustClose() 470 471 if err := db.Update(func(tx *bdb.Tx) error { 472 b, err := tx.CreateBucket([]byte("widgets")) 473 if err != nil { 474 t.Fatal(err) 475 } 476 477 _, err = b.CreateBucket([]byte("foo")) 478 if err != nil { 479 t.Fatal(err) 480 } 481 482 if err := b.Put([]byte("bar"), []byte("0000")); err != nil { 483 t.Fatal(err) 484 } 485 486 return nil 487 }); err != nil { 488 t.Fatal(err) 489 } 490 db.MustCheck() 491 492 if err := db.Update(func(tx *bdb.Tx) error { 493 b := tx.Bucket([]byte("widgets")) 494 if err := b.Put([]byte("bar"), []byte("xxxx")); err != nil { 495 t.Fatal(err) 496 } 497 return nil 498 }); err != nil { 499 t.Fatal(err) 500 } 501 db.MustCheck() 502 503 if err := db.Update(func(tx *bdb.Tx) error { 504 var b = tx.Bucket([]byte("widgets")) 505 for i := 0; i < 10000; i++ { 506 if err := b.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { 507 t.Fatal(err) 508 } 509 } 510 return nil 511 }); err != nil { 512 t.Fatal(err) 513 } 514 db.MustCheck() 515 516 if err := db.Update(func(tx *bdb.Tx) error { 517 var b = tx.Bucket([]byte("widgets")) 518 if err := b.Bucket([]byte("foo")).Put([]byte("baz"), []byte("yyyy")); err != nil { 519 t.Fatal(err) 520 } 521 return nil 522 }); err != nil { 523 t.Fatal(err) 524 } 525 db.MustCheck() 526 527 if err := db.View(func(tx *bdb.Tx) error { 528 var b = tx.Bucket([]byte("widgets")) 529 if v := b.Bucket([]byte("foo")).Get([]byte("baz")); !bytes.Equal(v, []byte("yyyy")) { 530 t.Fatalf("unexpected value: %v", v) 531 } 532 if v := b.Get([]byte("bar")); !bytes.Equal(v, []byte("xxxx")) { 533 t.Fatalf("unexpected value: %v", v) 534 } 535 for i := 0; i < 10000; i++ { 536 if v := b.Get([]byte(strconv.Itoa(i))); !bytes.Equal(v, []byte(strconv.Itoa(i))) { 537 t.Fatalf("unexpected value: %v", v) 538 } 539 } 540 return nil 541 }); err != nil { 542 t.Fatal(err) 543 } 544 } 545 546 func TestBucket_Delete_Bucket(t *testing.T) { 547 db := MustOpenDB() 548 defer db.MustClose() 549 if err := db.Update(func(tx *bdb.Tx) error { 550 b, err := tx.CreateBucket([]byte("widgets")) 551 if err != nil { 552 t.Fatal(err) 553 } 554 if _, err := b.CreateBucket([]byte("foo")); err != nil { 555 t.Fatal(err) 556 } 557 if err := b.Delete([]byte("foo")); err != bdb.ErrIncompatibleValue { 558 t.Fatalf("unexpected error: %s", err) 559 } 560 return nil 561 }); err != nil { 562 t.Fatal(err) 563 } 564 } 565 566 func TestBucket_Delete_ReadOnly(t *testing.T) { 567 db := MustOpenDB() 568 defer db.MustClose() 569 570 if err := db.Update(func(tx *bdb.Tx) error { 571 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 572 t.Fatal(err) 573 } 574 return nil 575 }); err != nil { 576 t.Fatal(err) 577 } 578 579 if err := db.View(func(tx *bdb.Tx) error { 580 if err := tx.Bucket([]byte("widgets")).Delete([]byte("foo")); err != bdb.ErrTxNotWritable { 581 t.Fatalf("unexpected error: %s", err) 582 } 583 return nil 584 }); err != nil { 585 t.Fatal(err) 586 } 587 } 588 589 func TestBucket_Delete_Closed(t *testing.T) { 590 db := MustOpenDB() 591 defer db.MustClose() 592 593 tx, err := db.Begin(true) 594 if err != nil { 595 t.Fatal(err) 596 } 597 598 b, err := tx.CreateBucket([]byte("widgets")) 599 if err != nil { 600 t.Fatal(err) 601 } 602 603 if err := tx.Rollback(); err != nil { 604 t.Fatal(err) 605 } 606 if err := b.Delete([]byte("foo")); err != bdb.ErrTxClosed { 607 t.Fatalf("unexpected error: %s", err) 608 } 609 } 610 611 func TestBucket_DeleteBucket_Nested(t *testing.T) { 612 db := MustOpenDB() 613 defer db.MustClose() 614 615 if err := db.Update(func(tx *bdb.Tx) error { 616 widgets, err := tx.CreateBucket([]byte("widgets")) 617 if err != nil { 618 t.Fatal(err) 619 } 620 621 foo, err := widgets.CreateBucket([]byte("foo")) 622 if err != nil { 623 t.Fatal(err) 624 } 625 626 bar, err := foo.CreateBucket([]byte("bar")) 627 if err != nil { 628 t.Fatal(err) 629 } 630 if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { 631 t.Fatal(err) 632 } 633 if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != nil { 634 t.Fatal(err) 635 } 636 return nil 637 }); err != nil { 638 t.Fatal(err) 639 } 640 } 641 642 func TestBucket_DeleteBucket_Nested2(t *testing.T) { 643 db := MustOpenDB() 644 defer db.MustClose() 645 646 if err := db.Update(func(tx *bdb.Tx) error { 647 widgets, err := tx.CreateBucket([]byte("widgets")) 648 if err != nil { 649 t.Fatal(err) 650 } 651 652 foo, err := widgets.CreateBucket([]byte("foo")) 653 if err != nil { 654 t.Fatal(err) 655 } 656 657 bar, err := foo.CreateBucket([]byte("bar")) 658 if err != nil { 659 t.Fatal(err) 660 } 661 662 if err := bar.Put([]byte("baz"), []byte("bat")); err != nil { 663 t.Fatal(err) 664 } 665 return nil 666 }); err != nil { 667 t.Fatal(err) 668 } 669 670 if err := db.Update(func(tx *bdb.Tx) error { 671 widgets := tx.Bucket([]byte("widgets")) 672 if widgets == nil { 673 t.Fatal("expected widgets bucket") 674 } 675 676 foo := widgets.Bucket([]byte("foo")) 677 if foo == nil { 678 t.Fatal("expected foo bucket") 679 } 680 681 bar := foo.Bucket([]byte("bar")) 682 if bar == nil { 683 t.Fatal("expected bar bucket") 684 } 685 686 if v := bar.Get([]byte("baz")); !bytes.Equal(v, []byte("bat")) { 687 t.Fatalf("unexpected value: %v", v) 688 } 689 if err := tx.DeleteBucket([]byte("widgets")); err != nil { 690 t.Fatal(err) 691 } 692 return nil 693 }); err != nil { 694 t.Fatal(err) 695 } 696 697 if err := db.View(func(tx *bdb.Tx) error { 698 if tx.Bucket([]byte("widgets")) != nil { 699 t.Fatal("expected bucket to be deleted") 700 } 701 return nil 702 }); err != nil { 703 t.Fatal(err) 704 } 705 } 706 707 func TestBucket_DeleteBucket_Large(t *testing.T) { 708 db := MustOpenDB() 709 defer db.MustClose() 710 711 if err := db.Update(func(tx *bdb.Tx) error { 712 widgets, err := tx.CreateBucket([]byte("widgets")) 713 if err != nil { 714 t.Fatal(err) 715 } 716 717 foo, err := widgets.CreateBucket([]byte("foo")) 718 if err != nil { 719 t.Fatal(err) 720 } 721 722 for i := 0; i < 1000; i++ { 723 if err := foo.Put([]byte(fmt.Sprintf("%d", i)), []byte(fmt.Sprintf("%0100d", i))); err != nil { 724 t.Fatal(err) 725 } 726 } 727 return nil 728 }); err != nil { 729 t.Fatal(err) 730 } 731 732 if err := db.Update(func(tx *bdb.Tx) error { 733 if err := tx.DeleteBucket([]byte("widgets")); err != nil { 734 t.Fatal(err) 735 } 736 return nil 737 }); err != nil { 738 t.Fatal(err) 739 } 740 } 741 742 func TestBucket_Bucket_IncompatibleValue(t *testing.T) { 743 db := MustOpenDB() 744 defer db.MustClose() 745 746 if err := db.Update(func(tx *bdb.Tx) error { 747 widgets, err := tx.CreateBucket([]byte("widgets")) 748 if err != nil { 749 t.Fatal(err) 750 } 751 752 if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { 753 t.Fatal(err) 754 } 755 if b := tx.Bucket([]byte("widgets")).Bucket([]byte("foo")); b != nil { 756 t.Fatal("expected nil bucket") 757 } 758 return nil 759 }); err != nil { 760 t.Fatal(err) 761 } 762 } 763 764 func TestBucket_CreateBucket_IncompatibleValue(t *testing.T) { 765 db := MustOpenDB() 766 defer db.MustClose() 767 if err := db.Update(func(tx *bdb.Tx) error { 768 widgets, err := tx.CreateBucket([]byte("widgets")) 769 if err != nil { 770 t.Fatal(err) 771 } 772 773 if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { 774 t.Fatal(err) 775 } 776 if _, err := widgets.CreateBucket([]byte("foo")); err != bdb.ErrIncompatibleValue { 777 t.Fatalf("unexpected error: %s", err) 778 } 779 return nil 780 }); err != nil { 781 t.Fatal(err) 782 } 783 } 784 785 func TestBucket_DeleteBucket_IncompatibleValue(t *testing.T) { 786 db := MustOpenDB() 787 defer db.MustClose() 788 789 if err := db.Update(func(tx *bdb.Tx) error { 790 widgets, err := tx.CreateBucket([]byte("widgets")) 791 if err != nil { 792 t.Fatal(err) 793 } 794 if err := widgets.Put([]byte("foo"), []byte("bar")); err != nil { 795 t.Fatal(err) 796 } 797 if err := tx.Bucket([]byte("widgets")).DeleteBucket([]byte("foo")); err != bdb.ErrIncompatibleValue { 798 t.Fatalf("unexpected error: %s", err) 799 } 800 return nil 801 }); err != nil { 802 t.Fatal(err) 803 } 804 } 805 806 func TestBucket_Sequence(t *testing.T) { 807 db := MustOpenDB() 808 defer db.MustClose() 809 810 if err := db.Update(func(tx *bdb.Tx) error { 811 bkt, err := tx.CreateBucket([]byte("0")) 812 if err != nil { 813 t.Fatal(err) 814 } 815 816 if v := bkt.Sequence(); v != 0 { 817 t.Fatalf("unexpected sequence: %d", v) 818 } 819 820 if err := bkt.SetSequence(1000); err != nil { 821 t.Fatal(err) 822 } 823 824 if v := bkt.Sequence(); v != 1000 { 825 t.Fatalf("unexpected sequence: %d", v) 826 } 827 828 return nil 829 }); err != nil { 830 t.Fatal(err) 831 } 832 833 if err := db.View(func(tx *bdb.Tx) error { 834 if v := tx.Bucket([]byte("0")).Sequence(); v != 1000 { 835 t.Fatalf("unexpected sequence: %d", v) 836 } 837 return nil 838 }); err != nil { 839 t.Fatal(err) 840 } 841 } 842 843 func TestBucket_NextSequence(t *testing.T) { 844 db := MustOpenDB() 845 defer db.MustClose() 846 847 if err := db.Update(func(tx *bdb.Tx) error { 848 widgets, err := tx.CreateBucket([]byte("widgets")) 849 if err != nil { 850 t.Fatal(err) 851 } 852 woojits, err := tx.CreateBucket([]byte("woojits")) 853 if err != nil { 854 t.Fatal(err) 855 } 856 857 if seq, err := widgets.NextSequence(); err != nil { 858 t.Fatal(err) 859 } else if seq != 1 { 860 t.Fatalf("unexpecte sequence: %d", seq) 861 } 862 863 if seq, err := widgets.NextSequence(); err != nil { 864 t.Fatal(err) 865 } else if seq != 2 { 866 t.Fatalf("unexpected sequence: %d", seq) 867 } 868 869 if seq, err := woojits.NextSequence(); err != nil { 870 t.Fatal(err) 871 } else if seq != 1 { 872 t.Fatalf("unexpected sequence: %d", 1) 873 } 874 875 return nil 876 }); err != nil { 877 t.Fatal(err) 878 } 879 } 880 881 func TestBucket_NextSequence_Persist(t *testing.T) { 882 db := MustOpenDB() 883 defer db.MustClose() 884 885 if err := db.Update(func(tx *bdb.Tx) error { 886 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 887 t.Fatal(err) 888 } 889 return nil 890 }); err != nil { 891 t.Fatal(err) 892 } 893 894 if err := db.Update(func(tx *bdb.Tx) error { 895 if _, err := tx.Bucket([]byte("widgets")).NextSequence(); err != nil { 896 t.Fatal(err) 897 } 898 return nil 899 }); err != nil { 900 t.Fatal(err) 901 } 902 903 if err := db.Update(func(tx *bdb.Tx) error { 904 seq, err := tx.Bucket([]byte("widgets")).NextSequence() 905 if err != nil { 906 t.Fatalf("unexpected error: %s", err) 907 } else if seq != 2 { 908 t.Fatalf("unexpected sequence: %d", seq) 909 } 910 return nil 911 }); err != nil { 912 t.Fatal(err) 913 } 914 } 915 916 func TestBucket_NextSequence_ReadOnly(t *testing.T) { 917 db := MustOpenDB() 918 defer db.MustClose() 919 920 if err := db.Update(func(tx *bdb.Tx) error { 921 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 922 t.Fatal(err) 923 } 924 return nil 925 }); err != nil { 926 t.Fatal(err) 927 } 928 929 if err := db.View(func(tx *bdb.Tx) error { 930 _, err := tx.Bucket([]byte("widgets")).NextSequence() 931 if err != bdb.ErrTxNotWritable { 932 t.Fatalf("unexpected error: %s", err) 933 } 934 return nil 935 }); err != nil { 936 t.Fatal(err) 937 } 938 } 939 940 func TestBucket_NextSequence_Closed(t *testing.T) { 941 db := MustOpenDB() 942 defer db.MustClose() 943 tx, err := db.Begin(true) 944 if err != nil { 945 t.Fatal(err) 946 } 947 b, err := tx.CreateBucket([]byte("widgets")) 948 if err != nil { 949 t.Fatal(err) 950 } 951 if err := tx.Rollback(); err != nil { 952 t.Fatal(err) 953 } 954 if _, err := b.NextSequence(); err != bdb.ErrTxClosed { 955 t.Fatal(err) 956 } 957 } 958 959 func TestBucket_ForEach(t *testing.T) { 960 db := MustOpenDB() 961 defer db.MustClose() 962 963 if err := db.Update(func(tx *bdb.Tx) error { 964 b, err := tx.CreateBucket([]byte("widgets")) 965 if err != nil { 966 t.Fatal(err) 967 } 968 if err := b.Put([]byte("foo"), []byte("0000")); err != nil { 969 t.Fatal(err) 970 } 971 if err := b.Put([]byte("baz"), []byte("0001")); err != nil { 972 t.Fatal(err) 973 } 974 if err := b.Put([]byte("bar"), []byte("0002")); err != nil { 975 t.Fatal(err) 976 } 977 978 var index int 979 if err := b.ForEach(func(k, v []byte) error { 980 switch index { 981 case 0: 982 if !bytes.Equal(k, []byte("bar")) { 983 t.Fatalf("unexpected key: %v", k) 984 } else if !bytes.Equal(v, []byte("0002")) { 985 t.Fatalf("unexpected value: %v", v) 986 } 987 case 1: 988 if !bytes.Equal(k, []byte("baz")) { 989 t.Fatalf("unexpected key: %v", k) 990 } else if !bytes.Equal(v, []byte("0001")) { 991 t.Fatalf("unexpected value: %v", v) 992 } 993 case 2: 994 if !bytes.Equal(k, []byte("foo")) { 995 t.Fatalf("unexpected key: %v", k) 996 } else if !bytes.Equal(v, []byte("0000")) { 997 t.Fatalf("unexpected value: %v", v) 998 } 999 } 1000 index++ 1001 return nil 1002 }); err != nil { 1003 t.Fatal(err) 1004 } 1005 1006 if index != 3 { 1007 t.Fatalf("unexpected index: %d", index) 1008 } 1009 1010 return nil 1011 }); err != nil { 1012 t.Fatal(err) 1013 } 1014 } 1015 1016 func TestBucket_ForEach_ShortCircuit(t *testing.T) { 1017 db := MustOpenDB() 1018 defer db.MustClose() 1019 if err := db.Update(func(tx *bdb.Tx) error { 1020 b, err := tx.CreateBucket([]byte("widgets")) 1021 if err != nil { 1022 t.Fatal(err) 1023 } 1024 if err := b.Put([]byte("bar"), []byte("0000")); err != nil { 1025 t.Fatal(err) 1026 } 1027 if err := b.Put([]byte("baz"), []byte("0000")); err != nil { 1028 t.Fatal(err) 1029 } 1030 if err := b.Put([]byte("foo"), []byte("0000")); err != nil { 1031 t.Fatal(err) 1032 } 1033 1034 var index int 1035 if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { 1036 index++ 1037 if bytes.Equal(k, []byte("baz")) { 1038 return errors.New("marker") 1039 } 1040 return nil 1041 }); err == nil || err.Error() != "marker" { 1042 t.Fatalf("unexpected error: %s", err) 1043 } 1044 if index != 2 { 1045 t.Fatalf("unexpected index: %d", index) 1046 } 1047 1048 return nil 1049 }); err != nil { 1050 t.Fatal(err) 1051 } 1052 } 1053 1054 func TestBucket_ForEach_Closed(t *testing.T) { 1055 db := MustOpenDB() 1056 defer db.MustClose() 1057 1058 tx, err := db.Begin(true) 1059 if err != nil { 1060 t.Fatal(err) 1061 } 1062 1063 b, err := tx.CreateBucket([]byte("widgets")) 1064 if err != nil { 1065 t.Fatal(err) 1066 } 1067 1068 if err := tx.Rollback(); err != nil { 1069 t.Fatal(err) 1070 } 1071 1072 if err := b.ForEach(func(k, v []byte) error { return nil }); err != bdb.ErrTxClosed { 1073 t.Fatalf("unexpected error: %s", err) 1074 } 1075 } 1076 1077 func TestBucket_Put_EmptyKey(t *testing.T) { 1078 db := MustOpenDB() 1079 defer db.MustClose() 1080 1081 if err := db.Update(func(tx *bdb.Tx) error { 1082 b, err := tx.CreateBucket([]byte("widgets")) 1083 if err != nil { 1084 t.Fatal(err) 1085 } 1086 if err := b.Put([]byte(""), []byte("bar")); err != bdb.ErrKeyRequired { 1087 t.Fatalf("unexpected error: %s", err) 1088 } 1089 if err := b.Put(nil, []byte("bar")); err != bdb.ErrKeyRequired { 1090 t.Fatalf("unexpected error: %s", err) 1091 } 1092 return nil 1093 }); err != nil { 1094 t.Fatal(err) 1095 } 1096 } 1097 1098 func TestBucket_Put_KeyTooLarge(t *testing.T) { 1099 db := MustOpenDB() 1100 defer db.MustClose() 1101 if err := db.Update(func(tx *bdb.Tx) error { 1102 b, err := tx.CreateBucket([]byte("widgets")) 1103 if err != nil { 1104 t.Fatal(err) 1105 } 1106 if err := b.Put(make([]byte, 32769), []byte("bar")); err != bdb.ErrKeyTooLarge { 1107 t.Fatalf("unexpected error: %s", err) 1108 } 1109 return nil 1110 }); err != nil { 1111 t.Fatal(err) 1112 } 1113 } 1114 1115 func TestBucket_Put_ValueTooLarge(t *testing.T) { 1116 if os.Getenv("DRONE") == "true" { 1117 t.Skip("not enough RAM for test") 1118 } 1119 1120 db := MustOpenDB() 1121 defer db.MustClose() 1122 1123 if err := db.Update(func(tx *bdb.Tx) error { 1124 b, err := tx.CreateBucket([]byte("widgets")) 1125 if err != nil { 1126 t.Fatal(err) 1127 } 1128 if err := b.Put([]byte("foo"), make([]byte, bdb.MaxValueSize+1)); err != bdb.ErrValueTooLarge { 1129 t.Fatalf("unexpected error: %s", err) 1130 } 1131 return nil 1132 }); err != nil { 1133 t.Fatal(err) 1134 } 1135 } 1136 1137 func TestBucket_Stats_RandomFill(t *testing.T) { 1138 if testing.Short() { 1139 t.Skip("skipping test in short mode.") 1140 } else if os.Getpagesize() != 4096 { 1141 t.Skip("invalid page size for test") 1142 } 1143 1144 db := MustOpenDB() 1145 defer db.MustClose() 1146 1147 var count int 1148 rand := rand.New(rand.NewSource(42)) 1149 for _, i := range rand.Perm(1000) { 1150 if err := db.Update(func(tx *bdb.Tx) error { 1151 b, err := tx.CreateBucketIfNotExists([]byte("woojits")) 1152 if err != nil { 1153 t.Fatal(err) 1154 } 1155 b.FillPercent = 0.9 1156 for _, j := range rand.Perm(100) { 1157 index := (j * 10000) + i 1158 if err := b.Put([]byte(fmt.Sprintf("%d000000000000000", index)), []byte("0000000000")); err != nil { 1159 t.Fatal(err) 1160 } 1161 count++ 1162 } 1163 return nil 1164 }); err != nil { 1165 t.Fatal(err) 1166 } 1167 } 1168 1169 db.MustCheck() 1170 1171 if err := db.View(func(tx *bdb.Tx) error { 1172 stats := tx.Bucket([]byte("woojits")).Stats() 1173 if stats.KeyN != 100000 { 1174 t.Fatalf("unexpected KeyN: %d", stats.KeyN) 1175 } 1176 1177 if stats.BranchPageN != 98 { 1178 t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) 1179 } else if stats.BranchOverflowN != 0 { 1180 t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) 1181 } else if stats.BranchInuse != 130984 { 1182 t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) 1183 } else if stats.BranchAlloc != 401408 { 1184 t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) 1185 } 1186 1187 if stats.LeafPageN != 3412 { 1188 t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) 1189 } else if stats.LeafOverflowN != 0 { 1190 t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) 1191 } else if stats.LeafInuse != 4742482 { 1192 t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) 1193 } else if stats.LeafAlloc != 13975552 { 1194 t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) 1195 } 1196 return nil 1197 }); err != nil { 1198 t.Fatal(err) 1199 } 1200 } 1201 1202 func TestBucket_Stats_Small(t *testing.T) { 1203 db := MustOpenDB() 1204 defer db.MustClose() 1205 1206 if err := db.Update(func(tx *bdb.Tx) error { 1207 b, err := tx.CreateBucket([]byte("whozawhats")) 1208 if err != nil { 1209 t.Fatal(err) 1210 } 1211 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 1212 t.Fatal(err) 1213 } 1214 1215 return nil 1216 }); err != nil { 1217 t.Fatal(err) 1218 } 1219 1220 db.MustCheck() 1221 1222 if err := db.View(func(tx *bdb.Tx) error { 1223 b := tx.Bucket([]byte("whozawhats")) 1224 stats := b.Stats() 1225 if stats.BranchPageN != 0 { 1226 t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) 1227 } else if stats.BranchOverflowN != 0 { 1228 t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) 1229 } else if stats.LeafPageN != 0 { 1230 t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) 1231 } else if stats.LeafOverflowN != 0 { 1232 t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) 1233 } else if stats.KeyN != 1 { 1234 t.Fatalf("unexpected KeyN: %d", stats.KeyN) 1235 } else if stats.Depth != 1 { 1236 t.Fatalf("unexpected Depth: %d", stats.Depth) 1237 } else if stats.BranchInuse != 0 { 1238 t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) 1239 } else if stats.LeafInuse != 0 { 1240 t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) 1241 } 1242 1243 if db.Info().PageSize == 4096 { 1244 if stats.BranchAlloc != 0 { 1245 t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) 1246 } else if stats.LeafAlloc != 0 { 1247 t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) 1248 } 1249 } 1250 1251 if stats.BucketN != 1 { 1252 t.Fatalf("unexpected BucketN: %d", stats.BucketN) 1253 } else if stats.InlineBucketN != 1 { 1254 t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) 1255 } else if stats.InlineBucketInuse != 16+16+6 { 1256 t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) 1257 } 1258 1259 return nil 1260 }); err != nil { 1261 t.Fatal(err) 1262 } 1263 } 1264 1265 func TestBucket_Stats_EmptyBucket(t *testing.T) { 1266 db := MustOpenDB() 1267 defer db.MustClose() 1268 1269 if err := db.Update(func(tx *bdb.Tx) error { 1270 if _, err := tx.CreateBucket([]byte("whozawhats")); err != nil { 1271 t.Fatal(err) 1272 } 1273 return nil 1274 }); err != nil { 1275 t.Fatal(err) 1276 } 1277 1278 db.MustCheck() 1279 1280 if err := db.View(func(tx *bdb.Tx) error { 1281 b := tx.Bucket([]byte("whozawhats")) 1282 stats := b.Stats() 1283 if stats.BranchPageN != 0 { 1284 t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) 1285 } else if stats.BranchOverflowN != 0 { 1286 t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) 1287 } else if stats.LeafPageN != 0 { 1288 t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) 1289 } else if stats.LeafOverflowN != 0 { 1290 t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) 1291 } else if stats.KeyN != 0 { 1292 t.Fatalf("unexpected KeyN: %d", stats.KeyN) 1293 } else if stats.Depth != 1 { 1294 t.Fatalf("unexpected Depth: %d", stats.Depth) 1295 } else if stats.BranchInuse != 0 { 1296 t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) 1297 } else if stats.LeafInuse != 0 { 1298 t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) 1299 } 1300 1301 if db.Info().PageSize == 4096 { 1302 if stats.BranchAlloc != 0 { 1303 t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) 1304 } else if stats.LeafAlloc != 0 { 1305 t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) 1306 } 1307 } 1308 1309 if stats.BucketN != 1 { 1310 t.Fatalf("unexpected BucketN: %d", stats.BucketN) 1311 } else if stats.InlineBucketN != 1 { 1312 t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) 1313 } else if stats.InlineBucketInuse != 16 { 1314 t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) 1315 } 1316 1317 return nil 1318 }); err != nil { 1319 t.Fatal(err) 1320 } 1321 } 1322 1323 func TestBucket_Stats_Nested(t *testing.T) { 1324 db := MustOpenDB() 1325 defer db.MustClose() 1326 1327 if err := db.Update(func(tx *bdb.Tx) error { 1328 b, err := tx.CreateBucket([]byte("foo")) 1329 if err != nil { 1330 t.Fatal(err) 1331 } 1332 for i := 0; i < 100; i++ { 1333 if err := b.Put([]byte(fmt.Sprintf("%02d", i)), []byte(fmt.Sprintf("%02d", i))); err != nil { 1334 t.Fatal(err) 1335 } 1336 } 1337 1338 bar, err := b.CreateBucket([]byte("bar")) 1339 if err != nil { 1340 t.Fatal(err) 1341 } 1342 for i := 0; i < 10; i++ { 1343 if err := bar.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { 1344 t.Fatal(err) 1345 } 1346 } 1347 1348 baz, err := bar.CreateBucket([]byte("baz")) 1349 if err != nil { 1350 t.Fatal(err) 1351 } 1352 for i := 0; i < 10; i++ { 1353 if err := baz.Put([]byte(strconv.Itoa(i)), []byte(strconv.Itoa(i))); err != nil { 1354 t.Fatal(err) 1355 } 1356 } 1357 1358 return nil 1359 }); err != nil { 1360 t.Fatal(err) 1361 } 1362 1363 db.MustCheck() 1364 1365 if err := db.View(func(tx *bdb.Tx) error { 1366 b := tx.Bucket([]byte("foo")) 1367 stats := b.Stats() 1368 if stats.BranchPageN != 0 { 1369 t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) 1370 } else if stats.BranchOverflowN != 0 { 1371 t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) 1372 } else if stats.LeafPageN != 2 { 1373 t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) 1374 } else if stats.LeafOverflowN != 0 { 1375 t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) 1376 } else if stats.KeyN != 122 { 1377 t.Fatalf("unexpected KeyN: %d", stats.KeyN) 1378 } else if stats.Depth != 3 { 1379 t.Fatalf("unexpected Depth: %d", stats.Depth) 1380 } else if stats.BranchInuse != 0 { 1381 t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) 1382 } 1383 1384 foo := 16 1385 foo += 101 * 16 1386 foo += 100*2 + 100*2 1387 foo += 3 + 16 1388 1389 bar := 16 1390 bar += 11 * 16 1391 bar += 10 + 10 1392 bar += 3 + 16 1393 1394 baz := 16 1395 baz += 10 * 16 1396 baz += 10 + 10 1397 1398 if stats.LeafInuse != foo+bar+baz { 1399 t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) 1400 } 1401 1402 if db.Info().PageSize == 4096 { 1403 if stats.BranchAlloc != 0 { 1404 t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) 1405 } else if stats.LeafAlloc != 8192 { 1406 t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) 1407 } 1408 } 1409 1410 if stats.BucketN != 3 { 1411 t.Fatalf("unexpected BucketN: %d", stats.BucketN) 1412 } else if stats.InlineBucketN != 1 { 1413 t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) 1414 } else if stats.InlineBucketInuse != baz { 1415 t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) 1416 } 1417 1418 return nil 1419 }); err != nil { 1420 t.Fatal(err) 1421 } 1422 } 1423 1424 func No_TestBucket_Stats_Large(t *testing.T) { 1425 if testing.Short() { 1426 t.Skip("skipping test in short mode.") 1427 } 1428 1429 db := MustOpenDB() 1430 defer db.MustClose() 1431 1432 var index int 1433 for i := 0; i < 100; i++ { 1434 if err := db.Update(func(tx *bdb.Tx) error { 1435 b, err := tx.CreateBucketIfNotExists([]byte("widgets")) 1436 if err != nil { 1437 t.Fatal(err) 1438 } 1439 for i := 0; i < 1000; i++ { 1440 if err := b.Put([]byte(strconv.Itoa(index)), []byte(strconv.Itoa(index))); err != nil { 1441 t.Fatal(err) 1442 } 1443 index++ 1444 } 1445 return nil 1446 }); err != nil { 1447 t.Fatal(err) 1448 } 1449 } 1450 1451 db.MustCheck() 1452 1453 if err := db.View(func(tx *bdb.Tx) error { 1454 stats := tx.Bucket([]byte("widgets")).Stats() 1455 if stats.BranchPageN != 13 { 1456 t.Fatalf("unexpected BranchPageN: %d", stats.BranchPageN) 1457 } else if stats.BranchOverflowN != 0 { 1458 t.Fatalf("unexpected BranchOverflowN: %d", stats.BranchOverflowN) 1459 } else if stats.LeafPageN != 1196 { 1460 t.Fatalf("unexpected LeafPageN: %d", stats.LeafPageN) 1461 } else if stats.LeafOverflowN != 0 { 1462 t.Fatalf("unexpected LeafOverflowN: %d", stats.LeafOverflowN) 1463 } else if stats.KeyN != 100000 { 1464 t.Fatalf("unexpected KeyN: %d", stats.KeyN) 1465 } else if stats.Depth != 3 { 1466 t.Fatalf("unexpected Depth: %d", stats.Depth) 1467 } else if stats.BranchInuse != 25257 { 1468 t.Fatalf("unexpected BranchInuse: %d", stats.BranchInuse) 1469 } else if stats.LeafInuse != 2596916 { 1470 t.Fatalf("unexpected LeafInuse: %d", stats.LeafInuse) 1471 } 1472 1473 if db.Info().PageSize == 4096 { 1474 if stats.BranchAlloc != 53248 { 1475 t.Fatalf("unexpected BranchAlloc: %d", stats.BranchAlloc) 1476 } else if stats.LeafAlloc != 4898816 { 1477 t.Fatalf("unexpected LeafAlloc: %d", stats.LeafAlloc) 1478 } 1479 } 1480 1481 if stats.BucketN != 1 { 1482 t.Fatalf("unexpected BucketN: %d", stats.BucketN) 1483 } else if stats.InlineBucketN != 0 { 1484 t.Fatalf("unexpected InlineBucketN: %d", stats.InlineBucketN) 1485 } else if stats.InlineBucketInuse != 0 { 1486 t.Fatalf("unexpected InlineBucketInuse: %d", stats.InlineBucketInuse) 1487 } 1488 1489 return nil 1490 }); err != nil { 1491 t.Fatal(err) 1492 } 1493 } 1494 1495 func TestBucket_Put_Single(t *testing.T) { 1496 if testing.Short() { 1497 t.Skip("skipping test in short mode.") 1498 } 1499 1500 index := 0 1501 if err := quick.Check(func(items testdata) bool { 1502 db := MustOpenDB() 1503 defer db.MustClose() 1504 1505 m := make(map[string][]byte) 1506 1507 if err := db.Update(func(tx *bdb.Tx) error { 1508 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 1509 t.Fatal(err) 1510 } 1511 return nil 1512 }); err != nil { 1513 t.Fatal(err) 1514 } 1515 1516 for _, item := range items { 1517 if err := db.Update(func(tx *bdb.Tx) error { 1518 if err := tx.Bucket([]byte("widgets")).Put(item.Key, item.Value); err != nil { 1519 panic("put error: " + err.Error()) 1520 } 1521 m[string(item.Key)] = item.Value 1522 return nil 1523 }); err != nil { 1524 t.Fatal(err) 1525 } 1526 1527 if err := db.View(func(tx *bdb.Tx) error { 1528 i := 0 1529 for k, v := range m { 1530 value := tx.Bucket([]byte("widgets")).Get([]byte(k)) 1531 if !bytes.Equal(value, v) { 1532 t.Logf("value mismatch [run %d] (%d of %d):\nkey: %x\ngot: %x\nexp: %x", index, i, len(m), []byte(k), value, v) 1533 db.CopyTempFile() 1534 t.FailNow() 1535 } 1536 i++ 1537 } 1538 return nil 1539 }); err != nil { 1540 t.Fatal(err) 1541 } 1542 } 1543 1544 index++ 1545 return true 1546 }, qconfig()); err != nil { 1547 t.Error(err) 1548 } 1549 } 1550 1551 func TestBucket_Put_Multiple(t *testing.T) { 1552 if testing.Short() { 1553 t.Skip("skipping test in short mode.") 1554 } 1555 1556 if err := quick.Check(func(items testdata) bool { 1557 db := MustOpenDB() 1558 defer db.MustClose() 1559 1560 if err := db.Update(func(tx *bdb.Tx) error { 1561 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 1562 t.Fatal(err) 1563 } 1564 return nil 1565 }); err != nil { 1566 t.Fatal(err) 1567 } 1568 1569 if err := db.Update(func(tx *bdb.Tx) error { 1570 b := tx.Bucket([]byte("widgets")) 1571 for _, item := range items { 1572 if err := b.Put(item.Key, item.Value); err != nil { 1573 t.Fatal(err) 1574 } 1575 } 1576 return nil 1577 }); err != nil { 1578 t.Fatal(err) 1579 } 1580 1581 if err := db.View(func(tx *bdb.Tx) error { 1582 b := tx.Bucket([]byte("widgets")) 1583 for _, item := range items { 1584 value := b.Get(item.Key) 1585 if !bytes.Equal(item.Value, value) { 1586 db.CopyTempFile() 1587 t.Fatalf("exp=%x; got=%x", item.Value, value) 1588 } 1589 } 1590 return nil 1591 }); err != nil { 1592 t.Fatal(err) 1593 } 1594 1595 return true 1596 }, qconfig()); err != nil { 1597 t.Error(err) 1598 } 1599 } 1600 1601 func TestBucket_Delete_Quick(t *testing.T) { 1602 if testing.Short() { 1603 t.Skip("skipping test in short mode.") 1604 } 1605 1606 if err := quick.Check(func(items testdata) bool { 1607 db := MustOpenDB() 1608 defer db.MustClose() 1609 1610 if err := db.Update(func(tx *bdb.Tx) error { 1611 if _, err := tx.CreateBucket([]byte("widgets")); err != nil { 1612 t.Fatal(err) 1613 } 1614 return nil 1615 }); err != nil { 1616 t.Fatal(err) 1617 } 1618 1619 if err := db.Update(func(tx *bdb.Tx) error { 1620 b := tx.Bucket([]byte("widgets")) 1621 for _, item := range items { 1622 if err := b.Put(item.Key, item.Value); err != nil { 1623 t.Fatal(err) 1624 } 1625 } 1626 return nil 1627 }); err != nil { 1628 t.Fatal(err) 1629 } 1630 1631 for _, item := range items { 1632 if err := db.Update(func(tx *bdb.Tx) error { 1633 return tx.Bucket([]byte("widgets")).Delete(item.Key) 1634 }); err != nil { 1635 t.Fatal(err) 1636 } 1637 } 1638 1639 if err := db.View(func(tx *bdb.Tx) error { 1640 if err := tx.Bucket([]byte("widgets")).ForEach(func(k, v []byte) error { 1641 t.Fatalf("bucket should be empty; found: %06x", trunc(k, 3)) 1642 return nil 1643 }); err != nil { 1644 t.Fatal(err) 1645 } 1646 return nil 1647 }); err != nil { 1648 t.Fatal(err) 1649 } 1650 1651 return true 1652 }, qconfig()); err != nil { 1653 t.Error(err) 1654 } 1655 } 1656 1657 func ExampleBucket_Put() { 1658 db, err := bdb.Open(tempfile(), nil) 1659 if err != nil { 1660 log.Fatal(err) 1661 } 1662 defer os.Remove(db.Path()) 1663 1664 if err := db.Update(func(tx *bdb.Tx) error { 1665 b, err := tx.CreateBucket([]byte("widgets")) 1666 if err != nil { 1667 return err 1668 } 1669 1670 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 1671 return err 1672 } 1673 return nil 1674 }); err != nil { 1675 log.Fatal(err) 1676 } 1677 1678 if err := db.View(func(tx *bdb.Tx) error { 1679 value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) 1680 fmt.Printf("The value of 'foo' is: %s\n", value) 1681 return nil 1682 }); err != nil { 1683 log.Fatal(err) 1684 } 1685 1686 if err := db.Close(); err != nil { 1687 log.Fatal(err) 1688 } 1689 } 1690 1691 func ExampleBucket_Delete() { 1692 db, err := bdb.Open(tempfile(), nil) 1693 if err != nil { 1694 log.Fatal(err) 1695 } 1696 defer os.Remove(db.Path()) 1697 1698 if err := db.Update(func(tx *bdb.Tx) error { 1699 b, err := tx.CreateBucket([]byte("widgets")) 1700 if err != nil { 1701 return err 1702 } 1703 1704 if err := b.Put([]byte("foo"), []byte("bar")); err != nil { 1705 return err 1706 } 1707 1708 value := b.Get([]byte("foo")) 1709 fmt.Printf("The value of 'foo' was: %s\n", value) 1710 1711 return nil 1712 }); err != nil { 1713 log.Fatal(err) 1714 } 1715 1716 if err := db.Update(func(tx *bdb.Tx) error { 1717 return tx.Bucket([]byte("widgets")).Delete([]byte("foo")) 1718 }); err != nil { 1719 log.Fatal(err) 1720 } 1721 1722 if err := db.View(func(tx *bdb.Tx) error { 1723 value := tx.Bucket([]byte("widgets")).Get([]byte("foo")) 1724 if value == nil { 1725 fmt.Printf("The value of 'foo' is now: nil\n") 1726 } 1727 return nil 1728 }); err != nil { 1729 log.Fatal(err) 1730 } 1731 1732 if err := db.Close(); err != nil { 1733 log.Fatal(err) 1734 } 1735 } 1736 1737 func ExampleBucket_ForEach() { 1738 db, err := bdb.Open(tempfile(), nil) 1739 if err != nil { 1740 log.Fatal(err) 1741 } 1742 defer os.Remove(db.Path()) 1743 1744 if err := db.Update(func(tx *bdb.Tx) error { 1745 b, err := tx.CreateBucket([]byte("animals")) 1746 if err != nil { 1747 return err 1748 } 1749 1750 if err := b.Put([]byte("dog"), []byte("fun")); err != nil { 1751 return err 1752 } 1753 if err := b.Put([]byte("cat"), []byte("lame")); err != nil { 1754 return err 1755 } 1756 if err := b.Put([]byte("liger"), []byte("awesome")); err != nil { 1757 return err 1758 } 1759 1760 if err := b.ForEach(func(k, v []byte) error { 1761 fmt.Printf("A %s is %s.\n", k, v) 1762 return nil 1763 }); err != nil { 1764 return err 1765 } 1766 1767 return nil 1768 }); err != nil { 1769 log.Fatal(err) 1770 } 1771 1772 if err := db.Close(); err != nil { 1773 log.Fatal(err) 1774 } 1775 }