1 package bbolt_test
2
3 import (
4 "bytes"
5 "encoding/binary"
6 "fmt"
7 "log"
8 "os"
9 "reflect"
10 "sort"
11 "testing"
12 "testing/quick"
13
14 bolt "go.etcd.io/bbolt"
15 "go.etcd.io/bbolt/internal/btesting"
16 )
17
18
19 func TestCursor_Bucket(t *testing.T) {
20 db := btesting.MustCreateDB(t)
21 if err := db.Update(func(tx *bolt.Tx) error {
22 b, err := tx.CreateBucket([]byte("widgets"))
23 if err != nil {
24 t.Fatal(err)
25 }
26 if cb := b.Cursor().Bucket(); !reflect.DeepEqual(cb, b) {
27 t.Fatal("cursor bucket mismatch")
28 }
29 return nil
30 }); err != nil {
31 t.Fatal(err)
32 }
33 }
34
35
36 func TestCursor_Seek(t *testing.T) {
37 db := btesting.MustCreateDB(t)
38 if err := db.Update(func(tx *bolt.Tx) error {
39 b, err := tx.CreateBucket([]byte("widgets"))
40 if err != nil {
41 t.Fatal(err)
42 }
43 if err := b.Put([]byte("foo"), []byte("0001")); err != nil {
44 t.Fatal(err)
45 }
46 if err := b.Put([]byte("bar"), []byte("0002")); err != nil {
47 t.Fatal(err)
48 }
49 if err := b.Put([]byte("baz"), []byte("0003")); err != nil {
50 t.Fatal(err)
51 }
52
53 if _, err := b.CreateBucket([]byte("bkt")); err != nil {
54 t.Fatal(err)
55 }
56 return nil
57 }); err != nil {
58 t.Fatal(err)
59 }
60
61 if err := db.View(func(tx *bolt.Tx) error {
62 c := tx.Bucket([]byte("widgets")).Cursor()
63
64
65 if k, v := c.Seek([]byte("bar")); !bytes.Equal(k, []byte("bar")) {
66 t.Fatalf("unexpected key: %v", k)
67 } else if !bytes.Equal(v, []byte("0002")) {
68 t.Fatalf("unexpected value: %v", v)
69 }
70
71
72 if k, v := c.Seek([]byte("bas")); !bytes.Equal(k, []byte("baz")) {
73 t.Fatalf("unexpected key: %v", k)
74 } else if !bytes.Equal(v, []byte("0003")) {
75 t.Fatalf("unexpected value: %v", v)
76 }
77
78
79 if k, v := c.Seek([]byte("")); !bytes.Equal(k, []byte("bar")) {
80 t.Fatalf("unexpected key: %v", k)
81 } else if !bytes.Equal(v, []byte("0002")) {
82 t.Fatalf("unexpected value: %v", v)
83 }
84
85
86 if k, v := c.Seek([]byte("zzz")); k != nil {
87 t.Fatalf("expected nil key: %v", k)
88 } else if v != nil {
89 t.Fatalf("expected nil value: %v", v)
90 }
91
92
93 if k, v := c.Seek([]byte("bkt")); !bytes.Equal(k, []byte("bkt")) {
94 t.Fatalf("unexpected key: %v", k)
95 } else if v != nil {
96 t.Fatalf("expected nil value: %v", v)
97 }
98
99 return nil
100 }); err != nil {
101 t.Fatal(err)
102 }
103 }
104
105 func TestCursor_Delete(t *testing.T) {
106 db := btesting.MustCreateDB(t)
107
108 const count = 1000
109
110
111 if err := db.Update(func(tx *bolt.Tx) error {
112 b, err := tx.CreateBucket([]byte("widgets"))
113 if err != nil {
114 t.Fatal(err)
115 }
116 for i := 0; i < count; i += 1 {
117 k := make([]byte, 8)
118 binary.BigEndian.PutUint64(k, uint64(i))
119 if err := b.Put(k, make([]byte, 100)); err != nil {
120 t.Fatal(err)
121 }
122 }
123 if _, err := b.CreateBucket([]byte("sub")); err != nil {
124 t.Fatal(err)
125 }
126 return nil
127 }); err != nil {
128 t.Fatal(err)
129 }
130
131 if err := db.Update(func(tx *bolt.Tx) error {
132 c := tx.Bucket([]byte("widgets")).Cursor()
133 bound := make([]byte, 8)
134 binary.BigEndian.PutUint64(bound, uint64(count/2))
135 for key, _ := c.First(); bytes.Compare(key, bound) < 0; key, _ = c.Next() {
136 if err := c.Delete(); err != nil {
137 t.Fatal(err)
138 }
139 }
140
141 c.Seek([]byte("sub"))
142 if err := c.Delete(); err != bolt.ErrIncompatibleValue {
143 t.Fatalf("unexpected error: %s", err)
144 }
145
146 return nil
147 }); err != nil {
148 t.Fatal(err)
149 }
150
151 if err := db.View(func(tx *bolt.Tx) error {
152 stats := tx.Bucket([]byte("widgets")).Stats()
153 if stats.KeyN != count/2+1 {
154 t.Fatalf("unexpected KeyN: %d", stats.KeyN)
155 }
156 return nil
157 }); err != nil {
158 t.Fatal(err)
159 }
160 }
161
162
163
164
165
166
167 func TestCursor_Seek_Large(t *testing.T) {
168 db := btesting.MustCreateDB(t)
169
170 var count = 10000
171
172
173 if err := db.Update(func(tx *bolt.Tx) error {
174 b, err := tx.CreateBucket([]byte("widgets"))
175 if err != nil {
176 t.Fatal(err)
177 }
178
179 for i := 0; i < count; i += 100 {
180 for j := i; j < i+100; j += 2 {
181 k := make([]byte, 8)
182 binary.BigEndian.PutUint64(k, uint64(j))
183 if err := b.Put(k, make([]byte, 100)); err != nil {
184 t.Fatal(err)
185 }
186 }
187 }
188 return nil
189 }); err != nil {
190 t.Fatal(err)
191 }
192
193 if err := db.View(func(tx *bolt.Tx) error {
194 c := tx.Bucket([]byte("widgets")).Cursor()
195 for i := 0; i < count; i++ {
196 seek := make([]byte, 8)
197 binary.BigEndian.PutUint64(seek, uint64(i))
198
199 k, _ := c.Seek(seek)
200
201
202
203 if i == count-1 {
204 if k != nil {
205 t.Fatal("expected nil key")
206 }
207 continue
208 }
209
210
211 num := binary.BigEndian.Uint64(k)
212 if i%2 == 0 {
213 if num != uint64(i) {
214 t.Fatalf("unexpected num: %d", num)
215 }
216 } else {
217 if num != uint64(i+1) {
218 t.Fatalf("unexpected num: %d", num)
219 }
220 }
221 }
222
223 return nil
224 }); err != nil {
225 t.Fatal(err)
226 }
227 }
228
229
230 func TestCursor_EmptyBucket(t *testing.T) {
231 db := btesting.MustCreateDB(t)
232 if err := db.Update(func(tx *bolt.Tx) error {
233 _, err := tx.CreateBucket([]byte("widgets"))
234 return err
235 }); err != nil {
236 t.Fatal(err)
237 }
238
239 if err := db.View(func(tx *bolt.Tx) error {
240 c := tx.Bucket([]byte("widgets")).Cursor()
241 k, v := c.First()
242 if k != nil {
243 t.Fatalf("unexpected key: %v", k)
244 } else if v != nil {
245 t.Fatalf("unexpected value: %v", v)
246 }
247 return nil
248 }); err != nil {
249 t.Fatal(err)
250 }
251 }
252
253
254 func TestCursor_EmptyBucketReverse(t *testing.T) {
255 db := btesting.MustCreateDB(t)
256
257 if err := db.Update(func(tx *bolt.Tx) error {
258 _, err := tx.CreateBucket([]byte("widgets"))
259 return err
260 }); err != nil {
261 t.Fatal(err)
262 }
263 if err := db.View(func(tx *bolt.Tx) error {
264 c := tx.Bucket([]byte("widgets")).Cursor()
265 k, v := c.Last()
266 if k != nil {
267 t.Fatalf("unexpected key: %v", k)
268 } else if v != nil {
269 t.Fatalf("unexpected value: %v", v)
270 }
271 return nil
272 }); err != nil {
273 t.Fatal(err)
274 }
275 }
276
277
278 func TestCursor_Iterate_Leaf(t *testing.T) {
279 db := btesting.MustCreateDB(t)
280
281 if err := db.Update(func(tx *bolt.Tx) error {
282 b, err := tx.CreateBucket([]byte("widgets"))
283 if err != nil {
284 t.Fatal(err)
285 }
286 if err := b.Put([]byte("baz"), []byte{}); err != nil {
287 t.Fatal(err)
288 }
289 if err := b.Put([]byte("foo"), []byte{0}); err != nil {
290 t.Fatal(err)
291 }
292 if err := b.Put([]byte("bar"), []byte{1}); err != nil {
293 t.Fatal(err)
294 }
295 return nil
296 }); err != nil {
297 t.Fatal(err)
298 }
299 tx, err := db.Begin(false)
300 if err != nil {
301 t.Fatal(err)
302 }
303 defer func() { _ = tx.Rollback() }()
304
305 c := tx.Bucket([]byte("widgets")).Cursor()
306
307 k, v := c.First()
308 if !bytes.Equal(k, []byte("bar")) {
309 t.Fatalf("unexpected key: %v", k)
310 } else if !bytes.Equal(v, []byte{1}) {
311 t.Fatalf("unexpected value: %v", v)
312 }
313
314 k, v = c.Next()
315 if !bytes.Equal(k, []byte("baz")) {
316 t.Fatalf("unexpected key: %v", k)
317 } else if !bytes.Equal(v, []byte{}) {
318 t.Fatalf("unexpected value: %v", v)
319 }
320
321 k, v = c.Next()
322 if !bytes.Equal(k, []byte("foo")) {
323 t.Fatalf("unexpected key: %v", k)
324 } else if !bytes.Equal(v, []byte{0}) {
325 t.Fatalf("unexpected value: %v", v)
326 }
327
328 k, v = c.Next()
329 if k != nil {
330 t.Fatalf("expected nil key: %v", k)
331 } else if v != nil {
332 t.Fatalf("expected nil value: %v", v)
333 }
334
335 k, v = c.Next()
336 if k != nil {
337 t.Fatalf("expected nil key: %v", k)
338 } else if v != nil {
339 t.Fatalf("expected nil value: %v", v)
340 }
341
342 if err := tx.Rollback(); err != nil {
343 t.Fatal(err)
344 }
345 }
346
347
348 func TestCursor_LeafRootReverse(t *testing.T) {
349 db := btesting.MustCreateDB(t)
350
351 if err := db.Update(func(tx *bolt.Tx) error {
352 b, err := tx.CreateBucket([]byte("widgets"))
353 if err != nil {
354 t.Fatal(err)
355 }
356 if err := b.Put([]byte("baz"), []byte{}); err != nil {
357 t.Fatal(err)
358 }
359 if err := b.Put([]byte("foo"), []byte{0}); err != nil {
360 t.Fatal(err)
361 }
362 if err := b.Put([]byte("bar"), []byte{1}); err != nil {
363 t.Fatal(err)
364 }
365 return nil
366 }); err != nil {
367 t.Fatal(err)
368 }
369 tx, err := db.Begin(false)
370 if err != nil {
371 t.Fatal(err)
372 }
373 c := tx.Bucket([]byte("widgets")).Cursor()
374
375 if k, v := c.Last(); !bytes.Equal(k, []byte("foo")) {
376 t.Fatalf("unexpected key: %v", k)
377 } else if !bytes.Equal(v, []byte{0}) {
378 t.Fatalf("unexpected value: %v", v)
379 }
380
381 if k, v := c.Prev(); !bytes.Equal(k, []byte("baz")) {
382 t.Fatalf("unexpected key: %v", k)
383 } else if !bytes.Equal(v, []byte{}) {
384 t.Fatalf("unexpected value: %v", v)
385 }
386
387 if k, v := c.Prev(); !bytes.Equal(k, []byte("bar")) {
388 t.Fatalf("unexpected key: %v", k)
389 } else if !bytes.Equal(v, []byte{1}) {
390 t.Fatalf("unexpected value: %v", v)
391 }
392
393 if k, v := c.Prev(); k != nil {
394 t.Fatalf("expected nil key: %v", k)
395 } else if v != nil {
396 t.Fatalf("expected nil value: %v", v)
397 }
398
399 if k, v := c.Prev(); k != nil {
400 t.Fatalf("expected nil key: %v", k)
401 } else if v != nil {
402 t.Fatalf("expected nil value: %v", v)
403 }
404
405 if err := tx.Rollback(); err != nil {
406 t.Fatal(err)
407 }
408 }
409
410
411 func TestCursor_Restart(t *testing.T) {
412 db := btesting.MustCreateDB(t)
413
414 if err := db.Update(func(tx *bolt.Tx) error {
415 b, err := tx.CreateBucket([]byte("widgets"))
416 if err != nil {
417 t.Fatal(err)
418 }
419 if err := b.Put([]byte("bar"), []byte{}); err != nil {
420 t.Fatal(err)
421 }
422 if err := b.Put([]byte("foo"), []byte{}); err != nil {
423 t.Fatal(err)
424 }
425 return nil
426 }); err != nil {
427 t.Fatal(err)
428 }
429
430 tx, err := db.Begin(false)
431 if err != nil {
432 t.Fatal(err)
433 }
434 c := tx.Bucket([]byte("widgets")).Cursor()
435
436 if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) {
437 t.Fatalf("unexpected key: %v", k)
438 }
439 if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) {
440 t.Fatalf("unexpected key: %v", k)
441 }
442
443 if k, _ := c.First(); !bytes.Equal(k, []byte("bar")) {
444 t.Fatalf("unexpected key: %v", k)
445 }
446 if k, _ := c.Next(); !bytes.Equal(k, []byte("foo")) {
447 t.Fatalf("unexpected key: %v", k)
448 }
449
450 if err := tx.Rollback(); err != nil {
451 t.Fatal(err)
452 }
453 }
454
455
456 func TestCursor_First_EmptyPages(t *testing.T) {
457 db := btesting.MustCreateDB(t)
458
459
460 if err := db.Update(func(tx *bolt.Tx) error {
461 b, err := tx.CreateBucket([]byte("widgets"))
462 if err != nil {
463 t.Fatal(err)
464 }
465
466 for i := 0; i < 1000; i++ {
467 if err := b.Put(u64tob(uint64(i)), []byte{}); err != nil {
468 t.Fatal(err)
469 }
470 }
471
472 return nil
473 }); err != nil {
474 t.Fatal(err)
475 }
476
477
478 if err := db.Update(func(tx *bolt.Tx) error {
479 b := tx.Bucket([]byte("widgets"))
480 for i := 0; i < 600; i++ {
481 if err := b.Delete(u64tob(uint64(i))); err != nil {
482 t.Fatal(err)
483 }
484 }
485
486 c := b.Cursor()
487 var n int
488 for k, _ := c.First(); k != nil; k, _ = c.Next() {
489 n++
490 }
491 if n != 400 {
492 t.Fatalf("unexpected key count: %d", n)
493 }
494
495 return nil
496 }); err != nil {
497 t.Fatal(err)
498 }
499 }
500
501
502 func TestCursor_Last_EmptyPages(t *testing.T) {
503 db := btesting.MustCreateDB(t)
504
505
506 if err := db.Update(func(tx *bolt.Tx) error {
507 b, err := tx.CreateBucket([]byte("widgets"))
508 if err != nil {
509 t.Fatal(err)
510 }
511
512 for i := 0; i < 1000; i++ {
513 if err := b.Put(u64tob(uint64(i)), []byte{}); err != nil {
514 t.Fatal(err)
515 }
516 }
517
518 return nil
519 }); err != nil {
520 t.Fatal(err)
521 }
522
523
524 if err := db.Update(func(tx *bolt.Tx) error {
525 b := tx.Bucket([]byte("widgets"))
526 for i := 200; i < 1000; i++ {
527 if err := b.Delete(u64tob(uint64(i))); err != nil {
528 t.Fatal(err)
529 }
530 }
531
532 c := b.Cursor()
533 var n int
534 for k, _ := c.Last(); k != nil; k, _ = c.Prev() {
535 n++
536 }
537 if n != 200 {
538 t.Fatalf("unexpected key count: %d", n)
539 }
540
541 return nil
542 }); err != nil {
543 t.Fatal(err)
544 }
545 }
546
547
548 func TestCursor_QuickCheck(t *testing.T) {
549 f := func(items testdata) bool {
550 db := btesting.MustCreateDB(t)
551 defer db.MustClose()
552
553
554 tx, err := db.Begin(true)
555 if err != nil {
556 t.Fatal(err)
557 }
558 b, err := tx.CreateBucket([]byte("widgets"))
559 if err != nil {
560 t.Fatal(err)
561 }
562 for _, item := range items {
563 if err := b.Put(item.Key, item.Value); err != nil {
564 t.Fatal(err)
565 }
566 }
567 if err := tx.Commit(); err != nil {
568 t.Fatal(err)
569 }
570
571
572 sort.Sort(items)
573
574
575 var index = 0
576 tx, err = db.Begin(false)
577 if err != nil {
578 t.Fatal(err)
579 }
580
581 c := tx.Bucket([]byte("widgets")).Cursor()
582 for k, v := c.First(); k != nil && index < len(items); k, v = c.Next() {
583 if !bytes.Equal(k, items[index].Key) {
584 t.Fatalf("unexpected key: %v", k)
585 } else if !bytes.Equal(v, items[index].Value) {
586 t.Fatalf("unexpected value: %v", v)
587 }
588 index++
589 }
590 if len(items) != index {
591 t.Fatalf("unexpected item count: %v, expected %v", len(items), index)
592 }
593
594 if err := tx.Rollback(); err != nil {
595 t.Fatal(err)
596 }
597
598 return true
599 }
600 if err := quick.Check(f, qconfig()); err != nil {
601 t.Error(err)
602 }
603 }
604
605
606 func TestCursor_QuickCheck_Reverse(t *testing.T) {
607 f := func(items testdata) bool {
608 db := btesting.MustCreateDB(t)
609 defer db.MustClose()
610
611
612 tx, err := db.Begin(true)
613 if err != nil {
614 t.Fatal(err)
615 }
616 b, err := tx.CreateBucket([]byte("widgets"))
617 if err != nil {
618 t.Fatal(err)
619 }
620 for _, item := range items {
621 if err := b.Put(item.Key, item.Value); err != nil {
622 t.Fatal(err)
623 }
624 }
625 if err := tx.Commit(); err != nil {
626 t.Fatal(err)
627 }
628
629
630 sort.Sort(revtestdata(items))
631
632
633 var index = 0
634 tx, err = db.Begin(false)
635 if err != nil {
636 t.Fatal(err)
637 }
638 c := tx.Bucket([]byte("widgets")).Cursor()
639 for k, v := c.Last(); k != nil && index < len(items); k, v = c.Prev() {
640 if !bytes.Equal(k, items[index].Key) {
641 t.Fatalf("unexpected key: %v", k)
642 } else if !bytes.Equal(v, items[index].Value) {
643 t.Fatalf("unexpected value: %v", v)
644 }
645 index++
646 }
647 if len(items) != index {
648 t.Fatalf("unexpected item count: %v, expected %v", len(items), index)
649 }
650
651 if err := tx.Rollback(); err != nil {
652 t.Fatal(err)
653 }
654
655 return true
656 }
657 if err := quick.Check(f, qconfig()); err != nil {
658 t.Error(err)
659 }
660 }
661
662
663 func TestCursor_QuickCheck_BucketsOnly(t *testing.T) {
664 db := btesting.MustCreateDB(t)
665
666 if err := db.Update(func(tx *bolt.Tx) error {
667 b, err := tx.CreateBucket([]byte("widgets"))
668 if err != nil {
669 t.Fatal(err)
670 }
671 if _, err := b.CreateBucket([]byte("foo")); err != nil {
672 t.Fatal(err)
673 }
674 if _, err := b.CreateBucket([]byte("bar")); err != nil {
675 t.Fatal(err)
676 }
677 if _, err := b.CreateBucket([]byte("baz")); err != nil {
678 t.Fatal(err)
679 }
680 return nil
681 }); err != nil {
682 t.Fatal(err)
683 }
684
685 if err := db.View(func(tx *bolt.Tx) error {
686 var names []string
687 c := tx.Bucket([]byte("widgets")).Cursor()
688 for k, v := c.First(); k != nil; k, v = c.Next() {
689 names = append(names, string(k))
690 if v != nil {
691 t.Fatalf("unexpected value: %v", v)
692 }
693 }
694 if !reflect.DeepEqual(names, []string{"bar", "baz", "foo"}) {
695 t.Fatalf("unexpected names: %+v", names)
696 }
697 return nil
698 }); err != nil {
699 t.Fatal(err)
700 }
701 }
702
703
704 func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) {
705 db := btesting.MustCreateDB(t)
706
707 if err := db.Update(func(tx *bolt.Tx) error {
708 b, err := tx.CreateBucket([]byte("widgets"))
709 if err != nil {
710 t.Fatal(err)
711 }
712 if _, err := b.CreateBucket([]byte("foo")); err != nil {
713 t.Fatal(err)
714 }
715 if _, err := b.CreateBucket([]byte("bar")); err != nil {
716 t.Fatal(err)
717 }
718 if _, err := b.CreateBucket([]byte("baz")); err != nil {
719 t.Fatal(err)
720 }
721 return nil
722 }); err != nil {
723 t.Fatal(err)
724 }
725
726 if err := db.View(func(tx *bolt.Tx) error {
727 var names []string
728 c := tx.Bucket([]byte("widgets")).Cursor()
729 for k, v := c.Last(); k != nil; k, v = c.Prev() {
730 names = append(names, string(k))
731 if v != nil {
732 t.Fatalf("unexpected value: %v", v)
733 }
734 }
735 if !reflect.DeepEqual(names, []string{"foo", "baz", "bar"}) {
736 t.Fatalf("unexpected names: %+v", names)
737 }
738 return nil
739 }); err != nil {
740 t.Fatal(err)
741 }
742 }
743
744 func ExampleCursor() {
745
746 db, err := bolt.Open(tempfile(), 0666, nil)
747 if err != nil {
748 log.Fatal(err)
749 }
750 defer os.Remove(db.Path())
751
752
753 if err := db.Update(func(tx *bolt.Tx) error {
754
755 b, err := tx.CreateBucket([]byte("animals"))
756 if err != nil {
757 return err
758 }
759
760
761 if err := b.Put([]byte("dog"), []byte("fun")); err != nil {
762 log.Fatal(err)
763 }
764 if err := b.Put([]byte("cat"), []byte("lame")); err != nil {
765 log.Fatal(err)
766 }
767 if err := b.Put([]byte("liger"), []byte("awesome")); err != nil {
768 log.Fatal(err)
769 }
770
771
772 c := b.Cursor()
773
774
775
776
777
778
779 for k, v := c.First(); k != nil; k, v = c.Next() {
780 fmt.Printf("A %s is %s.\n", k, v)
781 }
782
783 return nil
784 }); err != nil {
785 log.Fatal(err)
786 }
787
788 if err := db.Close(); err != nil {
789 log.Fatal(err)
790 }
791
792
793
794
795
796 }
797
798 func ExampleCursor_reverse() {
799
800 db, err := bolt.Open(tempfile(), 0666, nil)
801 if err != nil {
802 log.Fatal(err)
803 }
804 defer os.Remove(db.Path())
805
806
807 if err := db.Update(func(tx *bolt.Tx) error {
808
809 b, err := tx.CreateBucket([]byte("animals"))
810 if err != nil {
811 return err
812 }
813
814
815 if err := b.Put([]byte("dog"), []byte("fun")); err != nil {
816 log.Fatal(err)
817 }
818 if err := b.Put([]byte("cat"), []byte("lame")); err != nil {
819 log.Fatal(err)
820 }
821 if err := b.Put([]byte("liger"), []byte("awesome")); err != nil {
822 log.Fatal(err)
823 }
824
825
826 c := b.Cursor()
827
828
829
830
831
832
833
834 for k, v := c.Last(); k != nil; k, v = c.Prev() {
835 fmt.Printf("A %s is %s.\n", k, v)
836 }
837
838 return nil
839 }); err != nil {
840 log.Fatal(err)
841 }
842
843
844 if err := db.Close(); err != nil {
845 log.Fatal(err)
846 }
847
848
849
850
851
852 }
853
View as plain text