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  }