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  }