mirror of
https://github.com/etcd-io/bbolt.git
synced 2025-05-31 11:42:30 +00:00
CMD: add test cases for the 'surgery clear-page-elements' command
Signed-off-by: Benjamin Wang <wachao@vmware.com>
This commit is contained in:
parent
3c3da590b1
commit
95576a4f10
184
cmd/bbolt/command_surgery_cobra_test.go
Normal file
184
cmd/bbolt/command_surgery_cobra_test.go
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package main_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
bolt "go.etcd.io/bbolt"
|
||||||
|
main "go.etcd.io/bbolt/cmd/bbolt"
|
||||||
|
"go.etcd.io/bbolt/internal/btesting"
|
||||||
|
"go.etcd.io/bbolt/internal/guts_cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSurgery_ClearPageElement(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
from int
|
||||||
|
to int
|
||||||
|
setEndIdxAsCount bool
|
||||||
|
removeOnlyOneElement bool // only valid when setEndIdxAsCount == true, and startIdx = endIdx -1 in this case.
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
// normal range
|
||||||
|
{
|
||||||
|
name: "normal range: [4, 8)",
|
||||||
|
from: 4,
|
||||||
|
to: 8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal range: [5, -1)",
|
||||||
|
from: 4,
|
||||||
|
to: -1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal range: all",
|
||||||
|
from: 0,
|
||||||
|
to: -1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal range: [0, 7)",
|
||||||
|
from: 0,
|
||||||
|
to: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "normal range: [3, count)",
|
||||||
|
from: 4,
|
||||||
|
setEndIdxAsCount: true,
|
||||||
|
},
|
||||||
|
// remove only one element
|
||||||
|
{
|
||||||
|
name: "one element: the first one",
|
||||||
|
from: 0,
|
||||||
|
to: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "one element: [6, 7)",
|
||||||
|
from: 6,
|
||||||
|
to: 7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "one element: the last one",
|
||||||
|
setEndIdxAsCount: true,
|
||||||
|
removeOnlyOneElement: true,
|
||||||
|
},
|
||||||
|
// abnormal range
|
||||||
|
{
|
||||||
|
name: "abnormal range: [-1, 4)",
|
||||||
|
from: -1,
|
||||||
|
to: 4,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abnormal range: [-2, 5)",
|
||||||
|
from: -1,
|
||||||
|
to: 5,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abnormal range: [3, 3)",
|
||||||
|
from: 3,
|
||||||
|
to: 3,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abnormal range: [5, 3)",
|
||||||
|
from: 5,
|
||||||
|
to: 3,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abnormal range: [3, -2)",
|
||||||
|
from: 3,
|
||||||
|
to: -2,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abnormal range: [3, 1000000)",
|
||||||
|
from: -1,
|
||||||
|
to: 4,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
testSurgeryClearPageElement(t, tc.from, tc.to, tc.setEndIdxAsCount, tc.removeOnlyOneElement, tc.expectError)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSurgeryClearPageElement(t *testing.T, startIdx, endIdx int, setEndIdxAsCount, removeOnlyOne, expectError bool) {
|
||||||
|
pageSize := 4096
|
||||||
|
db := btesting.MustCreateDBWithOption(t, &bolt.Options{PageSize: pageSize})
|
||||||
|
srcPath := db.Path()
|
||||||
|
|
||||||
|
// Generate sample db
|
||||||
|
t.Log("Generate some sample data")
|
||||||
|
err := db.Fill([]byte("data"), 10, 200,
|
||||||
|
func(tx int, k int) []byte { return []byte(fmt.Sprintf("%04d", tx*10000+k)) },
|
||||||
|
func(tx int, k int) []byte { return make([]byte, 10) },
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
defer requireDBNoChange(t, dbData(t, srcPath), srcPath)
|
||||||
|
|
||||||
|
// find a page with at least 10 elements
|
||||||
|
var (
|
||||||
|
pageId uint64 = 2
|
||||||
|
elementCount uint16 = 0
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
p, _, err := guts_cli.ReadPage(srcPath, pageId)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
if p.IsLeafPage() && p.Count() > 10 {
|
||||||
|
elementCount = p.Count()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pageId++
|
||||||
|
}
|
||||||
|
t.Logf("The original element count: %d", elementCount)
|
||||||
|
|
||||||
|
if setEndIdxAsCount {
|
||||||
|
t.Logf("Set the endIdx as the element count: %d", elementCount)
|
||||||
|
endIdx = int(elementCount)
|
||||||
|
if removeOnlyOne {
|
||||||
|
startIdx = endIdx - 1
|
||||||
|
t.Logf("Set the startIdx as the endIdx-1: %d", startIdx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear elements [startIdx, endIdx) in the page
|
||||||
|
rootCmd := main.NewRootCommand()
|
||||||
|
output := filepath.Join(t.TempDir(), fmt.Sprintf("db_%d", rand.Intn(100)))
|
||||||
|
rootCmd.SetArgs([]string{
|
||||||
|
"surgery", "clear-page-elements", srcPath,
|
||||||
|
"--output", output,
|
||||||
|
"--pageId", fmt.Sprintf("%d", pageId),
|
||||||
|
"--from", fmt.Sprintf("%d", startIdx),
|
||||||
|
"--to", fmt.Sprintf("%d", endIdx),
|
||||||
|
})
|
||||||
|
err = rootCmd.Execute()
|
||||||
|
if expectError {
|
||||||
|
require.Error(t, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// check the element count again
|
||||||
|
expectedCnt := 0
|
||||||
|
if endIdx == -1 {
|
||||||
|
expectedCnt = startIdx
|
||||||
|
} else {
|
||||||
|
expectedCnt = int(elementCount) - (endIdx - startIdx)
|
||||||
|
}
|
||||||
|
p, _, err := guts_cli.ReadPage(output, pageId)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedCnt, int(p.Count()))
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user