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.

311 lines
8.0 KiB

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