...

Source file src/go.etcd.io/bbolt/internal/tests/tx_check_test.go

Documentation: go.etcd.io/bbolt/internal/tests

     1  package tests_test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	bolt "go.etcd.io/bbolt"
    10  	"go.etcd.io/bbolt/internal/btesting"
    11  	"go.etcd.io/bbolt/internal/guts_cli"
    12  	"go.etcd.io/bbolt/internal/surgeon"
    13  )
    14  
    15  func TestTx_RecursivelyCheckPages_MisplacedPage(t *testing.T) {
    16  	db := btesting.MustCreateDB(t)
    17  	require.NoError(t,
    18  		db.Fill([]byte("data"), 1, 10000,
    19  			func(tx int, k int) []byte { return []byte(fmt.Sprintf("%04d", k)) },
    20  			func(tx int, k int) []byte { return make([]byte, 100) },
    21  		))
    22  	require.NoError(t, db.Close())
    23  
    24  	xRay := surgeon.NewXRay(db.Path())
    25  
    26  	path1, err := xRay.FindPathsToKey([]byte("0451"))
    27  	require.NoError(t, err, "cannot find page that contains key:'0451'")
    28  	require.Len(t, path1, 1, "Expected only one page that contains key:'0451'")
    29  
    30  	path2, err := xRay.FindPathsToKey([]byte("7563"))
    31  	require.NoError(t, err, "cannot find page that contains key:'7563'")
    32  	require.Len(t, path2, 1, "Expected only one page that contains key:'7563'")
    33  
    34  	srcPage := path1[0][len(path1[0])-1]
    35  	targetPage := path2[0][len(path2[0])-1]
    36  	require.NoError(t, surgeon.CopyPage(db.Path(), srcPage, targetPage))
    37  
    38  	db.MustReopen()
    39  	require.NoError(t, db.Update(func(tx *bolt.Tx) error {
    40  		// Collect all the errors.
    41  		var errors []error
    42  		for err := range tx.Check() {
    43  			errors = append(errors, err)
    44  		}
    45  		require.Len(t, errors, 1)
    46  		require.ErrorContains(t, errors[0], fmt.Sprintf("leaf page(%v) needs to be >= the key in the ancestor", targetPage))
    47  		return nil
    48  	}))
    49  	require.NoError(t, db.Close())
    50  }
    51  
    52  func TestTx_RecursivelyCheckPages_CorruptedLeaf(t *testing.T) {
    53  	db := btesting.MustCreateDB(t)
    54  	require.NoError(t,
    55  		db.Fill([]byte("data"), 1, 10000,
    56  			func(tx int, k int) []byte { return []byte(fmt.Sprintf("%04d", k)) },
    57  			func(tx int, k int) []byte { return make([]byte, 100) },
    58  		))
    59  	require.NoError(t, db.Close())
    60  
    61  	xray := surgeon.NewXRay(db.Path())
    62  
    63  	path1, err := xray.FindPathsToKey([]byte("0451"))
    64  	require.NoError(t, err, "cannot find page that contains key:'0451'")
    65  	require.Len(t, path1, 1, "Expected only one page that contains key:'0451'")
    66  
    67  	srcPage := path1[0][len(path1[0])-1]
    68  	p, pbuf, err := guts_cli.ReadPage(db.Path(), uint64(srcPage))
    69  	require.NoError(t, err)
    70  	require.Positive(t, p.Count(), "page must be not empty")
    71  	p.LeafPageElement(p.Count() / 2).Key()[0] = 'z'
    72  	require.NoError(t, guts_cli.WritePage(db.Path(), pbuf))
    73  
    74  	db.MustReopen()
    75  	require.NoError(t, db.Update(func(tx *bolt.Tx) error {
    76  		// Collect all the errors.
    77  		var errors []error
    78  		for err := range tx.Check() {
    79  			errors = append(errors, err)
    80  		}
    81  		require.Len(t, errors, 2)
    82  		require.ErrorContains(t, errors[0], fmt.Sprintf("leaf page(%v) needs to be < than key of the next element in ancestor", srcPage))
    83  		require.ErrorContains(t, errors[1], fmt.Sprintf("leaf page(%v) needs to be > (found <) than previous element", srcPage))
    84  		return nil
    85  	}))
    86  	require.NoError(t, db.Close())
    87  }
    88  

View as plain text