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  }