github.com/devwanda/aphelion-staking@v0.33.9/libs/cli/setup_test.go (about) 1 package cli 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "strconv" 7 "strings" 8 "testing" 9 10 "github.com/pkg/errors" 11 "github.com/spf13/cobra" 12 "github.com/spf13/viper" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestSetupEnv(t *testing.T) { 18 cases := []struct { 19 args []string 20 env map[string]string 21 expected string 22 }{ 23 {nil, nil, ""}, 24 {[]string{"--foobar", "bang!"}, nil, "bang!"}, 25 // make sure reset is good 26 {nil, nil, ""}, 27 // test both variants of the prefix 28 {nil, map[string]string{"DEMO_FOOBAR": "good"}, "good"}, 29 {nil, map[string]string{"DEMOFOOBAR": "silly"}, "silly"}, 30 // and that cli overrides env... 31 {[]string{"--foobar", "important"}, 32 map[string]string{"DEMO_FOOBAR": "ignored"}, "important"}, 33 } 34 35 for idx, tc := range cases { 36 i := strconv.Itoa(idx) 37 // test command that store value of foobar in local variable 38 var foo string 39 demo := &cobra.Command{ 40 Use: "demo", 41 RunE: func(cmd *cobra.Command, args []string) error { 42 foo = viper.GetString("foobar") 43 return nil 44 }, 45 } 46 demo.Flags().String("foobar", "", "Some test value from config") 47 cmd := PrepareBaseCmd(demo, "DEMO", "/qwerty/asdfgh") // some missing dir.. 48 cmd.Exit = func(int) {} 49 50 viper.Reset() 51 args := append([]string{cmd.Use}, tc.args...) 52 err := RunWithArgs(cmd, args, tc.env) 53 require.Nil(t, err, i) 54 assert.Equal(t, tc.expected, foo, i) 55 } 56 } 57 58 func tempDir() string { 59 cdir, err := ioutil.TempDir("", "test-cli") 60 if err != nil { 61 panic(err) 62 } 63 return cdir 64 } 65 66 func TestSetupConfig(t *testing.T) { 67 // we pre-create two config files we can refer to in the rest of 68 // the test cases. 69 cval1 := "fubble" 70 conf1 := tempDir() 71 err := WriteConfigVals(conf1, map[string]string{"boo": cval1}) 72 require.Nil(t, err) 73 74 cases := []struct { 75 args []string 76 env map[string]string 77 expected string 78 expectedTwo string 79 }{ 80 {nil, nil, "", ""}, 81 // setting on the command line 82 {[]string{"--boo", "haha"}, nil, "haha", ""}, 83 {[]string{"--two-words", "rocks"}, nil, "", "rocks"}, 84 {[]string{"--home", conf1}, nil, cval1, ""}, 85 // test both variants of the prefix 86 {nil, map[string]string{"RD_BOO": "bang"}, "bang", ""}, 87 {nil, map[string]string{"RD_TWO_WORDS": "fly"}, "", "fly"}, 88 {nil, map[string]string{"RDTWO_WORDS": "fly"}, "", "fly"}, 89 {nil, map[string]string{"RD_HOME": conf1}, cval1, ""}, 90 {nil, map[string]string{"RDHOME": conf1}, cval1, ""}, 91 } 92 93 for idx, tc := range cases { 94 i := strconv.Itoa(idx) 95 // test command that store value of foobar in local variable 96 var foo, two string 97 boo := &cobra.Command{ 98 Use: "reader", 99 RunE: func(cmd *cobra.Command, args []string) error { 100 foo = viper.GetString("boo") 101 two = viper.GetString("two-words") 102 return nil 103 }, 104 } 105 boo.Flags().String("boo", "", "Some test value from config") 106 boo.Flags().String("two-words", "", "Check out env handling -") 107 cmd := PrepareBaseCmd(boo, "RD", "/qwerty/asdfgh") // some missing dir... 108 cmd.Exit = func(int) {} 109 110 viper.Reset() 111 args := append([]string{cmd.Use}, tc.args...) 112 err := RunWithArgs(cmd, args, tc.env) 113 require.Nil(t, err, i) 114 assert.Equal(t, tc.expected, foo, i) 115 assert.Equal(t, tc.expectedTwo, two, i) 116 } 117 } 118 119 type DemoConfig struct { 120 Name string `mapstructure:"name"` 121 Age int `mapstructure:"age"` 122 Unused int `mapstructure:"unused"` 123 } 124 125 func TestSetupUnmarshal(t *testing.T) { 126 // we pre-create two config files we can refer to in the rest of 127 // the test cases. 128 cval1, cval2 := "someone", "else" 129 conf1 := tempDir() 130 err := WriteConfigVals(conf1, map[string]string{"name": cval1}) 131 require.Nil(t, err) 132 // even with some ignored fields, should be no problem 133 conf2 := tempDir() 134 err = WriteConfigVals(conf2, map[string]string{"name": cval2, "foo": "bar"}) 135 require.Nil(t, err) 136 137 // unused is not declared on a flag and remains from base 138 base := DemoConfig{ 139 Name: "default", 140 Age: 42, 141 Unused: -7, 142 } 143 c := func(name string, age int) DemoConfig { 144 r := base 145 // anything set on the flags as a default is used over 146 // the default config object 147 r.Name = "from-flag" 148 if name != "" { 149 r.Name = name 150 } 151 if age != 0 { 152 r.Age = age 153 } 154 return r 155 } 156 157 cases := []struct { 158 args []string 159 env map[string]string 160 expected DemoConfig 161 }{ 162 {nil, nil, c("", 0)}, 163 // setting on the command line 164 {[]string{"--name", "haha"}, nil, c("haha", 0)}, 165 {[]string{"--home", conf1}, nil, c(cval1, 0)}, 166 // test both variants of the prefix 167 {nil, map[string]string{"MR_AGE": "56"}, c("", 56)}, 168 {nil, map[string]string{"MR_HOME": conf1}, c(cval1, 0)}, 169 {[]string{"--age", "17"}, map[string]string{"MRHOME": conf2}, c(cval2, 17)}, 170 } 171 172 for idx, tc := range cases { 173 i := strconv.Itoa(idx) 174 // test command that store value of foobar in local variable 175 cfg := base 176 marsh := &cobra.Command{ 177 Use: "marsh", 178 RunE: func(cmd *cobra.Command, args []string) error { 179 return viper.Unmarshal(&cfg) 180 }, 181 } 182 marsh.Flags().String("name", "from-flag", "Some test value from config") 183 // if we want a flag to use the proper default, then copy it 184 // from the default config here 185 marsh.Flags().Int("age", base.Age, "Some test value from config") 186 cmd := PrepareBaseCmd(marsh, "MR", "/qwerty/asdfgh") // some missing dir... 187 cmd.Exit = func(int) {} 188 189 viper.Reset() 190 args := append([]string{cmd.Use}, tc.args...) 191 err := RunWithArgs(cmd, args, tc.env) 192 require.Nil(t, err, i) 193 assert.Equal(t, tc.expected, cfg, i) 194 } 195 } 196 197 func TestSetupTrace(t *testing.T) { 198 cases := []struct { 199 args []string 200 env map[string]string 201 long bool 202 expected string 203 }{ 204 {nil, nil, false, "Trace flag = false"}, 205 {[]string{"--trace"}, nil, true, "Trace flag = true"}, 206 {[]string{"--no-such-flag"}, nil, false, "unknown flag: --no-such-flag"}, 207 {nil, map[string]string{"DBG_TRACE": "true"}, true, "Trace flag = true"}, 208 } 209 210 for idx, tc := range cases { 211 i := strconv.Itoa(idx) 212 // test command that store value of foobar in local variable 213 trace := &cobra.Command{ 214 Use: "trace", 215 RunE: func(cmd *cobra.Command, args []string) error { 216 return errors.Errorf("Trace flag = %t", viper.GetBool(TraceFlag)) 217 }, 218 } 219 cmd := PrepareBaseCmd(trace, "DBG", "/qwerty/asdfgh") // some missing dir.. 220 cmd.Exit = func(int) {} 221 222 viper.Reset() 223 args := append([]string{cmd.Use}, tc.args...) 224 stdout, stderr, err := RunCaptureWithArgs(cmd, args, tc.env) 225 require.NotNil(t, err, i) 226 require.Equal(t, "", stdout, i) 227 require.NotEqual(t, "", stderr, i) 228 msg := strings.Split(stderr, "\n") 229 desired := fmt.Sprintf("ERROR: %s", tc.expected) 230 assert.Equal(t, desired, msg[0], i) 231 if tc.long && assert.True(t, len(msg) > 2, i) { 232 // the next line starts the stack trace... 233 assert.Contains(t, msg[1], "TestSetupTrace", i) 234 assert.Contains(t, msg[2], "setup_test.go", i) 235 } 236 } 237 }