os: implement os.ExpandEnv

This commit is contained in:
Dan Kegel
2022-01-16 03:20:05 +00:00
committed by Ron Evans
parent 94b075e423
commit db0efc52c7
4 changed files with 292 additions and 9 deletions
+112
View File
@@ -11,6 +11,82 @@ import (
"testing"
)
// testGetenv gives us a controlled set of variables for testing Expand.
func testGetenv(s string) string {
switch s {
case "*":
return "all the args"
case "#":
return "NARGS"
case "$":
return "PID"
case "1":
return "ARGUMENT1"
case "HOME":
return "/usr/gopher"
case "H":
return "(Value of H)"
case "home_1":
return "/usr/foo"
case "_":
return "underscore"
}
return ""
}
var expandTests = []struct {
in, out string
}{
{"", ""},
{"$*", "all the args"},
{"$$", "PID"},
{"${*}", "all the args"},
{"$1", "ARGUMENT1"},
{"${1}", "ARGUMENT1"},
{"now is the time", "now is the time"},
{"$HOME", "/usr/gopher"},
{"$home_1", "/usr/foo"},
{"${HOME}", "/usr/gopher"},
{"${H}OME", "(Value of H)OME"},
{"A$$$#$1$H$home_1*B", "APIDNARGSARGUMENT1(Value of H)/usr/foo*B"},
{"start$+middle$^end$", "start$+middle$^end$"},
{"mixed$|bag$$$", "mixed$|bagPID$"},
{"$", "$"},
{"$}", "$}"},
{"${", ""}, // invalid syntax; eat up the characters
{"${}", ""}, // invalid syntax; eat up the characters
}
func TestExpand(t *testing.T) {
for _, test := range expandTests {
result := Expand(test.in, testGetenv)
if result != test.out {
t.Errorf("Expand(%q)=%q; expected %q", test.in, result, test.out)
}
}
}
var global interface{}
func BenchmarkExpand(b *testing.B) {
b.Run("noop", func(b *testing.B) {
var s string
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s = Expand("tick tick tick tick", func(string) string { return "" })
}
global = s
})
b.Run("multiple", func(b *testing.B) {
var s string
b.ReportAllocs()
for i := 0; i < b.N; i++ {
s = Expand("$a $a $a $a", func(string) string { return "boom" })
}
global = s
})
}
func TestConsistentEnviron(t *testing.T) {
e0 := Environ()
for i := 0; i < 10; i++ {
@@ -90,3 +166,39 @@ func TestLookupEnv(t *testing.T) {
t.Errorf("smallpox release failed; world remains safe but LookupEnv is broken")
}
}
// On Windows, Environ was observed to report keys with a single leading "=".
// Check that they are properly reported by LookupEnv and can be set by SetEnv.
// See https://golang.org/issue/49886.
func TestEnvironConsistency(t *testing.T) {
for _, kv := range Environ() {
i := strings.Index(kv, "=")
if i == 0 {
// We observe in practice keys with a single leading "=" on Windows.
// TODO(#49886): Should we consume only the first leading "=" as part
// of the key, or parse through arbitrarily many of them until a non-=,
// or try each possible key/value boundary until LookupEnv succeeds?
i = strings.Index(kv[1:], "=") + 1
}
if i < 0 {
t.Errorf("Environ entry missing '=': %q", kv)
}
k := kv[:i]
v := kv[i+1:]
v2, ok := LookupEnv(k)
if ok && v == v2 {
t.Logf("LookupEnv(%q) = %q, %t", k, v2, ok)
} else {
t.Errorf("Environ contains %q, but LookupEnv(%q) = %q, %t", kv, k, v2, ok)
}
// Since k=v is already present in the environment,
// setting it should be a no-op.
if err := Setenv(k, v); err == nil {
t.Logf("Setenv(%q, %q)", k, v)
} else {
t.Errorf("Environ contains %q, but SetEnv(%q, %q) = %q", kv, k, v, err)
}
}
}