github.com/argoproj/argo-cd/v3@v3.2.1/util/env/env_test.go (about) 1 package env 2 3 import ( 4 "fmt" 5 "math" 6 "strconv" 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/assert" 11 "k8s.io/utils/ptr" 12 ) 13 14 func TestParseNumFromEnv(t *testing.T) { 15 const envKey = "SOMEKEY" 16 const minimum = math.MinInt + 1 17 const maximum = math.MaxInt - 1 18 const def = 10 19 testCases := []struct { 20 name string 21 env string 22 expected int 23 }{ 24 {"Valid positive number", "200", 200}, 25 {"Valid negative number", "-200", -200}, 26 {"Invalid number", "abc", def}, 27 {"Equals minimum", strconv.Itoa(math.MinInt + 1), minimum}, 28 {"Equals maximum", strconv.Itoa(math.MaxInt - 1), maximum}, 29 {"Less than minimum", strconv.Itoa(math.MinInt), def}, 30 {"Greater than maximum", strconv.Itoa(math.MaxInt), def}, 31 {"Variable not set", "", def}, 32 } 33 34 for _, tt := range testCases { 35 t.Run(tt.name, func(t *testing.T) { 36 t.Setenv(envKey, tt.env) 37 n := ParseNumFromEnv(envKey, def, minimum, maximum) 38 assert.Equal(t, tt.expected, n) 39 }) 40 } 41 } 42 43 func TestParseFloatFromEnv(t *testing.T) { 44 const envKey = "SOMEKEY" 45 var minimum float32 = -1000.5 46 var maximum float32 = 1000.5 47 const def float32 = 10.5 48 testCases := []struct { 49 name string 50 env string 51 expected float32 52 }{ 53 {"Valid positive float", "2.0", 2.0}, 54 {"Valid negative float", "-2.0", -2.0}, 55 {"Valid integer as float", "2", 2.0}, 56 {"Text as invalid float", "abc", def}, 57 {"Equals maximum", fmt.Sprintf("%v", maximum), maximum}, 58 {"Equals minimum", fmt.Sprintf("%v", minimum), minimum}, 59 {"Greater than maximum", fmt.Sprintf("%f", maximum+1), def}, 60 {"Lesser than minimum", fmt.Sprintf("%f", minimum-1), def}, 61 {"Environment not set at", "", def}, 62 } 63 64 for _, tt := range testCases { 65 t.Run(tt.name, func(t *testing.T) { 66 t.Setenv(envKey, tt.env) 67 f := ParseFloatFromEnv(envKey, def, minimum, maximum) 68 assert.InEpsilon(t, tt.expected, f, 0.0001) 69 }) 70 } 71 } 72 73 func TestParseInt64FromEnv(t *testing.T) { 74 const envKey = "SOMEKEY" 75 const minimum int64 = 1 76 const maximum int64 = math.MaxInt64 - 1 77 const def int64 = 10 78 testCases := []struct { 79 name string 80 env string 81 expected int64 82 }{ 83 {"Valid int64", "200", 200}, 84 {"Text as invalid int64", "abc", def}, 85 {"Equals maximum", strconv.FormatInt(maximum, 10), maximum}, 86 {"Equals minimum", strconv.FormatInt(minimum, 10), minimum}, 87 {"Greater than maximum", strconv.FormatInt(maximum+1, 10), def}, 88 {"Less than minimum", strconv.FormatInt(minimum-1, 10), def}, 89 {"Environment not set", "", def}, 90 } 91 92 for _, tt := range testCases { 93 t.Run(tt.name, func(t *testing.T) { 94 t.Setenv(envKey, tt.env) 95 n := ParseInt64FromEnv(envKey, def, minimum, maximum) 96 assert.Equal(t, tt.expected, n) 97 }) 98 } 99 } 100 101 func TestParseDurationFromEnv(t *testing.T) { 102 envKey := "SOMEKEY" 103 def := 3 * time.Second 104 minimum := 2 * time.Second 105 maximum := 5 * time.Second 106 107 testCases := []struct { 108 name string 109 env string 110 expected time.Duration 111 }{{ 112 name: "EnvNotSet", 113 expected: def, 114 }, { 115 name: "ValidValueSet", 116 env: "2s", 117 expected: time.Second * 2, 118 }, { 119 name: "ValidValueSetMs", 120 env: "2500ms", 121 expected: time.Millisecond * 2500, 122 }, { 123 name: "MoreThanMaxSet", 124 env: "6s", 125 expected: def, 126 }, { 127 name: "LessThanMinSet", 128 env: "1s", 129 expected: def, 130 }, { 131 name: "InvalidSet", 132 env: "hello", 133 expected: def, 134 }} 135 136 for _, tc := range testCases { 137 t.Run(tc.name, func(t *testing.T) { 138 t.Setenv(envKey, tc.env) 139 val := ParseDurationFromEnv(envKey, def, minimum, maximum) 140 assert.Equal(t, tc.expected, val) 141 }) 142 } 143 } 144 145 func Test_ParseBoolFromEnv(t *testing.T) { 146 envKey := "SOMEKEY" 147 148 testCases := []struct { 149 name string 150 env string 151 expected bool 152 def bool 153 }{ 154 {"True value", "true", true, false}, 155 {"False value", "false", false, true}, 156 {"Invalid value with true default", "somevalue", true, true}, 157 {"Invalid value with false default", "somevalue", false, false}, 158 {"Env not set", "", false, false}, 159 } 160 161 for _, tt := range testCases { 162 t.Run(tt.name, func(t *testing.T) { 163 t.Setenv(envKey, tt.env) 164 b := ParseBoolFromEnv(envKey, tt.def) 165 assert.Equal(t, tt.expected, b) 166 }) 167 } 168 } 169 170 func TestStringFromEnv(t *testing.T) { 171 envKey := "SOMEKEY" 172 def := "somestring" 173 174 testCases := []struct { 175 name string 176 env *string 177 expected string 178 def string 179 opts []StringFromEnvOpts 180 }{ 181 {"Some string", ptr.To("true"), "true", def, nil}, 182 {"Empty string with default", ptr.To(""), def, def, nil}, 183 {"Empty string without default", ptr.To(""), "", "", nil}, 184 {"No env variable with default allow empty", nil, "default", "default", []StringFromEnvOpts{{AllowEmpty: true}}}, 185 {"Some variable with default allow empty", ptr.To("true"), "true", "default", []StringFromEnvOpts{{AllowEmpty: true}}}, 186 {"Empty variable with default allow empty", ptr.To(""), "", "default", []StringFromEnvOpts{{AllowEmpty: true}}}, 187 } 188 189 for _, tt := range testCases { 190 t.Run(tt.name, func(t *testing.T) { 191 if tt.env != nil { 192 t.Setenv(envKey, *tt.env) 193 } 194 b := StringFromEnv(envKey, tt.def, tt.opts...) 195 assert.Equal(t, tt.expected, b) 196 }) 197 } 198 } 199 200 func TestStringsFromEnv(t *testing.T) { 201 envKey := "SOMEKEY" 202 def := []string{"one", "two"} 203 204 testCases := []struct { 205 name string 206 env string 207 expected []string 208 def []string 209 sep string 210 }{ 211 {"List of strings", "one,two,three", []string{"one", "two", "three"}, def, ","}, 212 {"Comma separated with other delimeter", "one,two,three", []string{"one,two,three"}, def, ";"}, 213 {"With trimmed white space", "one, two , three", []string{"one", "two", "three"}, def, ","}, 214 {"Env not set", "", def, def, ","}, 215 } 216 217 for _, tt := range testCases { 218 t.Run(tt.name, func(t *testing.T) { 219 t.Setenv(envKey, tt.env) 220 ss := StringsFromEnv(envKey, tt.def, tt.sep) 221 assert.Equal(t, tt.expected, ss) 222 }) 223 } 224 } 225 226 func TestParseStringToStringFromEnv(t *testing.T) { 227 envKey := "SOMEKEY" 228 def := map[string]string{} 229 230 testCases := []struct { 231 name string 232 env string 233 expected map[string]string 234 def map[string]string 235 sep string 236 }{ 237 {"success, no key-value", "", map[string]string{}, def, ","}, 238 {"success, one key, no value", "key1=", map[string]string{"key1": ""}, def, ","}, 239 {"success, one key, no value, with spaces", "key1 = ", map[string]string{"key1": ""}, def, ","}, 240 {"success, one pair", "key1=value1", map[string]string{"key1": "value1"}, def, ","}, 241 {"success, one pair with spaces", "key1 = value1", map[string]string{"key1": "value1"}, def, ","}, 242 {"success, one pair with spaces and no value", "key1 = ", map[string]string{"key1": ""}, def, ","}, 243 {"success, two keys, no value", "key1=,key2=", map[string]string{"key1": "", "key2": ""}, def, ","}, 244 {"success, two keys, no value, with spaces", "key1 = , key2 = ", map[string]string{"key1": "", "key2": ""}, def, ","}, 245 {"success, two pairs", "key1=value1,key2=value2", map[string]string{"key1": "value1", "key2": "value2"}, def, ","}, 246 {"success, two pairs with semicolon as separator", "key1=value1;key2=value2", map[string]string{"key1": "value1", "key2": "value2"}, def, ";"}, 247 {"success, two pairs with spaces", "key1 = value1, key2 = value2", map[string]string{"key1": "value1", "key2": "value2"}, def, ","}, 248 {"failure, one key", "key1", map[string]string{}, def, ","}, 249 {"failure, duplicate keys", "key1=value1,key1=value2", map[string]string{}, def, ","}, 250 {"failure, one key ending with two successive equals to", "key1==", map[string]string{}, def, ","}, 251 {"failure, one valid pair and invalid one key", "key1=value1,key2", map[string]string{}, def, ","}, 252 {"failure, two valid pairs and invalid two keys", "key1=value1,key2=value2,key3,key4", map[string]string{}, def, ","}, 253 } 254 255 for _, tt := range testCases { 256 t.Run(tt.name, func(t *testing.T) { 257 t.Setenv(envKey, tt.env) 258 got := ParseStringToStringFromEnv(envKey, tt.def, tt.sep) 259 assert.Equal(t, tt.expected, got) 260 }) 261 } 262 }