2020-08-19 08:58:43 -07:00
|
|
|
package cosmovisor
|
|
|
|
|
|
|
|
import (
|
2021-10-18 08:32:24 -07:00
|
|
|
"bytes"
|
2020-08-19 08:58:43 -07:00
|
|
|
"fmt"
|
2021-10-18 08:32:24 -07:00
|
|
|
"io"
|
2021-08-30 08:17:12 -07:00
|
|
|
"os"
|
2020-08-19 08:58:43 -07:00
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
2021-09-28 16:08:31 -07:00
|
|
|
"time"
|
2020-08-19 08:58:43 -07:00
|
|
|
|
2021-10-18 08:32:24 -07:00
|
|
|
"github.com/rs/zerolog"
|
2021-09-28 16:08:31 -07:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/stretchr/testify/require"
|
2020-11-11 04:46:11 -08:00
|
|
|
"github.com/stretchr/testify/suite"
|
2021-09-28 16:08:31 -07:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/cosmovisor/errors"
|
2020-08-19 08:58:43 -07:00
|
|
|
)
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
type argsTestSuite struct {
|
|
|
|
suite.Suite
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestArgsTestSuite(t *testing.T) {
|
|
|
|
suite.Run(t, new(argsTestSuite))
|
|
|
|
}
|
|
|
|
|
2021-09-28 16:08:31 -07:00
|
|
|
// cosmovisorEnv are the string values of environment variables used to configure Cosmovisor.
|
|
|
|
type cosmovisorEnv struct {
|
|
|
|
Home string
|
|
|
|
Name string
|
|
|
|
DownloadBin string
|
|
|
|
RestartUpgrade string
|
|
|
|
SkipBackup string
|
2022-01-04 06:25:45 -08:00
|
|
|
DataBackupPath string
|
2021-09-28 16:08:31 -07:00
|
|
|
Interval string
|
|
|
|
PreupgradeMaxRetries string
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToMap creates a map of the cosmovisorEnv where the keys are the env var names.
|
|
|
|
func (c cosmovisorEnv) ToMap() map[string]string {
|
|
|
|
return map[string]string{
|
|
|
|
EnvHome: c.Home,
|
|
|
|
EnvName: c.Name,
|
|
|
|
EnvDownloadBin: c.DownloadBin,
|
|
|
|
EnvRestartUpgrade: c.RestartUpgrade,
|
|
|
|
EnvSkipBackup: c.SkipBackup,
|
2022-01-04 06:25:45 -08:00
|
|
|
EnvDataBackupPath: c.DataBackupPath,
|
2021-09-28 16:08:31 -07:00
|
|
|
EnvInterval: c.Interval,
|
|
|
|
EnvPreupgradeMaxRetries: c.PreupgradeMaxRetries,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set sets the field in this cosmovisorEnv corresponding to the provided envVar to the given envVal.
|
|
|
|
func (c *cosmovisorEnv) Set(envVar, envVal string) {
|
|
|
|
switch envVar {
|
|
|
|
case EnvHome:
|
|
|
|
c.Home = envVal
|
|
|
|
case EnvName:
|
|
|
|
c.Name = envVal
|
|
|
|
case EnvDownloadBin:
|
|
|
|
c.DownloadBin = envVal
|
|
|
|
case EnvRestartUpgrade:
|
|
|
|
c.RestartUpgrade = envVal
|
|
|
|
case EnvSkipBackup:
|
|
|
|
c.SkipBackup = envVal
|
2022-01-04 06:25:45 -08:00
|
|
|
case EnvDataBackupPath:
|
|
|
|
c.DataBackupPath = envVal
|
2021-09-28 16:08:31 -07:00
|
|
|
case EnvInterval:
|
|
|
|
c.Interval = envVal
|
|
|
|
case EnvPreupgradeMaxRetries:
|
|
|
|
c.PreupgradeMaxRetries = envVal
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("Unknown environment variable [%s]. Ccannot set field to [%s]. ", envVar, envVal))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// clearEnv clears environment variables and what they were.
|
|
|
|
// Designed to be used like this:
|
|
|
|
// initialEnv := clearEnv()
|
|
|
|
// defer setEnv(nil, initialEnv)
|
|
|
|
func (s *argsTestSuite) clearEnv() *cosmovisorEnv {
|
|
|
|
s.T().Logf("Clearing environment variables.")
|
|
|
|
rv := cosmovisorEnv{}
|
|
|
|
for envVar := range rv.ToMap() {
|
|
|
|
rv.Set(envVar, os.Getenv(envVar))
|
|
|
|
s.Require().NoError(os.Unsetenv(envVar))
|
|
|
|
}
|
|
|
|
return &rv
|
|
|
|
}
|
|
|
|
|
|
|
|
// setEnv sets environment variables to the values provided.
|
|
|
|
// If t is not nil, and there's a problem, the test will fail immediately.
|
|
|
|
// If t is nil, problems will just be logged using s.T().
|
|
|
|
func (s *argsTestSuite) setEnv(t *testing.T, env *cosmovisorEnv) {
|
|
|
|
if t == nil {
|
|
|
|
s.T().Logf("Restoring environment variables.")
|
|
|
|
}
|
|
|
|
for envVar, envVal := range env.ToMap() {
|
|
|
|
var err error
|
|
|
|
var msg string
|
|
|
|
if len(envVal) != 0 {
|
|
|
|
err = os.Setenv(envVar, envVal)
|
|
|
|
msg = fmt.Sprintf("setting %s to %s", envVar, envVal)
|
|
|
|
} else {
|
|
|
|
err = os.Unsetenv(envVar)
|
|
|
|
msg = fmt.Sprintf("unsetting %s", envVar)
|
|
|
|
}
|
|
|
|
switch {
|
|
|
|
case t != nil:
|
|
|
|
require.NoError(t, err, msg)
|
|
|
|
case err != nil:
|
|
|
|
s.T().Logf("error %s: %v", msg, err)
|
|
|
|
default:
|
|
|
|
s.T().Logf("done %s", msg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
func (s *argsTestSuite) TestConfigPaths() {
|
2020-08-19 08:58:43 -07:00
|
|
|
cases := map[string]struct {
|
|
|
|
cfg Config
|
|
|
|
upgradeName string
|
|
|
|
expectRoot string
|
|
|
|
expectGenesis string
|
|
|
|
expectUpgrade string
|
|
|
|
}{
|
|
|
|
"simple": {
|
|
|
|
cfg: Config{Home: "/foo", Name: "myd"},
|
|
|
|
upgradeName: "bar",
|
|
|
|
expectRoot: fmt.Sprintf("/foo/%s", rootName),
|
|
|
|
expectGenesis: fmt.Sprintf("/foo/%s/genesis/bin/myd", rootName),
|
|
|
|
expectUpgrade: fmt.Sprintf("/foo/%s/upgrades/bar/bin/myd", rootName),
|
|
|
|
},
|
|
|
|
"handle space": {
|
|
|
|
cfg: Config{Home: "/longer/prefix/", Name: "yourd"},
|
|
|
|
upgradeName: "some spaces",
|
|
|
|
expectRoot: fmt.Sprintf("/longer/prefix/%s", rootName),
|
|
|
|
expectGenesis: fmt.Sprintf("/longer/prefix/%s/genesis/bin/yourd", rootName),
|
|
|
|
expectUpgrade: "/longer/prefix/cosmovisor/upgrades/some%20spaces/bin/yourd",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
for _, tc := range cases {
|
|
|
|
s.Require().Equal(tc.cfg.Root(), filepath.FromSlash(tc.expectRoot))
|
|
|
|
s.Require().Equal(tc.cfg.GenesisBin(), filepath.FromSlash(tc.expectGenesis))
|
|
|
|
s.Require().Equal(tc.cfg.UpgradeBin(tc.upgradeName), filepath.FromSlash(tc.expectUpgrade))
|
2020-08-19 08:58:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test validate
|
2022-01-04 06:25:45 -08:00
|
|
|
// add more test in test validate
|
2020-11-11 04:46:11 -08:00
|
|
|
func (s *argsTestSuite) TestValidate() {
|
2020-08-19 08:58:43 -07:00
|
|
|
relPath := filepath.Join("testdata", "validate")
|
|
|
|
absPath, err := filepath.Abs(relPath)
|
2020-11-11 04:46:11 -08:00
|
|
|
s.Require().NoError(err)
|
2020-08-19 08:58:43 -07:00
|
|
|
|
|
|
|
testdata, err := filepath.Abs("testdata")
|
2020-11-11 04:46:11 -08:00
|
|
|
s.Require().NoError(err)
|
2020-08-19 08:58:43 -07:00
|
|
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
cfg Config
|
|
|
|
valid bool
|
|
|
|
}{
|
|
|
|
"happy": {
|
2022-01-04 06:25:45 -08:00
|
|
|
cfg: Config{Home: absPath, Name: "bind", DataBackupPath: absPath},
|
2020-08-19 08:58:43 -07:00
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"happy with download": {
|
2022-01-04 06:25:45 -08:00
|
|
|
cfg: Config{Home: absPath, Name: "bind", AllowDownloadBinaries: true, DataBackupPath: absPath},
|
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"happy with skip data backup": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: absPath},
|
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"happy with skip data backup and empty data backup path": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: ""},
|
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"happy with skip data backup and no such data backup path dir": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: filepath.FromSlash("/no/such/dir")},
|
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"happy with skip data backup and relative data backup path": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", UnsafeSkipBackup: true, DataBackupPath: relPath},
|
2020-08-19 08:58:43 -07:00
|
|
|
valid: true,
|
|
|
|
},
|
|
|
|
"missing home": {
|
|
|
|
cfg: Config{Name: "bind"},
|
|
|
|
valid: false,
|
|
|
|
},
|
|
|
|
"missing name": {
|
|
|
|
cfg: Config{Home: absPath},
|
|
|
|
valid: false,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
"relative home path": {
|
2020-08-19 08:58:43 -07:00
|
|
|
cfg: Config{Home: relPath, Name: "bind"},
|
|
|
|
valid: false,
|
|
|
|
},
|
|
|
|
"no upgrade manager subdir": {
|
|
|
|
cfg: Config{Home: testdata, Name: "bind"},
|
|
|
|
valid: false,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
"no such home dir": {
|
2020-08-19 08:58:43 -07:00
|
|
|
cfg: Config{Home: filepath.FromSlash("/no/such/dir"), Name: "bind"},
|
|
|
|
valid: false,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
"empty data backup path": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", DataBackupPath: ""},
|
|
|
|
valid: false,
|
|
|
|
},
|
|
|
|
"no such data backup path dir": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", DataBackupPath: filepath.FromSlash("/no/such/dir")},
|
|
|
|
valid: false,
|
|
|
|
},
|
|
|
|
"relative data backup path": {
|
|
|
|
cfg: Config{Home: absPath, Name: "bind", DataBackupPath: relPath},
|
|
|
|
valid: false,
|
|
|
|
},
|
2020-08-19 08:58:43 -07:00
|
|
|
}
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
for _, tc := range cases {
|
2021-09-28 16:08:31 -07:00
|
|
|
errs := tc.cfg.validate()
|
2020-11-11 04:46:11 -08:00
|
|
|
if tc.valid {
|
2021-09-28 16:08:31 -07:00
|
|
|
s.Require().Len(errs, 0)
|
2020-11-11 04:46:11 -08:00
|
|
|
} else {
|
2021-09-28 16:08:31 -07:00
|
|
|
s.Require().Greater(len(errs), 0, "number of errors returned")
|
2020-11-11 04:46:11 -08:00
|
|
|
}
|
2020-08-19 08:58:43 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
func (s *argsTestSuite) TestEnsureBin() {
|
2020-08-19 08:58:43 -07:00
|
|
|
relPath := filepath.Join("testdata", "validate")
|
|
|
|
absPath, err := filepath.Abs(relPath)
|
2020-11-11 04:46:11 -08:00
|
|
|
s.Require().NoError(err)
|
2020-08-19 08:58:43 -07:00
|
|
|
|
2022-01-04 06:25:45 -08:00
|
|
|
cfg := Config{Home: absPath, Name: "dummyd", DataBackupPath: absPath}
|
2021-09-28 16:08:31 -07:00
|
|
|
s.Require().Len(cfg.validate(), 0, "validation errors")
|
2020-08-19 08:58:43 -07:00
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
s.Require().NoError(EnsureBinary(cfg.GenesisBin()))
|
2020-08-19 08:58:43 -07:00
|
|
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
upgrade string
|
|
|
|
hasBin bool
|
|
|
|
}{
|
|
|
|
"proper": {"chain2", true},
|
|
|
|
"no binary": {"nobin", false},
|
|
|
|
"not executable": {"noexec", false},
|
|
|
|
"no directory": {"foobarbaz", false},
|
|
|
|
}
|
|
|
|
|
2020-11-11 04:46:11 -08:00
|
|
|
for _, tc := range cases {
|
|
|
|
err := EnsureBinary(cfg.UpgradeBin(tc.upgrade))
|
|
|
|
if tc.hasBin {
|
|
|
|
s.Require().NoError(err)
|
|
|
|
} else {
|
|
|
|
s.Require().Error(err)
|
|
|
|
}
|
2020-08-19 08:58:43 -07:00
|
|
|
}
|
|
|
|
}
|
2021-08-30 08:17:12 -07:00
|
|
|
|
|
|
|
func (s *argsTestSuite) TestBooleanOption() {
|
2021-09-28 16:08:31 -07:00
|
|
|
initialEnv := s.clearEnv()
|
|
|
|
defer s.setEnv(nil, initialEnv)
|
|
|
|
|
2021-08-30 08:17:12 -07:00
|
|
|
name := "COSMOVISOR_TEST_VAL"
|
|
|
|
|
|
|
|
check := func(def, expected, isErr bool, msg string) {
|
|
|
|
v, err := booleanOption(name, def)
|
|
|
|
if isErr {
|
2021-09-28 16:08:31 -07:00
|
|
|
s.Require().Error(err)
|
2021-08-30 08:17:12 -07:00
|
|
|
return
|
|
|
|
}
|
2021-09-28 16:08:31 -07:00
|
|
|
s.Require().NoError(err)
|
|
|
|
s.Require().Equal(expected, v, msg)
|
2021-08-30 08:17:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
os.Setenv(name, "")
|
|
|
|
check(true, true, false, "should correctly set default value")
|
|
|
|
check(false, false, false, "should correctly set default value")
|
|
|
|
|
|
|
|
os.Setenv(name, "wrong")
|
|
|
|
check(true, true, true, "should error on wrong value")
|
|
|
|
os.Setenv(name, "truee")
|
|
|
|
check(true, true, true, "should error on wrong value")
|
|
|
|
|
|
|
|
os.Setenv(name, "false")
|
|
|
|
check(true, false, false, "should handle false value")
|
|
|
|
check(false, false, false, "should handle false value")
|
|
|
|
os.Setenv(name, "faLSe")
|
|
|
|
check(true, false, false, "should handle false value case not sensitive")
|
|
|
|
check(false, false, false, "should handle false value case not sensitive")
|
|
|
|
|
|
|
|
os.Setenv(name, "true")
|
|
|
|
check(true, true, false, "should handle true value")
|
|
|
|
check(false, true, false, "should handle true value")
|
|
|
|
|
|
|
|
os.Setenv(name, "TRUE")
|
|
|
|
check(true, true, false, "should handle true value case not sensitive")
|
|
|
|
check(false, true, false, "should handle true value case not sensitive")
|
2021-09-28 16:08:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *argsTestSuite) TestDetailString() {
|
|
|
|
home := "/home"
|
|
|
|
name := "test-name"
|
|
|
|
allowDownloadBinaries := true
|
|
|
|
restartAfterUpgrade := true
|
|
|
|
pollInterval := 406 * time.Millisecond
|
|
|
|
unsafeSkipBackup := false
|
2022-01-04 06:25:45 -08:00
|
|
|
dataBackupPath := "/home"
|
2021-09-28 16:08:31 -07:00
|
|
|
preupgradeMaxRetries := 8
|
|
|
|
cfg := &Config{
|
|
|
|
Home: home,
|
|
|
|
Name: name,
|
|
|
|
AllowDownloadBinaries: allowDownloadBinaries,
|
|
|
|
RestartAfterUpgrade: restartAfterUpgrade,
|
|
|
|
PollInterval: pollInterval,
|
|
|
|
UnsafeSkipBackup: unsafeSkipBackup,
|
2022-01-04 06:25:45 -08:00
|
|
|
DataBackupPath: dataBackupPath,
|
2021-09-28 16:08:31 -07:00
|
|
|
PreupgradeMaxRetries: preupgradeMaxRetries,
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedPieces := []string{
|
|
|
|
"Configurable Values:",
|
|
|
|
fmt.Sprintf("%s: %s", EnvHome, home),
|
|
|
|
fmt.Sprintf("%s: %s", EnvName, name),
|
|
|
|
fmt.Sprintf("%s: %t", EnvDownloadBin, allowDownloadBinaries),
|
|
|
|
fmt.Sprintf("%s: %t", EnvRestartUpgrade, restartAfterUpgrade),
|
|
|
|
fmt.Sprintf("%s: %s", EnvInterval, pollInterval),
|
|
|
|
fmt.Sprintf("%s: %t", EnvSkipBackup, unsafeSkipBackup),
|
2022-01-04 06:25:45 -08:00
|
|
|
fmt.Sprintf("%s: %s", EnvDataBackupPath, home),
|
2021-09-28 16:08:31 -07:00
|
|
|
fmt.Sprintf("%s: %d", EnvPreupgradeMaxRetries, preupgradeMaxRetries),
|
|
|
|
"Derived Values:",
|
|
|
|
fmt.Sprintf("Root Dir: %s", home),
|
|
|
|
fmt.Sprintf("Upgrade Dir: %s", home),
|
|
|
|
fmt.Sprintf("Genesis Bin: %s", home),
|
|
|
|
fmt.Sprintf("Monitored File: %s", home),
|
2022-01-04 06:25:45 -08:00
|
|
|
fmt.Sprintf("Data Backup Dir: %s", home),
|
2021-09-28 16:08:31 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
actual := cfg.DetailString()
|
|
|
|
|
|
|
|
for _, piece := range expectedPieces {
|
|
|
|
s.Assert().Contains(actual, piece)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *argsTestSuite) TestGetConfigFromEnv() {
|
|
|
|
initialEnv := s.clearEnv()
|
|
|
|
defer s.setEnv(nil, initialEnv)
|
2021-08-30 08:17:12 -07:00
|
|
|
|
2021-09-28 16:08:31 -07:00
|
|
|
relPath := filepath.Join("testdata", "validate")
|
|
|
|
absPath, perr := filepath.Abs(relPath)
|
|
|
|
s.Require().NoError(perr)
|
|
|
|
|
2022-01-04 06:25:45 -08:00
|
|
|
newConfig := func(home, name, dataBackupPath string, downloadBin, restartUpgrade, skipBackup bool, interval, preupgradeMaxRetries int) *Config {
|
2021-09-28 16:08:31 -07:00
|
|
|
return &Config{
|
|
|
|
Home: home,
|
|
|
|
Name: name,
|
|
|
|
AllowDownloadBinaries: downloadBin,
|
|
|
|
RestartAfterUpgrade: restartUpgrade,
|
|
|
|
PollInterval: time.Millisecond * time.Duration(interval),
|
|
|
|
UnsafeSkipBackup: skipBackup,
|
2022-01-04 06:25:45 -08:00
|
|
|
DataBackupPath: dataBackupPath,
|
2021-09-28 16:08:31 -07:00
|
|
|
PreupgradeMaxRetries: preupgradeMaxRetries,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
envVals cosmovisorEnv
|
|
|
|
expectedCfg *Config
|
|
|
|
expectedErrCount int
|
|
|
|
}{
|
2022-01-04 06:25:45 -08:00
|
|
|
// EnvHome, EnvName, EnvDownloadBin, EnvRestartUpgrade, EnvSkipBackup, EnvDataBackupPath, EnvDataBackupPath, EnvInterval, EnvPreupgradeMaxRetries
|
2021-09-28 16:08:31 -07:00
|
|
|
{
|
|
|
|
name: "all bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{"", "", "bad", "bad", "bad", "", "bad", "bad"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
2022-01-04 06:25:45 -08:00
|
|
|
expectedErrCount: 8,
|
2021-09-28 16:08:31 -07:00
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "all good",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "nothing set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{"", "", "", "", "", "", "", ""},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
2022-01-04 06:25:45 -08:00
|
|
|
expectedErrCount: 3,
|
2021-09-28 16:08:31 -07:00
|
|
|
},
|
|
|
|
// Note: Home and Name tests are done in TestValidate
|
|
|
|
{
|
|
|
|
name: "download bin bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "bad", "false", "true", "", "303", "1"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "download bin not set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "download bin true",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "download bin false",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
// EnvHome, EnvName, EnvDownloadBin, EnvRestartUpgrade, EnvSkipBackup, EnvDataBackupPath, EnvInterval, EnvPreupgradeMaxRetries
|
2021-09-28 16:08:31 -07:00
|
|
|
{
|
|
|
|
name: "restart upgrade bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "bad", "true", "", "303", "1"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "restart upgrade not set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, true, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "restart upgrade true",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "true", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, true, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "restart upgrade true",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
// EnvHome, EnvName, EnvDownloadBin, EnvRestartUpgrade, EnvSkipBackup, EnvDataBackupPath, EnvInterval, EnvPreupgradeMaxRetries
|
2021-09-28 16:08:31 -07:00
|
|
|
{
|
|
|
|
name: "skip unsafe backups bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "bad", "", "303", "1"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "skip unsafe backups not set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, false, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "skip unsafe backups true",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "true", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, true, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "skip unsafe backups false",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "true", "false", "false", "", "303", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, true, false, false, 303, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
// EnvHome, EnvName, EnvDownloadBin, EnvRestartUpgrade, EnvSkipBackup, EnvDataBackupPath, EnvInterval, EnvPreupgradeMaxRetries
|
2021-09-28 16:08:31 -07:00
|
|
|
{
|
|
|
|
name: "poll interval bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "bad", "1"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "poll interval 0",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "0", "1"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "poll interval not set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 300, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "poll interval 987",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "987", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 987, 1),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
2021-10-18 08:32:24 -07:00
|
|
|
{
|
|
|
|
name: "poll interval 1s",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "1s", "1"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 1000, 1),
|
2021-10-18 08:32:24 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "poll interval -3m",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "-3m", "1"},
|
2021-10-18 08:32:24 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
2022-01-04 06:25:45 -08:00
|
|
|
// EnvHome, EnvName, EnvDownloadBin, EnvRestartUpgrade, EnvSkipBackup, EnvDataBackupPath, EnvInterval, EnvPreupgradeMaxRetries
|
2021-09-28 16:08:31 -07:00
|
|
|
{
|
|
|
|
name: "prepupgrade max retries bad",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "406", "bad"},
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedCfg: nil,
|
|
|
|
expectedErrCount: 1,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "prepupgrade max retries 0",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "406", "0"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 406, 0),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "prepupgrade max retries not set",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "406", ""},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 406, 0),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "prepupgrade max retries 5",
|
2022-01-04 06:25:45 -08:00
|
|
|
envVals: cosmovisorEnv{absPath, "testname", "false", "false", "false", "", "406", "5"},
|
|
|
|
expectedCfg: newConfig(absPath, "testname", absPath, false, false, false, 406, 5),
|
2021-09-28 16:08:31 -07:00
|
|
|
expectedErrCount: 0,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
s.T().Run(tc.name, func(t *testing.T) {
|
|
|
|
s.setEnv(t, &tc.envVals)
|
|
|
|
cfg, err := GetConfigFromEnv()
|
|
|
|
if tc.expectedErrCount == 0 {
|
|
|
|
assert.NoError(t, err)
|
|
|
|
} else {
|
|
|
|
if assert.Error(t, err) {
|
|
|
|
errCount := 1
|
|
|
|
if multi, isMulti := err.(*errors.MultiError); isMulti {
|
|
|
|
errCount = multi.Len()
|
|
|
|
}
|
|
|
|
assert.Equal(t, tc.expectedErrCount, errCount, "error count")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert.Equal(t, tc.expectedCfg, cfg, "config")
|
|
|
|
})
|
|
|
|
}
|
2021-08-30 08:17:12 -07:00
|
|
|
}
|
2021-10-18 08:32:24 -07:00
|
|
|
|
|
|
|
func (s *argsTestSuite) TestLogConfigOrError() {
|
|
|
|
cfg := &Config{
|
|
|
|
Home: "/no/place/like/it",
|
|
|
|
Name: "cosmotestvisor",
|
|
|
|
AllowDownloadBinaries: true,
|
|
|
|
RestartAfterUpgrade: true,
|
|
|
|
PollInterval: 999,
|
|
|
|
UnsafeSkipBackup: false,
|
2022-01-04 06:25:45 -08:00
|
|
|
DataBackupPath: "/no/place/like/it",
|
2021-10-18 08:32:24 -07:00
|
|
|
PreupgradeMaxRetries: 20,
|
|
|
|
}
|
|
|
|
errNormal := fmt.Errorf("this is a single error")
|
|
|
|
errs := []error{
|
|
|
|
fmt.Errorf("multi-error error 1"),
|
|
|
|
fmt.Errorf("multi-error error 2"),
|
|
|
|
fmt.Errorf("multi-error error 3"),
|
|
|
|
}
|
|
|
|
errMulti := errors.FlattenErrors(errs...)
|
|
|
|
|
|
|
|
makeTestLogger := func(testName string, out io.Writer) zerolog.Logger {
|
|
|
|
output := zerolog.ConsoleWriter{Out: out, TimeFormat: time.Kitchen, NoColor: true}
|
|
|
|
return zerolog.New(output).With().Str("test", testName).Timestamp().Logger()
|
|
|
|
}
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
cfg *Config
|
|
|
|
err error
|
|
|
|
contains []string
|
|
|
|
notcontains []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "normal error",
|
|
|
|
cfg: nil,
|
|
|
|
err: errNormal,
|
|
|
|
contains: []string{"configuration error", errNormal.Error()}, // TODO: Fix this.
|
|
|
|
notcontains: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "multi error",
|
|
|
|
cfg: nil,
|
|
|
|
err: errMulti,
|
2021-11-19 09:35:56 -08:00
|
|
|
contains: []string{"configuration errors found", errs[0].Error(), errs[1].Error(), errs[2].Error()},
|
2021-10-18 08:32:24 -07:00
|
|
|
notcontains: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "config",
|
|
|
|
cfg: cfg,
|
|
|
|
err: nil,
|
2021-11-19 09:35:56 -08:00
|
|
|
contains: []string{"Configurable Values", cfg.DetailString()},
|
2021-10-18 08:32:24 -07:00
|
|
|
notcontains: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "error and config - no config details",
|
|
|
|
cfg: cfg,
|
|
|
|
err: errNormal,
|
|
|
|
contains: []string{"error"},
|
|
|
|
notcontains: []string{"Configuration is valid", EnvName, cfg.Home}, // Just some spot checks.
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "nil nil - no output",
|
|
|
|
cfg: nil,
|
|
|
|
err: nil,
|
|
|
|
contains: nil,
|
|
|
|
notcontains: []string{" "},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
s.T().Run(tc.name, func(t *testing.T) {
|
|
|
|
var b bytes.Buffer
|
|
|
|
logger := makeTestLogger(tc.name, &b)
|
|
|
|
LogConfigOrError(logger, tc.cfg, tc.err)
|
|
|
|
output := b.String()
|
|
|
|
for _, expected := range tc.contains {
|
|
|
|
assert.Contains(t, output, expected)
|
|
|
|
}
|
|
|
|
for _, unexpected := range tc.notcontains {
|
|
|
|
assert.NotContains(t, output, unexpected)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|