Skip to content

Commit bca8641

Browse files
committed
add bucket content verification
1 parent 1104182 commit bca8641

File tree

2 files changed

+110
-8
lines changed

2 files changed

+110
-8
lines changed

bucket.go

+4
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,10 @@ func (b *Bucket) write() []byte {
739739
return value
740740
}
741741

742+
func (b *Bucket) Write() []byte {
743+
return b.write()
744+
}
745+
742746
// rebalance attempts to balance all nodes.
743747
func (b *Bucket) rebalance() {
744748
for _, n := range b.nodes {

bucket_test.go

+106-8
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ func TestBucket_MoveBucket2(t *testing.T) {
475475
{
476476
name: "happy path",
477477
srcBucketPath: []string{"x", "y", "z"},
478-
dstBucketPath: []string{"x", "y"},
478+
dstBucketPath: []string{"a", "b"},
479479
isInlined: false,
480480
expErr: nil,
481481
},
@@ -484,10 +484,64 @@ func TestBucket_MoveBucket2(t *testing.T) {
484484
for _, tc := range testCases {
485485
t.Run(tc.name, func(*testing.T) {
486486
db := btesting.MustCreateDB(t)
487-
if err := db.Update(func(tx *bolt.Tx) error {
488487

488+
// arrange
489+
if err := db.Update(func(tx *bolt.Tx) error {
489490
bk := createBucketIfNotExist(t, tx, tc.srcBucketPath...)
490-
insertRandKeysValuesBucket(t, bk, rand.Int())
491+
insertRandKeysValuesBucket(t, bk, rand.Intn(4096))
492+
createBucketIfNotExist(t, tx, tc.dstBucketPath...)
493+
494+
return nil
495+
}); err != nil {
496+
t.Fatal(err)
497+
}
498+
db.MustCheck()
499+
500+
// act
501+
var tmpFile string
502+
if err := db.Update(func(tx *bolt.Tx) error {
503+
srcBucket := retrieveParentBucket(t, tx, tc.srcBucketPath...)
504+
dstBucket := retrieveChildBucket(t, tx, tc.dstBucketPath...)
505+
bucketToMove := tc.srcBucketPath[len(tc.srcBucketPath)-1]
506+
507+
// dump bucketToMove to bbolt file for assertion
508+
bk := srcBucket.Bucket([]byte(bucketToMove))
509+
tmpFile = dumpBucketToFile(t, bk)
510+
511+
mErr := srcBucket.MoveBucket([]byte(bucketToMove), dstBucket)
512+
require.Equal(t, tc.expErr, mErr)
513+
514+
return nil
515+
}); err != nil {
516+
t.Fatal(err)
517+
}
518+
db.MustCheck()
519+
520+
// assert
521+
if err := db.View(func(tx *bolt.Tx) error {
522+
srcBucket := retrieveParentBucket(t, tx, tc.srcBucketPath...)
523+
bucketToMove := tc.srcBucketPath[len(tc.srcBucketPath)-1]
524+
525+
if bk := srcBucket.Bucket([]byte(bucketToMove)); bk != nil {
526+
t.Fatalf("expected childBucket %v to be moved from srcBucket %v", bucketToMove, srcBucket)
527+
}
528+
529+
dstBucket := retrieveChildBucket(t, tx, tc.dstBucketPath...)
530+
if bk := dstBucket.Bucket([]byte(bucketToMove)); bk == nil {
531+
t.Fatalf("expected childBucket %v to be child of dstBucket %v", bucketToMove, dstBucket)
532+
}
533+
534+
childBucket := dstBucket.Bucket([]byte(bucketToMove))
535+
if childBucket == nil {
536+
t.Fatalf("expected subBucket %v to exist within dstBucket %v", bucketToMove, dstBucket)
537+
}
538+
539+
bucketOnDisk, err := os.ReadFile(tmpFile)
540+
if err != nil {
541+
t.Fatalf("error reading tmp file %v", tmpFile)
542+
}
543+
544+
require.Equal(t, bucketOnDisk, childBucket.Write())
491545

492546
return nil
493547
}); err != nil {
@@ -507,16 +561,57 @@ func createBucketIfNotExist(t testing.TB, tx *bolt.Tx, paths ...string) *bolt.Bu
507561

508562
for _, key := range paths[1:] {
509563
bk, err = bk.CreateBucketIfNotExists([]byte(key))
510-
t.Fatalf("error creating bucket %v: %v", key, err)
564+
if err != nil {
565+
t.Fatalf("error creating bucket %v: %v", key, err)
566+
}
511567
}
512568

513569
return bk
514570
}
515571

572+
func retrieveParentBucket(t testing.TB, tx *bolt.Tx, paths ...string) *bolt.Bucket {
573+
paths = paths[:len(paths)-1]
574+
return retrieveChildBucket(t, tx, paths...)
575+
}
576+
577+
func retrieveChildBucket(t testing.TB, tx *bolt.Tx, paths ...string) *bolt.Bucket {
578+
t.Helper()
579+
580+
var bk *bolt.Bucket = nil
581+
for _, path := range paths {
582+
if bk == nil {
583+
bk = tx.Bucket([]byte(path))
584+
} else {
585+
bk = bk.Bucket([]byte(path))
586+
}
587+
if bk == nil {
588+
t.Fatalf("error retrieving bucket %v within paths %v", path, strings.TrimSuffix(strings.Join(paths, "->"), "->"))
589+
}
590+
}
591+
return bk
592+
}
593+
594+
func dumpBucketToFile(t testing.TB, bk *bolt.Bucket) string {
595+
tmpFile := tempfile()
596+
f, err := os.Create(tmpFile)
597+
if err != nil {
598+
t.Fatalf("error creating tmp file %v: %v", tmpFile, err)
599+
}
600+
defer f.Close()
601+
602+
data := bk.Write()
603+
_, err = f.Write(data)
604+
if err != nil {
605+
t.Fatalf("error writing bucket %v to file %v tmpFile", bk, tmpFile)
606+
}
607+
608+
return tmpFile
609+
}
610+
516611
func insertRandKeysValuesBucket(t testing.TB, bk *bolt.Bucket, n int) {
517612

518-
var min, max = 1, 1024
519613
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
614+
var min, max = 1, 1024
520615

521616
for i := 0; i < n; i++ {
522617
// generate rand key/value length
@@ -526,9 +621,12 @@ func insertRandKeysValuesBucket(t testing.TB, bk *bolt.Bucket, n int) {
526621
keyData := make([]rune, keyLength)
527622
valData := make([]rune, valLength)
528623

529-
for i := range keyData {
530-
keyData[i] = letters[rand.Intn(len(letters))]
531-
valData[i] = letters[rand.Intn(len(letters))]
624+
for j := range keyData {
625+
keyData[j] = letters[rand.Intn(len(letters))]
626+
}
627+
628+
for j := range valData {
629+
valData[j] = letters[rand.Intn(len(letters))]
532630
}
533631

534632
pErr := bk.Put([]byte(string(keyData)), []byte(string(valData)))

0 commit comments

Comments
 (0)