Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Parallel capability for integration tests #378

Merged
merged 10 commits into from
Apr 16, 2017
10 changes: 8 additions & 2 deletions cmd/dep/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions cmd/dep/remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package main

import (
"os"
"testing"

"github.com/golang/dep/test"
Expand All @@ -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
Expand Down
6 changes: 1 addition & 5 deletions test/integration_testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
162 changes: 144 additions & 18 deletions test/integration_testproj.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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 {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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()
}
Expand All @@ -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
}