You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
5.1 KiB

  1. package commands
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "github.com/spf13/cobra"
  9. "github.com/spf13/viper"
  10. "github.com/stretchr/testify/assert"
  11. "github.com/stretchr/testify/require"
  12. cfg "github.com/tendermint/tendermint/config"
  13. "github.com/tendermint/tendermint/libs/cli"
  14. "github.com/tendermint/tendermint/libs/log"
  15. tmos "github.com/tendermint/tendermint/libs/os"
  16. )
  17. // writeConfigVals writes a toml file with the given values.
  18. // It returns an error if writing was impossible.
  19. func writeConfigVals(dir string, vals map[string]string) error {
  20. data := ""
  21. for k, v := range vals {
  22. data += fmt.Sprintf("%s = \"%s\"\n", k, v)
  23. }
  24. cfile := filepath.Join(dir, "config.toml")
  25. return os.WriteFile(cfile, []byte(data), 0600)
  26. }
  27. // clearConfig clears env vars, the given root dir, and resets viper.
  28. func clearConfig(t *testing.T, dir string) *cfg.Config {
  29. t.Helper()
  30. require.NoError(t, os.Unsetenv("TMHOME"))
  31. require.NoError(t, os.Unsetenv("TM_HOME"))
  32. require.NoError(t, os.RemoveAll(dir))
  33. viper.Reset()
  34. conf := cfg.DefaultConfig()
  35. conf.RootDir = dir
  36. return conf
  37. }
  38. // prepare new rootCmd
  39. func testRootCmd(conf *cfg.Config) *cobra.Command {
  40. logger := log.NewNopLogger()
  41. cmd := RootCommand(conf, logger)
  42. cmd.RunE = func(cmd *cobra.Command, args []string) error { return nil }
  43. var l string
  44. cmd.PersistentFlags().String("log", l, "Log")
  45. return cmd
  46. }
  47. func testSetup(ctx context.Context, t *testing.T, conf *cfg.Config, args []string, env map[string]string) error {
  48. t.Helper()
  49. cmd := testRootCmd(conf)
  50. viper.Set(cli.HomeFlag, conf.RootDir)
  51. // run with the args and env
  52. args = append([]string{cmd.Use}, args...)
  53. return cli.RunWithArgs(ctx, cmd, args, env)
  54. }
  55. func TestRootHome(t *testing.T) {
  56. defaultRoot := t.TempDir()
  57. newRoot := filepath.Join(defaultRoot, "something-else")
  58. cases := []struct {
  59. args []string
  60. env map[string]string
  61. root string
  62. }{
  63. {nil, nil, defaultRoot},
  64. {[]string{"--home", newRoot}, nil, newRoot},
  65. {nil, map[string]string{"TMHOME": newRoot}, newRoot},
  66. }
  67. ctx, cancel := context.WithCancel(context.Background())
  68. defer cancel()
  69. for i, tc := range cases {
  70. t.Run(fmt.Sprint(i), func(t *testing.T) {
  71. conf := clearConfig(t, tc.root)
  72. err := testSetup(ctx, t, conf, tc.args, tc.env)
  73. require.NoError(t, err)
  74. require.Equal(t, tc.root, conf.RootDir)
  75. require.Equal(t, tc.root, conf.P2P.RootDir)
  76. require.Equal(t, tc.root, conf.Consensus.RootDir)
  77. require.Equal(t, tc.root, conf.Mempool.RootDir)
  78. })
  79. }
  80. }
  81. func TestRootFlagsEnv(t *testing.T) {
  82. // defaults
  83. defaults := cfg.DefaultConfig()
  84. defaultDir := t.TempDir()
  85. defaultLogLvl := defaults.LogLevel
  86. cases := []struct {
  87. args []string
  88. env map[string]string
  89. logLevel string
  90. }{
  91. {[]string{"--log", "debug"}, nil, defaultLogLvl}, // wrong flag
  92. {[]string{"--log-level", "debug"}, nil, "debug"}, // right flag
  93. {nil, map[string]string{"TM_LOW": "debug"}, defaultLogLvl}, // wrong env flag
  94. {nil, map[string]string{"MT_LOG_LEVEL": "debug"}, defaultLogLvl}, // wrong env prefix
  95. {nil, map[string]string{"TM_LOG_LEVEL": "debug"}, "debug"}, // right env
  96. }
  97. ctx, cancel := context.WithCancel(context.Background())
  98. defer cancel()
  99. for i, tc := range cases {
  100. t.Run(fmt.Sprint(i), func(t *testing.T) {
  101. conf := clearConfig(t, defaultDir)
  102. err := testSetup(ctx, t, conf, tc.args, tc.env)
  103. require.NoError(t, err)
  104. assert.Equal(t, tc.logLevel, conf.LogLevel)
  105. })
  106. }
  107. }
  108. func TestRootConfig(t *testing.T) {
  109. ctx, cancel := context.WithCancel(context.Background())
  110. defer cancel()
  111. // write non-default config
  112. nonDefaultLogLvl := "debug"
  113. cvals := map[string]string{
  114. "log-level": nonDefaultLogLvl,
  115. }
  116. cases := []struct {
  117. args []string
  118. env map[string]string
  119. logLvl string
  120. }{
  121. {nil, nil, nonDefaultLogLvl}, // should load config
  122. {[]string{"--log-level=info"}, nil, "info"}, // flag over rides
  123. {nil, map[string]string{"TM_LOG_LEVEL": "info"}, "info"}, // env over rides
  124. }
  125. for i, tc := range cases {
  126. t.Run(fmt.Sprint(i), func(t *testing.T) {
  127. defaultRoot := t.TempDir()
  128. conf := clearConfig(t, defaultRoot)
  129. conf.LogLevel = tc.logLvl
  130. // XXX: path must match cfg.defaultConfigPath
  131. configFilePath := filepath.Join(defaultRoot, "config")
  132. err := tmos.EnsureDir(configFilePath, 0700)
  133. require.NoError(t, err)
  134. // write the non-defaults to a different path
  135. // TODO: support writing sub configs so we can test that too
  136. err = writeConfigVals(configFilePath, cvals)
  137. require.NoError(t, err)
  138. cmd := testRootCmd(conf)
  139. // run with the args and env
  140. tc.args = append([]string{cmd.Use}, tc.args...)
  141. err = cli.RunWithArgs(ctx, cmd, tc.args, tc.env)
  142. require.NoError(t, err)
  143. require.Equal(t, tc.logLvl, conf.LogLevel)
  144. })
  145. }
  146. }
  147. // WriteConfigVals writes a toml file with the given values.
  148. // It returns an error if writing was impossible.
  149. func WriteConfigVals(dir string, vals map[string]string) error {
  150. data := ""
  151. for k, v := range vals {
  152. data += fmt.Sprintf("%s = \"%s\"\n", k, v)
  153. }
  154. cfile := filepath.Join(dir, "config.toml")
  155. return os.WriteFile(cfile, []byte(data), 0600)
  156. }