403 lines
14 KiB
Go
403 lines
14 KiB
Go
package env_test
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/sclevine/spec"
|
|
"github.com/sclevine/spec/report"
|
|
|
|
"github.com/buildpacks/lifecycle/env"
|
|
)
|
|
|
|
func TestEnv(t *testing.T) {
|
|
spec.Run(t, "Env", testEnv, spec.Report(report.Terminal{}))
|
|
}
|
|
|
|
func testEnv(t *testing.T, when spec.G, it spec.S) {
|
|
var (
|
|
envv *env.Env
|
|
tmpDir string
|
|
)
|
|
|
|
it.Before(func() {
|
|
var err error
|
|
tmpDir, err = os.MkdirTemp("", "lifecycle")
|
|
if err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
envv = &env.Env{
|
|
RootDirMap: map[string][]string{
|
|
"bin": {
|
|
"PATH",
|
|
},
|
|
"lib": {
|
|
"LD_LIBRARY_PATH",
|
|
"LIBRARY_PATH",
|
|
},
|
|
},
|
|
Vars: env.NewVars(map[string]string{}, runtime.GOOS == "windows"),
|
|
}
|
|
})
|
|
|
|
it.After(func() {
|
|
os.RemoveAll(tmpDir)
|
|
})
|
|
|
|
when("#AddRootDir", func() {
|
|
it("should append POSIX directories to existing POSIX env vars", func() {
|
|
mkdir(t,
|
|
filepath.Join(tmpDir, "bin"),
|
|
filepath.Join(tmpDir, "lib"),
|
|
)
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"PATH": "some",
|
|
"LD_LIBRARY_PATH": "some-ld",
|
|
"LIBRARY_PATH": "some-library",
|
|
}, false)
|
|
if err := envv.AddRootDir(tmpDir); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
out := envv.List()
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
formEnv("LD_LIBRARY_PATH", filepath.Join(tmpDir, "lib"), "some-ld"),
|
|
formEnv("LIBRARY_PATH", filepath.Join(tmpDir, "lib"), "some-library"),
|
|
formEnv("PATH", filepath.Join(tmpDir, "bin"), "some"),
|
|
}
|
|
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
|
|
it("should set POSIX directories on empty POSIX env vars", func() {
|
|
mkdir(t,
|
|
filepath.Join(tmpDir, "bin"),
|
|
filepath.Join(tmpDir, "lib"),
|
|
)
|
|
if err := envv.AddRootDir(tmpDir); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
out := envv.List()
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
formEnv("LD_LIBRARY_PATH", filepath.Join(tmpDir, "lib")),
|
|
formEnv("LIBRARY_PATH", filepath.Join(tmpDir, "lib")),
|
|
formEnv("PATH", filepath.Join(tmpDir, "bin")),
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
|
|
when("#AddEnvDir", func() {
|
|
when("env files have a suffix", func() {
|
|
it.Before(func() {
|
|
mkdir(t, filepath.Join(tmpDir, "some-dir"))
|
|
mkfile(t, "value-append", filepath.Join(tmpDir, "VAR_APPEND.append"), filepath.Join(tmpDir, "VAR_APPEND_NEW.append"))
|
|
mkfile(t, "value-append-delim", filepath.Join(tmpDir, "VAR_APPEND_DELIM.append"), filepath.Join(tmpDir, "VAR_APPEND_DELIM_NEW.append"))
|
|
mkfile(t, "[]", filepath.Join(tmpDir, "VAR_APPEND_DELIM.delim"), filepath.Join(tmpDir, "VAR_APPEND_DELIM_NEW.delim"))
|
|
|
|
mkfile(t, "value-prepend", filepath.Join(tmpDir, "VAR_PREPEND.prepend"), filepath.Join(tmpDir, "VAR_PREPEND_NEW.prepend"))
|
|
mkfile(t, "value-prepend-delim", filepath.Join(tmpDir, "VAR_PREPEND_DELIM.prepend"), filepath.Join(tmpDir, "VAR_PREPEND_DELIM_NEW.prepend"))
|
|
mkfile(t, "[]", filepath.Join(tmpDir, "VAR_PREPEND_DELIM.delim"), filepath.Join(tmpDir, "VAR_PREPEND_DELIM_NEW.delim"))
|
|
|
|
mkfile(t, "value-default", filepath.Join(tmpDir, "VAR_DEFAULT.default"), filepath.Join(tmpDir, "VAR_DEFAULT_NEW.default"))
|
|
mkfile(t, "value-override", filepath.Join(tmpDir, "VAR_OVERRIDE.override"), filepath.Join(tmpDir, "VAR_OVERRIDE_NEW.override"))
|
|
mkfile(t, "value-ignore", filepath.Join(tmpDir, "VAR_IGNORE.ignore"))
|
|
})
|
|
|
|
it("performs the matching action", func() {
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_APPEND": "value-append-orig",
|
|
"VAR_APPEND_DELIM": "value-append-delim-orig",
|
|
"VAR_PREPEND": "value-prepend-orig",
|
|
"VAR_PREPEND_DELIM": "value-prepend-delim-orig",
|
|
"VAR_DEFAULT": "value-default-orig",
|
|
"VAR_OVERRIDE": "value-override-orig",
|
|
}, false)
|
|
if err := envv.AddEnvDir(tmpDir, ""); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
out := envv.List()
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
"VAR_APPEND=value-append-origvalue-append",
|
|
"VAR_APPEND_DELIM=value-append-delim-orig[]value-append-delim",
|
|
"VAR_APPEND_DELIM_NEW=value-append-delim",
|
|
"VAR_APPEND_NEW=value-append",
|
|
"VAR_DEFAULT=value-default-orig",
|
|
"VAR_DEFAULT_NEW=value-default",
|
|
"VAR_OVERRIDE=value-override",
|
|
"VAR_OVERRIDE_NEW=value-override",
|
|
"VAR_PREPEND=value-prependvalue-prepend-orig",
|
|
"VAR_PREPEND_DELIM=value-prepend-delim[]value-prepend-delim-orig",
|
|
"VAR_PREPEND_DELIM_NEW=value-prepend-delim",
|
|
"VAR_PREPEND_NEW=value-prepend",
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
|
|
when("env files have no suffix", func() {
|
|
it.Before(func() {
|
|
mkdir(t, filepath.Join(tmpDir, "some-dir"))
|
|
mkfile(t, "value-normal", filepath.Join(tmpDir, "VAR_NORMAL"), filepath.Join(tmpDir, "VAR_NORMAL_NEW"))
|
|
mkfile(t, "value-normal-delim", filepath.Join(tmpDir, "VAR_NORMAL_DELIM"), filepath.Join(tmpDir, "VAR_NORMAL_DELIM_NEW"))
|
|
mkfile(t, "[]", filepath.Join(tmpDir, "VAR_NORMAL_DELIM.delim"), filepath.Join(tmpDir, "VAR_NORMAL_DELIM_NEW.delim"))
|
|
})
|
|
|
|
when("default action is PrependPath", func() {
|
|
it("should prepend with pathlist separator or given delimiter", func() {
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_NORMAL": "value-normal-orig",
|
|
"VAR_NORMAL_DELIM": "value-normal-delim-orig",
|
|
}, false)
|
|
if err := envv.AddEnvDir(tmpDir, env.ActionTypePrependPath); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
out := envv.List()
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
"VAR_NORMAL=value-normal" + string(os.PathListSeparator) + "value-normal-orig",
|
|
"VAR_NORMAL_DELIM=value-normal-delim[]value-normal-delim-orig",
|
|
"VAR_NORMAL_DELIM_NEW=value-normal-delim",
|
|
"VAR_NORMAL_NEW=value-normal",
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
|
|
when("default action is Override", func() {
|
|
it("should override the value with the new value", func() {
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_NORMAL": "value-normal-orig",
|
|
"VAR_NORMAL_DELIM": "value-normal-delim-orig",
|
|
}, false)
|
|
if err := envv.AddEnvDir(tmpDir, env.ActionTypeOverride); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
out := envv.List()
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
"VAR_NORMAL=value-normal",
|
|
"VAR_NORMAL_DELIM=value-normal-delim", // override ignores delimiter
|
|
"VAR_NORMAL_DELIM_NEW=value-normal-delim",
|
|
"VAR_NORMAL_NEW=value-normal",
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
when("#Set", func() {
|
|
it("sets the variable", func() {
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR": "orig-val",
|
|
}, false)
|
|
envv.Set("VAR", "new-val")
|
|
out := envv.List()
|
|
expected := []string{"VAR=new-val"}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
|
|
when("#WithOverrides", func() {
|
|
when("it has a platform dir", func() {
|
|
it("should apply platform env vars as filename=file-contents", func() {
|
|
mkdir(t, filepath.Join(tmpDir, "env", "some-dir"))
|
|
mkfile(t, "value-path", filepath.Join(tmpDir, "env", "PATH"))
|
|
mkfile(t, "value-ld-library-path", filepath.Join(tmpDir, "env", "LD_LIBRARY_PATH"))
|
|
mkfile(t, "value-library-path", filepath.Join(tmpDir, "env", "LIBRARY_PATH"))
|
|
mkfile(t, "value-normal", filepath.Join(tmpDir, "env", "VAR_NORMAL"))
|
|
mkfile(t, "value-override", filepath.Join(tmpDir, "env", "VAR_OVERRIDE"))
|
|
mksymlink(t, filepath.Join(tmpDir, "env", "some-dir"), filepath.Join(tmpDir, "env", "some-sym-dir"))
|
|
mksymlink(t, filepath.Join(tmpDir, "env", "VAR_NORMAL"), filepath.Join(tmpDir, "env", "VAR_SYM"))
|
|
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_EMPTY": "",
|
|
"VAR_OVERRIDE": "value-override-orig",
|
|
"PATH": "value-path-orig",
|
|
"LD_LIBRARY_PATH": strings.Join([]string{"value-ld-library-path-orig1", "value-ld-library-path-orig2"}, string(os.PathListSeparator)),
|
|
}, false)
|
|
out, err := envv.WithOverrides(tmpDir, "")
|
|
if err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
formEnv("LD_LIBRARY_PATH", "value-ld-library-path", "value-ld-library-path-orig1", "value-ld-library-path-orig2"),
|
|
formEnv("LIBRARY_PATH", "value-library-path"),
|
|
formEnv("PATH", "value-path", "value-path-orig"),
|
|
formEnv("VAR_EMPTY", ""),
|
|
formEnv("VAR_NORMAL", "value-normal"),
|
|
formEnv("VAR_OVERRIDE", "value-override"),
|
|
formEnv("VAR_SYM", "value-normal"),
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
when("it has a base config dir", func() {
|
|
it("should apply base config env vars appropriately", func() {
|
|
mkdir(t, filepath.Join(tmpDir, "env", "some-dir"))
|
|
mkfile(t, "value-normal", filepath.Join(tmpDir, "env", "VAR_NORMAL"))
|
|
mkfile(t, "value-dne", filepath.Join(tmpDir, "env", "VAR_DNE.default"))
|
|
mkfile(t, "value-override", filepath.Join(tmpDir, "env", "VAR_EXIST"))
|
|
mkfile(t, "value-override", filepath.Join(tmpDir, "env", "VAR_OVERRIDE.override"))
|
|
mkfile(t, "value-prepend", filepath.Join(tmpDir, "env", "VAR_CHANGE.prepend"))
|
|
mkfile(t, ":", filepath.Join(tmpDir, "env", "VAR_CHANGE.delim"))
|
|
mkfile(t, "value-append", filepath.Join(tmpDir, "env", "VAR_CHANGE.append"))
|
|
mksymlink(t, filepath.Join(tmpDir, "env", "some-dir"), filepath.Join(tmpDir, "env", "some-sym-dir"))
|
|
mksymlink(t, filepath.Join(tmpDir, "env", "VAR_NORMAL"), filepath.Join(tmpDir, "env", "VAR_SYM"))
|
|
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_EMPTY": "",
|
|
"VAR_EXIST": "value-exist",
|
|
"VAR_OVERRIDE": "value-override-orig",
|
|
}, false)
|
|
out, err := envv.WithOverrides("", tmpDir)
|
|
if err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
formEnv("VAR_CHANGE", "value-prepend:value-append"),
|
|
formEnv("VAR_DNE", "value-dne"),
|
|
formEnv("VAR_EMPTY", ""),
|
|
formEnv("VAR_EXIST", "value-exist"),
|
|
formEnv("VAR_NORMAL", "value-normal"),
|
|
formEnv("VAR_OVERRIDE", "value-override"),
|
|
formEnv("VAR_SYM", "value-normal"),
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
when("it has both a platform dir and a base config dir", func() {
|
|
it("should apply platform env and then the base config env vars appropriately", func() {
|
|
platformDir := filepath.Join(tmpDir, "platform")
|
|
mkdir(t, filepath.Join(platformDir, "env", "some-dir"))
|
|
mkfile(t, "value-platform-dne", filepath.Join(platformDir, "env", "VAR_DNE"))
|
|
mkfile(t, "value-platform-override", filepath.Join(platformDir, "env", "VAR_PLATFORM_DEFAULT"))
|
|
mkfile(t, "value-platform-change", filepath.Join(platformDir, "env", "VAR_CHANGE"))
|
|
mkfile(t, "value-platform", filepath.Join(platformDir, "env", "VAR_OVERRIDE"))
|
|
baseConfigDir := filepath.Join(tmpDir, "base")
|
|
mkdir(t, filepath.Join(baseConfigDir, "env", "some-dir"))
|
|
mkfile(t, "value-normal", filepath.Join(baseConfigDir, "env", "VAR_NORMAL"))
|
|
mkfile(t, "value-override", filepath.Join(baseConfigDir, "env", "VAR_OVERRIDE.override"))
|
|
mkfile(t, "value-dne", filepath.Join(baseConfigDir, "env", "VAR_DNE.default"))
|
|
mkfile(t, "value-override", filepath.Join(baseConfigDir, "env", "VAR_EXIST.default"))
|
|
mkfile(t, "value-default", filepath.Join(baseConfigDir, "env", "VAR_DEFAULT"))
|
|
mkfile(t, "value-prepend", filepath.Join(baseConfigDir, "env", "VAR_CHANGE.prepend"))
|
|
mkfile(t, ":", filepath.Join(baseConfigDir, "env", "VAR_CHANGE.delim"))
|
|
mkfile(t, "value-append", filepath.Join(baseConfigDir, "env", "VAR_CHANGE.append"))
|
|
mksymlink(t, filepath.Join(baseConfigDir, "env", "some-dir"), filepath.Join(baseConfigDir, "env", "some-sym-dir"))
|
|
mksymlink(t, filepath.Join(baseConfigDir, "env", "VAR_NORMAL"), filepath.Join(baseConfigDir, "env", "VAR_SYM"))
|
|
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"VAR_EMPTY": "",
|
|
"VAR_EXIST": "value-exist",
|
|
"VAR_DEFAULT": "value-override-orig",
|
|
}, false)
|
|
out, err := envv.WithOverrides(platformDir, baseConfigDir)
|
|
if err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
sort.Strings(out)
|
|
|
|
expected := []string{
|
|
formEnv("VAR_CHANGE", "value-prepend:value-platform-change:value-append"),
|
|
formEnv("VAR_DEFAULT", "value-override-orig"),
|
|
formEnv("VAR_DNE", "value-platform-dne"),
|
|
formEnv("VAR_EMPTY", ""),
|
|
formEnv("VAR_EXIST", "value-exist"),
|
|
formEnv("VAR_NORMAL", "value-normal"),
|
|
formEnv("VAR_OVERRIDE", "value-override"),
|
|
formEnv("VAR_PLATFORM_DEFAULT", "value-platform-override"),
|
|
formEnv("VAR_SYM", "value-normal"),
|
|
}
|
|
if s := cmp.Diff(out, expected); s != "" {
|
|
t.Fatalf("Unexpected env:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
})
|
|
|
|
when("#Get", func() {
|
|
it("should get a value", func() {
|
|
mkdir(t,
|
|
filepath.Join(tmpDir, "bin"),
|
|
)
|
|
envv.Vars = env.NewVars(map[string]string{
|
|
"PATH": "path-orig",
|
|
}, false)
|
|
if err := envv.AddRootDir(tmpDir); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
|
|
expected := strings.Join([]string{filepath.Join(tmpDir, "bin"), "path-orig"}, string(os.PathListSeparator))
|
|
if s := cmp.Diff(envv.Get("PATH"), expected); s != "" {
|
|
t.Fatalf("Unexpected val:\n%s\n", s)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
func formEnv(name string, values ...string) string {
|
|
return fmt.Sprintf("%s=%s", name, strings.Join(values, string(os.PathListSeparator)))
|
|
}
|
|
|
|
func mkdir(t *testing.T, dirs ...string) {
|
|
t.Helper()
|
|
for _, dir := range dirs {
|
|
if err := os.MkdirAll(dir, 0777); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func mkfile(t *testing.T, data string, paths ...string) {
|
|
t.Helper()
|
|
for _, p := range paths {
|
|
if err := os.WriteFile(p, []byte(data), 0600); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func mksymlink(t *testing.T, target string, paths ...string) {
|
|
t.Helper()
|
|
for _, p := range paths {
|
|
if err := os.Symlink(target, p); err != nil {
|
|
t.Fatalf("Error: %s\n", err)
|
|
}
|
|
}
|
|
}
|