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.

310 lines
7.9 KiB

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