From d7eb09a9d9feba0b617d23dab623e7351b7b0537 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:58:29 +0200 Subject: [PATCH] test: migrate e2e/genutil to systemtest (backport #22325) (#22366) Co-authored-by: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Co-authored-by: Julien Robert --- tests/e2e/genutil/export_test.go | 232 ------------------------------- tests/go.mod | 2 +- tests/systemtests/export_test.go | 88 ++++++++++++ tests/systemtests/system.go | 4 +- 4 files changed, 92 insertions(+), 234 deletions(-) delete mode 100644 tests/e2e/genutil/export_test.go create mode 100644 tests/systemtests/export_test.go diff --git a/tests/e2e/genutil/export_test.go b/tests/e2e/genutil/export_test.go deleted file mode 100644 index 798885c0900f..000000000000 --- a/tests/e2e/genutil/export_test.go +++ /dev/null @@ -1,232 +0,0 @@ -//go:build e2e -// +build e2e - -package genutil_test - -import ( - "bytes" - "context" - "encoding/json" - "fmt" - "io" - "os" - "path" - "testing" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmtcfg "github.com/cometbft/cometbft/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" - - corectx "cosmossdk.io/core/context" - corestore "cosmossdk.io/core/store" - coretesting "cosmossdk.io/core/testing" - "cosmossdk.io/log" - "cosmossdk.io/simapp" - - "github.com/cosmos/cosmos-sdk/client" - "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/server/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - gentestutil "github.com/cosmos/cosmos-sdk/testutil/x/genutil" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" -) - -func TestExportCmd_ConsensusParams(t *testing.T) { - tempDir := t.TempDir() - _, ctx, _, cmd := setupApp(t, tempDir) - - output := &bytes.Buffer{} - cmd.SetOut(output) - assert.NilError(t, cmd.ExecuteContext(ctx)) - - var exportedAppGenesis genutiltypes.AppGenesis - err := json.Unmarshal(output.Bytes(), &exportedAppGenesis) - assert.NilError(t, err) - - assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Block.MaxBytes, exportedAppGenesis.Consensus.Params.Block.MaxBytes) - assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Block.MaxGas, exportedAppGenesis.Consensus.Params.Block.MaxGas) - - assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeDuration, exportedAppGenesis.Consensus.Params.Evidence.MaxAgeDuration) - assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Evidence.MaxAgeNumBlocks, exportedAppGenesis.Consensus.Params.Evidence.MaxAgeNumBlocks) - - assert.DeepEqual(t, simtestutil.DefaultConsensusParams.Validator.PubKeyTypes, exportedAppGenesis.Consensus.Params.Validator.PubKeyTypes) -} - -func TestExportCmd_HomeDir(t *testing.T) { - _, ctx, _, cmd := setupApp(t, t.TempDir()) - - v := ctx.Value(corectx.ViperContextKey) - viper, ok := v.(*viper.Viper) - require.True(t, ok) - viper.Set(flags.FlagHome, "foobar") - - err := cmd.ExecuteContext(ctx) - assert.ErrorContains(t, err, "stat foobar/config/genesis.json: no such file or directory") -} - -func TestExportCmd_Height(t *testing.T) { - testCases := []struct { - name string - flags []string - fastForward int64 - expHeight int64 - }{ - { - "should export correct height", - []string{}, - 5, 6, - }, - { - "should export correct height with --height", - []string{ - fmt.Sprintf("--height=%d", 3), - }, - 5, 4, - }, - { - "should export height 0 with --for-zero-height", - []string{ - fmt.Sprintf("--for-zero-height=%s", "true"), - }, - 2, 0, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - tempDir := t.TempDir() - app, ctx, _, cmd := setupApp(t, tempDir) - - // Fast forward to block `tc.fastForward`. - for i := int64(2); i <= tc.fastForward; i++ { - _, err := app.FinalizeBlock(&abci.FinalizeBlockRequest{ - Height: i, - }) - assert.NilError(t, err) - _, err = app.Commit() - assert.NilError(t, err) - } - - output := &bytes.Buffer{} - cmd.SetOut(output) - cmd.SetArgs(tc.flags) - assert.NilError(t, cmd.ExecuteContext(ctx)) - - var exportedAppGenesis genutiltypes.AppGenesis - err := json.Unmarshal(output.Bytes(), &exportedAppGenesis) - assert.NilError(t, err) - assert.Equal(t, tc.expHeight, exportedAppGenesis.InitialHeight) - }) - } -} - -func TestExportCmd_Output(t *testing.T) { - testCases := []struct { - name string - flags []string - outputDocument string - }{ - { - "should export state to the specified file", - []string{ - fmt.Sprintf("--%s=%s", flags.FlagOutputDocument, "foobar.json"), - }, - "foobar.json", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - tempDir := t.TempDir() - _, ctx, _, cmd := setupApp(t, tempDir) - - output := &bytes.Buffer{} - cmd.SetOut(output) - cmd.SetArgs(tc.flags) - assert.NilError(t, cmd.ExecuteContext(ctx)) - - var exportedAppGenesis genutiltypes.AppGenesis - f, err := os.ReadFile(tc.outputDocument) - assert.NilError(t, err) - assert.NilError(t, json.Unmarshal(f, &exportedAppGenesis)) - - // Cleanup - assert.NilError(t, os.Remove(tc.outputDocument)) - }) - } -} - -func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, genutiltypes.AppGenesis, *cobra.Command) { - t.Helper() - - logger := log.NewTestLogger(t) - err := createConfigFolder(tempDir) - assert.NilError(t, err) - - db := coretesting.NewMemDB() - app := simapp.NewSimApp(logger, db, nil, true, simtestutil.NewAppOptionsWithFlagHome(tempDir)) - - genesisState := simapp.GenesisStateWithSingleValidator(t, app) - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - assert.NilError(t, err) - - viper := viper.New() - err = gentestutil.WriteAndTrackCometConfig(viper, tempDir, cmtcfg.DefaultConfig()) - assert.NilError(t, err) - - clientCtx := client.Context{}.WithCodec(app.AppCodec()) - appGenesis := genutiltypes.AppGenesis{ - ChainID: "theChainId", - AppState: stateBytes, - Consensus: &genutiltypes.ConsensusGenesis{ - Validators: []sdk.GenesisValidator{}, - }, - } - - // save genesis file - err = genutil.ExportGenesisFile(&appGenesis, client.GetConfigFromViper(viper).GenesisFile()) - assert.NilError(t, err) - - _, err = app.InitChain(&abci.InitChainRequest{ - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: simtestutil.DefaultConsensusParams, - AppStateBytes: appGenesis.AppState, - }) - assert.NilError(t, err) - _, err = app.FinalizeBlock(&abci.FinalizeBlockRequest{ - Height: 1, - }) - assert.NilError(t, err) - _, err = app.Commit() - assert.NilError(t, err) - - cmd := genutilcli.ExportCmd(func(_ log.Logger, _ corestore.KVStoreWithBatch, _ io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOptions types.AppOptions, modulesToExport []string) (types.ExportedApp, error) { - var simApp *simapp.SimApp - if height != -1 { - simApp = simapp.NewSimApp(logger, db, nil, false, appOptions) - if err := simApp.LoadHeight(height); err != nil { - return types.ExportedApp{}, err - } - } else { - simApp = simapp.NewSimApp(logger, db, nil, true, appOptions) - } - - return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport) - }) - - ctx := context.Background() - ctx = context.WithValue(ctx, client.ClientContextKey, &clientCtx) - ctx = context.WithValue(ctx, corectx.ViperContextKey, viper) - - return app, ctx, appGenesis, cmd -} - -func createConfigFolder(dir string) error { - return os.Mkdir(path.Join(dir, "config"), 0o700) -} diff --git a/tests/go.mod b/tests/go.mod index 39969b7ebd78..a266bac67c65 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -43,7 +43,7 @@ require ( github.com/google/gofuzz v1.2.0 github.com/jhump/protoreflect v1.17.0 github.com/rs/zerolog v1.33.0 - github.com/spf13/cobra v1.8.1 + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 google.golang.org/grpc v1.67.1 diff --git a/tests/systemtests/export_test.go b/tests/systemtests/export_test.go new file mode 100644 index 000000000000..5d392d8ce10f --- /dev/null +++ b/tests/systemtests/export_test.go @@ -0,0 +1,88 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "os" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" +) + +func TestExportCmd_WithHeight(t *testing.T) { + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + sut.StartChain(t) + + // Wait 10s for producing blocks + time.Sleep(10 * time.Second) + + sut.StopChain() + + testCases := []struct { + name string + args []string + expZeroHeight bool + }{ + {"should export correct height", []string{"genesis", "export", "--home", sut.nodePath(0)}, false}, + {"should export correct height with --height", []string{"genesis", "export", "--height=5", "--home", sut.nodePath(0), "--log_level=disabled"}, false}, + {"should export height 0 with --for-zero-height", []string{"genesis", "export", "--for-zero-height=true", "--home", sut.nodePath(0)}, true}, + } + + for _, tc := range testCases { + res := cli.RunCommandWithArgs(tc.args...) + height := gjson.Get(res, "initial_height").Int() + if tc.expZeroHeight { + require.Equal(t, height, int64(0)) + } else { + require.Greater(t, height, int64(0)) + } + + // Check consensus params of exported state + maxGas := gjson.Get(res, "consensus.params.block.max_gas").Int() + require.Equal(t, maxGas, int64(MaxGas)) + } +} + +func TestExportCmd_WithFileFlag(t *testing.T) { + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + exportFile := "foobar.json" + + sut.StartChain(t) + + // Wait 10s for producing blocks + time.Sleep(10 * time.Second) + + sut.StopChain() + + testCases := []struct { + name string + args []string + expErr bool + errMsg string + }{ + {"invalid home dir", []string{"genesis", "export", "--home=foo"}, true, "no such file or directory"}, + {"should export state to the specified file", []string{"genesis", "export", fmt.Sprintf("--output-document=%s", exportFile), "--home", sut.nodePath(0)}, false, ""}, + } + + for _, tc := range testCases { + if tc.expErr { + assertOutput := func(_ assert.TestingT, gotErr error, gotOutputs ...interface{}) bool { + require.Contains(t, gotOutputs[0], tc.errMsg) + return false + } + cli.WithRunErrorMatcher(assertOutput).RunCommandWithArgs(tc.args...) + } else { + cli.RunCommandWithArgs(tc.args...) + require.FileExists(t, exportFile) + err := os.Remove(exportFile) + require.NoError(t, err) + } + } +} diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index adaa6da91d77..7105ff400ed1 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -35,6 +35,8 @@ var ( // ExecBinaryUnversionedRegExp regular expression to extract the unversioned binary name ExecBinaryUnversionedRegExp = regexp.MustCompile(`^(\w+)-?.*$`) + + MaxGas = 10_000_000 ) type TestnetInitializer interface { @@ -130,7 +132,7 @@ func (s *SystemUnderTest) SetupChain() { panic(fmt.Sprintf("failed to load genesis: %s", err)) } - genesisBz, err = sjson.SetRawBytes(genesisBz, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, 10_000_000))) + genesisBz, err = sjson.SetRawBytes(genesisBz, "consensus.params.block.max_gas", []byte(fmt.Sprintf(`"%d"`, MaxGas))) if err != nil { panic(fmt.Sprintf("failed to set block max gas: %s", err)) }