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.

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