github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/search/indexed_block_db_test.go (about)

     1  // Copyright 2019 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package search
     6  
     7  import (
     8  	"os"
     9  	"path/filepath"
    10  	"testing"
    11  
    12  	"github.com/keybase/client/go/kbfs/data"
    13  	"github.com/keybase/client/go/kbfs/kbfsblock"
    14  	"github.com/keybase/client/go/kbfs/kbfsmd"
    15  	"github.com/keybase/client/go/kbfs/libkbfs"
    16  	"github.com/keybase/client/go/kbfs/tlf"
    17  	"github.com/stretchr/testify/require"
    18  	"github.com/syndtr/goleveldb/leveldb/storage"
    19  	"golang.org/x/net/context"
    20  )
    21  
    22  func newIndexedBlockDbForTestWithStorage(
    23  	t *testing.T, blockS, tlfS storage.Storage) (db *IndexedBlockDb, done func()) {
    24  	config := libkbfs.MakeTestConfigOrBust(t, "user1")
    25  	db, err := newIndexedBlockDbFromStorage(config, blockS, tlfS)
    26  	require.NoError(t, err)
    27  	return db, func() { _ = config.Shutdown(context.Background()) }
    28  }
    29  
    30  func newIndexedBlockDbForTest(t *testing.T) (
    31  	db *IndexedBlockDb, tempdir string, done func()) {
    32  	// Use a disk-based level, instead of memory storage, because we
    33  	// want to simulate a restart and memory storages can't be reused.
    34  	tempdir, err := os.MkdirTemp(os.TempDir(), "indexed_blocks_db")
    35  	require.NoError(t, err)
    36  	blockS, err := storage.OpenFile(filepath.Join(tempdir, "blocks"), false)
    37  	require.NoError(t, err)
    38  	tlfS, err := storage.OpenFile(filepath.Join(tempdir, "tlf"), false)
    39  	require.NoError(t, err)
    40  
    41  	db, done = newIndexedBlockDbForTestWithStorage(t, blockS, tlfS)
    42  	return db, tempdir, done
    43  }
    44  
    45  func shutdownIndexedBlockDbTest(db *IndexedBlockDb, tempdir string) {
    46  	db.Shutdown(context.Background())
    47  	os.RemoveAll(tempdir)
    48  }
    49  
    50  func TestIndexedBlockDbCreate(t *testing.T) {
    51  	config := libkbfs.MakeTestConfigOrBust(t, "user1")
    52  	defer func() {
    53  		err := config.Shutdown(context.Background())
    54  		require.NoError(t, err)
    55  	}()
    56  	tempdir, err := os.MkdirTemp(os.TempDir(), "indexed_blocks_db")
    57  	require.NoError(t, err)
    58  	db, err := newIndexedBlockDb(config, tempdir)
    59  	require.NoError(t, err)
    60  	shutdownIndexedBlockDbTest(db, tempdir)
    61  }
    62  
    63  func TestIndexedBlockDb(t *testing.T) {
    64  	t.Parallel()
    65  	t.Log("Test that indexed block db Put and Get operations work.")
    66  	db, tempdir, done := newIndexedBlockDbForTest(t)
    67  	defer func() {
    68  		shutdownIndexedBlockDbTest(db, tempdir)
    69  		done()
    70  	}()
    71  
    72  	ctx := context.Background()
    73  	tlfID := tlf.FakeID(1, tlf.Private)
    74  
    75  	id1, err := kbfsblock.MakeTemporaryID()
    76  	require.NoError(t, err)
    77  	ptr1 := data.BlockPointer{
    78  		ID:      id1,
    79  		KeyGen:  kbfsmd.FirstValidKeyGen,
    80  		DataVer: 1,
    81  	}
    82  	ver1 := uint64(1)
    83  	docID1 := "1"
    84  	dirDone1 := false
    85  
    86  	t.Log("Put block MD into the db.")
    87  	_, _, _, err = db.Get(ctx, ptr1)
    88  	require.Error(t, err) // not dbd yet
    89  	err = db.Put(ctx, tlfID, ptr1, ver1, docID1, dirDone1)
    90  	require.NoError(t, err)
    91  
    92  	t.Log("Get block MD from the db.")
    93  	getVer1, getDocID1, getDirDone1, err := db.Get(ctx, ptr1)
    94  	require.NoError(t, err)
    95  	checkWrite := func(
    96  		expectedVer, ver uint64, expectedDocID, docID string,
    97  		expectedDirDone, dirDone bool) {
    98  		require.Equal(t, expectedVer, ver)
    99  		require.Equal(t, expectedDocID, docID)
   100  		require.Equal(t, expectedDirDone, dirDone)
   101  	}
   102  	checkWrite(ver1, getVer1, docID1, getDocID1, dirDone1, getDirDone1)
   103  
   104  	t.Log("A second entry.")
   105  	id2, err := kbfsblock.MakeTemporaryID()
   106  	require.NoError(t, err)
   107  	ptr2 := data.BlockPointer{
   108  		ID:      id2,
   109  		KeyGen:  kbfsmd.FirstValidKeyGen,
   110  		DataVer: 1,
   111  	}
   112  	ver2 := uint64(1)
   113  	docID2 := "2"
   114  	dirDone2 := true
   115  
   116  	err = db.Put(ctx, tlfID, ptr2, ver2, docID2, dirDone2)
   117  	require.NoError(t, err)
   118  	getVer2, getDocID2, getDirDone2, err := db.Get(ctx, ptr2)
   119  	require.NoError(t, err)
   120  	checkWrite(ver2, getVer2, docID2, getDocID2, dirDone2, getDirDone2)
   121  
   122  	t.Log("Override the first block with new version.")
   123  	ver1 = 2
   124  	err = db.Put(ctx, tlfID, ptr1, ver1, docID1, dirDone1)
   125  	require.NoError(t, err)
   126  	getVer1, getDocID1, getDirDone1, err = db.Get(ctx, ptr1)
   127  	require.NoError(t, err)
   128  	checkWrite(ver1, getVer1, docID1, getDocID1, dirDone1, getDirDone1)
   129  
   130  	t.Log("Add a pointer with the same ID, but a non-zero ref nonce")
   131  	nonce, err := kbfsblock.MakeRefNonce()
   132  	require.NoError(t, err)
   133  	ptr3 := data.BlockPointer{
   134  		ID:      id2,
   135  		KeyGen:  kbfsmd.FirstValidKeyGen,
   136  		DataVer: 1,
   137  		Context: kbfsblock.Context{
   138  			RefNonce: nonce,
   139  		},
   140  	}
   141  	ver3 := uint64(1)
   142  	docID3 := "3"
   143  	dirDone3 := false
   144  	err = db.Put(ctx, tlfID, ptr3, ver3, docID3, dirDone3)
   145  	require.NoError(t, err)
   146  	getVer3, getDocID3, getDirDone3, err := db.Get(ctx, ptr3)
   147  	require.NoError(t, err)
   148  	checkWrite(ver3, getVer3, docID3, getDocID3, dirDone3, getDirDone3)
   149  	getVer2, getDocID2, getDirDone2, err = db.Get(ctx, ptr2)
   150  	require.NoError(t, err)
   151  	checkWrite(ver2, getVer2, docID2, getDocID2, dirDone2, getDirDone2)
   152  
   153  	t.Log("Get new doc IDs")
   154  	res, err := db.GetNextDocIDs(11)
   155  	require.NoError(t, err)
   156  	require.Len(t, res, 11)
   157  	require.Equal(t, "1", res[0])
   158  	require.Equal(t, "b", res[10])
   159  
   160  	t.Log("Restart the db and check the MD")
   161  	db.Shutdown(ctx)
   162  	blockS, err := storage.OpenFile(filepath.Join(tempdir, "blocks"), false)
   163  	require.NoError(t, err)
   164  	tlfS, err := storage.OpenFile(filepath.Join(tempdir, "tlfs"), false)
   165  	require.NoError(t, err)
   166  	db, done2 := newIndexedBlockDbForTestWithStorage(t, blockS, tlfS)
   167  	defer done2()
   168  	getVer1, getDocID1, getDirDone1, err = db.Get(ctx, ptr1)
   169  	require.NoError(t, err)
   170  	checkWrite(ver1, getVer1, docID1, getDocID1, dirDone1, getDirDone1)
   171  	getVer2, getDocID2, getDirDone2, err = db.Get(ctx, ptr2)
   172  	require.NoError(t, err)
   173  	checkWrite(ver2, getVer2, docID2, getDocID2, dirDone2, getDirDone2)
   174  	getVer3, getDocID3, getDirDone3, err = db.Get(ctx, ptr3)
   175  	require.NoError(t, err)
   176  	checkWrite(ver3, getVer3, docID3, getDocID3, dirDone3, getDirDone3)
   177  	res, err = db.GetNextDocIDs(1)
   178  	require.NoError(t, err)
   179  	require.Len(t, res, 1)
   180  	require.Equal(t, "c", res[0])
   181  }