OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / abci / example / dummy / dummy_test.go
1 package dummy
2
3 import (
4         "bytes"
5         "io/ioutil"
6         "sort"
7         "testing"
8
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"
16 )
17
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)
24
25         // make sure query is fine
26         resQuery := app.Query(types.RequestQuery{
27                 Path: "/store",
28                 Data: []byte(key),
29         })
30         require.Equal(t, types.CodeType_OK, resQuery.Code)
31         require.Equal(t, value, string(resQuery.Value))
32
33         // make sure proof is fine
34         resQuery = app.Query(types.RequestQuery{
35                 Path:  "/store",
36                 Data:  []byte(key),
37                 Prove: true,
38         })
39         require.Equal(t, types.CodeType_OK, resQuery.Code)
40         require.Equal(t, value, string(resQuery.Value))
41         proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
42         require.Nil(t, err)
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
45 }
46
47 func TestDummyKV(t *testing.T) {
48         dummy := NewDummyApplication()
49         key := "abc"
50         value := key
51         tx := []byte(key)
52         testDummy(t, dummy, tx, key, value)
53
54         value = "def"
55         tx = []byte(key + "=" + value)
56         testDummy(t, dummy, tx, key, value)
57 }
58
59 func TestPersistentDummyKV(t *testing.T) {
60         dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
61         if err != nil {
62                 t.Fatal(err)
63         }
64         dummy := NewPersistentDummyApplication(dir)
65         key := "abc"
66         value := key
67         tx := []byte(key)
68         testDummy(t, dummy, tx, key, value)
69
70         value = "def"
71         tx = []byte(key + "=" + value)
72         testDummy(t, dummy, tx, key, value)
73 }
74
75 func TestPersistentDummyInfo(t *testing.T) {
76         dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
77         if err != nil {
78                 t.Fatal(err)
79         }
80         dummy := NewPersistentDummyApplication(dir)
81         InitDummy(dummy)
82         height := uint64(0)
83
84         resInfo := dummy.Info(types.RequestInfo{})
85         if resInfo.LastBlockHeight != height {
86                 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
87         }
88
89         // make and apply block
90         height = uint64(1)
91         hash := []byte("foo")
92         header := &types.Header{
93                 Height: uint64(height),
94         }
95         dummy.BeginBlock(types.RequestBeginBlock{hash, header})
96         dummy.EndBlock(height)
97         dummy.Commit()
98
99         resInfo = dummy.Info(types.RequestInfo{})
100         if resInfo.LastBlockHeight != height {
101                 t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
102         }
103
104 }
105
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
109         if err != nil {
110                 t.Fatal(err)
111         }
112         dummy := NewPersistentDummyApplication(dir)
113
114         // init with some validators
115         total := 10
116         nInit := 5
117         vals := RandVals(total)
118         // iniitalize with the first nInit
119         dummy.InitChain(types.RequestInitChain{vals[:nInit]})
120
121         vals1, vals2 := vals[:nInit], dummy.Validators()
122         valsEqual(t, vals1, vals2)
123
124         var v1, v2, v3 *types.Validator
125
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)
131
132         makeApplyBlock(t, dummy, 1, diff, tx1, tx2)
133
134         vals1, vals2 = vals[:nInit+2], dummy.Validators()
135         valsEqual(t, vals1, vals2)
136
137         // remove some validators
138         v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
139         v1.Power = 0
140         v2.Power = 0
141         v3.Power = 0
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)
146
147         makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3)
148
149         vals1 = append(vals[:nInit-2], vals[nInit+1])
150         vals2 = dummy.Validators()
151         valsEqual(t, vals1, vals2)
152
153         // update some validators
154         v1 = vals[0]
155         if v1.Power == 5 {
156                 v1.Power = 6
157         } else {
158                 v1.Power = 5
159         }
160         diff = []*types.Validator{v1}
161         tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
162
163         makeApplyBlock(t, dummy, 3, diff, tx1)
164
165         vals1 = append([]*types.Validator{v1}, vals1[1:]...)
166         vals2 = dummy.Validators()
167         valsEqual(t, vals1, vals2)
168
169 }
170
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{
176                 Height: height,
177         }
178
179         dummy.BeginBlock(types.RequestBeginBlock{hash, header})
180         for _, tx := range txs {
181                 if r := dummy.DeliverTx(tx); r.IsErr() {
182                         t.Fatal(r)
183                 }
184         }
185         resEndBlock := dummy.EndBlock(height)
186         dummy.Commit()
187
188         valsEqual(t, diff, resEndBlock.Diffs)
189
190 }
191
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))
196         }
197         sort.Sort(types.Validators(vals1))
198         sort.Sort(types.Validators(vals2))
199         for i, v1 := range vals1 {
200                 v2 := vals2[i]
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)
204                 }
205         }
206 }
207
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()
212
213         server := server.NewSocketServer(socket, app)
214         server.SetLogger(logger.With("module", "abci-server"))
215         if _, err := server.Start(); err != nil {
216                 return nil, nil, err
217         }
218
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 {
223                 server.Stop()
224                 return nil, nil, err
225         }
226
227         return client, server, nil
228 }
229
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()
234
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 {
239                 return nil, nil, err
240         }
241
242         client := abcicli.NewGRPCClient(socket, true)
243         client.SetLogger(logger.With("module", "abci-client"))
244         if _, err := client.Start(); err != nil {
245                 server.Stop()
246                 return nil, nil, err
247         }
248         return client, server, nil
249 }
250
251 func TestClientServer(t *testing.T) {
252         // set up socket app
253         dummy := NewDummyApplication()
254         client, server, err := makeSocketClientServer(dummy, "dummy-socket")
255         require.Nil(t, err)
256         defer server.Stop()
257         defer client.Stop()
258
259         runClientTests(t, client)
260
261         // set up grpc app
262         dummy = NewDummyApplication()
263         gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc")
264         require.Nil(t, err)
265         defer gserver.Stop()
266         defer gclient.Stop()
267
268         runClientTests(t, gclient)
269 }
270
271 func runClientTests(t *testing.T, client abcicli.Client) {
272         // run some tests....
273         key := "abc"
274         value := key
275         tx := []byte(key)
276         testClient(t, client, tx, key, value)
277
278         value = "def"
279         tx = []byte(key + "=" + value)
280         testClient(t, client, tx, key, value)
281 }
282
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)
289
290         // make sure query is fine
291         resQuery, err := app.QuerySync(types.RequestQuery{
292                 Path: "/store",
293                 Data: []byte(key),
294         })
295         require.Nil(t, err)
296         require.Equal(t, types.CodeType_OK, resQuery.Code)
297         require.Equal(t, value, string(resQuery.Value))
298
299         // make sure proof is fine
300         resQuery, err = app.QuerySync(types.RequestQuery{
301                 Path:  "/store",
302                 Data:  []byte(key),
303                 Prove: true,
304         })
305         require.Nil(t, err)
306         require.Equal(t, types.CodeType_OK, resQuery.Code)
307         require.Equal(t, value, string(resQuery.Value))
308         proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
309         require.Nil(t, err)
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
312 }