github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/abci/example/kvstore/kvstore_test.go (about) 1 package kvstore 2 3 import ( 4 "io/ioutil" 5 "sort" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/lazyledger/lazyledger-core/abci/example/code" 11 "github.com/lazyledger/lazyledger-core/abci/types" 12 tmproto "github.com/lazyledger/lazyledger-core/proto/tendermint/types" 13 ) 14 15 const ( 16 testKey = "abc" 17 testValue = "def" 18 ) 19 20 func testKVStore(t *testing.T, app types.Application, tx []byte, key, value string) { 21 req := types.RequestDeliverTx{Tx: tx} 22 ar := app.DeliverTx(req) 23 require.False(t, ar.IsErr(), ar) 24 // repeating tx doesn't raise error 25 ar = app.DeliverTx(req) 26 require.False(t, ar.IsErr(), ar) 27 // commit 28 app.Commit() 29 30 info := app.Info(types.RequestInfo{}) 31 require.NotZero(t, info.LastBlockHeight) 32 33 // make sure query is fine 34 resQuery := app.Query(types.RequestQuery{ 35 Path: "/store", 36 Data: []byte(key), 37 }) 38 require.Equal(t, code.CodeTypeOK, resQuery.Code) 39 require.Equal(t, key, string(resQuery.Key)) 40 require.Equal(t, value, string(resQuery.Value)) 41 require.EqualValues(t, info.LastBlockHeight, resQuery.Height) 42 43 // make sure proof is fine 44 resQuery = app.Query(types.RequestQuery{ 45 Path: "/store", 46 Data: []byte(key), 47 Prove: true, 48 }) 49 require.EqualValues(t, code.CodeTypeOK, resQuery.Code) 50 require.Equal(t, key, string(resQuery.Key)) 51 require.Equal(t, value, string(resQuery.Value)) 52 require.EqualValues(t, info.LastBlockHeight, resQuery.Height) 53 } 54 55 func TestKVStoreKV(t *testing.T) { 56 kvstore := NewApplication() 57 key := testKey 58 value := key 59 tx := []byte(key) 60 testKVStore(t, kvstore, tx, key, value) 61 62 value = testValue 63 tx = []byte(key + "=" + value) 64 testKVStore(t, kvstore, tx, key, value) 65 } 66 67 func TestPersistentKVStoreKV(t *testing.T) { 68 dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO 69 if err != nil { 70 t.Fatal(err) 71 } 72 kvstore := NewPersistentKVStoreApplication(dir) 73 key := testKey 74 value := key 75 tx := []byte(key) 76 testKVStore(t, kvstore, tx, key, value) 77 78 value = testValue 79 tx = []byte(key + "=" + value) 80 testKVStore(t, kvstore, tx, key, value) 81 } 82 83 func TestPersistentKVStoreInfo(t *testing.T) { 84 dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO 85 if err != nil { 86 t.Fatal(err) 87 } 88 kvstore := NewPersistentKVStoreApplication(dir) 89 InitKVStore(kvstore) 90 height := int64(0) 91 92 resInfo := kvstore.Info(types.RequestInfo{}) 93 if resInfo.LastBlockHeight != height { 94 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) 95 } 96 97 // make and apply block 98 height = int64(1) 99 hash := []byte("foo") 100 header := tmproto.Header{ 101 Height: height, 102 } 103 kvstore.BeginBlock(types.RequestBeginBlock{Hash: hash, Header: header}) 104 kvstore.EndBlock(types.RequestEndBlock{Height: header.Height}) 105 kvstore.Commit() 106 107 resInfo = kvstore.Info(types.RequestInfo{}) 108 if resInfo.LastBlockHeight != height { 109 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight) 110 } 111 112 } 113 114 // add a validator, remove a validator, update a validator 115 func TestValUpdates(t *testing.T) { 116 dir, err := ioutil.TempDir("/tmp", "abci-kvstore-test") // TODO 117 if err != nil { 118 t.Fatal(err) 119 } 120 kvstore := NewPersistentKVStoreApplication(dir) 121 122 // init with some validators 123 total := 10 124 nInit := 5 125 vals := RandVals(total) 126 // initialize with the first nInit 127 kvstore.InitChain(types.RequestInitChain{ 128 Validators: vals[:nInit], 129 }) 130 131 vals1, vals2 := vals[:nInit], kvstore.Validators() 132 valsEqual(t, vals1, vals2) 133 134 var v1, v2, v3 types.ValidatorUpdate 135 136 // add some validators 137 v1, v2 = vals[nInit], vals[nInit+1] 138 diff := []types.ValidatorUpdate{v1, v2} 139 tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power) 140 tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power) 141 142 makeApplyBlock(t, kvstore, 1, diff, tx1, tx2) 143 144 vals1, vals2 = vals[:nInit+2], kvstore.Validators() 145 valsEqual(t, vals1, vals2) 146 147 // remove some validators 148 v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit] 149 v1.Power = 0 150 v2.Power = 0 151 v3.Power = 0 152 diff = []types.ValidatorUpdate{v1, v2, v3} 153 tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) 154 tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power) 155 tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power) 156 157 makeApplyBlock(t, kvstore, 2, diff, tx1, tx2, tx3) 158 159 vals1 = append(vals[:nInit-2], vals[nInit+1]) // nolint: gocritic 160 vals2 = kvstore.Validators() 161 valsEqual(t, vals1, vals2) 162 163 // update some validators 164 v1 = vals[0] 165 if v1.Power == 5 { 166 v1.Power = 6 167 } else { 168 v1.Power = 5 169 } 170 diff = []types.ValidatorUpdate{v1} 171 tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power) 172 173 makeApplyBlock(t, kvstore, 3, diff, tx1) 174 175 vals1 = append([]types.ValidatorUpdate{v1}, vals1[1:]...) 176 vals2 = kvstore.Validators() 177 valsEqual(t, vals1, vals2) 178 179 } 180 181 func makeApplyBlock( 182 t *testing.T, 183 kvstore types.Application, 184 heightInt int, 185 diff []types.ValidatorUpdate, 186 txs ...[]byte) { 187 // make and apply block 188 height := int64(heightInt) 189 hash := []byte("foo") 190 header := tmproto.Header{ 191 Height: height, 192 } 193 194 kvstore.BeginBlock(types.RequestBeginBlock{Hash: hash, Header: header}) 195 for _, tx := range txs { 196 if r := kvstore.DeliverTx(types.RequestDeliverTx{Tx: tx}); r.IsErr() { 197 t.Fatal(r) 198 } 199 } 200 resEndBlock := kvstore.EndBlock(types.RequestEndBlock{Height: header.Height}) 201 kvstore.Commit() 202 203 valsEqual(t, diff, resEndBlock.ValidatorUpdates) 204 205 } 206 207 // order doesn't matter 208 func valsEqual(t *testing.T, vals1, vals2 []types.ValidatorUpdate) { 209 if len(vals1) != len(vals2) { 210 t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1)) 211 } 212 sort.Sort(types.ValidatorUpdates(vals1)) 213 sort.Sort(types.ValidatorUpdates(vals2)) 214 for i, v1 := range vals1 { 215 v2 := vals2[i] 216 if !v1.PubKey.Equal(v2.PubKey) || 217 v1.Power != v2.Power { 218 t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power) 219 } 220 } 221 }