From c29d3e819f357964fb9bbde98686d3504d68e610 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 14:02:01 +0200 Subject: [PATCH] test(server/v2): Add system-test for store's command (backport #21357) (#22093) Co-authored-by: Hieu Vu <72878483+hieuvubk@users.noreply.github.com> Co-authored-by: Julien Robert --- tests/systemtests/cli.go | 7 +++ tests/systemtests/snapshots_test.go | 98 +++++++++++++++++++++++++++++ tests/systemtests/system.go | 8 ++- tests/systemtests/testnet_init.go | 22 ++++++- 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 tests/systemtests/snapshots_test.go diff --git a/tests/systemtests/cli.go b/tests/systemtests/cli.go index fcc6bb518c..d7ac2368ae 100644 --- a/tests/systemtests/cli.go +++ b/tests/systemtests/cli.go @@ -179,6 +179,13 @@ func (c CLIWrapper) RunAndWait(args ...string) string { return txResult } +// RunCommandWithArgs use for run cli command, not tx +func (c CLIWrapper) RunCommandWithArgs(args ...string) string { + c.t.Helper() + execOutput, _ := c.run(args) + return execOutput +} + // AwaitTxCommitted wait for tx committed on chain // returns the server execution result and true when found within 3 blocks. func (c CLIWrapper) AwaitTxCommitted(submitResp string, timeout ...time.Duration) (string, bool) { diff --git a/tests/systemtests/snapshots_test.go b/tests/systemtests/snapshots_test.go new file mode 100644 index 0000000000..42569a0317 --- /dev/null +++ b/tests/systemtests/snapshots_test.go @@ -0,0 +1,98 @@ +//go:build system_test + +package systemtests + +import ( + "fmt" + "github.com/stretchr/testify/require" + "os" + "testing" +) + +func TestSnapshots(t *testing.T) { + + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + sut.StartChain(t) + + // Wait for chain produce some blocks + sut.AwaitNBlocks(t, 6) + // Stop all nodes + sut.StopChain() + + var ( + command string + restoreableDirs []string + ) + node0Dir := sut.NodeDir(0) + if isV2() { + command = "store" + restoreableDirs = []string{fmt.Sprintf("%s/data/application.db", node0Dir), fmt.Sprintf("%s/data/ss", node0Dir)} + } else { + command = "snapshots" + restoreableDirs = []string{fmt.Sprintf("%s/data/application.db", node0Dir)} + } + + // export snapshot at height 5 + res := cli.RunCommandWithArgs(command, "export", "--height=5", fmt.Sprintf("--home=%s", node0Dir)) + require.Contains(t, res, "Snapshot created at height 5") + require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Check snapshots list + res = cli.RunCommandWithArgs(command, "list", fmt.Sprintf("--home=%s", node0Dir)) + require.Contains(t, res, "height: 5") + + // Dump snapshot + res = cli.RunCommandWithArgs(command, "dump", "5", "3", fmt.Sprintf("--home=%s", node0Dir), fmt.Sprintf("--output=%s/5-3.tar.gz", node0Dir)) + // Check if output file exist + require.FileExists(t, fmt.Sprintf("%s/5-3.tar.gz", node0Dir)) + + // Delete snapshots + res = cli.RunCommandWithArgs(command, "delete", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + require.NoDirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Load snapshot from file + res = cli.RunCommandWithArgs(command, "load", fmt.Sprintf("%s/5-3.tar.gz", node0Dir), fmt.Sprintf("--home=%s", node0Dir)) + require.DirExists(t, fmt.Sprintf("%s/data/snapshots/5/3", node0Dir)) + + // Restore from snapshots + for _, dir := range restoreableDirs { + require.NoError(t, os.RemoveAll(dir)) + } + // Remove database + err := os.RemoveAll(fmt.Sprintf("%s/data/application.db", node0Dir)) + require.NoError(t, err) + if isV2() { + require.NoError(t, os.RemoveAll(fmt.Sprintf("%s/data/ss", node0Dir))) + } + + res = cli.RunCommandWithArgs(command, "restore", "5", "3", fmt.Sprintf("--home=%s", node0Dir)) + for _, dir := range restoreableDirs { + require.DirExists(t, dir) + } +} + +func TestPrune(t *testing.T) { + sut.ResetChain(t) + cli := NewCLIWrapper(t, sut, verbose) + + sut.StartChain(t) + + // Wait for chain produce some blocks + sut.AwaitNBlocks(t, 6) + + // Stop all nodes + sut.StopChain() + + node0Dir := sut.NodeDir(0) + + // prune + var command []string + if isV2() { + command = []string{"store", "prune", "--keep-recent=1"} + } else { + command = []string{"prune", "everything"} + } + res := cli.RunCommandWithArgs(append(command, fmt.Sprintf("--home=%s", node0Dir))...) + require.Contains(t, res, "successfully pruned the application root multi stores") +} diff --git a/tests/systemtests/system.go b/tests/systemtests/system.go index 7b7fa864ba..fd6a53781e 100644 --- a/tests/systemtests/system.go +++ b/tests/systemtests/system.go @@ -373,7 +373,7 @@ func (s *SystemUnderTest) AwaitNBlocks(t *testing.T, n int64, timeout ...time.Du s.AwaitBlockHeight(t, s.CurrentHeight()+n, timeout...) } -// AwaitBlockHeight blocks until te target height is reached. An optional timeout parameter can be passed to abort early +// AwaitBlockHeight blocks until the target height is reached. An optional timeout parameter can be passed to abort early func (s *SystemUnderTest) AwaitBlockHeight(t *testing.T, targetHeight int64, timeout ...time.Duration) { t.Helper() require.Greater(t, targetHeight, s.currentHeight.Load()) @@ -590,6 +590,7 @@ func (s *SystemUnderTest) startNodesAsync(t *testing.T, xargs ...string) { }) } +// tracks the PID in state with a go routine waiting for the shutdown completion to unregister func (s *SystemUnderTest) awaitProcessCleanup(cmd *exec.Cmd) { pid := cmd.Process.Pid s.pidsLock.Lock() @@ -610,6 +611,11 @@ func (s *SystemUnderTest) withEachNodeHome(cb func(i int, home string)) { } } +// NodeDir returns the workdir and path to the node home folder. +func (s *SystemUnderTest) NodeDir(i int) string { + return filepath.Join(WorkDir, s.nodePath(i)) +} + // nodePath returns the path of the node within the work dir. not absolute func (s *SystemUnderTest) nodePath(i int) string { return NodePath(i, s.outputDir, s.projectName) diff --git a/tests/systemtests/testnet_init.go b/tests/systemtests/testnet_init.go index 43c5409a8c..bdb2a85d25 100644 --- a/tests/systemtests/testnet_init.go +++ b/tests/systemtests/testnet_init.go @@ -13,6 +13,12 @@ import ( "github.com/creachadair/tomledit/parser" ) +// isV2 checks if the tests run with simapp v2 +func isV2() bool { + buildOptions := os.Getenv("COSMOS_BUILD_OPTIONS") + return strings.Contains(buildOptions, "v2") +} + // SingleHostTestnetCmdInitializer default testnet cmd that supports the --single-host param type SingleHostTestnetCmdInitializer struct { execBinary string @@ -53,10 +59,16 @@ func (s SingleHostTestnetCmdInitializer) Initialize() { "--output-dir=" + s.outputDir, "--validator-count=" + strconv.Itoa(s.initialNodesCount), "--keyring-backend=test", - "--minimum-gas-prices=" + s.minGasPrice, "--commit-timeout=" + s.commitTimeout.String(), "--single-host", } + + if isV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) out, err := RunShellCmd(s.execBinary, args...) if err != nil { @@ -108,8 +120,14 @@ func (s ModifyConfigYamlInitializer) Initialize() { "--output-dir=" + s.outputDir, "--v=" + strconv.Itoa(s.initialNodesCount), "--keyring-backend=test", - "--minimum-gas-prices=" + s.minGasPrice, } + + if isV2() { + args = append(args, "--server.minimum-gas-prices="+s.minGasPrice) + } else { + args = append(args, "--minimum-gas-prices="+s.minGasPrice) + } + s.log(fmt.Sprintf("+++ %s %s\n", s.execBinary, strings.Join(args, " "))) out, err := RunShellCmd(s.execBinary, args...)