github.com/AbsaOSS/env-binder@v1.0.1/env/bind_test.go (about)

     1  /*
     2  Copyright 2021 The k8gb Contributors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  
    16  Generated by GoLic, for more details see: https://github.com/AbsaOSS/golic
    17  */
    18  
    19  package env
    20  
    21  import (
    22  	"os"
    23  	"reflect"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  // Testee public test structure
    31  type Testee struct {
    32  	ID    int    `env:"TESTEE_ID"`
    33  	Value string `env:"TESTEE_VALUE"`
    34  }
    35  
    36  func TestDefaultAndRequireinOppositeOrder(t *testing.T) {
    37  	defer cleanup()
    38  	// arrange
    39  	_ = os.Setenv(tokenID, "")
    40  	_ = os.Setenv(tokenValue, "")
    41  	type token struct {
    42  		ID    int    `env:"TOKEN_ID, require=true, default = 066, protected=true"`
    43  		Value string `env:"TOKEN_VALUE, protected=true, default = AAAA, require=true"`
    44  	}
    45  	// act
    46  	tok := &token{ID: 5}
    47  	err := Bind(tok)
    48  	// assert
    49  	assert.NoError(t, err)
    50  	assert.Equal(t, 5, tok.ID)
    51  	assert.Equal(t, "", tok.Value)
    52  }
    53  
    54  func TestParseNil(t *testing.T) {
    55  	defer cleanup()
    56  	err := Bind(nil)
    57  	assert.Error(t, err)
    58  }
    59  
    60  func TestParseNotPointer(t *testing.T) {
    61  	defer cleanup()
    62  	err := Bind(Testee{})
    63  	assert.Error(t, err)
    64  }
    65  
    66  func TestInvalidEnvVar(t *testing.T) {
    67  	defer cleanup()
    68  	// arrange
    69  	type token struct {
    70  		ID int `env:"GG%%^"`
    71  	}
    72  	// act
    73  	tok := &token{ID: 5}
    74  	err := Bind(tok)
    75  	// assert
    76  	assert.NoError(t, err)
    77  	assert.Equal(t, 0, tok.ID)
    78  }
    79  
    80  func TestUnsupportedDataType(t *testing.T) {
    81  	defer cleanup()
    82  	// arrange
    83  	type token struct {
    84  		ID reflect.Type `env:"TOKEN_ID"`
    85  	}
    86  	// act
    87  	tok := &token{}
    88  	err := Bind(tok)
    89  	// assert
    90  	assert.Error(t, err)
    91  }
    92  
    93  func TestENVVARIsRequiredError(t *testing.T) {
    94  	defer cleanup()
    95  	// arrange
    96  	type token struct {
    97  		ID    int    `env:"TOKEN_ID, require=true"`
    98  		Value string `env:"TOKEN_VALUE"`
    99  	}
   100  	// act
   101  	tok := &token{ID: 5}
   102  	err := Bind(tok)
   103  	// assert
   104  	assert.Error(t, err)
   105  	assert.Equal(t, 5, tok.ID)
   106  }
   107  
   108  func TestENVVARIsRequiredPass(t *testing.T) {
   109  	defer cleanup()
   110  	// arrange
   111  	const val = "4BMKKDsdfsf5f7="
   112  	_ = os.Setenv(tokenValue, val)
   113  	type token struct {
   114  		Value string `env:"TOKEN_VALUE, require=true"`
   115  	}
   116  	// act
   117  	tok := &token{Value: "AAAA"}
   118  	err := Bind(tok)
   119  	// assert
   120  	assert.NoError(t, err)
   121  	assert.Equal(t, val, tok.Value)
   122  }
   123  
   124  func TestENVVARIsNotRequiredPass(t *testing.T) {
   125  	defer cleanup()
   126  	// arrange
   127  	type token struct {
   128  		ID string `env:"TOKEN_ID, require=false"`
   129  	}
   130  	tok := &token{ID: "AAAA"}
   131  	// act
   132  	err := Bind(tok)
   133  	// assert
   134  	assert.NoError(t, err)
   135  	assert.Equal(t, "", tok.ID)
   136  }
   137  
   138  func TestSetDefaultEmpty(t *testing.T) {
   139  	defer cleanup()
   140  	// arrange
   141  	type token struct {
   142  		ID          int       `env:"TOKEN_ID, default=0"`
   143  		Value       string    `env:"TOKEN_VALUE, default="`
   144  		Ratio       float64   `env:"TOKEN_RATIO, default=0"`
   145  		Readonly    bool      `env:"TOKEN_READONLY, default=false"`
   146  		Hours       []int     `env:"TOKEN_HOURS, default[]"` // can't be parsed!
   147  		URLs        []string  `env:"TOKEN_URLS, default=[]"`
   148  		Enabled     []bool    `env:"TOKEN_BOOLS, default=[]"`
   149  		Coordinates []float64 `env:"TOKEN_COORDINATES, default=[]"`
   150  	}
   151  	tok := &token{}
   152  	// act
   153  	err := Bind(tok)
   154  
   155  	// assert
   156  	assert.NoError(t, err)
   157  	assert.Equal(t, 0, tok.ID)
   158  	assert.Equal(t, "", tok.Value)
   159  	assert.Equal(t, 0., tok.Ratio)
   160  	assert.Equal(t, false, tok.Readonly)
   161  	assert.Equal(t, []int(nil), tok.Hours)
   162  	assert.Equal(t, []string{}, tok.URLs)
   163  	assert.Equal(t, []bool{}, tok.Enabled)
   164  	assert.Equal(t, []float64{}, tok.Coordinates)
   165  }
   166  
   167  func TestInvalidValue(t *testing.T) {
   168  	defer cleanup()
   169  	_ = os.Setenv(envString, "invalid")
   170  	_ = os.Setenv(envBool, "invalid")
   171  	_ = os.Setenv(envFloat64, "invalid")
   172  	_ = os.Setenv(envInt, "invalid")
   173  	_ = os.Setenv(envStringSlice, "[]")
   174  	_ = os.Setenv(envBoolSlice, "invalid")
   175  	_ = os.Setenv(envFloat64Slice, "invalid")
   176  	_ = os.Setenv(envIntSlice, "invalid")
   177  	// arrange
   178  	type token1 struct {
   179  		envString string `env:"ENV_STRING, default=test"`
   180  	}
   181  	type token2 struct {
   182  		envInt int `env:"ENV_INT, default=22"`
   183  	}
   184  	type token3 struct {
   185  		envBool bool `env:"ENV_BOOL, default=true"`
   186  	}
   187  	type token4 struct {
   188  		envFloat float32 `env:"ENV_FLOAT64, default=22.0"`
   189  	}
   190  	type token5 struct {
   191  		envStringSlice []string `env:"ENV_STRING_SLICE, default=[test,test]"`
   192  	}
   193  	type token6 struct {
   194  		envIntSlice []int `env:"ENV_INT_SLICE, default=[22]"`
   195  	}
   196  	type token7 struct {
   197  		envBoolSlice []bool `env:"ENV_BOOL_SLICE, default=[T]"`
   198  	}
   199  	type token8 struct {
   200  		envFloatSlice []float32 `env:"ENV_FLOAT64_SLICE, default=[22.0]"`
   201  	}
   202  
   203  	// act
   204  	// assert
   205  	err := Bind(&token1{})
   206  	assert.NoError(t, err)
   207  	err = Bind(&token2{})
   208  	assert.Error(t, err)
   209  	err = Bind(&token3{})
   210  	assert.Error(t, err)
   211  	err = Bind(&token4{})
   212  	assert.Error(t, err)
   213  	err = Bind(&token5{})
   214  	assert.NoError(t, err)
   215  	err = Bind(&token6{})
   216  	assert.Error(t, err)
   217  	err = Bind(&token7{})
   218  	assert.Error(t, err)
   219  	err = Bind(&token8{})
   220  	assert.Error(t, err)
   221  }
   222  
   223  func TestEmptyValue(t *testing.T) {
   224  	defer cleanup()
   225  	_ = os.Setenv(envString, "")
   226  	_ = os.Setenv(envInt, "")
   227  	_ = os.Setenv(envBool, "")
   228  	_ = os.Setenv(envFloat64, "")
   229  	_ = os.Setenv(envStringSlice, "")
   230  	_ = os.Setenv(envIntSlice, "")
   231  	_ = os.Setenv(envBoolSlice, "")
   232  	_ = os.Setenv(envFloat64Slice, "")
   233  	// arrange
   234  	// arrange
   235  	type tokenString struct {
   236  		envString string `env:"ENV_STRING, default=test"`
   237  	}
   238  	type tokenInt struct {
   239  		envInt int `env:"ENV_INT, default=22"`
   240  	}
   241  	type tokenBool struct {
   242  		envBool bool `env:"ENV_BOOL, default=true"`
   243  	}
   244  	type tokenFloat struct {
   245  		envFloat float32 `env:"ENV_FLOAT64, default=22.0"`
   246  	}
   247  	type tokenStringSlice struct {
   248  		envStringSlice []string `env:"ENV_STRING_SLICE, default=[test,test]"`
   249  	}
   250  	type tokenIntSlice struct {
   251  		envIntSlice []int `env:"ENV_INT_SLICE, default=[22]"`
   252  	}
   253  	type tokenBoolSlice struct {
   254  		envBoolSlice []bool `env:"ENV_BOOL_SLICE, default=[T]"`
   255  	}
   256  	type tokenFloatSlice struct {
   257  		envFloatSlice []float32 `env:"ENV_FLOAT64_SLICE, default=[22.0]"`
   258  	}
   259  
   260  	// act
   261  	// assert
   262  	t1 := &tokenString{}
   263  	err := Bind(t1)
   264  	assert.NoError(t, err)
   265  	assert.Equal(t, "", t1.envString)
   266  	err = Bind(&tokenInt{})
   267  	assert.Error(t, err)
   268  	err = Bind(&tokenBool{})
   269  	assert.Error(t, err)
   270  	err = Bind(&tokenFloat{})
   271  	assert.Error(t, err)
   272  	t5 := &tokenStringSlice{}
   273  	err = Bind(t5)
   274  	assert.NoError(t, err)
   275  	assert.Equal(t, []string{}, t5.envStringSlice)
   276  	t6 := &tokenIntSlice{}
   277  	err = Bind(t6)
   278  	assert.NoError(t, err)
   279  	assert.Equal(t, []int{}, t6.envIntSlice)
   280  	t7 := &tokenBoolSlice{}
   281  	err = Bind(t7)
   282  	assert.NoError(t, err)
   283  	assert.Equal(t, []bool{}, t7.envBoolSlice)
   284  	t8 := &tokenFloatSlice{}
   285  	err = Bind(t8)
   286  	assert.NoError(t, err)
   287  	assert.Equal(t, []float32{}, t8.envFloatSlice)
   288  }
   289  
   290  func TestProtected(t *testing.T) {
   291  	defer cleanup()
   292  	_ = os.Setenv(envString, "200")
   293  	_ = os.Setenv(envInt, "200")
   294  	_ = os.Setenv(envBool, "false")
   295  	_ = os.Setenv(envFloat64, "200")
   296  	_ = os.Setenv(envStringSlice, "2,0,0")
   297  	_ = os.Setenv(envIntSlice, "2,0,0")
   298  	_ = os.Setenv(envBoolSlice, "1,0,0")
   299  	_ = os.Setenv(envFloat64Slice, "2,0,0")
   300  	// arrange
   301  	type token struct {
   302  		envInt         int       `env:"ENV_INT, protected=true, default=100"`
   303  		envString      string    `env:"ENV_STRING, default=100, protected=true"`
   304  		envBool        bool      `env:"ENV_BOOL, default=F, protected=true"`
   305  		envFloat       float64   `env:"ENV_FLOAT64, default=100, protected =true"`
   306  		envIntSlice    []int     `env:"ENV_INT_SLICE, default=[1,0,0], protected=true"`
   307  		envStringSlice []string  `env:"ENV_STRING_SLICE, protected=true, default=[1,0,0]"`
   308  		envBoolSlice   []bool    `env:"ENV_BOOL_SLICE, protected=true, default=[1,0,0]"`
   309  		envFloatSlice  []float64 `env:"ENV_FLOAT64_SLICE, protected=true, default=[100,100,100]"`
   310  	}
   311  	type token2 struct {
   312  		envInt         int       `env:"ENV_INT, protected=false, default=100"`
   313  		envString      string    `env:"ENV_STRING, default=100, protected=false"`
   314  		envBool        bool      `env:"ENV_BOOL, default=F, protected=false"`
   315  		envFloat       float64   `env:"ENV_FLOAT64, default=100"`
   316  		envIntSlice    []int     `env:"ENV_INT_SLICE, default=[1,0,0]"`
   317  		envStringSlice []string  `env:"ENV_STRING_SLICE, default=[1,0,0]"`
   318  		envBoolSlice   []bool    `env:"ENV_BOOL_SLICE, protected=false, default=[1,0,0]"`
   319  		envFloatSlice  []float64 `env:"ENV_FLOAT64_SLICE, protected=false, default=[100,100,100]"`
   320  	}
   321  	unprotected := &token2{
   322  		envInt:         300,
   323  		envString:      "300",
   324  		envFloat:       300.0,
   325  		envBool:        true,
   326  		envIntSlice:    []int{3, 0, 0},
   327  		envBoolSlice:   []bool{true, true, true},
   328  		envStringSlice: []string{"300"},
   329  		envFloatSlice:  []float64{3, 0, 0},
   330  	}
   331  	unprotectedEmpty := &token2{}
   332  
   333  	filled := &token{
   334  		envInt:         300,
   335  		envString:      "300",
   336  		envFloat:       300.0,
   337  		envBool:        true,
   338  		envIntSlice:    []int{3, 0, 0},
   339  		envBoolSlice:   []bool{true, true, true},
   340  		envStringSlice: []string{"300"},
   341  		envFloatSlice:  []float64{3, 0, 0},
   342  	}
   343  	empty := &token{}
   344  	// act
   345  	err1 := Bind(filled)
   346  	err2 := Bind(empty)
   347  	err3 := Bind(unprotected)
   348  	err4 := Bind(unprotectedEmpty)
   349  
   350  	// assert
   351  	assert.NoError(t, err1)
   352  	assert.Equal(t, filled.envInt, 300)
   353  	assert.Equal(t, filled.envString, "300")
   354  	assert.Equal(t, filled.envBool, true)
   355  	assert.Equal(t, filled.envFloat, 300.0)
   356  	assert.Equal(t, filled.envIntSlice, []int{3, 0, 0})
   357  	assert.Equal(t, filled.envStringSlice, []string{"300"})
   358  	assert.Equal(t, filled.envBoolSlice, []bool{true, true, true})
   359  	assert.Equal(t, filled.envFloatSlice, []float64{3, 0, 0})
   360  	assert.NoError(t, err2)
   361  	assert.Equal(t, empty.envInt, 200)
   362  	assert.Equal(t, empty.envString, "200")
   363  	assert.Equal(t, empty.envBool, false)
   364  	assert.Equal(t, empty.envFloat, 200.0)
   365  	assert.Equal(t, empty.envIntSlice, []int{2, 0, 0})
   366  	assert.Equal(t, empty.envStringSlice, []string{"2", "0", "0"})
   367  	assert.Equal(t, empty.envBoolSlice, []bool{true, false, false})
   368  	assert.Equal(t, empty.envFloatSlice, []float64{2, 0, 0})
   369  
   370  	assert.NoError(t, err3)
   371  	assert.Equal(t, unprotected.envInt, 200)
   372  	assert.Equal(t, unprotected.envString, "200")
   373  	assert.Equal(t, unprotected.envBool, false)
   374  	assert.Equal(t, unprotected.envFloat, 200.0)
   375  	assert.Equal(t, unprotected.envIntSlice, []int{2, 0, 0})
   376  	assert.Equal(t, unprotected.envStringSlice, []string{"2", "0", "0"})
   377  	assert.Equal(t, unprotected.envBoolSlice, []bool{true, false, false})
   378  	assert.Equal(t, unprotected.envFloatSlice, []float64{2, 0, 0})
   379  	assert.NoError(t, err4)
   380  	assert.Equal(t, unprotectedEmpty.envInt, 200)
   381  	assert.Equal(t, unprotectedEmpty.envString, "200")
   382  	assert.Equal(t, unprotectedEmpty.envBool, false)
   383  	assert.Equal(t, unprotectedEmpty.envFloat, 200.0)
   384  	assert.Equal(t, unprotectedEmpty.envIntSlice, []int{2, 0, 0})
   385  	assert.Equal(t, unprotectedEmpty.envStringSlice, []string{"2", "0", "0"})
   386  	assert.Equal(t, unprotectedEmpty.envBoolSlice, []bool{true, false, false})
   387  	assert.Equal(t, unprotectedEmpty.envFloatSlice, []float64{2, 0, 0})
   388  }
   389  
   390  func TestEnvVarDoesntExists(t *testing.T) {
   391  	defer cleanup()
   392  	// arrange
   393  	type token struct {
   394  		ID int `env:"TOKEN_IDX, default=22"`
   395  	}
   396  	tok := &token{ID: 50}
   397  	// act
   398  	err := Bind(tok)
   399  
   400  	// assert
   401  	assert.NoError(t, err)
   402  	assert.Equal(t, 22, tok.ID)
   403  }
   404  
   405  func TestSetFieldWhenVariableDoesntExists(t *testing.T) {
   406  	defer cleanup()
   407  
   408  	// arrange
   409  	type token struct {
   410  		ID          int       `env:"TOKEN_ID, default=22"`
   411  		Value       string    `env:"TOKEN_VALUE, default=fc3"`
   412  		Ratio       float64   `env:"TOKEN_RATIO, default=-0.000123"`
   413  		Readonly    bool      `env:"TOKEN_READONLY, default=1"`
   414  		Hours       []int     `env:"TOKEN_HOURS, default=[2,5,10]"`
   415  		URLs        []string  `env:"TOKEN_URLS, default=[http://server.local:8080,https://server.exposed.com:80]"`
   416  		Enabled     []bool    `env:"TOKEN_BOOLS, default=[true, false, true]"`
   417  		Coordinates []float64 `env:"TOKEN_COORDINATES, default=[0.000123,-12.2250]"`
   418  		EmptySlice  []bool    `env:"EMPTY_SLICE, default=[]"`
   419  	}
   420  	tok := &token{
   421  		ID:          11,
   422  		Value:       "AAAA",
   423  		Ratio:       70.0,
   424  		Readonly:    false,
   425  		Hours:       []int{0},
   426  		URLs:        nil,
   427  		Enabled:     []bool{},
   428  		Coordinates: nil,
   429  		EmptySlice:  []bool{true, true},
   430  	}
   431  
   432  	// act
   433  	err := Bind(tok)
   434  
   435  	// assert
   436  	assert.NoError(t, err)
   437  	assert.Equal(t, 22, tok.ID)
   438  	assert.Equal(t, "fc3", tok.Value)
   439  	assert.Equal(t, -0.000123, tok.Ratio)
   440  	assert.Equal(t, true, tok.Readonly)
   441  	assert.Equal(t, []int{2, 5, 10}, tok.Hours)
   442  	assert.Equal(t, []string{"http://server.local:8080", "https://server.exposed.com:80"}, tok.URLs)
   443  	assert.Equal(t, []bool{true, false, true}, tok.Enabled)
   444  	assert.Equal(t, []float64{0.000123, -12.2250}, tok.Coordinates)
   445  	assert.Equal(t, []bool{}, tok.EmptySlice)
   446  }
   447  
   448  func TestReadingPrivateFields(t *testing.T) {
   449  	defer cleanup()
   450  	// arrange
   451  	const val = "4BMKKDsdfsf5f7="
   452  	_ = os.Setenv(tokenValue, val)
   453  	type token struct {
   454  		id       int    `env:"TOKEN_ID, default=22"`
   455  		readonly bool   `env:"TOKEN_READONLY, require=0"`
   456  		value    string `env:"TOKEN_VALUE, default=fc3, require=1"`
   457  	}
   458  
   459  	// act
   460  	tok := &token{id: 11, value: ""}
   461  
   462  	// act
   463  	err := Bind(tok)
   464  	assert.NoError(t, err)
   465  	assert.Equal(t, 22, tok.id)
   466  	assert.Equal(t, false, tok.readonly)
   467  	assert.Equal(t, val, tok.value)
   468  }
   469  
   470  func TestReadingAnonymousFields(t *testing.T) {
   471  	defer cleanup()
   472  	// arrange
   473  	_ = os.Setenv(tokenReadOnly, "false, false")
   474  	type token struct {
   475  		private struct {
   476  			readonly []bool `env:"TOKEN_READONLY, require=0"`
   477  		}
   478  		Exported struct {
   479  			Value string `env:"TOKEN_VALUE, default=#fc3, require=1"`
   480  		}
   481  	}
   482  
   483  	// act
   484  	tok := &token{}
   485  
   486  	// act
   487  	err := Bind(tok)
   488  	assert.NoError(t, err)
   489  	assert.Equal(t, []bool{false, false}, tok.private.readonly)
   490  	assert.Equal(t, "#fc3", tok.Exported.Value)
   491  }
   492  
   493  func TestReadingStructuresFields(t *testing.T) {
   494  	defer cleanup()
   495  	// arrange
   496  	_ = os.Setenv(tokenReadOnly, "false, false")
   497  	type private struct {
   498  		readonly []bool `env:"TOKEN_READONLY, require=0"`
   499  	}
   500  	type Exported struct {
   501  		Value string `env:"TOKEN_VALUE, default=#fc3, require=1"`
   502  	}
   503  	type token struct {
   504  		ID       int
   505  		private  private
   506  		Exported Exported
   507  	}
   508  
   509  	// act
   510  	tok := &token{ID: 50}
   511  
   512  	// act
   513  	err := Bind(tok)
   514  	assert.NoError(t, err)
   515  	assert.Equal(t, []bool{false, false}, tok.private.readonly)
   516  	assert.Equal(t, "#fc3", tok.Exported.Value)
   517  }
   518  
   519  func TestNoEnv(t *testing.T) {
   520  	defer cleanup()
   521  	// arrange
   522  	type private struct {
   523  		readonly []bool
   524  	}
   525  	type Exported struct {
   526  		Value string
   527  	}
   528  	type token struct {
   529  		ID        int
   530  		private   private
   531  		Exported  Exported
   532  		Anonymous struct {
   533  			A string
   534  			b string
   535  		}
   536  	}
   537  
   538  	// act
   539  	tok := &token{
   540  		ID: 22,
   541  		private: private{
   542  			readonly: []bool{true, true},
   543  		},
   544  		Exported: Exported{
   545  			Value: "exported"},
   546  	}
   547  	tok.Anonymous.A = "B"
   548  	tok.Anonymous.b = "a"
   549  
   550  	// assert
   551  	err := Bind(tok)
   552  	assert.NoError(t, err)
   553  	assert.Equal(t, 22, tok.ID)
   554  	assert.Equal(t, []bool{true, true}, tok.private.readonly)
   555  	assert.Equal(t, "exported", tok.Exported.Value)
   556  	assert.Equal(t, "B", tok.Anonymous.A)
   557  	assert.Equal(t, "a", tok.Anonymous.b)
   558  }
   559  
   560  func TestSpecialSymbols(t *testing.T) {
   561  	defer cleanup()
   562  	// arrange
   563  	_ = os.Setenv(tokenValue, `----~<>/?.;:/!@#$%^&*()_+_=---\-\`)
   564  	type token struct {
   565  		ID    string   `env:"TOKEN_ID, default=----~<>/?.;:/!@#$%^&*()_+_=---\\-"`
   566  		Value string   `env:"TOKEN_VALUE, require=true"`
   567  		Slice []string `env:"TOKEN_SLICE, default=[--- -~<>/?.;:/!@#$%^&*()_+_=----,  ----~<>/?.;:/!@#$%^&*()_+_=----]"`
   568  	}
   569  	tok := &token{}
   570  	// act
   571  	err := Bind(tok)
   572  	// assert
   573  	assert.NoError(t, err)
   574  	assert.Equal(t, `----~<>/?.;:/!@#$%^&*()_+_=---\-`, tok.ID)
   575  	assert.Equal(t, "----~<>/?.;:/!@#$%^&*()_+_=---\\-\\", tok.Value)
   576  	assert.Equal(t, []string{"--- -~<>/?.;:/!@#$%^&*()_+_=----", "  ----~<>/?.;:/!@#$%^&*()_+_=----"}, tok.Slice)
   577  }
   578  
   579  func TestSetFieldWhenVariableExists(t *testing.T) {
   580  	defer cleanup()
   581  	// arrange
   582  	const val = "4BMKKDsdfsf5f7="
   583  	_ = os.Setenv(tokenValue, val)
   584  	type token struct {
   585  		ID    int    `env:"TOKEN_ID"`
   586  		Value string `env:"TOKEN_VALUE"`
   587  	}
   588  	tok := &token{Value: "AAAA", ID: 5}
   589  	// act
   590  	err := Bind(tok)
   591  	// assert
   592  	assert.NoError(t, err)
   593  	assert.Equal(t, val, tok.Value)
   594  	assert.Equal(t, 0, tok.ID)
   595  }
   596  
   597  func TestArray(t *testing.T) {
   598  	defer cleanup()
   599  	// arrange
   600  	_ = os.Setenv(tokenValue, "1,2,3")
   601  	_ = os.Setenv(tokenID, "1, 2, 3")
   602  	_ = os.Setenv(tokenBools, "1, 0, false, true, F,T")
   603  	_ = os.Setenv(tokenCoordinates, "1.01, -0.05")
   604  	type token struct {
   605  		IDs    []int     `env:"TOKEN_VALUE"`
   606  		Value  []string  `env:"TOKEN_VALUE"`
   607  		Bools  []bool    `env:"TOKEN_SWITCH"`
   608  		Floats []float64 `env:"TOKEN_COORDINATES"`
   609  	}
   610  	tok := &token{}
   611  	// act
   612  	err := Bind(tok)
   613  	// assert
   614  	assert.NoError(t, err)
   615  	assert.Equal(t, []int{1, 2, 3}, tok.IDs)
   616  	assert.Equal(t, []string{"1", "2", "3"}, tok.Value)
   617  	assert.Equal(t, []bool{true, false, false, true, false, true}, tok.Bools)
   618  	assert.Equal(t, []float64{1.01, -0.05}, tok.Floats)
   619  }
   620  
   621  func TestSetMultipleFieldsByOneVariable(t *testing.T) {
   622  	// arrange
   623  	defer cleanup()
   624  	const val = "4BMKKDsdfsf5f7="
   625  	_ = os.Setenv(tokenValue, val)
   626  	type token struct {
   627  		ID1    int    `env:"TOKEN_ID, default=50"`
   628  		ID2    int    `env:"TOKEN_ID, default=10"`
   629  		Value1 string `env:"TOKEN_VALUE, require=true"`
   630  		Value2 string `env:"TOKEN_VALUE, require=true"`
   631  	}
   632  	// act
   633  	tok := &token{}
   634  	err := Bind(tok)
   635  	// assert
   636  	assert.NoError(t, err)
   637  	assert.Equal(t, tok.ID1, 50)
   638  	assert.Equal(t, tok.ID2, 10)
   639  	assert.Equal(t, tok.Value1, val)
   640  	assert.Equal(t, tok.Value2, val)
   641  }
   642  
   643  func TestLowercase(t *testing.T) {
   644  	// arrange
   645  	val := "private field"
   646  	_ = os.Unsetenv(strings.ToLower(strings.ToLower(privateTokenValue)))
   647  	_ = os.Setenv(strings.ToLower(privateTokenValue), val)
   648  	// act
   649  	type token struct {
   650  		valLowerCase string `env:"private_token_value"`
   651  		valUpperCase string `env:"PRIVATE_TOKEN_VALUE"`
   652  	}
   653  	tok := &token{}
   654  
   655  	// assert
   656  	err := Bind(tok)
   657  	assert.NoError(t, err)
   658  	assert.Equal(t, val, tok.valLowerCase)
   659  	assert.Equal(t, "", tok.valUpperCase)
   660  }
   661  
   662  func TestPrefixSuccessfully(t *testing.T) {
   663  	defer cleanup()
   664  	// arrange
   665  	_ = os.Setenv(privateTokenValue, "private field")
   666  	_ = os.Setenv(exportedTokenValue, "exported field")
   667  	_ = os.Setenv(privateExportedTokenValue, "private in exported field")
   668  	_ = os.Setenv("TEMP_TOKEN_ID", "20")
   669  	_ = os.Setenv("TEMP_FIELD_HIDDEN", "very hidden")
   670  	type private struct {
   671  		Value string `env:"TOKEN_VALUE, require=0"`
   672  	}
   673  	type Exported struct {
   674  		Value string `env:"TOKEN_VALUE, require=1"`
   675  	}
   676  	type token struct {
   677  		private  private  `env:"PRIVATE"`
   678  		Exported Exported `env:"EXPORTED"`
   679  		Temp     struct {
   680  			ID    int `env:"TOKEN_ID"`
   681  			field struct {
   682  				hidden string `env:"HIDDEN"`
   683  			} `env:"FIELD"`
   684  		} `env:"TEMP"`
   685  		ID int `env:"TOKEN_ID, default=-1"`
   686  	}
   687  
   688  	// act
   689  	tok := &token{ID: 50}
   690  	err := Bind(tok)
   691  	// assert
   692  	assert.NoError(t, err)
   693  	assert.Equal(t, -1, tok.ID)
   694  	assert.Equal(t, tok.private.Value, "private field")
   695  	assert.Equal(t, tok.Exported.Value, "exported field")
   696  	assert.Equal(t, tok.Temp.ID, 20)
   697  	assert.Equal(t, tok.Temp.field.hidden, "very hidden")
   698  }
   699  
   700  func TestParseSimple(t *testing.T) {
   701  	// arrange
   702  	defer cleanup()
   703  	env := make(map[string]string)
   704  	env[envString] = "foo"
   705  	env[envBool] = "true"
   706  	setEnv(env)
   707  
   708  	type token struct {
   709  		ID    int    `env:"TOKEN_ID"`
   710  		Value string `env:"TOKEN_VALUE"`
   711  	}
   712  	type s struct {
   713  		UID       int       `env:"ENV_INT,default=55"`
   714  		name      string    `env:"ENV_STRING,require=true, default=michal"`
   715  		B         bool      `env:"ENV_BOOL"`
   716  		Bs        []bool    `env:"ENV_BOOL_SLICE,default=[true, false, true]"`
   717  		nums      []int     `env:"ENV_INT_SLICE,default=[10,0,5, 3, 4, 5]"`
   718  		F         float64   `env:"ENV_FLOAT64, default=0.000000002121"`
   719  		Fs        []float64 `env:"ENV_FLOAT64_SLICE,default=[0.0021,0.002,1.13,2.15]"`
   720  		surname   string
   721  		Token     token
   722  		Anonymous struct {
   723  			secret      string `env:"ENV_STRING_PRIVATE"`
   724  			TopSecret   bool
   725  			TokenBase64 string   `env:"ENV_STRING_EXPORTED"`
   726  			arr         []string `env:"ANONYMOUS_ARR, default= [abc, xyz, 123] "`
   727  		}
   728  	}
   729  	testee := &s{name: "Michal"}
   730  
   731  	// act
   732  	err := Bind(testee)
   733  
   734  	// assert
   735  	assert.Equal(t, testee.name, "foo")
   736  	assert.Equal(t, testee.UID, 55)
   737  	assert.Equal(t, testee.nums, []int{10, 0, 5, 3, 4, 5})
   738  	assert.Equal(t, testee.Bs, []bool{true, false, true})
   739  	assert.True(t, reflect.DeepEqual(testee.Anonymous.arr, []string{"abc", " xyz", " 123"}))
   740  	assert.Equal(t, testee.F, 0.000000002121)
   741  	assert.Equal(t, []float64{0.0021, 0.002, 1.13, 2.15}, testee.Fs)
   742  	assert.False(t, testee.Anonymous.TopSecret)
   743  	assert.NoError(t, err)
   744  }
   745  
   746  func TestService(t *testing.T) {
   747  	type Endpoint struct {
   748  		URL string `env:"ENDPOINT_URL, require=true"`
   749  	}
   750  	type Config struct {
   751  		// reading string value from NAME
   752  		Name string `env:"NAME"`
   753  		// reading int with 8080 as default value
   754  		DefaultPot int `env:"PORT, default=8080"`
   755  		// reading slice of strings with default values
   756  		Regions []string `env:"REGIONS, default=[us-east-1,us-east-2,us-west-1]"`
   757  		// inline structure
   758  		Credentials struct {
   759  			// binding required value
   760  			KeyID string `env:"ACCESS_KEY_ID, require=true"`
   761  			// binding to private field
   762  			secretKey string `env:"SECRET_ACCESS_KEY, require=true"`
   763  		}
   764  		// expected PRIMARY_ prefix in nested environment variables
   765  		Endpoint1 Endpoint `env:"PRIMARY"`
   766  		// expected FAILOVER_ prefix in nested environment variables
   767  		Endpoint2 Endpoint `env:"FAILOVER"`
   768  		// reuse an already bound env variable NAME
   769  		Description string `env:"NAME"`
   770  		// the field does not have a bind tag set, so it will be ignored during bind
   771  		Args []string
   772  	}
   773  
   774  	_ = os.Setenv(primaryEndpointURL, "https://ep1.cloud.example.com")
   775  	_ = os.Setenv(failoverEndpointURL, "https://ep2.cloud.example.com")
   776  	_ = os.Setenv(name, "Hello from 12-factor")
   777  	_ = os.Setenv(defaultPort, "9000")
   778  	_ = os.Setenv(accessKeyID, "AKIAIOSFODNN7EXAMPLE")
   779  	_ = os.Setenv(secretAccessKey, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`)
   780  
   781  	// act
   782  	c := Config{Description: "Hello from os.LookupEnv()", Args: []string{"debug=true"}}
   783  	err := Bind(&c)
   784  	// assert
   785  	assert.NoError(t, err)
   786  	assert.Equal(t, "https://ep1.cloud.example.com", c.Endpoint1.URL)
   787  	assert.Equal(t, "https://ep2.cloud.example.com", c.Endpoint2.URL)
   788  	assert.Equal(t, "Hello from 12-factor", c.Name)
   789  	assert.Equal(t, 9000, c.DefaultPot)
   790  	assert.Equal(t, "AKIAIOSFODNN7EXAMPLE", c.Credentials.KeyID)
   791  	assert.Equal(t, `wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`, c.Credentials.secretKey)
   792  }
   793  
   794  func TestTypeInt(t *testing.T) {
   795  	cleanup()
   796  	_ = os.Setenv(envInt, "")
   797  	_ = os.Setenv(envInt2, "1")
   798  	type token struct {
   799  		empty        int `env:"ENV_INT"`
   800  		filled       int `env:"ENV_INT2, require=true"`
   801  		protected    int `env:"ENV_INT, protected=true"`
   802  		doesntExists int `env:"ENV_INT3, default=20"`
   803  	}
   804  
   805  	tok := &token{protected: 80}
   806  	err := Bind(tok)
   807  	assert.Error(t, err)
   808  	_ = os.Setenv(envInt, "1")
   809  	err = Bind(tok)
   810  	assert.NoError(t, err)
   811  	assert.Equal(t, 1, tok.empty)
   812  	assert.Equal(t, 1, tok.filled)
   813  	assert.Equal(t, 80, tok.protected)
   814  	assert.Equal(t, 20, tok.doesntExists)
   815  }
   816  
   817  func TestTypeInt8(t *testing.T) {
   818  	cleanup()
   819  	_ = os.Setenv(envInt, "")
   820  	_ = os.Setenv(envInt2, "1")
   821  	type token struct {
   822  		empty        int8 `env:"ENV_INT"`
   823  		filled       int8 `env:"ENV_INT2, require=true"`
   824  		protected    int8 `env:"ENV_INT, protected=true"`
   825  		doesntExists int8 `env:"ENV_INT3, default=20"`
   826  	}
   827  
   828  	tok := &token{protected: 80}
   829  	err := Bind(tok)
   830  	assert.Error(t, err)
   831  	_ = os.Setenv(envInt, "1")
   832  	err = Bind(tok)
   833  	assert.NoError(t, err)
   834  	assert.Equal(t, int8(1), tok.empty)
   835  	assert.Equal(t, int8(1), tok.filled)
   836  	assert.Equal(t, int8(80), tok.protected)
   837  	assert.Equal(t, int8(20), tok.doesntExists)
   838  }
   839  
   840  func TestTypeInt16(t *testing.T) {
   841  	cleanup()
   842  	_ = os.Setenv(envInt, "")
   843  	_ = os.Setenv(envInt2, "1")
   844  	type token struct {
   845  		empty        int16 `env:"ENV_INT"`
   846  		filled       int16 `env:"ENV_INT2, require=true"`
   847  		protected    int16 `env:"ENV_INT, protected=true"`
   848  		doesntExists int16 `env:"ENV_INT3, default=20"`
   849  	}
   850  
   851  	tok := &token{protected: 80}
   852  	err := Bind(tok)
   853  	assert.Error(t, err)
   854  	_ = os.Setenv(envInt, "1")
   855  	err = Bind(tok)
   856  	assert.NoError(t, err)
   857  	assert.Equal(t, int16(1), tok.empty)
   858  	assert.Equal(t, int16(1), tok.filled)
   859  	assert.Equal(t, int16(80), tok.protected)
   860  	assert.Equal(t, int16(20), tok.doesntExists)
   861  }
   862  
   863  func TestTypeInt32(t *testing.T) {
   864  	cleanup()
   865  	_ = os.Setenv(envInt, "")
   866  	_ = os.Setenv(envInt2, "1")
   867  	type token struct {
   868  		empty        int32 `env:"ENV_INT"`
   869  		filled       int32 `env:"ENV_INT2, require=true"`
   870  		protected    int32 `env:"ENV_INT, protected=true"`
   871  		doesntExists int32 `env:"ENV_INT3, default=20"`
   872  	}
   873  
   874  	tok := &token{protected: 80}
   875  	err := Bind(tok)
   876  	assert.Error(t, err)
   877  	_ = os.Setenv(envInt, "1")
   878  	err = Bind(tok)
   879  	assert.NoError(t, err)
   880  	assert.Equal(t, int32(1), tok.empty)
   881  	assert.Equal(t, int32(1), tok.filled)
   882  	assert.Equal(t, int32(80), tok.protected)
   883  	assert.Equal(t, int32(20), tok.doesntExists)
   884  }
   885  
   886  func TestTypeInt64(t *testing.T) {
   887  	cleanup()
   888  	_ = os.Setenv(envInt, "")
   889  	_ = os.Setenv(envInt2, "1")
   890  	type token struct {
   891  		empty        int64 `env:"ENV_INT"`
   892  		filled       int64 `env:"ENV_INT2, require=true"`
   893  		protected    int64 `env:"ENV_INT, protected=true"`
   894  		doesntExists int64 `env:"ENV_INT3, default=20"`
   895  	}
   896  
   897  	tok := &token{protected: 80}
   898  	err := Bind(tok)
   899  	assert.Error(t, err)
   900  	_ = os.Setenv(envInt, "1")
   901  	err = Bind(tok)
   902  	assert.NoError(t, err)
   903  	assert.Equal(t, int64(1), tok.empty)
   904  	assert.Equal(t, int64(1), tok.filled)
   905  	assert.Equal(t, int64(80), tok.protected)
   906  	assert.Equal(t, int64(20), tok.doesntExists)
   907  }
   908  
   909  func TestTypeFloat32(t *testing.T) {
   910  	cleanup()
   911  	_ = os.Setenv(envInt, "")
   912  	_ = os.Setenv(envInt2, "1")
   913  	type token struct {
   914  		empty        float32 `env:"ENV_INT"`
   915  		filled       float32 `env:"ENV_INT2, require=true"`
   916  		protected    float32 `env:"ENV_INT, protected=true"`
   917  		doesntExists float32 `env:"ENV_INT3, default=20"`
   918  	}
   919  
   920  	tok := &token{protected: 80}
   921  	err := Bind(tok)
   922  	assert.Error(t, err)
   923  	_ = os.Setenv(envInt, "1")
   924  	err = Bind(tok)
   925  	assert.NoError(t, err)
   926  	assert.Equal(t, float32(1), tok.empty)
   927  	assert.Equal(t, float32(1), tok.filled)
   928  	assert.Equal(t, float32(80), tok.protected)
   929  	assert.Equal(t, float32(20), tok.doesntExists)
   930  }
   931  
   932  func TestTypeFloat64(t *testing.T) {
   933  	cleanup()
   934  	_ = os.Setenv(envInt, "")
   935  	_ = os.Setenv(envInt2, "1")
   936  	type token struct {
   937  		empty        float64 `env:"ENV_INT"`
   938  		filled       float64 `env:"ENV_INT2, require=true"`
   939  		protected    float64 `env:"ENV_INT, protected=true"`
   940  		doesntExists float64 `env:"ENV_INT3, default=20"`
   941  	}
   942  
   943  	tok := &token{protected: 80}
   944  	err := Bind(tok)
   945  	assert.Error(t, err)
   946  	_ = os.Setenv(envInt, "1")
   947  	err = Bind(tok)
   948  	assert.NoError(t, err)
   949  	assert.Equal(t, float64(1), tok.empty)
   950  	assert.Equal(t, float64(1), tok.filled)
   951  	assert.Equal(t, float64(80), tok.protected)
   952  	assert.Equal(t, float64(20), tok.doesntExists)
   953  }
   954  
   955  func TestTypeUint(t *testing.T) {
   956  	cleanup()
   957  	_ = os.Setenv(envInt, "")
   958  	_ = os.Setenv(envInt2, "1")
   959  	type token struct {
   960  		empty        uint `env:"ENV_INT"`
   961  		filled       uint `env:"ENV_INT2, require=true"`
   962  		protected    uint `env:"ENV_INT, protected=true"`
   963  		doesntExists uint `env:"ENV_INT3, default=20"`
   964  	}
   965  
   966  	tok := &token{protected: 80}
   967  	err := Bind(tok)
   968  	assert.Error(t, err)
   969  	_ = os.Setenv(envInt, "1")
   970  	err = Bind(tok)
   971  	assert.NoError(t, err)
   972  	assert.Equal(t, uint(1), tok.empty)
   973  	assert.Equal(t, uint(1), tok.filled)
   974  	assert.Equal(t, uint(80), tok.protected)
   975  	assert.Equal(t, uint(20), tok.doesntExists)
   976  }
   977  
   978  func TestTypeUint8(t *testing.T) {
   979  	cleanup()
   980  	_ = os.Setenv(envInt, "")
   981  	_ = os.Setenv(envInt2, "1")
   982  	type token struct {
   983  		empty        uint8 `env:"ENV_INT"`
   984  		filled       uint8 `env:"ENV_INT2, require=true"`
   985  		protected    uint8 `env:"ENV_INT, protected=true"`
   986  		doesntExists uint8 `env:"ENV_INT3, default=20"`
   987  	}
   988  
   989  	tok := &token{protected: 80}
   990  	err := Bind(tok)
   991  	assert.Error(t, err)
   992  	_ = os.Setenv(envInt, "1")
   993  	err = Bind(tok)
   994  	assert.NoError(t, err)
   995  	assert.Equal(t, uint8(1), tok.empty)
   996  	assert.Equal(t, uint8(1), tok.filled)
   997  	assert.Equal(t, uint8(80), tok.protected)
   998  	assert.Equal(t, uint8(20), tok.doesntExists)
   999  }
  1000  
  1001  func TestTypeUint16(t *testing.T) {
  1002  	cleanup()
  1003  	_ = os.Setenv(envInt, "")
  1004  	_ = os.Setenv(envInt2, "1")
  1005  	type token struct {
  1006  		empty        uint16 `env:"ENV_INT"`
  1007  		filled       uint16 `env:"ENV_INT2, require=true"`
  1008  		protected    uint16 `env:"ENV_INT, protected=true"`
  1009  		doesntExists uint16 `env:"ENV_INT3, default=20"`
  1010  	}
  1011  
  1012  	tok := &token{protected: 80}
  1013  	err := Bind(tok)
  1014  	assert.Error(t, err)
  1015  	_ = os.Setenv(envInt, "1")
  1016  	err = Bind(tok)
  1017  	assert.NoError(t, err)
  1018  	assert.Equal(t, uint16(1), tok.empty)
  1019  	assert.Equal(t, uint16(1), tok.filled)
  1020  	assert.Equal(t, uint16(80), tok.protected)
  1021  	assert.Equal(t, uint16(20), tok.doesntExists)
  1022  }
  1023  
  1024  func TestTypeUint32(t *testing.T) {
  1025  	cleanup()
  1026  	_ = os.Setenv(envInt, "")
  1027  	_ = os.Setenv(envInt2, "1")
  1028  	type token struct {
  1029  		empty        uint32 `env:"ENV_INT"`
  1030  		filled       uint32 `env:"ENV_INT2, require=true"`
  1031  		protected    uint32 `env:"ENV_INT, protected=true"`
  1032  		doesntExists uint32 `env:"ENV_INT3, default=20"`
  1033  	}
  1034  
  1035  	tok := &token{protected: 80}
  1036  	err := Bind(tok)
  1037  	assert.Error(t, err)
  1038  	_ = os.Setenv(envInt, "1")
  1039  	err = Bind(tok)
  1040  	assert.NoError(t, err)
  1041  	assert.Equal(t, uint32(1), tok.empty)
  1042  	assert.Equal(t, uint32(1), tok.filled)
  1043  	assert.Equal(t, uint32(80), tok.protected)
  1044  	assert.Equal(t, uint32(20), tok.doesntExists)
  1045  }
  1046  
  1047  func TestTypeUint64(t *testing.T) {
  1048  	cleanup()
  1049  	_ = os.Setenv(envInt, "")
  1050  	_ = os.Setenv(envInt2, "1")
  1051  	type token struct {
  1052  		empty        uint64 `env:"ENV_INT"`
  1053  		filled       uint64 `env:"ENV_INT2, require=true"`
  1054  		protected    uint64 `env:"ENV_INT, protected=true"`
  1055  		doesntExists uint64 `env:"ENV_INT3, default=20"`
  1056  	}
  1057  
  1058  	tok := &token{protected: 80}
  1059  	err := Bind(tok)
  1060  	assert.Error(t, err)
  1061  	_ = os.Setenv(envInt, "1")
  1062  	err = Bind(tok)
  1063  	assert.NoError(t, err)
  1064  	assert.Equal(t, uint64(1), tok.empty)
  1065  	assert.Equal(t, uint64(1), tok.filled)
  1066  	assert.Equal(t, uint64(80), tok.protected)
  1067  	assert.Equal(t, uint64(20), tok.doesntExists)
  1068  }
  1069  
  1070  func TestTypeString(t *testing.T) {
  1071  	cleanup()
  1072  	_ = os.Setenv(envInt, "")
  1073  	_ = os.Setenv(envInt2, "1")
  1074  	type token struct {
  1075  		empty        string `env:"ENV_INT"`
  1076  		filled       string `env:"ENV_INT2, require=true"`
  1077  		protected    string `env:"ENV_INT, protected=true"`
  1078  		doesntExists string `env:"ENV_INT3, default=20"`
  1079  	}
  1080  
  1081  	tok := &token{protected: "80"}
  1082  	err := Bind(tok)
  1083  	assert.NoError(t, err)
  1084  	_ = os.Setenv(envInt, "1")
  1085  	err = Bind(tok)
  1086  	assert.NoError(t, err)
  1087  	assert.Equal(t, "1", tok.empty)
  1088  	assert.Equal(t, "1", tok.filled)
  1089  	assert.Equal(t, "80", tok.protected)
  1090  	assert.Equal(t, "20", tok.doesntExists)
  1091  }
  1092  
  1093  func TestTypeBool(t *testing.T) {
  1094  	cleanup()
  1095  	_ = os.Setenv(envInt, "")
  1096  	_ = os.Setenv(envInt2, "1")
  1097  	type token struct {
  1098  		empty        bool `env:"ENV_INT"`
  1099  		filled       bool `env:"ENV_INT2, require=true"`
  1100  		protected    bool `env:"ENV_INT, protected=true"`
  1101  		doesntExists bool `env:"ENV_INT3, default=1"`
  1102  	}
  1103  
  1104  	tok := &token{protected: true}
  1105  	err := Bind(tok)
  1106  	assert.Error(t, err)
  1107  	_ = os.Setenv(envInt, "true")
  1108  	err = Bind(tok)
  1109  	assert.NoError(t, err)
  1110  	assert.Equal(t, true, tok.empty)
  1111  	assert.Equal(t, true, tok.filled)
  1112  	assert.Equal(t, true, tok.protected)
  1113  	assert.Equal(t, true, tok.doesntExists)
  1114  }
  1115  
  1116  func TestTypeIntSlice(t *testing.T) {
  1117  	cleanup()
  1118  	_ = os.Setenv(envInt, "")
  1119  	_ = os.Setenv(envInt2, "1,1")
  1120  	type token struct {
  1121  		empty        []int `env:"ENV_INT"`
  1122  		filled       []int `env:"ENV_INT2, require=true"`
  1123  		protected    []int `env:"ENV_INT, protected=true"`
  1124  		doesntExists []int `env:"ENV_INT3, default=[20,20]"`
  1125  	}
  1126  
  1127  	tok := &token{protected: []int{80, 80}}
  1128  	err := Bind(tok)
  1129  	assert.NoError(t, err)
  1130  	assert.Equal(t, []int{}, tok.empty)
  1131  	assert.Equal(t, []int{1, 1}, tok.filled)
  1132  	assert.Equal(t, []int{80, 80}, tok.protected)
  1133  	assert.Equal(t, []int{20, 20}, tok.doesntExists)
  1134  }
  1135  
  1136  func TestTypeInt8Slice(t *testing.T) {
  1137  	cleanup()
  1138  	_ = os.Setenv(envInt, "")
  1139  	_ = os.Setenv(envInt2, "1,1")
  1140  	type token struct {
  1141  		empty        []int8 `env:"ENV_INT"`
  1142  		filled       []int8 `env:"ENV_INT2, require=true"`
  1143  		protected    []int8 `env:"ENV_INT, protected=true"`
  1144  		doesntExists []int8 `env:"ENV_INT3, default=[20,20]"`
  1145  	}
  1146  
  1147  	tok := &token{protected: []int8{80, 80}}
  1148  	err := Bind(tok)
  1149  	assert.NoError(t, err)
  1150  	assert.Equal(t, []int8{}, tok.empty)
  1151  	assert.Equal(t, []int8{1, 1}, tok.filled)
  1152  	assert.Equal(t, []int8{80, 80}, tok.protected)
  1153  	assert.Equal(t, []int8{20, 20}, tok.doesntExists)
  1154  }
  1155  
  1156  func TestTypeInt16Slice(t *testing.T) {
  1157  	cleanup()
  1158  	_ = os.Setenv(envInt, "")
  1159  	_ = os.Setenv(envInt2, "1,1")
  1160  	type token struct {
  1161  		empty        []int16 `env:"ENV_INT"`
  1162  		filled       []int16 `env:"ENV_INT2, require=true"`
  1163  		protected    []int16 `env:"ENV_INT, protected=true"`
  1164  		doesntExists []int16 `env:"ENV_INT3, default=[20,20]"`
  1165  	}
  1166  
  1167  	tok := &token{protected: []int16{80, 80}}
  1168  	err := Bind(tok)
  1169  	assert.NoError(t, err)
  1170  	assert.Equal(t, []int16{}, tok.empty)
  1171  	assert.Equal(t, []int16{1, 1}, tok.filled)
  1172  	assert.Equal(t, []int16{80, 80}, tok.protected)
  1173  	assert.Equal(t, []int16{20, 20}, tok.doesntExists)
  1174  }
  1175  
  1176  func TestTypeInt32Slice(t *testing.T) {
  1177  	cleanup()
  1178  	_ = os.Setenv(envInt, "")
  1179  	_ = os.Setenv(envInt2, "1,1")
  1180  	type token struct {
  1181  		empty        []int32 `env:"ENV_INT"`
  1182  		filled       []int32 `env:"ENV_INT2, require=true"`
  1183  		protected    []int32 `env:"ENV_INT, protected=true"`
  1184  		doesntExists []int32 `env:"ENV_INT3, default=[20,20]"`
  1185  	}
  1186  
  1187  	tok := &token{protected: []int32{80, 80}}
  1188  	err := Bind(tok)
  1189  	assert.NoError(t, err)
  1190  	assert.Equal(t, []int32{}, tok.empty)
  1191  	assert.Equal(t, []int32{1, 1}, tok.filled)
  1192  	assert.Equal(t, []int32{80, 80}, tok.protected)
  1193  	assert.Equal(t, []int32{20, 20}, tok.doesntExists)
  1194  }
  1195  
  1196  func TestTypeInt64Slice(t *testing.T) {
  1197  	cleanup()
  1198  	_ = os.Setenv(envInt, "")
  1199  	_ = os.Setenv(envInt2, "1,1")
  1200  	type token struct {
  1201  		empty        []int64 `env:"ENV_INT"`
  1202  		filled       []int64 `env:"ENV_INT2, require=true"`
  1203  		protected    []int64 `env:"ENV_INT, protected=true"`
  1204  		doesntExists []int64 `env:"ENV_INT3, default=[20,20]"`
  1205  	}
  1206  
  1207  	tok := &token{protected: []int64{80, 80}}
  1208  	err := Bind(tok)
  1209  	assert.NoError(t, err)
  1210  	assert.Equal(t, []int64{}, tok.empty)
  1211  	assert.Equal(t, []int64{1, 1}, tok.filled)
  1212  	assert.Equal(t, []int64{80, 80}, tok.protected)
  1213  	assert.Equal(t, []int64{20, 20}, tok.doesntExists)
  1214  }
  1215  
  1216  func TestTypeFloat32Slice(t *testing.T) {
  1217  	cleanup()
  1218  	_ = os.Setenv(envInt, "")
  1219  	_ = os.Setenv(envInt2, "1,1")
  1220  	type token struct {
  1221  		empty        []float32 `env:"ENV_INT"`
  1222  		filled       []float32 `env:"ENV_INT2, require=true"`
  1223  		protected    []float32 `env:"ENV_INT, protected=true"`
  1224  		doesntExists []float32 `env:"ENV_INT3, default=[20,20]"`
  1225  	}
  1226  
  1227  	tok := &token{protected: []float32{80, 80}}
  1228  	err := Bind(tok)
  1229  	assert.NoError(t, err)
  1230  	assert.Equal(t, []float32{}, tok.empty)
  1231  	assert.Equal(t, []float32{1, 1}, tok.filled)
  1232  	assert.Equal(t, []float32{80, 80}, tok.protected)
  1233  	assert.Equal(t, []float32{20, 20}, tok.doesntExists)
  1234  }
  1235  
  1236  func TestTypeFloat64Slice(t *testing.T) {
  1237  	cleanup()
  1238  	_ = os.Setenv(envInt, "")
  1239  	_ = os.Setenv(envInt2, "1,1")
  1240  	type token struct {
  1241  		empty        []float64 `env:"ENV_INT"`
  1242  		filled       []float64 `env:"ENV_INT2, require=true"`
  1243  		protected    []float64 `env:"ENV_INT, protected=true"`
  1244  		doesntExists []float64 `env:"ENV_INT3, default=[20,20]"`
  1245  	}
  1246  
  1247  	tok := &token{protected: []float64{80, 80}}
  1248  	err := Bind(tok)
  1249  	assert.NoError(t, err)
  1250  	assert.Equal(t, []float64{}, tok.empty)
  1251  	assert.Equal(t, []float64{1, 1}, tok.filled)
  1252  	assert.Equal(t, []float64{80, 80}, tok.protected)
  1253  	assert.Equal(t, []float64{20, 20}, tok.doesntExists)
  1254  }
  1255  
  1256  func TestTypeUIntSlice(t *testing.T) {
  1257  	cleanup()
  1258  	_ = os.Setenv(envInt, "")
  1259  	_ = os.Setenv(envInt2, "1,1")
  1260  	type token struct {
  1261  		empty        []uint `env:"ENV_INT"`
  1262  		filled       []uint `env:"ENV_INT2, require=true"`
  1263  		protected    []uint `env:"ENV_INT, protected=true"`
  1264  		doesntExists []uint `env:"ENV_INT3, default=[20,20]"`
  1265  	}
  1266  
  1267  	tok := &token{protected: []uint{80, 80}}
  1268  	err := Bind(tok)
  1269  	assert.NoError(t, err)
  1270  	assert.Equal(t, []uint{}, tok.empty)
  1271  	assert.Equal(t, []uint{1, 1}, tok.filled)
  1272  	assert.Equal(t, []uint{80, 80}, tok.protected)
  1273  	assert.Equal(t, []uint{20, 20}, tok.doesntExists)
  1274  }
  1275  
  1276  func TestTypeUInt16Slice(t *testing.T) {
  1277  	cleanup()
  1278  	_ = os.Setenv(envInt, "")
  1279  	_ = os.Setenv(envInt2, "1,1")
  1280  	type token struct {
  1281  		empty        []uint16 `env:"ENV_INT"`
  1282  		filled       []uint16 `env:"ENV_INT2, require=true"`
  1283  		protected    []uint16 `env:"ENV_INT, protected=true"`
  1284  		doesntExists []uint16 `env:"ENV_INT3, default=[20,20]"`
  1285  	}
  1286  
  1287  	tok := &token{protected: []uint16{80, 80}}
  1288  	err := Bind(tok)
  1289  	assert.NoError(t, err)
  1290  	assert.Equal(t, []uint16{}, tok.empty)
  1291  	assert.Equal(t, []uint16{1, 1}, tok.filled)
  1292  	assert.Equal(t, []uint16{80, 80}, tok.protected)
  1293  	assert.Equal(t, []uint16{20, 20}, tok.doesntExists)
  1294  }
  1295  
  1296  func TestTypeUInt32Slice(t *testing.T) {
  1297  	cleanup()
  1298  	_ = os.Setenv(envInt, "")
  1299  	_ = os.Setenv(envInt2, "1,1")
  1300  	type token struct {
  1301  		empty        []uint32 `env:"ENV_INT"`
  1302  		filled       []uint32 `env:"ENV_INT2, require=true"`
  1303  		protected    []uint32 `env:"ENV_INT, protected=true"`
  1304  		doesntExists []uint32 `env:"ENV_INT3, default=[20,20]"`
  1305  	}
  1306  
  1307  	tok := &token{protected: []uint32{80, 80}}
  1308  	err := Bind(tok)
  1309  	assert.NoError(t, err)
  1310  	assert.Equal(t, []uint32{}, tok.empty)
  1311  	assert.Equal(t, []uint32{1, 1}, tok.filled)
  1312  	assert.Equal(t, []uint32{80, 80}, tok.protected)
  1313  	assert.Equal(t, []uint32{20, 20}, tok.doesntExists)
  1314  }
  1315  
  1316  func TestTypeUInt64Slice(t *testing.T) {
  1317  	cleanup()
  1318  	_ = os.Setenv(envInt, "")
  1319  	_ = os.Setenv(envInt2, "1,1")
  1320  	type token struct {
  1321  		empty        []uint64 `env:"ENV_INT"`
  1322  		filled       []uint64 `env:"ENV_INT2, require=true"`
  1323  		protected    []uint64 `env:"ENV_INT, protected=true"`
  1324  		doesntExists []uint64 `env:"ENV_INT3, default=[20,20]"`
  1325  	}
  1326  
  1327  	tok := &token{protected: []uint64{80, 80}}
  1328  	err := Bind(tok)
  1329  	assert.NoError(t, err)
  1330  	assert.Equal(t, []uint64{}, tok.empty)
  1331  	assert.Equal(t, []uint64{1, 1}, tok.filled)
  1332  	assert.Equal(t, []uint64{80, 80}, tok.protected)
  1333  	assert.Equal(t, []uint64{20, 20}, tok.doesntExists)
  1334  }
  1335  
  1336  func TestTypeStringSlice(t *testing.T) {
  1337  	cleanup()
  1338  	_ = os.Setenv(envInt, "")
  1339  	_ = os.Setenv(envInt2, "1,1")
  1340  	type token struct {
  1341  		empty        []string `env:"ENV_INT"`
  1342  		filled       []string `env:"ENV_INT2, require=true"`
  1343  		protected    []string `env:"ENV_INT, protected=true"`
  1344  		doesntExists []string `env:"ENV_INT3, default=[20,20]"`
  1345  	}
  1346  
  1347  	tok := &token{protected: []string{"80", "80"}}
  1348  	err := Bind(tok)
  1349  	assert.NoError(t, err)
  1350  	assert.Equal(t, []string{}, tok.empty)
  1351  	assert.Equal(t, []string{"1", "1"}, tok.filled)
  1352  	assert.Equal(t, []string{"80", "80"}, tok.protected)
  1353  	assert.Equal(t, []string{"20", "20"}, tok.doesntExists)
  1354  }
  1355  
  1356  func TestTypeBoolSlice(t *testing.T) {
  1357  	cleanup()
  1358  	_ = os.Setenv(envInt, "")
  1359  	_ = os.Setenv(envInt2, "1,1")
  1360  	type token struct {
  1361  		empty        []bool `env:"ENV_INT"`
  1362  		filled       []bool `env:"ENV_INT2, require=true"`
  1363  		protected    []bool `env:"ENV_INT, protected=true"`
  1364  		doesntExists []bool `env:"ENV_INT3, default=[true,true]"`
  1365  	}
  1366  
  1367  	tok := &token{protected: []bool{true, true}}
  1368  	err := Bind(tok)
  1369  	assert.NoError(t, err)
  1370  	assert.Equal(t, []bool{}, tok.empty)
  1371  	assert.Equal(t, []bool{true, true}, tok.filled)
  1372  	assert.Equal(t, []bool{true, true}, tok.protected)
  1373  	assert.Equal(t, []bool{true, true}, tok.doesntExists)
  1374  }
  1375  
  1376  func TestPublicAPI(t *testing.T) {
  1377  	defer cleanup()
  1378  	_ = os.Setenv(envInt, "1")
  1379  	_ = os.Setenv(envString, "1")
  1380  	_ = os.Setenv(envBool, "1")
  1381  	_ = os.Setenv(envFloat64, "1")
  1382  	_ = os.Setenv(envIntSlice, "1")
  1383  	_ = os.Setenv(envStringSlice, "1")
  1384  	_ = os.Setenv(envBoolSlice, "1")
  1385  	_ = os.Setenv(envFloat64Slice, "1")
  1386  	const none = "none"
  1387  	var err error
  1388  	var fs []float64
  1389  	var bs []bool
  1390  	var ss []string
  1391  	var is []int
  1392  
  1393  	var f float64
  1394  	var b bool
  1395  	var i int
  1396  	var s string
  1397  
  1398  	fs, err = GetEnvAsArrayOfFloat64OrFallback(envFloat64Slice, []float64{20, 20})
  1399  	assert.NoError(t, err)
  1400  	assert.Equal(t, []float64{1}, fs)
  1401  	fs, err = GetEnvAsArrayOfFloat64OrFallback(none, []float64{20, 20})
  1402  	assert.NoError(t, err)
  1403  	assert.Equal(t, []float64{20, 20}, fs)
  1404  
  1405  	ss = GetEnvAsArrayOfStringsOrFallback(envStringSlice, []string{"20", "20"})
  1406  	assert.Equal(t, []string{"1"}, ss)
  1407  	ss = GetEnvAsArrayOfStringsOrFallback(none, []string{"20", "20"})
  1408  	assert.Equal(t, []string{"20", "20"}, ss)
  1409  
  1410  	bs, err = GetEnvAsArrayOfBoolOrFallback(envStringSlice, []bool{true, true})
  1411  	assert.NoError(t, err)
  1412  	assert.Equal(t, []bool{true}, bs)
  1413  	bs, err = GetEnvAsArrayOfBoolOrFallback(none, []bool{true, true})
  1414  	assert.NoError(t, err)
  1415  	assert.Equal(t, []bool{true, true}, bs)
  1416  
  1417  	is, err = GetEnvAsArrayOfIntsOrFallback(envIntSlice, []int{1, 1})
  1418  	assert.NoError(t, err)
  1419  	assert.Equal(t, []int{1}, is)
  1420  	is, err = GetEnvAsArrayOfIntsOrFallback(none, []int{1, 1})
  1421  	assert.NoError(t, err)
  1422  	assert.Equal(t, []int{1, 1}, is)
  1423  
  1424  	i, err = GetEnvAsIntOrFallback(envInt, 1)
  1425  	assert.NoError(t, err)
  1426  	assert.Equal(t, 1, i)
  1427  	i, err = GetEnvAsIntOrFallback(none, 1)
  1428  	assert.NoError(t, err)
  1429  	assert.Equal(t, 1, i)
  1430  
  1431  	b, err = GetEnvAsBoolOrFallback(envBool, true)
  1432  	assert.NoError(t, err)
  1433  	assert.Equal(t, true, b)
  1434  	b, err = GetEnvAsBoolOrFallback(none, true)
  1435  	assert.NoError(t, err)
  1436  	assert.Equal(t, true, b)
  1437  
  1438  	f, err = GetEnvAsFloat64OrFallback(envFloat64, 1)
  1439  	assert.NoError(t, err)
  1440  	assert.Equal(t, 1., f)
  1441  	f, err = GetEnvAsFloat64OrFallback(none, 1)
  1442  	assert.NoError(t, err)
  1443  	assert.Equal(t, 1., f)
  1444  
  1445  	s = GetEnvAsStringOrFallback(envString, "1")
  1446  	assert.Equal(t, "1", s)
  1447  	s = GetEnvAsStringOrFallback(none, "1")
  1448  	assert.Equal(t, "1", s)
  1449  }
  1450  
  1451  func TestEmptySlice(t *testing.T) {
  1452  	defer cleanup()
  1453  	type token struct {
  1454  		strSlice      []string  `env:"NONE"`
  1455  		strSlice2     []string  `env:"NONE, default=[]"`
  1456  		intSlice      []int     `env:"NONE"`
  1457  		intSlice2     []int     `env:"NONE, default=[]"`
  1458  		int8Slice     []int8    `env:"NONE"`
  1459  		int8Slice2    []int8    `env:"NONE, default=[]"`
  1460  		int16Slice    []int16   `env:"NONE"`
  1461  		int16Slice2   []int16   `env:"NONE, default=[]"`
  1462  		int32Slice    []int32   `env:"NONE"`
  1463  		int32Slice2   []int32   `env:"NONE, default=[]"`
  1464  		int64Slice    []int64   `env:"NONE"`
  1465  		int64Slice2   []int64   `env:"NONE, default=[]"`
  1466  		uintSlice     []uint    `env:"NONE"`
  1467  		uintSlice2    []uint    `env:"NONE, default=[]"`
  1468  		uint8Slice    []uint8   `env:"NONE"`
  1469  		uint8Slice2   []uint8   `env:"NONE, default=[]"`
  1470  		uint16Slice   []uint16  `env:"NONE"`
  1471  		uint16Slice2  []uint16  `env:"NONE, default=[]"`
  1472  		uint32Slice   []uint32  `env:"NONE"`
  1473  		uint32Slice2  []uint32  `env:"NONE, default=[]"`
  1474  		uint64Slice   []uint64  `env:"NONE"`
  1475  		uint64Slice2  []uint64  `env:"NONE, default=[]"`
  1476  		float32Slice  []float32 `env:"NONE"`
  1477  		float32Slice2 []float32 `env:"NONE, default=[]"`
  1478  		float64Slice  []float64 `env:"NONE"`
  1479  		float64Slice2 []float64 `env:"NONE, default=[]"`
  1480  		boolSlice     []bool    `env:"NONE"`
  1481  		boolSlice2    []bool    `env:"NONE, default=[]"`
  1482  	}
  1483  	tok := &token{}
  1484  	err := Bind(tok)
  1485  	assert.NoError(t, err)
  1486  
  1487  	assert.Nil(t, tok.strSlice)
  1488  	assert.Equal(t, []string{}, tok.strSlice2)
  1489  
  1490  	assert.Nil(t, tok.intSlice)
  1491  	assert.Equal(t, []int{}, tok.intSlice2)
  1492  
  1493  	assert.Nil(t, tok.int8Slice)
  1494  	assert.Equal(t, []int8{}, tok.int8Slice2)
  1495  
  1496  	assert.Nil(t, tok.int16Slice)
  1497  	assert.Equal(t, []int16{}, tok.int16Slice2)
  1498  
  1499  	assert.Nil(t, tok.int32Slice)
  1500  	assert.Equal(t, []int32{}, tok.int32Slice2)
  1501  
  1502  	assert.Nil(t, tok.int64Slice)
  1503  	assert.Equal(t, []int64{}, tok.int64Slice2)
  1504  
  1505  	assert.Nil(t, tok.uintSlice)
  1506  	assert.Equal(t, []uint{}, tok.uintSlice2)
  1507  
  1508  	assert.Nil(t, tok.uint8Slice)
  1509  	assert.Equal(t, []uint8{}, tok.uint8Slice2)
  1510  
  1511  	assert.Nil(t, tok.uint16Slice)
  1512  	assert.Equal(t, []uint16{}, tok.uint16Slice2)
  1513  
  1514  	assert.Nil(t, tok.uint32Slice)
  1515  	assert.Equal(t, []uint32{}, tok.uint32Slice2)
  1516  
  1517  	assert.Nil(t, tok.uint64Slice)
  1518  	assert.Equal(t, []uint64{}, tok.uint64Slice2)
  1519  
  1520  	assert.Nil(t, tok.float32Slice)
  1521  	assert.Equal(t, []float32{}, tok.float32Slice2)
  1522  
  1523  	assert.Nil(t, tok.float64Slice)
  1524  	assert.Equal(t, []float64{}, tok.float64Slice2)
  1525  
  1526  	assert.Nil(t, tok.boolSlice)
  1527  	assert.Equal(t, []bool{}, tok.boolSlice2)
  1528  }
  1529  
  1530  func setEnv(m map[string]string) {
  1531  	for k, v := range m {
  1532  		_ = os.Setenv(k, v)
  1533  	}
  1534  }
  1535  
  1536  const (
  1537  	tokenID          = "TOKEN_ID"
  1538  	tokenValue       = "TOKEN_VALUE"
  1539  	tokenRatio       = "TOKEN_RATIO"
  1540  	tokenReadOnly    = "TOKEN_READONLY"
  1541  	tokenHours       = "TOKEN_HOURS"
  1542  	tokenURLs        = "TOKEN_URLS"
  1543  	tokenBools       = "TOKEN_SWITCH"
  1544  	tokenCoordinates = "TOKEN_COORDINATES"
  1545  
  1546  	privateTokenValue = "PRIVATE_TOKEN_VALUE"
  1547  	// #nosec G101;
  1548  	exportedTokenValue        = "EXPORTED_TOKEN_VALUE"
  1549  	privateExportedTokenValue = "PRIVATE_EXPORTED_TOKEN_VALUE"
  1550  
  1551  	primaryEndpointURL  = "PRIMARY_ENDPOINT_URL"
  1552  	failoverEndpointURL = "FAILOVER_ENDPOINT_URL"
  1553  	name                = "NAME"
  1554  	defaultPort         = "PORT"
  1555  	accessKeyID         = "ACCESS_KEY_ID"
  1556  	secretAccessKey     = "SECRET_ACCESS_KEY"
  1557  
  1558  	envInt            = "ENV_INT"
  1559  	envInt2           = "ENV_INT2"
  1560  	envString         = "ENV_STRING"
  1561  	envStringSlice    = "ENV_STRING_SLICE"
  1562  	envBool           = "ENV_BOOL"
  1563  	envBoolSlice      = "ENV_BOOL_SLICE"
  1564  	envFloat64        = "ENV_FLOAT64"
  1565  	envFloat64Slice   = "ENV_FLOAT64_SLICE"
  1566  	envStringPrivate  = "ENV_STRING_PRIVATE"
  1567  	envStringExported = "ENV_STRING_EXPORTED"
  1568  	envIntSlice       = "ENV_INT_SLICE"
  1569  )
  1570  
  1571  func cleanup() {
  1572  	_ = os.Unsetenv(tokenID)
  1573  	_ = os.Unsetenv(tokenValue)
  1574  	_ = os.Unsetenv(tokenRatio)
  1575  	_ = os.Unsetenv(tokenReadOnly)
  1576  	_ = os.Unsetenv(tokenHours)
  1577  	_ = os.Unsetenv(tokenURLs)
  1578  	_ = os.Unsetenv(tokenBools)
  1579  	_ = os.Unsetenv(tokenCoordinates)
  1580  
  1581  	_ = os.Unsetenv(privateTokenValue)
  1582  	_ = os.Unsetenv(privateExportedTokenValue)
  1583  	_ = os.Unsetenv(exportedTokenValue)
  1584  
  1585  	_ = os.Unsetenv(primaryEndpointURL)
  1586  	_ = os.Unsetenv(failoverEndpointURL)
  1587  	_ = os.Unsetenv(name)
  1588  	_ = os.Unsetenv(defaultPort)
  1589  	_ = os.Unsetenv(accessKeyID)
  1590  	_ = os.Unsetenv(secretAccessKey)
  1591  
  1592  	_ = os.Unsetenv(envInt)
  1593  	_ = os.Unsetenv(envString)
  1594  	_ = os.Unsetenv(envBool)
  1595  	_ = os.Unsetenv(envBoolSlice)
  1596  	_ = os.Unsetenv(envStringPrivate)
  1597  	_ = os.Unsetenv(envStringExported)
  1598  	_ = os.Unsetenv(envIntSlice)
  1599  	_ = os.Unsetenv(envFloat64)
  1600  	_ = os.Unsetenv(envFloat64Slice)
  1601  }