Skip to content

Commit 5078179

Browse files
committed
add test check page
Signed-off-by: Mustafa Elbehery <melbeher@redhat.com>
1 parent c1eb992 commit 5078179

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

tx_test.go

+98
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ package bbolt_test
22

33
import (
44
"bytes"
5+
crand "crypto/rand"
56
"errors"
67
"fmt"
8+
"go.etcd.io/bbolt/internal/common"
9+
"go.etcd.io/bbolt/internal/guts_cli"
710
"log"
11+
"math/rand"
812
"os"
913
"runtime"
1014
"testing"
@@ -18,6 +22,100 @@ import (
1822
"go.etcd.io/bbolt/internal/btesting"
1923
)
2024

25+
func TestTx_Check_Page(t *testing.T) {
26+
bucketKey := "testBucket"
27+
db := btesting.MustCreateDBWithOption(t, &bolt.Options{PageSize: pageSize})
28+
defer db.MustDeleteFile()
29+
30+
// arrange
31+
if err := db.Update(func(tx *bolt.Tx) error {
32+
b, err := tx.CreateBucketIfNotExists([]byte(bucketKey))
33+
if err != nil {
34+
t.Fatal(err)
35+
}
36+
// insert random data
37+
for i := 0; i < 10; i++ {
38+
insertRandKeysValuesBucket(t, b, 100)
39+
}
40+
return nil
41+
}); err != nil {
42+
t.Fatal(err)
43+
}
44+
db.MustCheck()
45+
46+
// act : corrupt a leaf page
47+
corruptLeafPageFromDB(t, db.Path())
48+
49+
// assert: expected an error after check
50+
if err := db.View(func(tx *bolt.Tx) error {
51+
for err := range tx.Check() {
52+
require.ErrorContains(t, err, "has unexpected type/flags: 20")
53+
}
54+
return nil
55+
}); err != nil {
56+
t.Fatal(err)
57+
}
58+
db.MustClose()
59+
}
60+
61+
func corruptLeafPageFromDB(t testing.TB, dbPath string) {
62+
_, hwm, err := guts_cli.ReadPageAndHWMSize(dbPath)
63+
if err != nil {
64+
t.Fatalf("error reading HWM from dbPath %v: %v", dbPath, err)
65+
}
66+
67+
var victimPage *common.Page
68+
var victimBuf []byte
69+
70+
// find first leaf page starting page after root bucket's page
71+
for pageID := uint64(4); pageID < uint64(hwm); {
72+
p, buf, err := guts_cli.ReadPage(dbPath, pageID)
73+
if err != nil {
74+
t.Fatalf("error reading page %v from dbPath %v: %v", pageID, dbPath, err)
75+
}
76+
77+
if p.IsLeafPage() {
78+
victimPage = p
79+
victimBuf = buf
80+
break
81+
}
82+
}
83+
84+
if victimPage == nil || victimBuf == nil {
85+
t.Fatalf("no leaf page is found in dbPath %v", dbPath)
86+
}
87+
88+
// corrupt page's type
89+
victimPage.SetFlags(0x20)
90+
// write page back to file
91+
err = guts_cli.WritePage(dbPath, victimBuf)
92+
if err != nil {
93+
t.Errorf("error writing victim page %v back to dbpath %v: %v", victimPage.Id(), dbPath, err)
94+
}
95+
}
96+
97+
func insertRandKeysValuesBucket(t testing.TB, bk *bolt.Bucket, n int) {
98+
var min, max = 1, 1024
99+
100+
for i := 0; i < n; i++ {
101+
// generate rand key/value length
102+
keyLength := rand.Intn(max-min) + min
103+
valLength := rand.Intn(max-min) + min
104+
105+
keyData := make([]byte, keyLength)
106+
valData := make([]byte, valLength)
107+
108+
_, err := crand.Read(keyData)
109+
require.NoError(t, err)
110+
111+
_, err = crand.Read(valData)
112+
require.NoError(t, err)
113+
114+
err = bk.Put(keyData, valData)
115+
require.NoError(t, err)
116+
}
117+
}
118+
21119
// TestTx_Check_ReadOnly tests consistency checking on a ReadOnly database.
22120
func TestTx_Check_ReadOnly(t *testing.T) {
23121
db := btesting.MustCreateDB(t)

0 commit comments

Comments
 (0)