func TestParsesEnv(t *testing.T) { os.Setenv("somevar", "somevalue") os.Setenv("othervar", "true") os.Setenv("PORT", "8080") os.Setenv("STRINGS", "string1,string2,string3") os.Setenv("SEPSTRINGS", "string1:string2:string3") os.Setenv("NUMBERS", "1,2,3,4") os.Setenv("BOOLS", "t,TRUE,0,1") defer os.Setenv("somevar", "") defer os.Setenv("othervar", "") defer os.Setenv("PORT", "") defer os.Setenv("STRINGS", "") defer os.Setenv("SEPSTRINGS", "") defer os.Setenv("NUMBERS", "") defer os.Setenv("BOOLS", "") cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "somevalue", cfg.Some) assert.Equal(t, true, cfg.Other) assert.Equal(t, 8080, cfg.Port) assert.Equal(t, []string{"string1", "string2", "string3"}, cfg.Strings) assert.Equal(t, []string{"string1", "string2", "string3"}, cfg.SepStrings) assert.Equal(t, []int{1, 2, 3, 4}, cfg.Numbers) assert.Equal(t, []bool{true, true, false, true}, cfg.Bools) }
func TestEmptyVars(t *testing.T) { cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "", cfg.Some) assert.Equal(t, false, cfg.Other) assert.Equal(t, 0, cfg.Port) }
func TestInvalidBool(t *testing.T) { os.Setenv("othervar", "should-be-a-bool") defer os.Setenv("othervar", "") cfg := Config{} assert.Error(t, env.Parse(&cfg)) }
func TestInvalidDuration(t *testing.T) { os.Setenv("DURATION", "should-be-a-valid-duration") defer os.Setenv("DURATION", "") cfg := Config{} assert.Error(t, env.Parse(&cfg)) }
func TestInvalidInt(t *testing.T) { os.Setenv("PORT", "should-be-an-int") defer os.Setenv("PORT", "") cfg := Config{} assert.Error(t, env.Parse(&cfg)) }
func TestParseStructWithInvalidFieldKind(t *testing.T) { type config struct { WontWork int64 `env:"BLAH"` } os.Setenv("BLAH", "10") cfg := config{} assert.Error(t, env.Parse(&cfg)) }
func TestErrorRequiredNotSet(t *testing.T) { type config struct { IsRequired string `env:"IS_REQUIRED,required"` } cfg := &config{} assert.Error(t, env.Parse(cfg)) }
func main() { cfg := config{} err := env.Parse(&cfg) if err != nil { fmt.Printf("%+v\n", err) } fmt.Printf("%+v\n", cfg) }
func TestErrorOptionNotRecognized(t *testing.T) { type config struct { Var string `env:"VAR,not_supported!"` } cfg := &config{} assert.Error(t, env.Parse(cfg)) }
func main() { var config config env.Parse(&config) log.Println(config) db := datastores.NewDBConnectionPool(config.DatabaseURL) defer db.Close() exec := server(config, db) exec.Run(":" + config.Port) }
func TestInvalidBoolsSlice(t *testing.T) { type config struct { BadBools []bool `env:"BADBOOLS"` } os.Setenv("BADBOOLS", "t,f,TRUE,faaaalse") cfg := &config{} assert.Error(t, env.Parse(cfg)) }
func TestUnsupportedSliceType(t *testing.T) { type config struct { WontWork []map[int]int `env:"WONTWORK"` } os.Setenv("WONTWORK", "1,2,3") defer os.Setenv("WONTWORK", "") cfg := &config{} assert.Error(t, env.Parse(cfg)) }
func TestEmptyVars(t *testing.T) { cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "", cfg.Some) assert.Equal(t, false, cfg.Other) assert.Equal(t, 0, cfg.Port) assert.Equal(t, 0, len(cfg.Strings)) assert.Equal(t, 0, len(cfg.SepStrings)) assert.Equal(t, 0, len(cfg.Numbers)) assert.Equal(t, 0, len(cfg.Bools)) }
func TestBadSeparator(t *testing.T) { type config struct { WontWork []int `env:"WONTWORK" envSeparator:":"` } cfg := &config{} os.Setenv("WONTWORK", "1,2,3,4") defer os.Setenv("WONTWORK", "") assert.Error(t, env.Parse(cfg)) }
func TestNoErrorRequiredSet(t *testing.T) { type config struct { IsRequired string `env:"IS_REQUIRED,required"` } cfg := &config{} os.Setenv("IS_REQUIRED", "val") defer os.Setenv("IS_REQUIRED", "") assert.NoError(t, env.Parse(cfg)) assert.Equal(t, "val", cfg.IsRequired) }
func TestEmptyOption(t *testing.T) { type config struct { Var string `env:"VAR,"` } cfg := &config{} os.Setenv("VAR", "val") defer os.Setenv("VAR", "") assert.NoError(t, env.Parse(cfg)) assert.Equal(t, "val", cfg.Var) }
func ExampleParse() { type config struct { Home string `env:"HOME"` Port int `env:"PORT" envDefault:"3000"` IsProduction bool `env:"PRODUCTION"` } os.Setenv("HOME", "/tmp/fakehome") cfg := config{} env.Parse(&cfg) fmt.Println(cfg) // Output: {/tmp/fakehome 3000 false} }
func loadArgs() Args { args := Args{ Listen: ":8080", KVBackend: "file", MSBackend: "file", StoragePath: "/var/lib/guble", } env.Parse(&args) arg.MustParse(&args) return args }
func ExampleParseRequiredField() { type config struct { Home string `env:"HOME"` Port int `env:"PORT" envDefault:"3000"` IsProduction bool `env:"PRODUCTION"` SecretKey string `env:"SECRET_KEY,required"` } os.Setenv("HOME", "/tmp/fakehome") cfg := config{} err := env.Parse(&cfg) fmt.Println(err) // Output: Required environment variable SECRET_KEY is not set }
func ExampleParseMultipleOptions() { type config struct { Home string `env:"HOME"` Port int `env:"PORT" envDefault:"3000"` IsProduction bool `env:"PRODUCTION"` SecretKey string `env:"SECRET_KEY,required,option1"` } os.Setenv("HOME", "/tmp/fakehome") cfg := config{} err := env.Parse(&cfg) fmt.Println(err) // Output: Env tag option option1 not supported. }
func TestParsesEnv(t *testing.T) { os.Setenv("somevar", "somevalue") os.Setenv("othervar", "true") os.Setenv("PORT", "8080") defer os.Setenv("somevar", "") defer os.Setenv("othervar", "") defer os.Setenv("PORT", "") cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "somevalue", cfg.Some) assert.Equal(t, true, cfg.Other) assert.Equal(t, 8080, cfg.Port) }
func TestParsesEnv(t *testing.T) { os.Setenv("somevar", "somevalue") os.Setenv("othervar", "true") os.Setenv("PORT", "8080") os.Setenv("STRINGS", "string1,string2,string3") os.Setenv("SEPSTRINGS", "string1:string2:string3") os.Setenv("NUMBERS", "1,2,3,4") os.Setenv("BOOLS", "t,TRUE,0,1") os.Setenv("DURATION", "1s") os.Setenv("FLOAT32", "3.40282346638528859811704183484516925440e+38") os.Setenv("FLOAT64", "1.797693134862315708145274237317043567981e+308") os.Setenv("FLOAT32S", "1.0,2.0,3.0") os.Setenv("FLOAT64S", "1.0,2.0,3.0") defer os.Setenv("somevar", "") defer os.Setenv("othervar", "") defer os.Setenv("PORT", "") defer os.Setenv("STRINGS", "") defer os.Setenv("SEPSTRINGS", "") defer os.Setenv("NUMBERS", "") defer os.Setenv("BOOLS", "") defer os.Setenv("DURATION", "") defer os.Setenv("FLOAT32", "") defer os.Setenv("FLOAT64", "") defer os.Setenv("FLOAT32S", "") defer os.Setenv("FLOAT64S", "") cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "somevalue", cfg.Some) assert.Equal(t, true, cfg.Other) assert.Equal(t, 8080, cfg.Port) assert.Equal(t, []string{"string1", "string2", "string3"}, cfg.Strings) assert.Equal(t, []string{"string1", "string2", "string3"}, cfg.SepStrings) assert.Equal(t, []int{1, 2, 3, 4}, cfg.Numbers) assert.Equal(t, []bool{true, true, false, true}, cfg.Bools) d, _ := time.ParseDuration("1s") assert.Equal(t, d, cfg.Duration) f32 := float32(3.40282346638528859811704183484516925440e+38) assert.Equal(t, f32, cfg.Float32) f64 := float64(1.797693134862315708145274237317043567981e+308) assert.Equal(t, f64, cfg.Float64) assert.Equal(t, []float32{float32(1.0), float32(2.0), float32(3.0)}, cfg.Float32s) assert.Equal(t, []float64{float64(1.0), float64(2.0), float64(3.0)}, cfg.Float64s) }
func parseConfig() (*config, error) { e := &envData{} env.Parse(e) // Parse the Length duration, err := time.ParseDuration(e.Duration) if err != nil { return nil, err } cfg := &config{ duration: duration, awsRegion: e.AWSRegion, s3Path: e.S3Path, s3Bucket: e.S3Bucket, outputFile: e.OutputFile, logFile: e.LogFile, } return cfg, nil }
func TestPassReference(t *testing.T) { cfg := Config{} assert.Error(t, env.Parse(cfg)) }
func TestPassAnInvalidPtr(t *testing.T) { var thisShouldBreak int assert.Error(t, env.Parse(&thisShouldBreak)) }
func TestParseStructWithoutEnvTag(t *testing.T) { cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Empty(t, cfg.NotAnEnv) }
// Load from the environment func Load() Config { var config Config env.Parse(&config) return config }
func main() { cfg := config{} env.Parse(&cfg) fmt.Println(cfg) }
func TestParsesDefaultConfig(t *testing.T) { cfg := Config{} assert.NoError(t, env.Parse(&cfg)) assert.Equal(t, "postgres://localhost:5432/db", cfg.DatabaseURL) }
// Init the IT framework: loads config, creates the database and startup the // server. func (i *IT) Init(server ServerHandlerFn, connectToDatabase db.PoolFn) func(http.ResponseWriter, *http.Request) { var cfg base.Config env.Parse(&cfg) i.db = db.New(connectToDatabase, &cfg) return server(i.db.Init()) }