You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
8.2 KiB

8 years ago
8 years ago
8 years ago
7 years ago
7 years ago
7 years ago
7 years ago
8 years ago
7 years ago
7 years ago
7 years ago
8 years ago
  1. package dummy
  2. import (
  3. "bytes"
  4. "io/ioutil"
  5. "sort"
  6. "testing"
  7. "github.com/stretchr/testify/require"
  8. "github.com/tendermint/iavl"
  9. cmn "github.com/tendermint/tmlibs/common"
  10. "github.com/tendermint/tmlibs/log"
  11. abcicli "github.com/tendermint/abci/client"
  12. "github.com/tendermint/abci/example/code"
  13. abciserver "github.com/tendermint/abci/server"
  14. "github.com/tendermint/abci/types"
  15. )
  16. func testDummy(t *testing.T, app types.Application, tx []byte, key, value string) {
  17. ar := app.DeliverTx(tx)
  18. require.False(t, ar.IsErr(), ar)
  19. // repeating tx doesn't raise error
  20. ar = app.DeliverTx(tx)
  21. require.False(t, ar.IsErr(), ar)
  22. // make sure query is fine
  23. resQuery := app.Query(types.RequestQuery{
  24. Path: "/store",
  25. Data: []byte(key),
  26. })
  27. require.Equal(t, code.CodeTypeOK, resQuery.Code)
  28. require.Equal(t, value, string(resQuery.Value))
  29. // make sure proof is fine
  30. resQuery = app.Query(types.RequestQuery{
  31. Path: "/store",
  32. Data: []byte(key),
  33. Prove: true,
  34. })
  35. require.EqualValues(t, code.CodeTypeOK, resQuery.Code)
  36. require.Equal(t, value, string(resQuery.Value))
  37. proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
  38. require.Nil(t, err)
  39. err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash)
  40. require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash
  41. }
  42. func TestDummyKV(t *testing.T) {
  43. dummy := NewDummyApplication()
  44. key := "abc"
  45. value := key
  46. tx := []byte(key)
  47. testDummy(t, dummy, tx, key, value)
  48. value = "def"
  49. tx = []byte(key + "=" + value)
  50. testDummy(t, dummy, tx, key, value)
  51. }
  52. func TestPersistentDummyKV(t *testing.T) {
  53. dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
  54. if err != nil {
  55. t.Fatal(err)
  56. }
  57. dummy := NewPersistentDummyApplication(dir)
  58. key := "abc"
  59. value := key
  60. tx := []byte(key)
  61. testDummy(t, dummy, tx, key, value)
  62. value = "def"
  63. tx = []byte(key + "=" + value)
  64. testDummy(t, dummy, tx, key, value)
  65. }
  66. func TestPersistentDummyInfo(t *testing.T) {
  67. dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
  68. if err != nil {
  69. t.Fatal(err)
  70. }
  71. dummy := NewPersistentDummyApplication(dir)
  72. InitDummy(dummy)
  73. height := int64(0)
  74. resInfo := dummy.Info(types.RequestInfo{})
  75. if resInfo.LastBlockHeight != height {
  76. t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
  77. }
  78. // make and apply block
  79. height = int64(1)
  80. hash := []byte("foo")
  81. header := &types.Header{
  82. Height: int64(height),
  83. }
  84. dummy.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil})
  85. dummy.EndBlock(types.RequestEndBlock{header.Height})
  86. dummy.Commit()
  87. resInfo = dummy.Info(types.RequestInfo{})
  88. if resInfo.LastBlockHeight != height {
  89. t.Fatalf("expected height of %d, got %d", height, resInfo.LastBlockHeight)
  90. }
  91. }
  92. // add a validator, remove a validator, update a validator
  93. func TestValUpdates(t *testing.T) {
  94. dir, err := ioutil.TempDir("/tmp", "abci-dummy-test") // TODO
  95. if err != nil {
  96. t.Fatal(err)
  97. }
  98. dummy := NewPersistentDummyApplication(dir)
  99. // init with some validators
  100. total := 10
  101. nInit := 5
  102. vals := RandVals(total)
  103. // iniitalize with the first nInit
  104. dummy.InitChain(types.RequestInitChain{vals[:nInit]})
  105. vals1, vals2 := vals[:nInit], dummy.Validators()
  106. valsEqual(t, vals1, vals2)
  107. var v1, v2, v3 *types.Validator
  108. // add some validators
  109. v1, v2 = vals[nInit], vals[nInit+1]
  110. diff := []*types.Validator{v1, v2}
  111. tx1 := MakeValSetChangeTx(v1.PubKey, v1.Power)
  112. tx2 := MakeValSetChangeTx(v2.PubKey, v2.Power)
  113. makeApplyBlock(t, dummy, 1, diff, tx1, tx2)
  114. vals1, vals2 = vals[:nInit+2], dummy.Validators()
  115. valsEqual(t, vals1, vals2)
  116. // remove some validators
  117. v1, v2, v3 = vals[nInit-2], vals[nInit-1], vals[nInit]
  118. v1.Power = 0
  119. v2.Power = 0
  120. v3.Power = 0
  121. diff = []*types.Validator{v1, v2, v3}
  122. tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
  123. tx2 = MakeValSetChangeTx(v2.PubKey, v2.Power)
  124. tx3 := MakeValSetChangeTx(v3.PubKey, v3.Power)
  125. makeApplyBlock(t, dummy, 2, diff, tx1, tx2, tx3)
  126. vals1 = append(vals[:nInit-2], vals[nInit+1])
  127. vals2 = dummy.Validators()
  128. valsEqual(t, vals1, vals2)
  129. // update some validators
  130. v1 = vals[0]
  131. if v1.Power == 5 {
  132. v1.Power = 6
  133. } else {
  134. v1.Power = 5
  135. }
  136. diff = []*types.Validator{v1}
  137. tx1 = MakeValSetChangeTx(v1.PubKey, v1.Power)
  138. makeApplyBlock(t, dummy, 3, diff, tx1)
  139. vals1 = append([]*types.Validator{v1}, vals1[1:]...)
  140. vals2 = dummy.Validators()
  141. valsEqual(t, vals1, vals2)
  142. }
  143. func makeApplyBlock(t *testing.T, dummy types.Application, heightInt int, diff []*types.Validator, txs ...[]byte) {
  144. // make and apply block
  145. height := int64(heightInt)
  146. hash := []byte("foo")
  147. header := &types.Header{
  148. Height: height,
  149. }
  150. dummy.BeginBlock(types.RequestBeginBlock{hash, header, nil, nil})
  151. for _, tx := range txs {
  152. if r := dummy.DeliverTx(tx); r.IsErr() {
  153. t.Fatal(r)
  154. }
  155. }
  156. resEndBlock := dummy.EndBlock(types.RequestEndBlock{header.Height})
  157. dummy.Commit()
  158. valsEqual(t, diff, resEndBlock.ValidatorUpdates)
  159. }
  160. // order doesn't matter
  161. func valsEqual(t *testing.T, vals1, vals2 []*types.Validator) {
  162. if len(vals1) != len(vals2) {
  163. t.Fatalf("vals dont match in len. got %d, expected %d", len(vals2), len(vals1))
  164. }
  165. sort.Sort(types.Validators(vals1))
  166. sort.Sort(types.Validators(vals2))
  167. for i, v1 := range vals1 {
  168. v2 := vals2[i]
  169. if !bytes.Equal(v1.PubKey, v2.PubKey) ||
  170. v1.Power != v2.Power {
  171. t.Fatalf("vals dont match at index %d. got %X/%d , expected %X/%d", i, v2.PubKey, v2.Power, v1.PubKey, v1.Power)
  172. }
  173. }
  174. }
  175. func makeSocketClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
  176. // Start the listener
  177. socket := cmn.Fmt("unix://%s.sock", name)
  178. logger := log.TestingLogger()
  179. server := abciserver.NewSocketServer(socket, app)
  180. server.SetLogger(logger.With("module", "abci-server"))
  181. if err := server.Start(); err != nil {
  182. return nil, nil, err
  183. }
  184. // Connect to the socket
  185. client := abcicli.NewSocketClient(socket, false)
  186. client.SetLogger(logger.With("module", "abci-client"))
  187. if err := client.Start(); err != nil {
  188. server.Stop()
  189. return nil, nil, err
  190. }
  191. return client, server, nil
  192. }
  193. func makeGRPCClientServer(app types.Application, name string) (abcicli.Client, cmn.Service, error) {
  194. // Start the listener
  195. socket := cmn.Fmt("unix://%s.sock", name)
  196. logger := log.TestingLogger()
  197. gapp := types.NewGRPCApplication(app)
  198. server := abciserver.NewGRPCServer(socket, gapp)
  199. server.SetLogger(logger.With("module", "abci-server"))
  200. if err := server.Start(); err != nil {
  201. return nil, nil, err
  202. }
  203. client := abcicli.NewGRPCClient(socket, true)
  204. client.SetLogger(logger.With("module", "abci-client"))
  205. if err := client.Start(); err != nil {
  206. server.Stop()
  207. return nil, nil, err
  208. }
  209. return client, server, nil
  210. }
  211. func TestClientServer(t *testing.T) {
  212. // set up socket app
  213. dummy := NewDummyApplication()
  214. client, server, err := makeSocketClientServer(dummy, "dummy-socket")
  215. require.Nil(t, err)
  216. defer server.Stop()
  217. defer client.Stop()
  218. runClientTests(t, client)
  219. // set up grpc app
  220. dummy = NewDummyApplication()
  221. gclient, gserver, err := makeGRPCClientServer(dummy, "dummy-grpc")
  222. require.Nil(t, err)
  223. defer gserver.Stop()
  224. defer gclient.Stop()
  225. runClientTests(t, gclient)
  226. }
  227. func runClientTests(t *testing.T, client abcicli.Client) {
  228. // run some tests....
  229. key := "abc"
  230. value := key
  231. tx := []byte(key)
  232. testClient(t, client, tx, key, value)
  233. value = "def"
  234. tx = []byte(key + "=" + value)
  235. testClient(t, client, tx, key, value)
  236. }
  237. func testClient(t *testing.T, app abcicli.Client, tx []byte, key, value string) {
  238. ar, err := app.DeliverTxSync(tx)
  239. require.NoError(t, err)
  240. require.False(t, ar.IsErr(), ar)
  241. // repeating tx doesn't raise error
  242. ar, err = app.DeliverTxSync(tx)
  243. require.NoError(t, err)
  244. require.False(t, ar.IsErr(), ar)
  245. // make sure query is fine
  246. resQuery, err := app.QuerySync(types.RequestQuery{
  247. Path: "/store",
  248. Data: []byte(key),
  249. })
  250. require.Nil(t, err)
  251. require.Equal(t, code.CodeTypeOK, resQuery.Code)
  252. require.Equal(t, value, string(resQuery.Value))
  253. // make sure proof is fine
  254. resQuery, err = app.QuerySync(types.RequestQuery{
  255. Path: "/store",
  256. Data: []byte(key),
  257. Prove: true,
  258. })
  259. require.Nil(t, err)
  260. require.Equal(t, code.CodeTypeOK, resQuery.Code)
  261. require.Equal(t, value, string(resQuery.Value))
  262. proof, err := iavl.ReadKeyExistsProof(resQuery.Proof)
  263. require.Nil(t, err)
  264. err = proof.Verify([]byte(key), resQuery.Value, proof.RootHash)
  265. require.Nil(t, err, "%+v", err) // NOTE: we have no way to verify the RootHash
  266. }