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