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 }