blob: 7a71acd0d7f4100a23c36bdee6a8a5e4de9f703b [file] [log] [blame]
/*Package env provides functions to test code that read environment variables
or the current working directory.
*/
package env // import "gotest.tools/v3/env"
import (
"os"
"strings"
"gotest.tools/v3/assert"
"gotest.tools/v3/internal/cleanup"
)
type helperT interface {
Helper()
}
// Patch changes the value of an environment variable, and returns a
// function which will reset the the value of that variable back to the
// previous state.
//
// When used with Go 1.14+ the unpatch function will be called automatically
// when the test ends, unless the TEST_NOCLEANUP env var is set to true.
func Patch(t assert.TestingT, key, value string) func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
oldValue, envVarExists := os.LookupEnv(key)
assert.NilError(t, os.Setenv(key, value))
clean := func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
if !envVarExists {
assert.NilError(t, os.Unsetenv(key))
return
}
assert.NilError(t, os.Setenv(key, oldValue))
}
cleanup.Cleanup(t, clean)
return clean
}
// PatchAll sets the environment to env, and returns a function which will
// reset the environment back to the previous state.
//
// When used with Go 1.14+ the unpatch function will be called automatically
// when the test ends, unless the TEST_NOCLEANUP env var is set to true.
func PatchAll(t assert.TestingT, env map[string]string) func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
oldEnv := os.Environ()
os.Clearenv()
for key, value := range env {
assert.NilError(t, os.Setenv(key, value), "setenv %s=%s", key, value)
}
clean := func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
os.Clearenv()
for key, oldVal := range ToMap(oldEnv) {
assert.NilError(t, os.Setenv(key, oldVal), "setenv %s=%s", key, oldVal)
}
}
cleanup.Cleanup(t, clean)
return clean
}
// ToMap takes a list of strings in the format returned by os.Environ() and
// returns a mapping of keys to values.
func ToMap(env []string) map[string]string {
result := map[string]string{}
for _, raw := range env {
key, value := getParts(raw)
result[key] = value
}
return result
}
func getParts(raw string) (string, string) {
if raw == "" {
return "", ""
}
// Environment variables on windows can begin with =
// http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
parts := strings.SplitN(raw[1:], "=", 2)
key := raw[:1] + parts[0]
if len(parts) == 1 {
return key, ""
}
return key, parts[1]
}
// ChangeWorkingDir to the directory, and return a function which restores the
// previous working directory.
//
// When used with Go 1.14+ the previous working directory will be restored
// automatically when the test ends, unless the TEST_NOCLEANUP env var is set to
// true.
func ChangeWorkingDir(t assert.TestingT, dir string) func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
cwd, err := os.Getwd()
assert.NilError(t, err)
assert.NilError(t, os.Chdir(dir))
clean := func() {
if ht, ok := t.(helperT); ok {
ht.Helper()
}
assert.NilError(t, os.Chdir(cwd))
}
cleanup.Cleanup(t, clean)
return clean
}