Skip to content

Commit b0ffa7b

Browse files
committed
add e2e tests
1 parent 5b07d25 commit b0ffa7b

14 files changed

+1318
-249
lines changed

interchaintest/basic_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,46 +13,64 @@ import (
1313
"go.uber.org/zap/zaptest"
1414
)
1515

16+
// TestBasicChain is a fundamental test that verifies the basic functionality of a single chain.
17+
// This test ensures that:
18+
// 1. The chain can be properly initialized and started
19+
// 2. The chain has the correct configuration (denom, chain ID, gas prices)
20+
// 3. Users can be created and funded with tokens
21+
// 4. The balance query functionality works correctly
1622
func TestBasicChain(t *testing.T) {
1723
ctx := context.Background()
1824
rep := testreporter.NewNopReporter()
1925
eRep := rep.RelayerExecReporter(t)
26+
// Set up Docker environment for the test
2027
client, network := interchaintest.DockerSetup(t)
2128

29+
// Create a chain factory with our default chain specification
2230
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
2331
&DefaultChainSpec,
2432
})
2533

34+
// Initialize the chains from the factory
2635
chains, err := cf.Chains(t.Name())
2736
require.NoError(t, err)
2837

38+
// Get the first chain from the list (we only have one in this test)
2939
chain := chains[0].(*cosmos.CosmosChain)
3040

31-
// Setup Interchain
41+
// Setup Interchain environment with our single chain
3242
ic := interchaintest.NewInterchain().
3343
AddChain(chain)
3444

45+
// Build the interchain environment
3546
require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
3647
TestName: t.Name(),
3748
Client: client,
3849
NetworkID: network,
3950
SkipPathCreation: false,
4051
}))
52+
// Clean up resources when the test completes
4153
t.Cleanup(func() {
4254
_ = ic.Close()
4355
})
4456

57+
// Create and fund a test user with 10 million tokens
4558
amt := math.NewInt(10_000_000)
4659
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", amt,
4760
chain,
4861
)
4962
user := users[0]
5063

64+
t.Run("validate configuration", func(t *testing.T) {
65+
// Check that the chain is configured correctly with the expected values
66+
require.Equal(t, chain.Config().Denom, "npush")
67+
require.Equal(t, chain.Config().ChainID, "localchain-1")
68+
require.Equal(t, chain.Config().GasPrices, "0npush")
69+
})
5170
t.Run("validate funding", func(t *testing.T) {
71+
// Verify that the user was properly funded with the expected amount
5272
bal, err := chain.BankQueryBalance(ctx, user.FormattedAddress(), chain.Config().Denom)
5373
require.NoError(t, err)
5474
require.EqualValues(t, amt, bal)
55-
5675
})
57-
5876
}

interchaintest/blocktime_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package e2e
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"cosmossdk.io/math"
9+
"github.com/strangelove-ventures/interchaintest/v8"
10+
"github.com/strangelove-ventures/interchaintest/v8/chain/cosmos"
11+
"github.com/strangelove-ventures/interchaintest/v8/testreporter"
12+
"github.com/strangelove-ventures/interchaintest/v8/testutil"
13+
"github.com/stretchr/testify/require"
14+
"go.uber.org/zap/zaptest"
15+
)
16+
17+
// TestBlockTimeConfiguration verifies that the blockchain respects a custom block time parameter.
18+
// This test ensures that:
19+
// 1. The chain can be properly initialized with a custom block time
20+
// 2. Blocks are produced at approximately the configured interval
21+
// 3. The actual block production time is close to the configured block time
22+
func TestBlockTimeConfiguration(t *testing.T) {
23+
ctx := context.Background()
24+
rep := testreporter.NewNopReporter()
25+
eRep := rep.RelayerExecReporter(t)
26+
27+
// Set up Docker environment for the test
28+
client, network := interchaintest.DockerSetup(t)
29+
30+
// Set a custom block time (2 seconds instead of default)
31+
customBlockTime := 2 * time.Second
32+
33+
// Create a modified chain spec with custom block time
34+
// Note: We need to modify the genesis to set the block time
35+
chainSpec := DefaultChainSpec
36+
37+
// Create a copy of the default genesis and add our custom block time
38+
genesisKVs := make([]cosmos.GenesisKV, len(DefaultGenesis))
39+
copy(genesisKVs, DefaultGenesis)
40+
41+
// Add the block time configuration to the genesis
42+
genesisKVs = append(genesisKVs,
43+
cosmos.NewGenesisKV("consensus.params.block.time_iota_ms", "2000")) // 2000ms = 2s
44+
45+
// Set the modified genesis
46+
chainSpec.ModifyGenesis = cosmos.ModifyGenesis(genesisKVs)
47+
48+
// Create a chain factory with our modified chain specification
49+
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
50+
&chainSpec,
51+
})
52+
53+
// Initialize the chains from the factory
54+
chains, err := cf.Chains(t.Name())
55+
require.NoError(t, err)
56+
57+
// Get the first chain from the list (we only have one in this test)
58+
chain := chains[0].(*cosmos.CosmosChain)
59+
60+
// Setup Interchain environment with our single chain
61+
ic := interchaintest.NewInterchain().
62+
AddChain(chain)
63+
64+
// Build the interchain environment
65+
require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
66+
TestName: t.Name(),
67+
Client: client,
68+
NetworkID: network,
69+
SkipPathCreation: true,
70+
}))
71+
72+
// Clean up resources when the test completes
73+
t.Cleanup(func() {
74+
_ = ic.Close()
75+
})
76+
77+
// Create and fund a test user with 10 million tokens
78+
amt := math.NewInt(10_000_000)
79+
users := interchaintest.GetAndFundTestUsers(t, ctx, "default", amt, chain)
80+
user := users[0]
81+
82+
// Verify that the user was properly funded with the expected amount
83+
bal, err := chain.BankQueryBalance(ctx, user.FormattedAddress(), chain.Config().Denom)
84+
require.NoError(t, err)
85+
require.EqualValues(t, amt, bal)
86+
87+
// Get the current block height
88+
height, err := chain.Height(ctx)
89+
require.NoError(t, err)
90+
startHeight := height
91+
92+
// Record the start time
93+
startTime := time.Now()
94+
95+
// Wait for a specific number of blocks to be produced
96+
numBlocksToWait := 5
97+
err = testutil.WaitForBlocks(ctx, numBlocksToWait, chain)
98+
require.NoError(t, err)
99+
100+
// Get the new block height
101+
height, err = chain.Height(ctx)
102+
require.NoError(t, err)
103+
endHeight := height
104+
105+
// Calculate the elapsed time
106+
elapsedTime := time.Since(startTime)
107+
108+
// Calculate the actual number of blocks produced
109+
blocksProduced := endHeight - startHeight
110+
111+
// Calculate the average time per block
112+
avgTimePerBlock := elapsedTime / time.Duration(blocksProduced)
113+
114+
// Verify that the average block time is close to the configured block time
115+
// Allow for a 50% margin of error to account for network delays and other factors
116+
maxAllowedDeviation := time.Duration(float64(customBlockTime) * 0.5)
117+
118+
t.Logf("Configured block time: %v", customBlockTime)
119+
t.Logf("Actual average block time: %v", avgTimePerBlock)
120+
t.Logf("Blocks produced: %d", blocksProduced)
121+
t.Logf("Elapsed time: %v", elapsedTime)
122+
123+
// Check if the average block time is within the acceptable range
124+
require.InDelta(t, customBlockTime.Seconds(), avgTimePerBlock.Seconds(),
125+
maxAllowedDeviation.Seconds(),
126+
"Average block time (%v) is not close enough to configured block time (%v)",
127+
avgTimePerBlock, customBlockTime)
128+
}

interchaintest/cosmwasm_test.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,86 +13,121 @@ import (
1313
"go.uber.org/zap/zaptest"
1414
)
1515

16+
// GetCountResponse represents the response structure from the CosmWasm contract's get_count query
1617
type GetCountResponse struct {
1718
// {"data":{"count":0}}
1819
Data *GetCountObj `json:"data"`
1920
}
2021

22+
// GetCountObj holds the actual count value from the contract's state
2123
type GetCountObj struct {
2224
Count int64 `json:"count"`
2325
}
2426

27+
// TestCosmWasmIntegration verifies that CosmWasm smart contracts can be deployed and executed on the chain.
28+
// This test ensures that:
29+
// 1. A chain with CosmWasm support can be properly initialized
30+
// 2. A CosmWasm contract can be stored on the chain
31+
// 3. The contract can be instantiated with initial state
32+
// 4. Contract execution (state changes) works correctly
33+
// 5. Contract queries return the expected results
2534
func TestCosmWasmIntegration(t *testing.T) {
2635
t.Parallel()
2736
ctx := context.Background()
2837
rep := testreporter.NewNopReporter()
2938
eRep := rep.RelayerExecReporter(t)
39+
// Set up Docker environment for the test
3040
client, network := interchaintest.DockerSetup(t)
3141

42+
// Create a chain factory with our default chain specification
3243
cf := interchaintest.NewBuiltinChainFactory(zaptest.NewLogger(t), []*interchaintest.ChainSpec{
3344
&DefaultChainSpec,
3445
})
3546

47+
// Initialize the chain from the factory
3648
chains, err := cf.Chains(t.Name())
3749
require.NoError(t, err)
3850

51+
// Get the chain from the list (we only have one in this test)
3952
chain := chains[0].(*cosmos.CosmosChain)
4053

41-
// Setup Interchain
54+
// Setup Interchain environment with our single chain
4255
ic := interchaintest.NewInterchain().
4356
AddChain(chain)
4457

58+
// Build the interchain environment
4559
require.NoError(t, ic.Build(ctx, eRep, interchaintest.InterchainBuildOptions{
4660
TestName: t.Name(),
4761
Client: client,
4862
NetworkID: network,
4963
SkipPathCreation: false,
5064
}))
65+
// Clean up resources when the test completes
5166
t.Cleanup(func() {
5267
_ = ic.Close()
5368
})
5469

70+
// Create and fund a test user
5571
users := interchaintest.GetAndFundTestUsers(t, ctx, t.Name(), GenesisFundsAmount, chain)
5672
user := users[0]
5773

74+
// Execute the standard CosmWasm test flow
5875
StdExecute(t, ctx, chain, user)
5976
}
6077

78+
// StdExecute performs a standard flow of CosmWasm operations:
79+
// 1. Uploads a contract to the chain
80+
// 2. Instantiates the contract with initial state
81+
// 3. Executes a transaction on the contract to increment the counter
82+
// 4. Queries the contract to verify the state change
6183
func StdExecute(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, user ibc.Wallet) (contractAddr string) {
84+
// Upload and instantiate the contract with initial count of 0
6285
_, contractAddr = SetupContract(t, ctx, chain, user.KeyName(), "contracts/cw_template.wasm", `{"count":0}`)
86+
87+
// Execute the increment operation on the contract
6388
chain.ExecuteContract(ctx, user.KeyName(), contractAddr, `{"increment":{}}`, "--fees", "10000"+chain.Config().Denom)
6489

90+
// Query the contract to verify the count was incremented
6591
var res GetCountResponse
6692
err := SmartQueryString(t, ctx, chain, contractAddr, `{"get_count":{}}`, &res)
6793
require.NoError(t, err)
6894

95+
// Verify the count is now 1 after the increment operation
6996
require.Equal(t, int64(1), res.Data.Count)
7097

7198
return contractAddr
7299
}
73100

101+
// SmartQueryString performs a query on a CosmWasm contract and unmarshals the result into the provided response object
74102
func SmartQueryString(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, contractAddr, queryMsg string, res interface{}) error {
103+
// Convert the query string to a JSON map for the chain's QueryContract method
75104
var jsonMap map[string]interface{}
76105
if err := json.Unmarshal([]byte(queryMsg), &jsonMap); err != nil {
77106
t.Fatal(err)
78107
}
108+
// Execute the query and unmarshal the result into the provided response object
79109
err := chain.QueryContract(ctx, contractAddr, jsonMap, &res)
80110
return err
81111
}
82112

113+
// SetupContract uploads a CosmWasm contract to the chain and instantiates it
114+
// Returns the code ID and contract address
83115
func SetupContract(t *testing.T, ctx context.Context, chain *cosmos.CosmosChain, keyname string, fileLoc string, message string, extraFlags ...string) (codeId, contract string) {
116+
// Store the contract on the chain
84117
codeId, err := chain.StoreContract(ctx, keyname, fileLoc)
85118
if err != nil {
86119
t.Fatal(err)
87120
}
88121

122+
// Determine if we need to add the --no-admin flag
89123
needsNoAdminFlag := true
90124
for _, flag := range extraFlags {
91125
if flag == "--admin" {
92126
needsNoAdminFlag = false
93127
}
94128
}
95129

130+
// Instantiate the contract with the provided message
96131
contractAddr, err := chain.InstantiateContract(ctx, keyname, codeId, message, needsNoAdminFlag, extraFlags...)
97132
if err != nil {
98133
t.Fatal(err)

0 commit comments

Comments
 (0)