-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: environment loading, manipulation, value parsing and state mana…
…gement
- Loading branch information
Showing
13 changed files
with
1,640 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
package env | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
) | ||
|
||
// Clear removes all environment variables. | ||
func Clear() { | ||
os.Clearenv() | ||
} | ||
|
||
// Get returns the value of the environment variable with the given name. If the | ||
// variable is not set an empty string is returned. | ||
// | ||
// To differentiate between a variable that is not set and a variable that is set to | ||
// an empty string, use the `Lookup` function. | ||
// | ||
// # parameters | ||
// | ||
// name string // the name of the environment variable | ||
// | ||
// # returns | ||
// | ||
// string // the value of the environment variable | ||
func Get(name string) string { | ||
return os.Getenv(name) | ||
} | ||
|
||
// GetVars returns a map of environment variables. If no variable names are provided | ||
// all environment variables are returned. If variable names are provided, only | ||
// those variables are returned (if set). | ||
// | ||
// # parameters | ||
// | ||
// names ...string // (optional) names of environment variables to return; | ||
// // if no names are provided the returned map contains all | ||
// // environment variables. | ||
// | ||
// If a name is provided that is not set in the environment it is not included in | ||
// the returned map. | ||
// | ||
// # returns | ||
// | ||
// Vars // a map of environment variables | ||
// | ||
// The returned map is a `map[string]string` where the key is the name of the | ||
// environment variable and the value is the value of the environment variable. | ||
// | ||
// If no environment variables are set or all specified variables names are not set, | ||
// the returned map is empty. | ||
func GetVars(names ...string) Vars { | ||
var result Vars | ||
|
||
switch len(names) { | ||
case 0: // all environment variables | ||
env := os.Environ() | ||
result = make(Vars, len(env)) | ||
for _, s := range env { | ||
k, v, _ := strings.Cut(s, "=") | ||
result[k] = v | ||
} | ||
default: // only the named variables (if set) | ||
result = make(Vars, len(names)) | ||
for _, k := range names { | ||
if v, ok := os.LookupEnv(k); ok { | ||
result[k] = v | ||
} | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
// Lookup returns the value of the environment variable with the given name and a | ||
// boolean indicating whether the variable is set. If the variable is not set the | ||
// returned value is an empty string and the boolean is `false`. | ||
// | ||
// If you do not need to differentiate between a variable that is not set and a | ||
// variable that is set to an empty string, use the `Get` function. | ||
// | ||
// # parameters | ||
// | ||
// name string // the name of the environment variable | ||
// | ||
// # returns | ||
// | ||
// string // the value of the environment variable | ||
// | ||
// bool // true if the variable is set, false otherwise | ||
func Lookup(name string) (string, bool) { | ||
return os.LookupEnv(name) | ||
} | ||
|
||
// Set sets the value of the environment variable with the given name. If the variable | ||
// does not exist it is created. | ||
// | ||
// # parameters | ||
// | ||
// name string // the name of the environment variable | ||
// | ||
// value string // the value to set | ||
// | ||
// # returns | ||
// | ||
// error // any error that occurs while setting the environment variable | ||
func Set(name, value string) error { | ||
return os.Setenv(name, value) | ||
} | ||
|
||
// Unset removes the environment variables with the given names. If a variable does | ||
// not exist (already not set) it is ignored. | ||
// | ||
// # parameters | ||
// | ||
// names ...string // the names of the environment variables to remove | ||
// | ||
// # returns | ||
// | ||
// error // any error that occurs while unsetting the environment variables | ||
// | ||
// On Unix systems (including Linux and macOS) the error is always `nil`, but | ||
// on Windows systems the error may be non-nil. | ||
func Unset(name ...string) error { | ||
for _, k := range name { | ||
if err := osUnsetenv(k); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package env | ||
|
||
import ( | ||
"errors" | ||
"os" | ||
"testing" | ||
|
||
"github.com/blugnu/test" | ||
) | ||
|
||
func TestClear(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Setenv("VAR", "value") | ||
|
||
// ACT | ||
Clear() | ||
|
||
// ASSERT | ||
_, isSet := os.LookupEnv("VAR") | ||
test.IsFalse(t, isSet) | ||
} | ||
|
||
func TestGet(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
os.Setenv("VAR", "value") | ||
|
||
// ACT | ||
result := Get("VAR") | ||
|
||
// ASSERT | ||
test.That(t, result, "variable present").Equals("value") | ||
|
||
// ACT | ||
result = Get("NOTSET") | ||
|
||
// ASSERT | ||
test.That(t, result, "variable not present").Equals("") | ||
} | ||
|
||
func TestGetVars(t *testing.T) { | ||
// ARRANGE | ||
testcases := []struct { | ||
scenario string | ||
exec func(t *testing.T) | ||
}{ | ||
{scenario: "all variables", | ||
exec: func(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
os.Setenv("VAR1", "value1") | ||
os.Setenv("VAR2", "value2") | ||
|
||
// ACT | ||
result := GetVars() | ||
|
||
// ASSERT | ||
test.Map(t, result).Equals(Vars{"VAR1": "value1", "VAR2": "value2"}) | ||
}, | ||
}, | ||
{scenario: "specified variables (including ones not set)", | ||
exec: func(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
os.Setenv("VAR1", "value1") | ||
os.Setenv("VAR2", "value2") | ||
|
||
// ACT | ||
result := GetVars("VAR1", "VAR3") | ||
|
||
// ASSERT | ||
test.Map(t, result).Equals(Vars{"VAR1": "value1"}) | ||
}, | ||
}, | ||
} | ||
for _, tc := range testcases { | ||
t.Run(tc.scenario, func(t *testing.T) { | ||
tc.exec(t) | ||
}) | ||
} | ||
} | ||
|
||
func TestLookup(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
os.Setenv("VAR", "value") | ||
|
||
// ACT | ||
result, ok := Lookup("VAR") | ||
|
||
// ASSERT | ||
test.That(t, result, "variable present").Equals("value") | ||
test.IsTrue(t, ok, "variable present") | ||
|
||
// ACT | ||
result, ok = Lookup("NOTSET") | ||
|
||
// ASSERT | ||
test.That(t, result, "variable not present").Equals("") | ||
test.IsFalse(t, ok, "variable not present") | ||
} | ||
|
||
func TestSet(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
|
||
// ACT | ||
err := Set("VAR1", "value1") | ||
|
||
// ASSERT | ||
test.That(t, err).IsNil() | ||
test.That(t, os.Getenv("VAR1")).Equals("value1") | ||
} | ||
|
||
func TestUnset(t *testing.T) { | ||
// ARRANGE | ||
testEnv := map[string]string{ | ||
"VAR1": "value1", | ||
"VAR2": "value2", | ||
} | ||
testcases := []struct { | ||
scenario string | ||
exec func(t *testing.T) | ||
}{ | ||
{scenario: "no names specified", | ||
exec: func(t *testing.T) { | ||
// ACT | ||
err := Unset() | ||
|
||
// ASSERT | ||
test.That(t, err).IsNil() | ||
test.That(t, os.Getenv("VAR1")).Equals("value1") | ||
test.That(t, os.Getenv("VAR2")).Equals("value2") | ||
}, | ||
}, | ||
{scenario: "name specified", | ||
exec: func(t *testing.T) { | ||
// ACT | ||
err := Unset("VAR1") | ||
|
||
// ASSERT | ||
test.That(t, err).IsNil() | ||
_, isSet := os.LookupEnv("VAR1") | ||
test.IsFalse(t, isSet) | ||
test.That(t, os.Getenv("VAR2")).Equals("value2") | ||
}, | ||
}, | ||
{ | ||
scenario: "error when unsetting", | ||
exec: func(t *testing.T) { | ||
// ARRANGE | ||
unseterr := errors.New("unset error") | ||
defer test.Using(&osUnsetenv, func(string) error { return unseterr })() | ||
|
||
// ACT | ||
err := Unset("VAR1", "VAR2") | ||
|
||
// ASSERT | ||
test.Error(t, err).Is(unseterr) | ||
test.That(t, os.Getenv("VAR1")).Equals("value1") | ||
test.That(t, os.Getenv("VAR2")).Equals("value2") | ||
}, | ||
}, | ||
} | ||
for _, tc := range testcases { | ||
t.Run(tc.scenario, func(t *testing.T) { | ||
// ARRANGE | ||
defer State().Reset() | ||
os.Clearenv() | ||
for k, v := range testEnv { | ||
os.Setenv(k, v) | ||
} | ||
|
||
// ACT & ASSERT | ||
tc.exec(t) | ||
}) | ||
} | ||
} |
Oops, something went wrong.