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.

188 lines
5.2 KiB

  1. package e2e_test
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "math/rand"
  7. "testing"
  8. "time"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. "github.com/tendermint/tendermint/rpc/client/http"
  12. e2e "github.com/tendermint/tendermint/test/e2e/pkg"
  13. "github.com/tendermint/tendermint/types"
  14. )
  15. // Tests that any initial state given in genesis has made it into the app.
  16. func TestApp_InitialState(t *testing.T) {
  17. testNode(t, func(t *testing.T, node e2e.Node) {
  18. if len(node.Testnet.InitialState) == 0 {
  19. return
  20. }
  21. client, err := node.Client()
  22. require.NoError(t, err)
  23. for k, v := range node.Testnet.InitialState {
  24. resp, err := client.ABCIQuery(ctx, "", []byte(k))
  25. require.NoError(t, err)
  26. assert.Equal(t, k, string(resp.Response.Key))
  27. assert.Equal(t, v, string(resp.Response.Value))
  28. }
  29. })
  30. }
  31. // Tests that the app hash (as reported by the app) matches the last
  32. // block and the node sync status.
  33. func TestApp_Hash(t *testing.T) {
  34. testNode(t, func(t *testing.T, node e2e.Node) {
  35. client, err := node.Client()
  36. require.NoError(t, err)
  37. info, err := client.ABCIInfo(ctx)
  38. require.NoError(t, err)
  39. require.NotEmpty(t, info.Response.LastBlockAppHash, "expected app to return app hash")
  40. status, err := client.Status(ctx)
  41. require.NoError(t, err)
  42. require.NotZero(t, status.SyncInfo.LatestBlockHeight)
  43. block, err := client.Block(ctx, &info.Response.LastBlockHeight)
  44. require.NoError(t, err)
  45. if info.Response.LastBlockHeight == block.Block.Height {
  46. require.Equal(t,
  47. fmt.Sprintf("%x", info.Response.LastBlockAppHash),
  48. fmt.Sprintf("%x", block.Block.AppHash.Bytes()),
  49. "app hash does not match last block's app hash")
  50. }
  51. require.True(t, status.SyncInfo.LatestBlockHeight >= info.Response.LastBlockHeight,
  52. "status out of sync with application")
  53. })
  54. }
  55. // Tests that the app and blockstore have and report the same height.
  56. func TestApp_Height(t *testing.T) {
  57. testNode(t, func(t *testing.T, node e2e.Node) {
  58. client, err := node.Client()
  59. require.NoError(t, err)
  60. info, err := client.ABCIInfo(ctx)
  61. require.NoError(t, err)
  62. require.NotZero(t, info.Response.LastBlockHeight)
  63. status, err := client.Status(ctx)
  64. require.NoError(t, err)
  65. require.NotZero(t, status.SyncInfo.LatestBlockHeight)
  66. block, err := client.Block(ctx, &info.Response.LastBlockHeight)
  67. require.NoError(t, err)
  68. require.Equal(t, info.Response.LastBlockHeight, block.Block.Height)
  69. require.True(t, status.SyncInfo.LatestBlockHeight >= info.Response.LastBlockHeight,
  70. "status out of sync with application")
  71. })
  72. }
  73. // Tests that we can set a value and retrieve it.
  74. func TestApp_Tx(t *testing.T) {
  75. type broadcastFunc func(context.Context, types.Tx) error
  76. testCases := []struct {
  77. Name string
  78. WaitTime time.Duration
  79. BroadcastTx func(client *http.HTTP) broadcastFunc
  80. ShouldSkip bool
  81. }{
  82. {
  83. Name: "Sync",
  84. WaitTime: time.Minute,
  85. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  86. return func(ctx context.Context, tx types.Tx) error {
  87. _, err := client.BroadcastTxSync(ctx, tx)
  88. return err
  89. }
  90. },
  91. },
  92. {
  93. Name: "Commit",
  94. WaitTime: 15 * time.Second,
  95. // TODO: turn this check back on if it can
  96. // return reliably. Currently these calls have
  97. // a hard timeout of 10s (server side
  98. // configured). The Sync check is probably
  99. // safe.
  100. ShouldSkip: true,
  101. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  102. return func(ctx context.Context, tx types.Tx) error {
  103. _, err := client.BroadcastTxCommit(ctx, tx)
  104. return err
  105. }
  106. },
  107. },
  108. {
  109. Name: "Async",
  110. WaitTime: 90 * time.Second,
  111. // TODO: turn this check back on if there's a
  112. // way to avoid failures in the case that the
  113. // transaction doesn't make it into the
  114. // mempool. (retries?)
  115. ShouldSkip: true,
  116. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  117. return func(ctx context.Context, tx types.Tx) error {
  118. _, err := client.BroadcastTxAsync(ctx, tx)
  119. return err
  120. }
  121. },
  122. },
  123. }
  124. for idx, test := range testCases {
  125. if test.ShouldSkip {
  126. continue
  127. }
  128. t.Run(test.Name, func(t *testing.T) {
  129. // testNode calls t.Parallel as well, so we should
  130. // have a copy of the
  131. test := testCases[idx]
  132. testNode(t, func(t *testing.T, node e2e.Node) {
  133. client, err := node.Client()
  134. require.NoError(t, err)
  135. // Generate a random value, to prevent duplicate tx errors when
  136. // manually running the test multiple times for a testnet.
  137. bz := make([]byte, 32)
  138. _, err = rand.Read(bz)
  139. require.NoError(t, err)
  140. key := fmt.Sprintf("testapp-tx-%v", node.Name)
  141. value := fmt.Sprintf("%x", bz)
  142. tx := types.Tx(fmt.Sprintf("%v=%v", key, value))
  143. require.NoError(t, test.BroadcastTx(client)(ctx, tx))
  144. hash := tx.Hash()
  145. require.Eventuallyf(t, func() bool {
  146. txResp, err := client.Tx(ctx, hash, false)
  147. return err == nil && bytes.Equal(txResp.Tx, tx)
  148. },
  149. test.WaitTime, // timeout
  150. time.Second, // interval
  151. "submitted tx %X wasn't committed after %v",
  152. hash, test.WaitTime,
  153. )
  154. abciResp, err := client.ABCIQuery(ctx, "", []byte(key))
  155. require.NoError(t, err)
  156. assert.Equal(t, key, string(abciResp.Response.Key))
  157. assert.Equal(t, value, string(abciResp.Response.Value))
  158. })
  159. })
  160. }
  161. }