diff --git a/cmd/dep/integration_test.go b/cmd/dep/integration_test.go index d03ad4eb28..fcf8411644 100644 --- a/cmd/dep/integration_test.go +++ b/cmd/dep/integration_test.go @@ -19,16 +19,22 @@ func TestIntegration(t *testing.T) { test.NeedsGit(t) filepath.Walk(filepath.Join("testdata", "harness_tests"), func(path string, info os.FileInfo, err error) error { + wd, err := os.Getwd() + if err != nil { + panic(err) + } if filepath.Base(path) == "testcase.json" { parse := strings.Split(path, string(filepath.Separator)) testName := strings.Join(parse[2:len(parse)-1], "/") t.Run(testName, func(t *testing.T) { + t.Parallel() + // Set up environment - testCase := test.NewTestCase(t, testName) + testCase := test.NewTestCase(t, testName, wd) defer testCase.Cleanup() - testProj := test.NewTestProject(t, testCase.InitialPath()) + testProj := test.NewTestProject(t, testCase.InitialPath(), wd) defer testProj.Cleanup() // Create and checkout the vendor revisions diff --git a/cmd/dep/remove_test.go b/cmd/dep/remove_test.go index f3e6c09da1..47a529b0da 100644 --- a/cmd/dep/remove_test.go +++ b/cmd/dep/remove_test.go @@ -5,6 +5,7 @@ package main import ( + "os" "testing" "github.com/golang/dep/test" @@ -15,9 +16,13 @@ func TestRemoveErrors(t *testing.T) { test.NeedsGit(t) testName := "remove/unused/case1" + wd, err := os.Getwd() + if err != nil { + panic(err) + } - testCase := test.NewTestCase(t, testName) - testProj := test.NewTestProject(t, testCase.InitialPath()) + testCase := test.NewTestCase(t, testName, wd) + testProj := test.NewTestProject(t, testCase.InitialPath(), wd) defer testProj.Cleanup() // Create and checkout the vendor revisions diff --git a/test/integration_testcase.go b/test/integration_testcase.go index d1826ebc89..75b0d626bb 100644 --- a/test/integration_testcase.go +++ b/test/integration_testcase.go @@ -32,11 +32,7 @@ type IntegrationTestCase struct { VendorFinal []string `json:"vendor-final"` } -func NewTestCase(t *testing.T, name string) *IntegrationTestCase { - wd, err := os.Getwd() - if err != nil { - panic(err) - } +func NewTestCase(t *testing.T, name, wd string) *IntegrationTestCase { rootPath := filepath.FromSlash(filepath.Join(wd, "testdata", "harness_tests", name)) n := &IntegrationTestCase{ t: t, diff --git a/test/integration_testproj.go b/test/integration_testproj.go index b3e72a493f..83ebfd9e34 100644 --- a/test/integration_testproj.go +++ b/test/integration_testproj.go @@ -5,12 +5,18 @@ package test import ( + "bytes" "io" + "io/ioutil" "os" + "os/exec" "path/filepath" + "runtime" "sort" "strings" "testing" + + "github.com/pkg/errors" ) const ( @@ -23,41 +29,60 @@ type IntegrationTestProject struct { t *testing.T h *Helper preImports []string + tempdir string + env []string + origWd string + stdout bytes.Buffer + stderr bytes.Buffer } -func NewTestProject(t *testing.T, initPath string) *IntegrationTestProject { +func NewTestProject(t *testing.T, initPath, wd string) *IntegrationTestProject { new := &IntegrationTestProject{ - t: t, - h: NewHelper(t), + t: t, + origWd: wd, + env: os.Environ(), } - new.TempDir(ProjectRoot) + new.makeRootTempDir() new.TempDir(ProjectRoot, "vendor") new.CopyTree(initPath) - new.h.Setenv("GOPATH", new.h.Path(".")) - new.h.Cd(new.Path(ProjectRoot)) + + // Note that the Travis darwin platform, directories with certain roots such + // as /var are actually links to a dirtree under /private. Without the patch + // below the wd, and therefore the GOPATH, is recorded as "/var/..." but the + // actual process runs in "/private/var/..." and dies due to not being in the + // GOPATH because the roots don't line up. + if runtime.GOOS == "darwin" && needsPrivateLeader(new.tempdir) { + new.Setenv("GOPATH", filepath.Join("/private", new.tempdir)) + } else { + new.Setenv("GOPATH", new.tempdir) + } + return new } func (p *IntegrationTestProject) Cleanup() { - p.h.Cleanup() + os.RemoveAll(p.tempdir) } func (p *IntegrationTestProject) Path(args ...string) string { - return p.h.Path(filepath.Join(args...)) + return filepath.Join(p.tempdir, filepath.Join(args...)) } -func (p *IntegrationTestProject) TempDir(args ...string) { - p.h.TempDir(filepath.Join(args...)) +func (p *IntegrationTestProject) ProjPath(args ...string) string { + localPath := append([]string{ProjectRoot}, args...) + return p.Path(localPath...) } -func (p *IntegrationTestProject) TempProjDir(args ...string) { - localPath := append([]string{ProjectRoot}, args...) - p.h.TempDir(filepath.Join(localPath...)) +func (p *IntegrationTestProject) TempDir(args ...string) { + fullPath := p.Path(args...) + if err := os.MkdirAll(fullPath, 0755); err != nil && !os.IsExist(err) { + p.t.Fatalf("%+v", errors.Errorf("Unable to create temp directory: %s", fullPath)) + } } -func (p *IntegrationTestProject) ProjPath(args ...string) string { +func (p *IntegrationTestProject) TempProjDir(args ...string) { localPath := append([]string{ProjectRoot}, args...) - return p.Path(localPath...) + p.TempDir(localPath...) } func (p *IntegrationTestProject) VendorPath(args ...string) string { @@ -67,11 +92,51 @@ func (p *IntegrationTestProject) VendorPath(args ...string) string { } func (p *IntegrationTestProject) RunGo(args ...string) { - p.h.RunGo(args...) + cmd := exec.Command("go", args...) + p.stdout.Reset() + p.stderr.Reset() + cmd.Stdout = &p.stdout + cmd.Stderr = &p.stderr + cmd.Dir = p.tempdir + cmd.Env = p.env + status := cmd.Run() + if p.stdout.Len() > 0 { + p.t.Log("go standard output:") + p.t.Log(p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Log("go standard error:") + p.t.Log(p.stderr.String()) + } + if status != nil { + p.t.Logf("go %v failed unexpectedly: %v", args, status) + p.t.FailNow() + } } func (p *IntegrationTestProject) RunGit(dir string, args ...string) { - p.h.RunGit(dir, args...) + cmd := exec.Command("git", args...) + p.stdout.Reset() + p.stderr.Reset() + cmd.Stdout = &p.stdout + cmd.Stderr = &p.stderr + cmd.Dir = dir + cmd.Env = p.env + status := cmd.Run() + if *PrintLogs { + if p.stdout.Len() > 0 { + p.t.Logf("git %v standard output:", args) + p.t.Log(p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Logf("git %v standard error:", args) + p.t.Log(p.stderr.String()) + } + } + if status != nil { + p.t.Logf("git %v failed unexpectedly: %v", args, status) + p.t.FailNow() + } } func (p *IntegrationTestProject) GetVendorGit(ip string) { @@ -82,7 +147,32 @@ func (p *IntegrationTestProject) GetVendorGit(ip string) { } func (p *IntegrationTestProject) DoRun(args []string) error { - return p.h.DoRun(args) + if *PrintLogs { + p.t.Logf("running testdep %v", args) + } + var prog string + prog = filepath.Join(p.origWd, "testdep"+ExeSuffix) + newargs := []string{args[0], "-v"} + newargs = append(newargs, args[1:]...) + cmd := exec.Command(prog, newargs...) + p.stdout.Reset() + p.stderr.Reset() + cmd.Stdout = &p.stdout + cmd.Stderr = &p.stderr + cmd.Env = p.env + cmd.Dir = p.ProjPath("") + status := cmd.Run() + if *PrintLogs { + if p.stdout.Len() > 0 { + p.t.Log("standard output:") + p.t.Log(p.stdout.String()) + } + if p.stderr.Len() > 0 { + p.t.Log("standard error:") + p.t.Log(p.stderr.String()) + } + } + return status } func (p *IntegrationTestProject) CopyTree(src string) { @@ -159,6 +249,7 @@ func (p *IntegrationTestProject) GetImportPaths() []string { return result } +// Take a snapshot of the import paths before test is run func (p *IntegrationTestProject) RecordImportPaths() { p.preImports = p.GetImportPaths() } @@ -176,3 +267,38 @@ func (p *IntegrationTestProject) CompareImportPaths() { } } } + +// makeRootTempdir makes a temporary directory for a run of testgo. If +// the temporary directory was already created, this does nothing. +func (p *IntegrationTestProject) makeRootTempDir() { + if p.tempdir == "" { + var err error + p.tempdir, err = ioutil.TempDir("", "gotest") + p.Must(err) + } +} + +// Setenv sets an environment variable to use when running the test go +// command. +func (p *IntegrationTestProject) Setenv(name, val string) { + p.env = append(p.env, name+"="+val) +} + +// Must gives a fatal error if err is not nil. +func (p *IntegrationTestProject) Must(err error) { + if err != nil { + p.t.Fatalf("%+v", err) + } +} + +// Checks for filepath beginnings that result in the "/private" leader +// on Mac platforms +func needsPrivateLeader(path string) bool { + var roots = []string{"/var", "/tmp", "/etc"} + for _, root := range roots { + if strings.HasPrefix(path, root) { + return true + } + } + return false +}