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.

314 lines
8.2 KiB

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