9 "github.com/stretchr/testify/require"
10 abcicli "github.com/tendermint/abci/client"
11 "github.com/tendermint/abci/server"
12 "github.com/tendermint/abci/types"
13 "github.com/tendermint/iavl"
14 cmn "github.com/tendermint/tmlibs/common"
15 "github.com/tendermint/tmlibs/log"
18 func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) {
19 ar := app.DeliverTx(tx)
20 require.False(t, ar.IsErr(), ar)
21 // repeating tx doesn't raise error
22 ar = app.DeliverTx(tx)
23 require.False(t, ar.IsErr(), ar)
25 // make sure query is fine
26 resQuery := app.Query(types.RequestQuery{
30 require.Equal(t, types.CodeType_OK, resQuery.Code)
31 require.Equal(t, value, string(resQuery.Value))
33 // make sure proof is fine
34 resQuery = app.Query(types.RequestQuery{
39 require.Equal(t, types.CodeType_OK, resQuery.Code)
40 require.Equal(t, value, string(resQuery.Value))
41 proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
43 err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash)
44 require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash
47 func TestDummyKV(t *testing.T) {
48 dummy := NewDummyApplication()
52 testDummy(t, dummy, tx, key, value)
55 tx = []byte(key + "=" + value)
56 testDummy(t, dummy, tx, key, value)
59 func TestPersistentDummyKV(t *testing.T) {
60 dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
64 dummy := NewPersistentDummyApplication(dir)
68 testDummy(t, dummy, tx, key, value)
71 tx = []byte(key + "=" + value)
72 testDummy(t, dummy, tx, key, value)
75 func TestPersistentDummyInfo(t *testing.T) {
76 dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
80 dummy := NewPersistentDummyApplication(dir)
84 resInfo := dummy.Info(types.RequestInfo{})
85 if resInfo.LastBlockHeight != height {
86 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
89 // make and apply block
92 header := &types.Header{
93 Height: uint64(height),
95 dummy.BeginBlock(types.RequestBeginBlock{hash, header})
96 dummy.EndBlock(height)
99 resInfo = dummy.Info(types.RequestInfo{})
100 if resInfo.LastBlockHeight != height {
101 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
106 // add a validator, remove a validator, update a validator
107 func TestValSetChanges(t *testing.T) {
108 dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
112 dummy := NewPersistentDummyApplication(dir)
114 // init with some validators
117 vals := RandVals(total)
118 // iniitalize with the first nInit
119 dummy.InitChain(types.RequestInitChain{vals[:nInit]})
121 vals1, vals2 := vals[:nInit], dummy.Validators()
122 valsEqual(t, vals1, vals2)
124 var v1, v2, v3 *types.Validator
126 // add some validators
127 v1, v2 = vals[nInit], vals[nInit+1]
128 diff := []*types.Validator{v1, v2}
129 tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
130 tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
132 makeApplyBlock(t, dummy, 1, diff, tx1, tx2)
134 vals1, vals2 = vals[:nInit+2], dummy.Validators()
135 valsEqual(t, vals1, vals2)
137 // remove some validators
138 v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
142 diff = []*types.Validator{v1, v2, v3}
143 tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
144 tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
145 tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
147 makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3)
149 vals1 = append(vals[:nInit-2], vals[nInit+1])
150 vals2 = dummy.Validators()
151 valsEqual(t, vals1, vals2)
153 // update some validators
160 diff = []*types.Validator{v1}
161 tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
163 makeApplyBlock(t, dummy, 3, diff, tx1)
165 vals1 = append([]*types.Validator{v1}, vals1[1:]...)
166 vals2 = dummy.Validators()
167 valsEqual(t, vals1, vals2)
171 func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) {
172 // make and apply block
173 height := uint64(heightInt)
174 hash := []byte("foo")
175 header := &types.Header{
179 dummy.BeginBlock(types.RequestBeginBlock{hash, header})
180 for _, tx := range txs {
181 if r := dummy.DeliverTx(tx); r.IsErr() {
185 resEndBlock := dummy.EndBlock(height)
188 valsEqual(t, diff, resEndBlock.Diffs)
192 // order doesn't matter
193 func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) {
194 if len(vals1) != len(vals2) {
195 t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1))
197 sort.Sort(types.Validators(vals1))
198 sort.Sort(types.Validators(vals2))
199 for i, v1 := range vals1 {
201 if !bytes.Equal(v1.PubKey, v2.PubKey) ||
202 v1.Power != v2.Power {
203 t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power)
208 func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
209 // Start the listener
210 socket := cmn.Fmt("unix://%s.sock", name)
211 logger := log.TestingLogger()
213 server := server.NewSocketServer(socket, app)
214 server.SetLogger(logger.With("module", "abci-server"))
215 if _, err := server.Start(); err != nil {
219 // Connect to the socket
220 client := abcicli.NewSocketClient(socket, false)
221 client.SetLogger(logger.With("module", "abci-client"))
222 if _, err := client.Start(); err != nil {
227 return client, server, nil
230 func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
231 // Start the listener
232 socket := cmn.Fmt("unix://%s.sock", name)
233 logger := log.TestingLogger()
235 gapp := types.NewGRPCApplication(app)
236 server := server.NewGRPCServer(socket, gapp)
237 server.SetLogger(logger.With("module", "abci-server"))
238 if _, err := server.Start(); err != nil {
242 client := abcicli.NewGRPCClient(socket, true)
243 client.SetLogger(logger.With("module", "abci-client"))
244 if _, err := client.Start(); err != nil {
248 return client, server, nil
251 func TestClientServer(t *testing.T) {
253 dummy := NewDummyApplication()
254 client, server, err := makeSocketClientServer(dummy, "dummy-socket")
259 runClientTests(t, client)
262 dummy = NewDummyApplication()
263 gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc")
268 runClientTests(t, gclient)
271 func runClientTests(t *testing.T, client abcicli.Client) {
272 // run some tests....
276 testClient(t, client, tx, key, value)
279 tx = []byte(key + "=" + value)
280 testClient(t, client, tx, key, value)
283 func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) {
284 ar := app.DeliverTxSync(tx)
285 require.False(t, ar.IsErr(), ar)
286 // repeating tx doesn't raise error
287 ar = app.DeliverTxSync(tx)
288 require.False(t, ar.IsErr(), ar)
290 // make sure query is fine
291 resQuery, err := app.QuerySync(types.RequestQuery{
296 require.Equal(t, types.CodeType_OK, resQuery.Code)
297 require.Equal(t, value, string(resQuery.Value))
299 // make sure proof is fine
300 resQuery, err = app.QuerySync(types.RequestQuery{
306 require.Equal(t, types.CodeType_OK, resQuery.Code)
307 require.Equal(t, value, string(resQuery.Value))
308 proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
310 err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash)
311 require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash