github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/confighistory/db_helper_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package confighistory 8 9 import ( 10 "bytes" 11 "math" 12 "os" 13 "testing" 14 15 "github.com/hechain20/hechain/common/ledger/util/leveldbhelper" 16 "github.com/stretchr/testify/require" 17 ) 18 19 func TestEncodeDecodeCompositeKey(t *testing.T) { 20 sampleKeys := []*compositeKey{ 21 {ns: "ns0", key: "key0", blockNum: 0}, 22 {ns: "ns1", key: "key1", blockNum: 1}, 23 {ns: "ns2", key: "key2", blockNum: 99}, 24 {ns: "ns3", key: "key3", blockNum: math.MaxUint64}, 25 } 26 for _, k := range sampleKeys { 27 k1 := decodeCompositeKey(encodeCompositeKey(k.ns, k.key, k.blockNum)) 28 require.Equal(t, k, k1) 29 } 30 } 31 32 func TestCompareEncodedHeight(t *testing.T) { 33 require.Equal(t, bytes.Compare(encodeBlockNum(20), encodeBlockNum(40)), 1) 34 require.Equal(t, bytes.Compare(encodeBlockNum(40), encodeBlockNum(10)), -1) 35 } 36 37 func TestQueries(t *testing.T) { 38 testDBPath := "/tmp/fabric/core/ledger/confighistory" 39 deleteTestPath(t, testDBPath) 40 provider, err := newDBProvider(testDBPath) 41 require.NoError(t, err) 42 defer deleteTestPath(t, testDBPath) 43 44 db := provider.getDB("ledger1") 45 // A query on an empty store 46 checkEntryAt(t, "testcase-query1", db, "ns1", "key1", 45, nil) 47 // test data 48 sampleData := []*compositeKV{ 49 {&compositeKey{ns: "ns1", key: "key1", blockNum: 40}, []byte("val1_40")}, 50 {&compositeKey{ns: "ns1", key: "key1", blockNum: 30}, []byte("val1_30")}, 51 {&compositeKey{ns: "ns1", key: "key1", blockNum: 20}, []byte("val1_20")}, 52 {&compositeKey{ns: "ns1", key: "key1", blockNum: 10}, []byte("val1_10")}, 53 {&compositeKey{ns: "ns1", key: "key1", blockNum: 0}, []byte("val1_0")}, 54 {&compositeKey{ns: "ns2", key: "key2", blockNum: 200}, []byte("val200")}, 55 {&compositeKey{ns: "ns3", key: "key3", blockNum: 300}, []byte("val300")}, 56 {&compositeKey{ns: "ns3", key: "key4", blockNum: 400}, []byte("val400")}, 57 } 58 populateDBWithSampleData(t, db, sampleData) 59 // access most recent entry below ht=[45] - expected item is the one committed at ht = 40 60 checkRecentEntryBelow(t, "testcase-query2", db, "ns1", "key1", 45, sampleData[0]) 61 checkRecentEntryBelow(t, "testcase-query3", db, "ns1", "key1", 35, sampleData[1]) 62 checkRecentEntryBelow(t, "testcase-query4", db, "ns1", "key1", 30, sampleData[2]) 63 checkRecentEntryBelow(t, "testcase-query5", db, "ns1", "key1", 10, sampleData[4]) 64 checkRecentEntryBelow(t, "testcase-query6", db, "ns2", "key2", 2000, sampleData[5]) 65 checkRecentEntryBelow(t, "testcase-query7", db, "ns2", "key2", 200, nil) 66 checkRecentEntryBelow(t, "testcase-query8", db, "ns3", "key3", 299, nil) 67 68 checkEntryAt(t, "testcase-query9", db, "ns1", "key1", 40, sampleData[0]) 69 checkEntryAt(t, "testcase-query10", db, "ns1", "key1", 30, sampleData[1]) 70 checkEntryAt(t, "testcase-query11", db, "ns1", "key1", 0, sampleData[4]) 71 checkEntryAt(t, "testcase-query12", db, "ns1", "key1", 35, nil) 72 checkEntryAt(t, "testcase-query13", db, "ns1", "key1", 45, nil) 73 74 t.Run("test-iter-error-path", func(t *testing.T) { 75 provider.Close() 76 ckv, err := db.mostRecentEntryBelow(45, "ns1", "key1") 77 require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed") 78 require.Nil(t, ckv) 79 }) 80 } 81 82 func TestGetNamespaceIterator(t *testing.T) { 83 testDBPath := "/tmp/fabric/core/ledger/confighistory" 84 provider, err := newDBProvider(testDBPath) 85 require.NoError(t, err) 86 defer deleteTestPath(t, testDBPath) 87 88 db := provider.getDB("ledger1") 89 nsItr1, err := db.getNamespaceIterator("ns1") 90 require.NoError(t, err) 91 defer nsItr1.Release() 92 verifyNsEntries(t, nsItr1, nil) 93 94 sampleData := []*compositeKV{ 95 {&compositeKey{ns: "ns1", key: "key1", blockNum: 40}, []byte("val1_40")}, // index 0 96 {&compositeKey{ns: "ns1", key: "key1", blockNum: 30}, []byte("val1_30")}, // index 1 97 {&compositeKey{ns: "ns1", key: "key1", blockNum: 20}, []byte("val1_20")}, // index 2 98 {&compositeKey{ns: "ns2", key: "key1", blockNum: 50}, []byte("val1_50")}, // index 3 99 {&compositeKey{ns: "ns2", key: "key1", blockNum: 20}, []byte("val1_20")}, // index 4 100 {&compositeKey{ns: "ns2", key: "key1", blockNum: 10}, []byte("val1_10")}, // index 5 101 } 102 populateDBWithSampleData(t, db, sampleData) 103 104 nsItr2, err := db.getNamespaceIterator("ns1") 105 require.NoError(t, err) 106 defer nsItr2.Release() 107 verifyNsEntries(t, nsItr2, sampleData[:3]) 108 109 nsItr3, err := db.getNamespaceIterator("ns2") 110 require.NoError(t, err) 111 defer nsItr3.Release() 112 verifyNsEntries(t, nsItr3, sampleData[3:]) 113 114 t.Run("test-iter-error-path", func(t *testing.T) { 115 provider.Close() 116 itr, err := db.getNamespaceIterator("ns1") 117 require.EqualError(t, err, "internal leveldb error while obtaining db iterator: leveldb: closed") 118 require.Nil(t, itr) 119 }) 120 } 121 122 func verifyNsEntries(t *testing.T, nsItr *leveldbhelper.Iterator, expectedEntries []*compositeKV) { 123 var retrievedEntries []*compositeKV 124 for nsItr.Next() { 125 require.NoError(t, nsItr.Error()) 126 key := decodeCompositeKey(nsItr.Key()) 127 val := make([]byte, len(nsItr.Value())) 128 copy(val, nsItr.Value()) 129 retrievedEntries = append(retrievedEntries, &compositeKV{key, val}) 130 } 131 require.Equal(t, expectedEntries, retrievedEntries) 132 } 133 134 func populateDBWithSampleData(t *testing.T, db *db, sampledata []*compositeKV) { 135 batch := db.newBatch() 136 for _, data := range sampledata { 137 batch.add(data.ns, data.key, data.blockNum, data.value) 138 } 139 require.NoError(t, db.writeBatch(batch, true)) 140 } 141 142 func checkRecentEntryBelow(t *testing.T, testcase string, db *db, ns, key string, commitHt uint64, expectedOutput *compositeKV) { 143 t.Run(testcase, 144 func(t *testing.T) { 145 kv, err := db.mostRecentEntryBelow(commitHt, ns, key) 146 require.NoError(t, err) 147 require.Equal(t, expectedOutput, kv) 148 }) 149 } 150 151 func checkEntryAt(t *testing.T, testcase string, db *db, ns, key string, commitHt uint64, expectedOutput *compositeKV) { 152 t.Run(testcase, 153 func(t *testing.T) { 154 kv, err := db.entryAt(commitHt, ns, key) 155 require.NoError(t, err) 156 require.Equal(t, expectedOutput, kv) 157 }) 158 } 159 160 func deleteTestPath(t *testing.T, dbPath string) { 161 err := os.RemoveAll(dbPath) 162 require.NoError(t, err) 163 }