From 31adccd662fd2b53b5f3148c5ed27fd1368ae8e7 Mon Sep 17 00:00:00 2001 From: tro3 Date: Thu, 13 Apr 2017 21:22:46 -0700 Subject: [PATCH 1/7] Allow parallel integration tests in harness --- cmd/dep/integration_test.go | 11 ++- cmd/dep/remove_test.go | 9 ++- test/integration_testcase.go | 6 +- test/integration_testproj.go | 130 ++++++++++++++++++++++++++++++----- 4 files changed, 129 insertions(+), 27 deletions(-) diff --git a/cmd/dep/integration_test.go b/cmd/dep/integration_test.go index 63937fdb1f..d33b022e2f 100644 --- a/cmd/dep/integration_test.go +++ b/cmd/dep/integration_test.go @@ -19,6 +19,10 @@ 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 runtime.GOOS == "windows" && strings.Contains(path, "remove") { // TODO skipping the remove tests on windows until some fixes happen in gps - @@ -31,10 +35,13 @@ func TestIntegration(t *testing.T) { testName := strings.Join(parse[2:len(parse)-1], "/") t.Run(testName, func(t *testing.T) { + // Uncomment once the gps improvements are in place + // 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..2e3851b034 100644 --- a/test/integration_testproj.go +++ b/test/integration_testproj.go @@ -6,11 +6,15 @@ package test import ( "io" + "io/ioutil" "os" + "os/exec" "path/filepath" "sort" "strings" "testing" + + "github.com/pkg/errors" ) const ( @@ -23,41 +27,48 @@ type IntegrationTestProject struct { t *testing.T h *Helper preImports []string + tempdir string + env []string + origWd string } -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, + h: NewHelper(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)) + 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 { - localPath := append([]string{ProjectRoot}, args...) - return p.Path(localPath...) +func (p *IntegrationTestProject) TempProjDir(args ...string) { + p.TempDir(p.ProjPath(args...)) } func (p *IntegrationTestProject) VendorPath(args ...string) string { @@ -67,11 +78,51 @@ func (p *IntegrationTestProject) VendorPath(args ...string) string { } func (p *IntegrationTestProject) RunGo(args ...string) { - p.h.RunGo(args...) + cmd := exec.Command("go", args...) + p.h.stdout.Reset() + p.h.stderr.Reset() + cmd.Stdout = &p.h.stdout + cmd.Stderr = &p.h.stderr + cmd.Dir = p.tempdir + cmd.Env = p.env + status := cmd.Run() + if p.h.stdout.Len() > 0 { + p.h.t.Log("go standard output:") + p.h.t.Log(p.h.stdout.String()) + } + if p.h.stderr.Len() > 0 { + p.h.t.Log("go standard error:") + p.h.t.Log(p.h.stderr.String()) + } + if status != nil { + p.h.t.Logf("go %v failed unexpectedly: %v", args, status) + p.h.t.FailNow() + } } func (p *IntegrationTestProject) RunGit(dir string, args ...string) { - p.h.RunGit(dir, args...) + cmd := exec.Command("git", args...) + p.h.stdout.Reset() + p.h.stderr.Reset() + cmd.Stdout = &p.h.stdout + cmd.Stderr = &p.h.stderr + cmd.Dir = dir + cmd.Env = p.env + status := cmd.Run() + if *PrintLogs { + if p.h.stdout.Len() > 0 { + p.t.Logf("git %v standard output:", args) + p.t.Log(p.h.stdout.String()) + } + if p.h.stderr.Len() > 0 { + p.t.Logf("git %v standard error:", args) + p.t.Log(p.h.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 +133,33 @@ func (p *IntegrationTestProject) GetVendorGit(ip string) { } func (p *IntegrationTestProject) DoRun(args []string) error { - return p.h.DoRun(args) + if *PrintLogs { + p.h.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.h.stdout.Reset() + p.h.stderr.Reset() + cmd.Stdout = &p.h.stdout + cmd.Stderr = &p.h.stderr + cmd.Env = p.env + cmd.Dir = p.ProjPath("") + status := cmd.Run() + if *PrintLogs { + if p.h.stdout.Len() > 0 { + p.h.t.Log("standard output:") + p.h.t.Log(p.h.stdout.String()) + } + if p.h.stderr.Len() > 0 { + p.h.t.Log("standard error:") + p.h.t.Log(p.h.stderr.String()) + } + } + p.h.ran = true + return status } func (p *IntegrationTestProject) CopyTree(src string) { @@ -159,6 +236,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 +254,19 @@ 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.h.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) +} From 3eeef83470daf6e9973ea7f9c7d22d0bd361c30b Mon Sep 17 00:00:00 2001 From: tro3 Date: Fri, 14 Apr 2017 13:00:23 -0700 Subject: [PATCH 2/7] Clearing TestHelper dependency in IntegrationTestProject --- test/integration_testproj.go | 80 ++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/test/integration_testproj.go b/test/integration_testproj.go index 2e3851b034..b4d4c31e17 100644 --- a/test/integration_testproj.go +++ b/test/integration_testproj.go @@ -5,6 +5,7 @@ package test import ( + "bytes" "io" "io/ioutil" "os" @@ -30,12 +31,13 @@ type IntegrationTestProject struct { tempdir string env []string origWd string + stdout bytes.Buffer + stderr bytes.Buffer } func NewTestProject(t *testing.T, initPath, wd string) *IntegrationTestProject { new := &IntegrationTestProject{ t: t, - h: NewHelper(t), origWd: wd, env: os.Environ(), } @@ -47,7 +49,6 @@ func NewTestProject(t *testing.T, initPath, wd string) *IntegrationTestProject { } func (p *IntegrationTestProject) Cleanup() { - p.h.Cleanup() os.RemoveAll(p.tempdir) } @@ -68,7 +69,8 @@ func (p *IntegrationTestProject) TempDir(args ...string) { } func (p *IntegrationTestProject) TempProjDir(args ...string) { - p.TempDir(p.ProjPath(args...)) + localPath := append([]string{ProjectRoot}, args...) + p.TempDir(localPath...) } func (p *IntegrationTestProject) VendorPath(args ...string) string { @@ -79,44 +81,44 @@ func (p *IntegrationTestProject) VendorPath(args ...string) string { func (p *IntegrationTestProject) RunGo(args ...string) { cmd := exec.Command("go", args...) - p.h.stdout.Reset() - p.h.stderr.Reset() - cmd.Stdout = &p.h.stdout - cmd.Stderr = &p.h.stderr + 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.h.stdout.Len() > 0 { - p.h.t.Log("go standard output:") - p.h.t.Log(p.h.stdout.String()) + if p.stdout.Len() > 0 { + p.t.Log("go standard output:") + p.t.Log(p.stdout.String()) } - if p.h.stderr.Len() > 0 { - p.h.t.Log("go standard error:") - p.h.t.Log(p.h.stderr.String()) + if p.stderr.Len() > 0 { + p.t.Log("go standard error:") + p.t.Log(p.stderr.String()) } if status != nil { - p.h.t.Logf("go %v failed unexpectedly: %v", args, status) - p.h.t.FailNow() + p.t.Logf("go %v failed unexpectedly: %v", args, status) + p.t.FailNow() } } func (p *IntegrationTestProject) RunGit(dir string, args ...string) { cmd := exec.Command("git", args...) - p.h.stdout.Reset() - p.h.stderr.Reset() - cmd.Stdout = &p.h.stdout - cmd.Stderr = &p.h.stderr + 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.h.stdout.Len() > 0 { + if p.stdout.Len() > 0 { p.t.Logf("git %v standard output:", args) - p.t.Log(p.h.stdout.String()) + p.t.Log(p.stdout.String()) } - if p.h.stderr.Len() > 0 { + if p.stderr.Len() > 0 { p.t.Logf("git %v standard error:", args) - p.t.Log(p.h.stderr.String()) + p.t.Log(p.stderr.String()) } } if status != nil { @@ -134,31 +136,30 @@ func (p *IntegrationTestProject) GetVendorGit(ip string) { func (p *IntegrationTestProject) DoRun(args []string) error { if *PrintLogs { - p.h.t.Logf("running testdep %v", args) + 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.h.stdout.Reset() - p.h.stderr.Reset() - cmd.Stdout = &p.h.stdout - cmd.Stderr = &p.h.stderr + 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.h.stdout.Len() > 0 { - p.h.t.Log("standard output:") - p.h.t.Log(p.h.stdout.String()) + if p.stdout.Len() > 0 { + p.t.Log("standard output:") + p.t.Log(p.stdout.String()) } - if p.h.stderr.Len() > 0 { - p.h.t.Log("standard error:") - p.h.t.Log(p.h.stderr.String()) + if p.stderr.Len() > 0 { + p.t.Log("standard error:") + p.t.Log(p.stderr.String()) } } - p.h.ran = true return status } @@ -261,7 +262,7 @@ func (p *IntegrationTestProject) makeRootTempDir() { if p.tempdir == "" { var err error p.tempdir, err = ioutil.TempDir("", "gotest") - p.h.Must(err) + p.Must(err) } } @@ -270,3 +271,10 @@ func (p *IntegrationTestProject) makeRootTempDir() { 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) + } +} From b4d0425c9a8e4532cb19d8fd236e08f963c24561 Mon Sep 17 00:00:00 2001 From: tro3 Date: Sat, 15 Apr 2017 19:16:55 -0700 Subject: [PATCH 3/7] Removing windows/remove restriction with updated gps --- cmd/dep/integration_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/cmd/dep/integration_test.go b/cmd/dep/integration_test.go index 99351ad949..f0f9c594ee 100644 --- a/cmd/dep/integration_test.go +++ b/cmd/dep/integration_test.go @@ -7,7 +7,6 @@ package main import ( "os" "path/filepath" - "runtime" "strings" "testing" @@ -25,12 +24,6 @@ func TestIntegration(t *testing.T) { panic(err) } - if runtime.GOOS == "windows" && strings.Contains(path, "remove") { - // TODO skipping the remove tests on windows until some fixes happen in gps - - // see https://github.com/golang/dep/issues/301 - return filepath.SkipDir - } - if filepath.Base(path) == "testcase.json" { parse := strings.Split(path, string(filepath.Separator)) testName := strings.Join(parse[2:len(parse)-1], "/") From e302f18937193ab988b07e415754f6e200bfe63e Mon Sep 17 00:00:00 2001 From: tro3 Date: Sat, 15 Apr 2017 20:37:40 -0700 Subject: [PATCH 4/7] Uncomment t.Parallel(), now that gps is updated --- cmd/dep/integration_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/dep/integration_test.go b/cmd/dep/integration_test.go index f0f9c594ee..76ec035228 100644 --- a/cmd/dep/integration_test.go +++ b/cmd/dep/integration_test.go @@ -29,8 +29,7 @@ func TestIntegration(t *testing.T) { testName := strings.Join(parse[2:len(parse)-1], "/") t.Run(testName, func(t *testing.T) { - // Uncomment once the gps improvements are in place - // t.Parallel() + t.Parallel() // Set up environment testCase := test.NewTestCase(t, testName, wd) From 1050f75c87d61cb46723698075089483a8746997 Mon Sep 17 00:00:00 2001 From: tro3 Date: Sun, 16 Apr 2017 10:32:43 -0700 Subject: [PATCH 5/7] Removing debug code --- context_test.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/context_test.go b/context_test.go index 02e5604245..699a5c6804 100644 --- a/context_test.go +++ b/context_test.go @@ -5,7 +5,6 @@ package dep import ( - "fmt" "os" "path/filepath" "runtime" @@ -382,16 +381,10 @@ func TestResolveProjectRoot(t *testing.T) { symlinkedPath := filepath.Join(tg.Path("."), "sym", "symlink") symlinkedInGoPath := filepath.Join(ctx.GOPATH, "src/sym/path") symlinkedInOtherGoPath := filepath.Join(tg.Path("."), "sym", "symtwo") - os.Symlink(realPath, symlinkedPath+".lnk") + os.Symlink(realPath, symlinkedPath) os.Symlink(realPath, symlinkedInGoPath) os.Symlink(realPathTwo, symlinkedInOtherGoPath) - fmt.Println(realPath) - fmt.Println(realPathTwo) - fmt.Println(symlinkedPath) - fmt.Println(symlinkedInGoPath) - fmt.Println(symlinkedInOtherGoPath) - // Real path should be returned, no symlinks to deal with p, err := ctx.resolveProjectRoot(realPath) if err != nil { From 6de6c7738d9b1681845ccc50b9230620788e943d Mon Sep 17 00:00:00 2001 From: tro3 Date: Sun, 16 Apr 2017 15:31:56 -0700 Subject: [PATCH 6/7] Adding darwin patch --- test/integration_testproj.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/integration_testproj.go b/test/integration_testproj.go index b4d4c31e17..d934c0beb5 100644 --- a/test/integration_testproj.go +++ b/test/integration_testproj.go @@ -11,6 +11,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "sort" "strings" "testing" @@ -44,7 +45,11 @@ func NewTestProject(t *testing.T, initPath, wd string) *IntegrationTestProject { new.makeRootTempDir() new.TempDir(ProjectRoot, "vendor") new.CopyTree(initPath) - new.Setenv("GOPATH", new.tempdir) + if runtime.GOOS == "darwin" { + new.Setenv("GOPATH", filepath.Join("/private", new.tempdir)) + } else { + new.Setenv("GOPATH", new.tempdir) + } return new } From 4811b1b639d97c315891f525cb036f01d90acd49 Mon Sep 17 00:00:00 2001 From: tro3 Date: Sun, 16 Apr 2017 16:00:23 -0700 Subject: [PATCH 7/7] Adding darwin leader check and documentation --- test/integration_testproj.go | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/test/integration_testproj.go b/test/integration_testproj.go index d934c0beb5..83ebfd9e34 100644 --- a/test/integration_testproj.go +++ b/test/integration_testproj.go @@ -45,11 +45,18 @@ func NewTestProject(t *testing.T, initPath, wd string) *IntegrationTestProject { new.makeRootTempDir() new.TempDir(ProjectRoot, "vendor") new.CopyTree(initPath) - if runtime.GOOS == "darwin" { + + // 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 } @@ -283,3 +290,15 @@ func (p *IntegrationTestProject) Must(err error) { 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 +}