env.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. Package env provides functions to test code that read environment variables
  3. or the current working directory.
  4. */
  5. package env // import "gotest.tools/v3/env"
  6. import (
  7. "os"
  8. "strings"
  9. "gotest.tools/v3/assert"
  10. "gotest.tools/v3/internal/cleanup"
  11. )
  12. type helperT interface {
  13. Helper()
  14. }
  15. // Patch changes the value of an environment variable, and returns a
  16. // function which will reset the the value of that variable back to the
  17. // previous state.
  18. //
  19. // When used with Go 1.14+ the unpatch function will be called automatically
  20. // when the test ends, unless the TEST_NOCLEANUP env var is set to true.
  21. //
  22. // Deprecated: use t.SetEnv
  23. func Patch(t assert.TestingT, key, value string) func() {
  24. if ht, ok := t.(helperT); ok {
  25. ht.Helper()
  26. }
  27. oldValue, envVarExists := os.LookupEnv(key)
  28. assert.NilError(t, os.Setenv(key, value))
  29. clean := func() {
  30. if ht, ok := t.(helperT); ok {
  31. ht.Helper()
  32. }
  33. if !envVarExists {
  34. assert.NilError(t, os.Unsetenv(key))
  35. return
  36. }
  37. assert.NilError(t, os.Setenv(key, oldValue))
  38. }
  39. cleanup.Cleanup(t, clean)
  40. return clean
  41. }
  42. // PatchAll sets the environment to env, and returns a function which will
  43. // reset the environment back to the previous state.
  44. //
  45. // When used with Go 1.14+ the unpatch function will be called automatically
  46. // when the test ends, unless the TEST_NOCLEANUP env var is set to true.
  47. func PatchAll(t assert.TestingT, env map[string]string) func() {
  48. if ht, ok := t.(helperT); ok {
  49. ht.Helper()
  50. }
  51. oldEnv := os.Environ()
  52. os.Clearenv()
  53. for key, value := range env {
  54. assert.NilError(t, os.Setenv(key, value), "setenv %s=%s", key, value)
  55. }
  56. clean := func() {
  57. if ht, ok := t.(helperT); ok {
  58. ht.Helper()
  59. }
  60. os.Clearenv()
  61. for key, oldVal := range ToMap(oldEnv) {
  62. assert.NilError(t, os.Setenv(key, oldVal), "setenv %s=%s", key, oldVal)
  63. }
  64. }
  65. cleanup.Cleanup(t, clean)
  66. return clean
  67. }
  68. // ToMap takes a list of strings in the format returned by [os.Environ] and
  69. // returns a mapping of keys to values.
  70. func ToMap(env []string) map[string]string {
  71. result := map[string]string{}
  72. for _, raw := range env {
  73. key, value := getParts(raw)
  74. result[key] = value
  75. }
  76. return result
  77. }
  78. func getParts(raw string) (string, string) {
  79. if raw == "" {
  80. return "", ""
  81. }
  82. // Environment variables on windows can begin with =
  83. // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
  84. parts := strings.SplitN(raw[1:], "=", 2)
  85. key := raw[:1] + parts[0]
  86. if len(parts) == 1 {
  87. return key, ""
  88. }
  89. return key, parts[1]
  90. }
  91. // ChangeWorkingDir to the directory, and return a function which restores the
  92. // previous working directory.
  93. //
  94. // When used with Go 1.14+ the previous working directory will be restored
  95. // automatically when the test ends, unless the TEST_NOCLEANUP env var is set to
  96. // true.
  97. func ChangeWorkingDir(t assert.TestingT, dir string) func() {
  98. if ht, ok := t.(helperT); ok {
  99. ht.Helper()
  100. }
  101. cwd, err := os.Getwd()
  102. assert.NilError(t, err)
  103. assert.NilError(t, os.Chdir(dir))
  104. clean := func() {
  105. if ht, ok := t.(helperT); ok {
  106. ht.Helper()
  107. }
  108. assert.NilError(t, os.Chdir(cwd))
  109. }
  110. cleanup.Cleanup(t, clean)
  111. return clean
  112. }