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.

158 lines
4.3 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. block, err := client.Block(ctx, &info.Response.LastBlockHeight)
  41. require.NoError(t, err)
  42. require.EqualValues(t, info.Response.LastBlockAppHash, block.Block.AppHash.Bytes(),
  43. "app hash does not match last block's app hash")
  44. status, err := client.Status(ctx)
  45. require.NoError(t, err)
  46. require.True(t, status.SyncInfo.LatestBlockHeight >= info.Response.LastBlockHeight,
  47. "status out of sync with application")
  48. })
  49. }
  50. // Tests that we can set a value and retrieve it.
  51. func TestApp_Tx(t *testing.T) {
  52. type broadcastFunc func(context.Context, types.Tx) error
  53. testCases := []struct {
  54. Name string
  55. WaitTime time.Duration
  56. BroadcastTx func(client *http.HTTP) broadcastFunc
  57. ShouldSkip bool
  58. }{
  59. {
  60. Name: "Sync",
  61. WaitTime: time.Minute,
  62. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  63. return func(ctx context.Context, tx types.Tx) error {
  64. _, err := client.BroadcastTxSync(ctx, tx)
  65. return err
  66. }
  67. },
  68. },
  69. {
  70. Name: "Commit",
  71. WaitTime: 15 * time.Second,
  72. // TODO: turn this check back on if it can
  73. // return reliably. Currently these calls have
  74. // a hard timeout of 10s (server side
  75. // configured). The Sync check is probably
  76. // safe.
  77. ShouldSkip: true,
  78. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  79. return func(ctx context.Context, tx types.Tx) error {
  80. _, err := client.BroadcastTxCommit(ctx, tx)
  81. return err
  82. }
  83. },
  84. },
  85. {
  86. Name: "Async",
  87. WaitTime: 90 * time.Second,
  88. // TODO: turn this check back on if there's a
  89. // way to avoid failures in the case that the
  90. // transaction doesn't make it into the
  91. // mempool. (retries?)
  92. ShouldSkip: true,
  93. BroadcastTx: func(client *http.HTTP) broadcastFunc {
  94. return func(ctx context.Context, tx types.Tx) error {
  95. _, err := client.BroadcastTxAsync(ctx, tx)
  96. return err
  97. }
  98. },
  99. },
  100. }
  101. for idx, test := range testCases {
  102. if test.ShouldSkip {
  103. continue
  104. }
  105. t.Run(test.Name, func(t *testing.T) {
  106. // testNode calls t.Parallel as well, so we should
  107. // have a copy of the
  108. test := testCases[idx]
  109. testNode(t, func(t *testing.T, node e2e.Node) {
  110. client, err := node.Client()
  111. require.NoError(t, err)
  112. // Generate a random value, to prevent duplicate tx errors when
  113. // manually running the test multiple times for a testnet.
  114. bz := make([]byte, 32)
  115. _, err = rand.Read(bz)
  116. require.NoError(t, err)
  117. key := fmt.Sprintf("testapp-tx-%v", node.Name)
  118. value := fmt.Sprintf("%x", bz)
  119. tx := types.Tx(fmt.Sprintf("%v=%v", key, value))
  120. require.NoError(t, test.BroadcastTx(client)(ctx, tx))
  121. hash := tx.Hash()
  122. require.Eventuallyf(t, func() bool {
  123. txResp, err := client.Tx(ctx, hash, false)
  124. return err == nil && bytes.Equal(txResp.Tx, tx)
  125. },
  126. test.WaitTime, // timeout
  127. time.Second, // interval
  128. "submitted tx %X wasn't committed after %v",
  129. hash, test.WaitTime,
  130. )
  131. abciResp, err := client.ABCIQuery(ctx, "", []byte(key))
  132. require.NoError(t, err)
  133. assert.Equal(t, key, string(abciResp.Response.Key))
  134. assert.Equal(t, value, string(abciResp.Response.Value))
  135. })
  136. })
  137. }
  138. }