570 lines
18 KiB
Go
570 lines
18 KiB
Go
//go:build linux || darwin
|
|
|
|
package cosmovisor_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"cosmossdk.io/log"
|
|
"cosmossdk.io/tools/cosmovisor"
|
|
upgradetypes "cosmossdk.io/x/upgrade/types"
|
|
)
|
|
|
|
var workDir string
|
|
|
|
func init() {
|
|
workDir, _ = os.Getwd()
|
|
}
|
|
|
|
// TestLaunchProcess will try running the script a few times and watch upgrades work properly
|
|
// and args are passed through
|
|
func TestLaunchProcess(t *testing.T) {
|
|
// binaries from testdata/validate directory
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/validate"),
|
|
cosmovisor.Config{
|
|
Name: "dummyd",
|
|
PollInterval: 15,
|
|
UnsafeSkipBackup: true,
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor")
|
|
|
|
// should run the genesis binary and produce expected output
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
upgradeFile := cfg.UpgradeInfoFilePath()
|
|
|
|
args := []string{"foo", "bar", "1234", upgradeFile}
|
|
doUpgrade, err := launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String())
|
|
|
|
// ensure this is upgraded now and produces new output
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, rPath, currentBin)
|
|
args = []string{"second", "run", "--verbose"}
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.False(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String())
|
|
|
|
// ended without other upgrade
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, rPath, currentBin)
|
|
}
|
|
|
|
// TestPlanDisableRecase will test upgrades without lower case plan names
|
|
func TestPlanDisableRecase(t *testing.T) {
|
|
// binaries from testdata/validate directory
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/norecase"),
|
|
cosmovisor.Config{
|
|
Name: "dummyd",
|
|
PollInterval: 20,
|
|
UnsafeSkipBackup: true,
|
|
DisableRecase: true,
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor")
|
|
|
|
// should run the genesis binary and produce expected output
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
upgradeFile := cfg.UpgradeInfoFilePath()
|
|
|
|
args := []string{"foo", "bar", "1234", upgradeFile}
|
|
doUpgrade, err := launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\n", upgradeFile), stdout.String())
|
|
|
|
// ensure this is upgraded now and produces new output
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("Chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
args = []string{"second", "run", "--verbose"}
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.False(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String())
|
|
|
|
// ended without other upgrade
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("Chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
}
|
|
|
|
func TestLaunchProcessWithRestartDelay(t *testing.T) {
|
|
// binaries from testdata/validate directory
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/validate"),
|
|
cosmovisor.Config{
|
|
Name: "dummyd",
|
|
RestartDelay: 5 * time.Second,
|
|
PollInterval: 20,
|
|
UnsafeSkipBackup: true,
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor")
|
|
|
|
// should run the genesis binary and produce expected output
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
upgradeFile := cfg.UpgradeInfoFilePath()
|
|
|
|
start := time.Now()
|
|
doUpgrade, err := launcher.Run([]string{"foo", "bar", "1234", upgradeFile}, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
|
|
// may not be the best way but the fastest way to check we meet the delay
|
|
// in addition to comparing both the runtime of this test and TestLaunchProcess in addition
|
|
if time.Since(start) < cfg.RestartDelay {
|
|
require.FailNow(t, "restart delay not met")
|
|
}
|
|
}
|
|
|
|
// TestPlanShutdownGrace will test upgrades without lower case plan names
|
|
func TestPlanShutdownGrace(t *testing.T) {
|
|
// binaries from testdata/validate directory
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/dontdie"),
|
|
cosmovisor.Config{
|
|
Name: "dummyd",
|
|
PollInterval: 15,
|
|
UnsafeSkipBackup: true,
|
|
ShutdownGrace: 2 * time.Second,
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmosvisor")
|
|
|
|
// should run the genesis binary and produce expected output
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
upgradeFile := cfg.UpgradeInfoFilePath()
|
|
|
|
args := []string{"foo", "bar", "1234", upgradeFile}
|
|
doUpgrade, err := launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, fmt.Sprintf("Genesis foo bar 1234 %s\nUPGRADE \"Chain2\" NEEDED at height: 49: {}\nWARN Need Flush\nFlushed\n", upgradeFile), stdout.String())
|
|
|
|
// ensure this is upgraded now and produces new output
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
args = []string{"second", "run", "--verbose"}
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.False(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 2 is live!\nArgs: second run --verbose\nFinished successfully\n", stdout.String())
|
|
|
|
// ended without other upgrade
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
}
|
|
|
|
// TestLaunchProcess will try running the script a few times and watch upgrades work properly
|
|
// and args are passed through
|
|
func TestLaunchProcessWithDownloads(t *testing.T) {
|
|
// test case upgrade path (binaries from testdata/download directory):
|
|
// genesis -> chain2-zip_bin
|
|
// chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir
|
|
// chain3-zip_dir - doesn't upgrade
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/download"),
|
|
cosmovisor.Config{
|
|
Name: "autod",
|
|
AllowDownloadBinaries: true,
|
|
PollInterval: 100,
|
|
UnsafeSkipBackup: true,
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmovisor")
|
|
upgradeFilename := cfg.UpgradeInfoFilePath()
|
|
|
|
// should run the genesis binary and produce expected output
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
args := []string{"some", "args", upgradeFilename}
|
|
doUpgrade, err := launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String())
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
// start chain2
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
args = []string{"run", "--fast", upgradeFilename}
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String())
|
|
// ended with one more upgrade
|
|
require.True(t, doUpgrade)
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain3"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
// run the last chain
|
|
args = []string{"end", "--halt", upgradeFilename}
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.False(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String())
|
|
|
|
// and this doesn't upgrade
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain3"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
}
|
|
|
|
// TestLaunchProcessWithDownloadsAndMissingPreupgrade will try running the script a few times and watch upgrades work properly
|
|
// and args are passed through
|
|
func TestLaunchProcessWithDownloadsAndMissingPreupgrade(t *testing.T) {
|
|
// test case upgrade path (binaries from testdata/download directory):
|
|
// genesis -> chain2-zip_bin
|
|
// chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir
|
|
// chain3-zip_dir - doesn't upgrade
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/download"),
|
|
cosmovisor.Config{
|
|
Name: "autod",
|
|
AllowDownloadBinaries: true,
|
|
PollInterval: 100,
|
|
UnsafeSkipBackup: true,
|
|
CustomPreUpgrade: "missing.sh",
|
|
},
|
|
)
|
|
|
|
logger := log.NewTestLogger(t).With(log.ModuleKey, "cosmovisor")
|
|
upgradeFilename := cfg.UpgradeInfoFilePath()
|
|
|
|
// should run the genesis binary and produce expected output
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
// Missing Preupgrade Script
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
args := []string{"some", "args", upgradeFilename}
|
|
_, err = launcher.Run(args, stdin, stdout, stderr)
|
|
|
|
require.ErrorContains(t, err, "missing.sh")
|
|
require.ErrorIs(t, err, fs.ErrNotExist)
|
|
}
|
|
|
|
// TestLaunchProcessWithDownloadsAndPreupgrade will try running the script a few times and watch upgrades work properly
|
|
// and args are passed through
|
|
func TestLaunchProcessWithDownloadsAndPreupgrade(t *testing.T) {
|
|
// test case upgrade path (binaries from testdata/download directory):
|
|
// genesis -> chain2-zip_bin
|
|
// chain2-zip_bin -> ref_to_chain3-zip_dir.json = (json for the next download instructions) -> chain3-zip_dir
|
|
// chain3-zip_dir - doesn't upgrade
|
|
cfg := prepareConfig(
|
|
t,
|
|
fmt.Sprintf("%s/%s", workDir, "testdata/download"),
|
|
cosmovisor.Config{
|
|
Name: "autod",
|
|
AllowDownloadBinaries: true,
|
|
PollInterval: 100,
|
|
UnsafeSkipBackup: true,
|
|
CustomPreUpgrade: "preupgrade.sh",
|
|
},
|
|
)
|
|
|
|
buf := newBuffer() // inspect output using buf.String()
|
|
logger := log.NewLogger(buf).With(log.ModuleKey, "cosmovisor")
|
|
upgradeFilename := cfg.UpgradeInfoFilePath()
|
|
|
|
// should run the genesis binary and produce expected output
|
|
currentBin, err := cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err := filepath.EvalSymlinks(cfg.GenesisBin())
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
launcher, err := cosmovisor.NewLauncher(logger, cfg)
|
|
require.NoError(t, err)
|
|
|
|
stdin, _ := os.Open(os.DevNull)
|
|
stdout, stderr := newBuffer(), newBuffer()
|
|
args := []string{"some", "args", upgradeFilename}
|
|
doUpgrade, err := launcher.Run(args, stdin, stdout, stderr)
|
|
|
|
require.NoError(t, err)
|
|
require.True(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Genesis autod. Args: some args "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain2" NEEDED at height: 49: zip_binary`+"\n", stdout.String())
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain2"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
// should have preupgrade.sh results
|
|
require.FileExists(t, filepath.Join(cfg.Home, "upgrade_name_chain2_height_49"))
|
|
|
|
// start chain2
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
args = []string{"run", "--fast", upgradeFilename}
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 2 from zipped binary\nArgs: run --fast "+upgradeFilename+"\n"+`ERROR: UPGRADE "chain3" NEEDED at height: 936: ref_to_chain3-zip_dir.json module=main`+"\n", stdout.String())
|
|
// ended with one more upgrade
|
|
require.True(t, doUpgrade)
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain3"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
|
|
// should have preupgrade.sh results
|
|
require.FileExists(t, filepath.Join(cfg.Home, "upgrade_name_chain3_height_936"))
|
|
|
|
// run the last chain
|
|
args = []string{"end", "--halt", upgradeFilename}
|
|
stdout.Reset()
|
|
stderr.Reset()
|
|
doUpgrade, err = launcher.Run(args, stdin, stdout, stderr)
|
|
require.NoError(t, err)
|
|
require.False(t, doUpgrade)
|
|
require.Empty(t, stderr.String())
|
|
require.Equal(t, "Chain 3 from zipped directory\nArgs: end --halt "+upgradeFilename+"\n", stdout.String())
|
|
|
|
// and this doesn't upgrade
|
|
currentBin, err = cfg.CurrentBin()
|
|
require.NoError(t, err)
|
|
rPath, err = filepath.EvalSymlinks(cfg.UpgradeBin("chain3"))
|
|
require.NoError(t, err)
|
|
require.Equal(t, rPath, currentBin)
|
|
}
|
|
|
|
// TestSkipUpgrade tests heights that are identified to be skipped and return if upgrade height matches the skip heights
|
|
func TestSkipUpgrade(t *testing.T) {
|
|
cases := []struct {
|
|
args []string
|
|
upgradeInfo upgradetypes.Plan
|
|
expectRes bool
|
|
}{{
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades"},
|
|
upgradeInfo: upgradetypes.Plan{Name: "upgrade1", Info: "some info", Height: 123},
|
|
expectRes: false,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "--abcd"},
|
|
upgradeInfo: upgradetypes.Plan{Name: "upgrade1", Info: "some info", Height: 123},
|
|
expectRes: false,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "--abcd"},
|
|
upgradeInfo: upgradetypes.Plan{Name: "upgrade1", Info: "some info", Height: 11},
|
|
expectRes: false,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd"},
|
|
upgradeInfo: upgradetypes.Plan{Name: "upgrade1", Info: "some info", Height: 20},
|
|
expectRes: true,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd", "34"},
|
|
upgradeInfo: upgradetypes.Plan{Name: "upgrade1", Info: "some info", Height: 34},
|
|
expectRes: false,
|
|
}}
|
|
|
|
for i := range cases {
|
|
tc := cases[i]
|
|
require := require.New(t)
|
|
h := cosmovisor.IsSkipUpgradeHeight(tc.args, tc.upgradeInfo)
|
|
require.Equal(h, tc.expectRes)
|
|
}
|
|
}
|
|
|
|
// TestUpgradeSkipHeights tests if correct skip upgrade heights are identified from the cli args
|
|
func TestUpgradeSkipHeights(t *testing.T) {
|
|
cases := []struct {
|
|
args []string
|
|
expectRes []int
|
|
}{{
|
|
args: []string{},
|
|
expectRes: nil,
|
|
}, {
|
|
args: []string{"appb", "start"},
|
|
expectRes: nil,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades"},
|
|
expectRes: nil,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "--abcd"},
|
|
expectRes: nil,
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "--abcd"},
|
|
expectRes: []int{10},
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd"},
|
|
expectRes: []int{10, 20},
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "20", "--abcd", "34"},
|
|
expectRes: []int{10, 20},
|
|
}, {
|
|
args: []string{"appb", "start", "--unsafe-skip-upgrades", "10", "as", "20", "--abcd"},
|
|
expectRes: []int{10, 20},
|
|
}}
|
|
|
|
for i := range cases {
|
|
tc := cases[i]
|
|
require := require.New(t)
|
|
h := cosmovisor.UpgradeSkipHeights(tc.args)
|
|
require.Equal(h, tc.expectRes)
|
|
}
|
|
}
|
|
|
|
// buffer is a thread safe bytes buffer
|
|
type buffer struct {
|
|
b bytes.Buffer
|
|
m sync.Mutex
|
|
}
|
|
|
|
func newBuffer() *buffer {
|
|
return &buffer{}
|
|
}
|
|
|
|
func (b *buffer) Write(bz []byte) (int, error) {
|
|
b.m.Lock()
|
|
defer b.m.Unlock()
|
|
return b.b.Write(bz)
|
|
}
|
|
|
|
func (b *buffer) String() string {
|
|
b.m.Lock()
|
|
defer b.m.Unlock()
|
|
return b.b.String()
|
|
}
|
|
|
|
func (b *buffer) Reset() {
|
|
b.m.Lock()
|
|
defer b.m.Unlock()
|
|
b.b.Reset()
|
|
}
|