...

Source file src/edge-infra.dev/pkg/lib/cli/rags/value_test.go

Documentation: edge-infra.dev/pkg/lib/cli/rags

     1  package rags
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  func TestValue_IsBoolFlag(t *testing.T) {
    12  	t.Parallel()
    13  
    14  	tcs := []struct {
    15  		val    flag.Getter
    16  		isBool bool
    17  	}{
    18  		{&Value[bool]{}, true},
    19  		{&Value[bool]{Var: new(bool)}, true},
    20  		{&Value[bool]{Default: true}, true},
    21  		{&Value[int]{}, false},
    22  		{&Value[int]{Var: new(int)}, false},
    23  		{&Value[int]{Default: 100}, false},
    24  	}
    25  
    26  	for i, tc := range tcs {
    27  		i := i
    28  		tc := tc
    29  		t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) {
    30  			t.Parallel()
    31  
    32  			b, ok := tc.val.(interface{ IsBoolFlag() bool })
    33  			assert.True(t, ok, "value was expected to implement IsBoolFlag()")
    34  			if tc.isBool {
    35  				assert.True(t, b.IsBoolFlag())
    36  			} else {
    37  				assert.False(t, b.IsBoolFlag())
    38  			}
    39  		})
    40  	}
    41  }
    42  
    43  func TestValue(t *testing.T) {
    44  	t.Parallel()
    45  
    46  	tcs := []struct {
    47  		ptr *int
    48  		def int
    49  		set string
    50  	}{
    51  		{},
    52  		{ptr: new(int)},
    53  		{def: 100},
    54  		{ptr: new(int), def: 100},
    55  	}
    56  
    57  	for i, tc := range tcs {
    58  		i := i
    59  		tc := tc
    60  		t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) {
    61  			t.Parallel()
    62  
    63  			// Test initialization
    64  			v := NewValueDefault(tc.ptr, tc.def)
    65  			assert.True(t, v.initialized)
    66  			assert.NotNil(t, v.Parse)
    67  			if tc.ptr != nil {
    68  				assert.Same(t, tc.ptr, v.Var)
    69  				assert.Equal(t, *tc.ptr, tc.def)
    70  			}
    71  			assert.Equal(t, tc.def, *v.Var)
    72  			assert.Equal(t, tc.def, v.Default)
    73  
    74  			// Test setting values
    75  			if tc.set != "" {
    76  				assert.NoError(t, v.Set(tc.set))
    77  				assert.Equal(t, tc.set, v.String())
    78  				parsedVal, _ := v.Parse(tc.set)
    79  				assert.Equal(t, parsedVal, v.Get())
    80  				assert.Equal(t, parsedVal, v.Var)
    81  				// Verify pointer was updated without changing it
    82  				// Only perform check if we created the value with a test pointer
    83  				if tc.ptr != nil {
    84  					assert.Same(t, tc.ptr, v.Var,
    85  						"pointer used to instantiate flag value is different than values current pointer")
    86  					assert.Equalf(t, tc.ptr, v.Get(),
    87  						"pointer used to instantiate flag value references different value than "+
    88  							"returned by value: want %v, got %v", *tc.ptr, v.Get())
    89  				}
    90  			}
    91  		})
    92  	}
    93  }
    94  
    95  func TestCollections(t *testing.T) {
    96  	t.Parallel()
    97  
    98  	tcs := map[string]struct {
    99  		def     []string
   100  		set     []string
   101  		expList []string
   102  		expSet  []string
   103  	}{
   104  		"one": {
   105  			set:     []string{"prometheus"},
   106  			expList: []string{"prometheus"},
   107  			expSet:  []string{"prometheus"},
   108  		},
   109  		"two": {
   110  			set:     []string{"prometheus", "linkerd"},
   111  			expList: []string{"prometheus", "linkerd"},
   112  			expSet:  []string{"prometheus", "linkerd"},
   113  		},
   114  		"trailing multivalue comma": {
   115  			set:     []string{"prometheus,linkerd,"},
   116  			expList: []string{"prometheus", "linkerd"},
   117  			expSet:  []string{"prometheus", "linkerd"},
   118  		},
   119  		"leading multivalue comma": {
   120  			set:     []string{",prometheus"},
   121  			expList: []string{"prometheus"},
   122  			expSet:  []string{"prometheus"},
   123  		},
   124  		"dupes": {
   125  			set:     []string{"prometheus", "prometheus"},
   126  			expList: []string{"prometheus", "prometheus"},
   127  			expSet:  []string{"prometheus"},
   128  		},
   129  		"blank": {
   130  			set:     []string{""},
   131  			expList: []string{""},
   132  			expSet:  []string{""},
   133  		},
   134  		"blank comma": {
   135  			set:     []string{","},
   136  			expList: []string{""},
   137  			expSet:  []string{""},
   138  		},
   139  		"defaults": {
   140  			set:     []string{"prometheus"},
   141  			expList: []string{"linkerd", "prometheus"},
   142  			expSet:  []string{"linkerd", "prometheus"},
   143  			def:     []string{"linkerd"},
   144  		},
   145  		"defaults duped": {
   146  			set:     []string{"prometheus"},
   147  			expList: []string{"prometheus", "prometheus"},
   148  			expSet:  []string{"prometheus"},
   149  			def:     []string{"prometheus"},
   150  		},
   151  	}
   152  
   153  	testCollection := func(t *testing.T, v flag.Getter, set, exp []string) {
   154  		t.Helper()
   155  
   156  		for _, s := range set {
   157  			assert.NoErrorf(t, v.Set(s), "setting valid value %s should not error", s)
   158  		}
   159  		assert.Equalf(t, collectionStringFn(exp), v.String(),
   160  			"incorrect value after Set(): want %s, got %s",
   161  			collectionStringFn(exp), v.String(),
   162  		)
   163  
   164  		assert.Equalf(t, exp, v.Get(),
   165  			"incorrect value after Set(): want %s, got %s",
   166  			exp, v.Get(),
   167  		)
   168  	}
   169  
   170  	testPtr := func(t *testing.T, v flag.Getter, ptr, valPtr *[]string) {
   171  		t.Helper()
   172  
   173  		assert.Same(t, ptr, valPtr,
   174  			"pointer used to instantiate flag value is different than values current pointer")
   175  
   176  		vals := v.Get()
   177  		for i := range *ptr {
   178  			assert.Equalf(t, (*ptr)[i], (vals.([]string))[i],
   179  				"pointer used to instantiate flag value references different value than "+
   180  					"returned by value: want %v, got %v", *ptr, v.Get())
   181  		}
   182  	}
   183  
   184  	for name, tc := range tcs {
   185  		tc := tc
   186  		name := name
   187  		t.Run(name, func(t *testing.T) {
   188  			t.Parallel()
   189  
   190  			// Test List implementation
   191  			t.Run(fmt.Sprintf("%s-List", name), func(t *testing.T) {
   192  				t.Parallel()
   193  
   194  				ptr := &([]string{})
   195  				v := &StringList{Var: ptr, Default: tc.def}
   196  				assert.NotPanics(t, func() { v.initialize() },
   197  					"initializing List should not panic")
   198  				assert.True(t, v.initialized)
   199  
   200  				testCollection(t, v, tc.set, tc.expList)
   201  				testPtr(t, v, ptr, v.Var)
   202  			})
   203  
   204  			// Test Set implementation
   205  			t.Run(fmt.Sprintf("%s-Set", name), func(t *testing.T) {
   206  				t.Parallel()
   207  
   208  				ptr := &([]string{})
   209  				v := &StringSet{Var: ptr, Default: tc.def}
   210  				assert.NotPanics(t, func() { v.initialize() },
   211  					"initializing Set should not panic")
   212  				assert.True(t, v.initialized)
   213  
   214  				testCollection(t, v, tc.set, tc.expSet)
   215  				testPtr(t, v, ptr, v.Var)
   216  			})
   217  		})
   218  	}
   219  }
   220  
   221  func TestEnum(t *testing.T) {
   222  	t.Parallel()
   223  
   224  	var s string
   225  	assert.Panics(t, func() { NewEnum(&s) },
   226  		"Enum value without any valid values specified should panic")
   227  	v := NewEnum(&s, "foo", "bar")
   228  	assert.Equalf(t, "foo", v.Default,
   229  		"when default value isnt set, default should be first valid value: "+
   230  			"wanted %s, got %s",
   231  		"foo", v.Default,
   232  	)
   233  
   234  	v = &StringEnum{Var: &s, Default: "bar", Valid: []string{"foo", "bar"}}
   235  	v.initialize()
   236  	assert.Equalf(t, "bar", v.Default,
   237  		"when default value is set explicitly, it should be honored if it is valid: "+
   238  			"wanted %s, got %s",
   239  		"bar", v.Default,
   240  	)
   241  
   242  	v = &StringEnum{Var: &s, Default: "baz", Valid: []string{"foo", "bar"}}
   243  	v.initialize()
   244  	assert.Equalf(t, "foo", v.Default,
   245  		"when default value is set explicitly to an invalid value, it should be "+
   246  			"replaced with first valid value: wanted %s, got %s",
   247  		"foo", v.Default,
   248  	)
   249  
   250  	assert.Error(t, v.Set("baz"), "invalid value should cause an error")
   251  	assert.NoError(t, v.Set("bar"), "setting a valid value should not cause an error")
   252  	assert.Equal(t, "bar", v.Get(), "enum value should reflect updates after Set()")
   253  }
   254  

View as plain text