Merge pull request #287 from tro3/test_harness

Integration test harness
This commit is contained in:
sam boyer 2017-03-09 12:51:05 -05:00 коммит произвёл GitHub
Родитель 97011c18f9 d3c1115674
Коммит 5b98ab1371
62 изменённых файлов: 785 добавлений и 412 удалений

Просмотреть файл

@ -5,10 +5,8 @@
package main
import (
"path/filepath"
"testing"
"github.com/golang/dep/test"
"github.com/sdboyer/gps"
)
@ -38,109 +36,3 @@ func TestDeduceConstraint(t *testing.T) {
}
}
}
type ensureTestCase struct {
dataRoot string
commands [][]string
sourceFiles map[string]string
goldenManifest string
goldenLock string
}
func TestEnsureCases(t *testing.T) {
tests := []ensureTestCase{
// Override test case
{
dataRoot: "ensure/override",
commands: [][]string{
{"init"},
{"ensure", "-override", "github.com/sdboyer/deptest@1.0.0"},
},
sourceFiles: map[string]string{
"main.go": "thing.go",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
// Empty repo test case
{
dataRoot: "ensure/empty",
commands: [][]string{
{"init"},
{"ensure"},
},
sourceFiles: map[string]string{
"main.go": "thing.go",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
// Update test case
{
dataRoot: "ensure/update",
commands: [][]string{
{"ensure", "-update", "github.com/sdboyer/deptest"},
},
sourceFiles: map[string]string{
"main.go": "thing.go",
"manifest.json": "manifest.json",
"lock.json": "lock.json",
},
goldenManifest: "manifest.json",
goldenLock: "lock.golden.json",
},
}
test.NeedsExternalNetwork(t)
test.NeedsGit(t)
for _, testCase := range tests {
t.Run(testCase.dataRoot, func(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir("src")
h.Setenv("GOPATH", h.Path("."))
// Build a fake consumer of these packages.
root := "src/thing"
for src, dest := range testCase.sourceFiles {
h.TempCopy(filepath.Join(root, dest), filepath.Join(testCase.dataRoot, src))
}
h.Cd(h.Path(root))
for _, cmd := range testCase.commands {
h.Run(cmd...)
}
wantPath := filepath.Join(testCase.dataRoot, testCase.goldenManifest)
wantManifest := h.GetTestFileString(wantPath)
gotManifest := h.ReadManifest()
if wantManifest != gotManifest {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotManifest); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantManifest, gotManifest)
}
}
wantPath = filepath.Join(testCase.dataRoot, testCase.goldenLock)
wantLock := h.GetTestFileString(wantPath)
gotLock := h.ReadLock()
if wantLock != gotLock {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotLock); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantLock, gotLock)
}
}
})
}
}

Просмотреть файл

@ -4,12 +4,7 @@
package main
import (
"path/filepath"
"testing"
"github.com/golang/dep/test"
)
import "testing"
func TestContains(t *testing.T) {
a := []string{"a", "b", "abcd"}
@ -38,120 +33,3 @@ func TestIsStdLib(t *testing.T) {
}
}
}
type initTestCase struct {
dataRoot string
importPaths map[string]string
sourceFiles map[string]string
goldenManifest string
goldenLock string
vendorPaths []string
}
func TestInit(t *testing.T) {
tests := []initTestCase{
// Both dependencies previously retrieved. Both will show up in manifest and lock
{
dataRoot: "init/case1",
importPaths: map[string]string{
"github.com/sdboyer/deptest": "v0.8.0", // semver
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea", // random sha
},
sourceFiles: map[string]string{
"thing.input.go": "foo/thing.go",
"bar.input.go": "foo/bar/bar.go",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
// One dependency previously retrieved by version. Both will show up in lock, but only retrieved one in manifest?
{
dataRoot: "init/case2",
importPaths: map[string]string{
"github.com/sdboyer/deptest": "v0.8.0", // semver
},
sourceFiles: map[string]string{
"thing.input.go": "foo/thing.go",
"bar.input.go": "foo/bar/bar.go",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
// One dependency previously retrieved by sha. Both will show up in lock and manifest
{
dataRoot: "init/case3",
importPaths: map[string]string{
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea",
},
sourceFiles: map[string]string{
"thing.input.go": "foo/thing.go",
"bar.input.go": "foo/bar/bar.go",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
}
test.NeedsExternalNetwork(t)
test.NeedsGit(t)
for _, testCase := range tests {
t.Run(testCase.dataRoot, func(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir("src")
h.Setenv("GOPATH", h.Path("."))
// checkout the specified revisions
for ip, rev := range testCase.importPaths {
h.RunGo("get", ip)
repoDir := h.Path(filepath.Join("src", ip))
h.RunGit(repoDir, "checkout", rev)
}
// Build a fake consumer of these packages.
root := "src/github.com/golang/notexist"
for src, dest := range testCase.sourceFiles {
h.TempCopy(filepath.Join(root, dest), filepath.Join(testCase.dataRoot, src))
}
h.Cd(h.Path(root))
h.Run("init")
wantPath := filepath.Join(testCase.dataRoot, testCase.goldenManifest)
wantManifest := h.GetTestFileString(wantPath)
gotManifest := h.ReadManifest()
if wantManifest != gotManifest {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotManifest); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantManifest, gotManifest)
}
}
wantPath = filepath.Join(testCase.dataRoot, testCase.goldenLock)
wantLock := h.GetTestFileString(wantPath)
gotLock := h.ReadLock()
if wantLock != gotLock {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotLock); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantLock, gotLock)
}
}
// vendor should have been created & populated
for ip := range testCase.importPaths {
h.MustExist(h.Path(filepath.Join(root, "vendor", ip)))
}
})
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/golang/dep/test"
)
func TestIntegration(t *testing.T) {
test.NeedsExternalNetwork(t)
test.NeedsGit(t)
filepath.Walk(filepath.Join("testdata", "harness_tests"), func(path string, info os.FileInfo, err error) error {
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], "/")
t.Run(testName, func(t *testing.T) {
// Set up environment
testCase := test.NewTestCase(t, testName)
testProj := test.NewTestProject(t, testCase.InitialPath)
defer testProj.Cleanup()
// Create and checkout the vendor revisions
for ip, rev := range testCase.InitialVendors {
testProj.GetVendorGit(ip)
testProj.RunGit(testProj.VendorPath(ip), "checkout", rev)
}
// Create and checkout the import revisions
for ip, rev := range testCase.Imports {
testProj.RunGo("get", ip)
testProj.RunGit(testProj.Path("src", ip), "checkout", rev)
}
// Run commands
testProj.RecordImportPaths()
for _, args := range testCase.Commands {
testProj.DoRun(args)
}
// Check final manifest and lock
testCase.CompareFile("manifest.json", testProj.ProjPath("manifest.json"))
testCase.CompareFile("lock.json", testProj.ProjPath("lock.json"))
// Check vendor paths
testProj.CompareImportPaths()
testCase.CompareVendorPaths(testProj.GetVendorPaths())
})
}
return nil
})
}

Просмотреть файл

@ -5,168 +5,46 @@
package main
import (
"path/filepath"
"runtime"
"testing"
"github.com/golang/dep/test"
)
type removeTestCase struct {
dataRoot string
command []string
importPaths map[string]string
sourceFiles map[string]string
goldenManifest string
goldenLock string
vendorPaths []string
}
func TestRemove(t *testing.T) {
if runtime.GOOS == "windows" {
// TODO skipping this test on windows until some fixes happen in gps -
// see https://github.com/golang/dep/issues/301
t.Skip()
}
tests := []removeTestCase{
{
dataRoot: "remove/case0",
command: []string{"remove", "-unused"},
importPaths: map[string]string{
"github.com/sdboyer/deptest": "v0.8.0", // semver
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea", // random sha
},
sourceFiles: map[string]string{
"main.go": "main.go",
"manifest.input.json": "manifest.json",
},
goldenManifest: "manifest.golden.json",
goldenLock: "",
},
{
dataRoot: "remove/case1",
command: []string{"remove", "github.com/not/used"},
importPaths: map[string]string{
"github.com/sdboyer/deptest": "v0.8.0", // semver
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea", // random sha
},
sourceFiles: map[string]string{
"main.go": "main.go",
"manifest.input.json": "manifest.json",
},
goldenManifest: "manifest.golden.json",
goldenLock: "",
},
{
dataRoot: "remove/case2",
command: []string{"remove", "-force", "github.com/sdboyer/deptestdos", "github.com/not/used"},
importPaths: map[string]string{
"github.com/sdboyer/deptest": "v0.8.0", // semver
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea", // random sha
},
sourceFiles: map[string]string{
"main.go": "main.go",
"manifest.input.json": "manifest.json",
},
goldenManifest: "manifest.golden.json",
goldenLock: "lock.golden.json",
},
}
test.NeedsExternalNetwork(t)
test.NeedsGit(t)
for _, testCase := range tests {
t.Run(testCase.dataRoot, func(t *testing.T) {
h := test.NewHelper(t)
defer h.Cleanup()
h.TempDir("src")
h.Setenv("GOPATH", h.Path("."))
// checkout the specified revisions
for ip, rev := range testCase.importPaths {
h.RunGo("get", ip)
repoDir := h.Path(filepath.Join("src", ip))
h.RunGit(repoDir, "checkout", rev)
}
// Build a fake consumer of these packages.
root := "src/github.com/golang/notexist"
for src, dest := range testCase.sourceFiles {
h.TempCopy(filepath.Join(root, dest), filepath.Join(testCase.dataRoot, src))
}
h.Cd(h.Path(root))
h.Run(testCase.command...)
wantPath := filepath.Join(testCase.dataRoot, testCase.goldenManifest)
wantManifest := h.GetTestFileString(wantPath)
gotManifest := h.ReadManifest()
if wantManifest != gotManifest {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotManifest); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantManifest, gotManifest)
}
}
if testCase.goldenLock != "" {
wantPath = filepath.Join(testCase.dataRoot, testCase.goldenLock)
wantLock := h.GetTestFileString(wantPath)
gotLock := h.ReadLock()
if wantLock != gotLock {
if *test.UpdateGolden {
if err := h.WriteTestFile(wantPath, gotLock); err != nil {
t.Fatal(err)
}
} else {
t.Errorf("expected %s, got %s", wantLock, gotLock)
}
}
}
})
}
}
func TestRemoveErrors(t *testing.T) {
test.NeedsExternalNetwork(t)
test.NeedsGit(t)
h := test.NewHelper(t)
defer h.Cleanup()
testName := "remove/unused/case1"
h.TempDir("src")
h.Setenv("GOPATH", h.Path("."))
testCase := test.NewTestCase(t, testName)
testProj := test.NewTestProject(t, testCase.InitialPath)
defer testProj.Cleanup()
// Build a fake consumer of these packages.
sourceFiles := map[string]string{
"main.go": "main.go",
"manifest.input.json": "manifest.json",
}
root := "src/github.com/golang/notexist"
for src, dest := range sourceFiles {
h.TempCopy(filepath.Join(root, dest), filepath.Join("remove/case0", src))
// Create and checkout the vendor revisions
for ip, rev := range testCase.InitialVendors {
testProj.GetVendorGit(ip)
testProj.RunGit(testProj.VendorPath(ip), "checkout", rev)
}
h.Cd(h.Path(root))
// Create and checkout the import revisions
for ip, rev := range testCase.Imports {
testProj.RunGo("get", ip)
testProj.RunGit(testProj.Path("src", ip), "checkout", rev)
}
if err := h.DoRun([]string{"remove", "-unused", "github.com/not/used"}); err == nil {
if err := testProj.DoRun([]string{"remove", "-unused", "github.com/not/used"}); err == nil {
t.Fatal("rm with both -unused and arg should have failed")
}
if err := h.DoRun([]string{"remove", "github.com/not/present"}); err == nil {
if err := testProj.DoRun([]string{"remove", "github.com/not/present"}); err == nil {
t.Fatal("rm with arg not in manifest should have failed")
}
if err := h.DoRun([]string{"remove", "github.com/not/used", "github.com/not/present"}); err == nil {
if err := testProj.DoRun([]string{"remove", "github.com/not/used", "github.com/not/present"}); err == nil {
t.Fatal("rm with one arg not in manifest should have failed")
}
if err := h.DoRun([]string{"remove", "github.com/sdboyer/deptest"}); err == nil {
if err := testProj.DoRun([]string{"remove", "github.com/sdboyer/deptest"}); err == nil {
t.Fatal("rm of arg in manifest and imports should have failed without -force")
}
}

79
cmd/dep/testdata/harness_tests/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,79 @@
# golang/dep Integration Tests
The `dep` integration tests use a consistent directory structure under `testdata`
to set up the initial project state, run `dep` commands, then check against an
expected final state to see if the test passes.
The directory structure is as follows:
testdata/
category1/
subcategory1/
case1/
testcase.json
initial/
file1.go
manifest.json
...
final/
manifest.json
lock.json
case2/
...
The test code itself simply walks down the directory tree, looking for
`testcase.json` files. These files can be as many levels down the tree as
desired. The test name will consist of the directory path from `testdata` to
the test case directory itself. In the above example, the test name would be
`category1/subcategory1/case1`, and could be singled out with the `-run` option
of `go test` (i.e.
`go test github.com/golang/dep/cmp/dep -run Integration/category1/subcategory1/case1`).
New tests can be added simply by adding a new directory with the json file to
the `testdata` tree. There is no need for code modification - the new test
will be included automatically.
The json file needs to be accompanied by `initial` and `final` directories. The
`initial` is copied verbatim into the test project before the `dep` commands are
run, are the `manifest` and `lock` files in `final`, if present, are used to
compare against the test project results after the commands.
The `testcase.json` file has the following format:
{
"commands": [
["init"],
["ensure", "github.com/sdboyer/deptesttres"]
],
"imports": {
"github.com/sdboyer/deptest": "v0.8.0",
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea"
},
"initialVendors": {
"github.com/sdboyer/deptesttres": "v2.1.0",
"github.com/sdboyer/deptestquatro": "cf596baa11ea047ddf8797287451d36b861bab45"
},
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos",
"github.com/sdboyer/deptesttres",
"github.com/sdboyer/deptestquatro"
]
}
All of the categories are optional - if the `imports` list for a test is empty,
for example, it can be completely left out.
The test procedure is as follows:
1. Create a temporary directory for the test project environment
2. Create `src/github.com/golang/notexist` as the project
3. Copy the contents of `initial` to the project
4. Fetch the repos and versions in `imports` to the `src` directory
5. Fetch the repos and versions in `initialVendors` to the `vendor` directory
6. Run the commands in `commands` in order on the project
7. Check the resulting files against those in `final`
8. Check the `vendor` directory for the repos listed under `finalVendors`
9. Check that there were no changes to `src` listings
10. Clean up
Note that for the remote fetches, only git repos are currently supported.

Просмотреть файл

Просмотреть файл

@ -0,0 +1,9 @@
{
"commands": [
["init"],
["ensure", "-update"]
],
"finalVendors": [
"github.com/sdboyer/deptest"
]
}

Просмотреть файл

@ -0,0 +1,13 @@
{
"memo": "1a99b419931283cb086167ddfb2e8322df12e2648e139eb27a42904360e962ad",
"projects": [
{
"name": "github.com/sdboyer/deptest",
"version": "v1.0.0",
"revision": "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
"packages": [
"."
]
}
]
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"dependencies": {
"github.com/sdboyer/deptest": {
"version": "^0.8.0"
}
}
}

Просмотреть файл

@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bar
package main
import "github.com/sdboyer/deptest"
import (
_ "github.com/sdboyer/deptest"
)
const Qux = deptest.Map["yo yo!"]
func main() {
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"commands": [
["ensure"]
],
"finalVendors": [
"github.com/sdboyer/deptest"
]
}

Просмотреть файл

@ -0,0 +1,9 @@
{
"commands": [
["init"],
["ensure", "-override", "github.com/sdboyer/deptest@1.0.0"]
],
"finalVendors": [
"github.com/sdboyer/deptest"
]
}

Просмотреть файл

@ -0,0 +1,7 @@
{
"dependencies": {
"github.com/sdboyer/deptest": {
"version": "~0.8.0"
}
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,7 @@
{
"dependencies": {
"github.com/sdboyer/deptest": {
"version": "~0.8.0"
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"commands": [
["init"],
["ensure", "-update", "github.com/sdboyer/deptest"]
],
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

Просмотреть файл

@ -1,9 +1,13 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bar
package foo
import "github.com/sdboyer/deptest"
const Qux = deptest.Map["yo yo!"]
func Foo() deptest.Foo {
var y deptest.Foo
return y
}

Просмотреть файл

@ -1,17 +1,19 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"github.com/golang/notexist/foo/bar"
"fmt"
"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)
func main() {
err := nil
if err != nil {
deptestdos.diMeLo(bar.Qux)
}
var x deptestdos.Bar
y := foo.FooFunc()
fmt.Println(x, y)
}

13
cmd/dep/testdata/harness_tests/init/case1/testcase.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
{
"commands": [
["init"]
],
"imports": {
"github.com/sdboyer/deptest": "v0.8.0",
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea"
},
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

Просмотреть файл

@ -1,9 +1,13 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bar
package foo
import "github.com/sdboyer/deptest"
const Qux = deptest.Map["yo yo!"]
func Foo() deptest.Foo {
var y deptest.Foo
return y
}

Просмотреть файл

@ -1,17 +1,19 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"github.com/golang/notexist/foo/bar"
"fmt"
"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)
func main() {
err := nil
if err != nil {
deptestdos.diMeLo(bar.Qux)
}
var x deptestdos.Bar
y := foo.FooFunc()
fmt.Println(x, y)
}

12
cmd/dep/testdata/harness_tests/init/case2/testcase.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
{
"commands": [
["init"]
],
"imports": {
"github.com/sdboyer/deptest": "v0.8.0"
},
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

13
cmd/dep/testdata/harness_tests/init/case3/initial/foo/bar.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,13 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package foo
import "github.com/sdboyer/deptest"
func Foo() deptest.Foo {
var y deptest.Foo
return y
}

19
cmd/dep/testdata/harness_tests/init/case3/initial/main.go поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"github.com/golang/notexist/foo"
"github.com/sdboyer/deptestdos"
)
func main() {
var x deptestdos.Bar
y := foo.FooFunc()
fmt.Println(x, y)
}

12
cmd/dep/testdata/harness_tests/init/case3/testcase.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1,12 @@
{
"commands": [
["init"]
],
"imports": {
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea"
},
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,9 @@
{
"commands": [
["remove", "-force", "github.com/sdboyer/deptestdos", "github.com/not/used"]
],
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

@ -0,0 +1,20 @@
{
"memo": "1a90a1bc14e6c5302e5c936186412f7e61e380a3b82afc54ea387f3a237843f8",
"projects": [
{
"name": "github.com/sdboyer/deptest",
"version": "v1.0.0",
"revision": "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
"packages": [
"."
]
},
{
"name": "github.com/sdboyer/deptestdos",
"revision": "a0196baa11ea047dd65037287451d36b861b00ea",
"packages": [
"."
]
}
]
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,9 @@
{
"commands": [
["remove", "github.com/not/used"]
],
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

@ -0,0 +1,13 @@
{
"memo": "ffb96eabfbb48ff1ae4f1ad2145a9e765f1e6aef7a3fbfd36a84ad875fcb3585",
"projects": [
{
"name": "github.com/sdboyer/deptest",
"version": "v1.0.0",
"revision": "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
"packages": [
"."
]
}
]
}

Просмотреть файл

@ -5,13 +5,12 @@
package main
import (
"github.com/golang/notexist/foo/bar"
"github.com/sdboyer/deptestdos"
"github.com/sdboyer/deptest"
)
func main() {
err := nil
if err != nil {
deptestdos.diMeLo(bar.Qux)
deptest.Map["yo yo!"]
}
}

Просмотреть файл

@ -0,0 +1,12 @@
{
"commands": [
["remove", "github.com/not/used"]
],
"initialVendors": {
"github.com/sdboyer/deptest": "v0.8.0",
"github.com/sdboyer/deptestdos": "a0196baa11ea047dd65037287451d36b861b00ea"
},
"finalVendors": [
"github.com/sdboyer/deptest"
]
}

Просмотреть файл

@ -0,0 +1,20 @@
{
"memo": "1a90a1bc14e6c5302e5c936186412f7e61e380a3b82afc54ea387f3a237843f8",
"projects": [
{
"name": "github.com/sdboyer/deptest",
"version": "v1.0.0",
"revision": "ff2948a2ac8f538c4ecd55962e919d1e13e74baf",
"packages": [
"."
]
},
{
"name": "github.com/sdboyer/deptestdos",
"revision": "a0196baa11ea047dd65037287451d36b861b00ea",
"packages": [
"."
]
}
]
}

Просмотреть файл

@ -0,0 +1,10 @@
{
"dependencies": {
"github.com/sdboyer/deptest": {
"version": ">=0.8.0, <1.0.0"
},
"github.com/sdboyer/deptestdos": {
"revision": "a0196baa11ea047dd65037287451d36b861b00ea"
}
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,13 @@
{
"dependencies": {
"github.com/not/used": {
"version": "2.0.0"
},
"github.com/sdboyer/deptest": {
"version": ">=0.8.0, <1.0.0"
},
"github.com/sdboyer/deptestdos": {
"revision": "a0196baa11ea047dd65037287451d36b861b00ea"
}
}
}

Просмотреть файл

@ -0,0 +1,9 @@
{
"commands": [
["remove", "-unused"]
],
"finalVendors": [
"github.com/sdboyer/deptest",
"github.com/sdboyer/deptestdos"
]
}

Просмотреть файл

@ -0,0 +1,126 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package test
import (
"encoding/json"
"flag"
"io/ioutil"
"os"
"path/filepath"
"testing"
)
var (
UpdateGolden *bool = flag.Bool("update", false, "update golden files")
)
// IntegrationTestCase manages a test case directory structure and content
type IntegrationTestCase struct {
t *testing.T
Name string
RootPath string
InitialPath string
FinalPath string
Commands [][]string `json:"commands"`
Imports map[string]string `json:"imports"`
InitialVendors map[string]string `json:"initialVendors"`
FinalVendors []string `json:"finalVendors"`
}
func NewTestCase(t *testing.T, name string) *IntegrationTestCase {
wd, err := os.Getwd()
if err != nil {
panic(err)
}
rootPath := filepath.FromSlash(filepath.Join(wd, "testdata", "harness_tests", name))
n := &IntegrationTestCase{
t: t,
Name: name,
RootPath: rootPath,
InitialPath: filepath.Join(rootPath, "initial"),
FinalPath: filepath.Join(rootPath, "final"),
}
j, err := ioutil.ReadFile(filepath.Join(rootPath, "testcase.json"))
if err != nil {
panic(err)
}
err = json.Unmarshal(j, n)
if err != nil {
panic(err)
}
return n
}
func (tc *IntegrationTestCase) CompareFile(goldenPath, working string) {
golden := filepath.Join(tc.FinalPath, goldenPath)
gotExists, got, err := getFile(working)
if err != nil {
tc.t.Fatalf("Error reading project file %s: %s", goldenPath, err)
}
wantExists, want, err := getFile(golden)
if err != nil {
tc.t.Fatalf("Error reading testcase file %s: %s", goldenPath, err)
}
if wantExists && gotExists {
if want != got {
if *UpdateGolden {
if err := tc.WriteFile(golden, got); err != nil {
tc.t.Fatal(err)
}
} else {
tc.t.Errorf("expected %s, got %s", want, got)
}
}
} else if !wantExists && gotExists {
if *UpdateGolden {
if err := tc.WriteFile(golden, got); err != nil {
tc.t.Fatal(err)
}
} else {
tc.t.Errorf("%s created where none was expected", goldenPath)
}
} else if wantExists && !gotExists {
if *UpdateGolden {
err := os.Remove(golden)
if err != nil {
tc.t.Fatal(err)
}
} else {
tc.t.Errorf("%s not created where one was expected", goldenPath)
}
}
}
func (tc *IntegrationTestCase) CompareVendorPaths(gotVendorPaths []string) {
wantVendorPaths := tc.FinalVendors
if len(gotVendorPaths) != len(wantVendorPaths) {
tc.t.Fatalf("Wrong number of vendor paths created: want %d got %d", len(wantVendorPaths), len(gotVendorPaths))
}
for ind := range gotVendorPaths {
if gotVendorPaths[ind] != wantVendorPaths[ind] {
tc.t.Errorf("Mismatch in vendor paths created: want %s got %s", gotVendorPaths, wantVendorPaths)
}
}
}
func (tc *IntegrationTestCase) WriteFile(src string, content string) error {
err := ioutil.WriteFile(src, []byte(content), 0666)
return err
}
func getFile(path string) (bool, string, error) {
_, err := os.Stat(path)
if err != nil {
return false, "", nil
}
f, err := ioutil.ReadFile(path)
if err != nil {
return true, "", err
}
return true, string(f), nil
}

Просмотреть файл

@ -0,0 +1,178 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package test
import (
"io"
"os"
"path/filepath"
"sort"
"strings"
"testing"
)
const (
ProjectRoot string = "src/github.com/golang/notexist"
)
// IntegrationTestProject manages the "virtual" test project directory structure
// and content
type IntegrationTestProject struct {
t *testing.T
h *Helper
preImports []string
}
func NewTestProject(t *testing.T, initPath string) *IntegrationTestProject {
new := &IntegrationTestProject{
t: t,
h: NewHelper(t),
}
new.TempDir(ProjectRoot)
new.TempDir(ProjectRoot, "vendor")
new.CopyTree(initPath)
new.h.Setenv("GOPATH", new.h.Path("."))
new.h.Cd(new.Path(ProjectRoot))
return new
}
func (p *IntegrationTestProject) Cleanup() {
p.h.Cleanup()
}
func (p *IntegrationTestProject) Path(args ...string) string {
return p.h.Path(filepath.Join(args...))
}
func (p *IntegrationTestProject) TempDir(args ...string) {
p.h.TempDir(filepath.Join(args...))
}
func (p *IntegrationTestProject) TempProjDir(args ...string) {
localPath := append([]string{ProjectRoot}, args...)
p.h.TempDir(filepath.Join(localPath...))
}
func (p *IntegrationTestProject) ProjPath(args ...string) string {
localPath := append([]string{ProjectRoot}, args...)
return p.Path(localPath...)
}
func (p *IntegrationTestProject) VendorPath(args ...string) string {
localPath := append([]string{ProjectRoot, "vendor"}, args...)
p.TempDir(localPath...)
return p.Path(localPath...)
}
func (p *IntegrationTestProject) RunGo(args ...string) {
p.h.RunGo(args...)
}
func (p *IntegrationTestProject) RunGit(dir string, args ...string) {
p.h.RunGit(dir, args...)
}
func (p *IntegrationTestProject) GetVendorGit(ip string) {
parse := strings.Split(ip, "/")
gitDir := strings.Join(parse[:len(parse)-1], string(filepath.Separator))
p.TempProjDir("vendor", gitDir)
p.RunGit(p.ProjPath("vendor", gitDir), "clone", "http://"+ip)
}
func (p *IntegrationTestProject) DoRun(args []string) error {
return p.h.DoRun(args)
}
func (p *IntegrationTestProject) CopyTree(src string) {
filepath.Walk(src,
func(path string, info os.FileInfo, err error) error {
if path != src {
localpath := path[len(src)+1:]
if info.IsDir() {
p.TempDir(ProjectRoot, localpath)
} else {
destpath := filepath.Join(p.ProjPath(), localpath)
copyFile(destpath, path)
}
}
return nil
})
}
func copyFile(dest, src string) {
in, err := os.Open(src)
if err != nil {
panic(err)
}
defer in.Close()
out, err := os.Create(dest)
if err != nil {
panic(err)
}
defer out.Close()
io.Copy(out, in)
}
// Collect final vendor paths at a depth of three levels
func (p *IntegrationTestProject) GetVendorPaths() []string {
vendorPath := p.ProjPath("vendor")
result := make([]string, 0)
filepath.Walk(
vendorPath,
func(path string, info os.FileInfo, err error) error {
if len(path) > len(vendorPath) && info.IsDir() {
parse := strings.Split(path[len(vendorPath)+1:], string(filepath.Separator))
if len(parse) == 3 {
result = append(result, strings.Join(parse, "/"))
return filepath.SkipDir
}
}
return nil
},
)
sort.Strings(result)
return result
}
// Collect final vendor paths at a depth of three levels
func (p *IntegrationTestProject) GetImportPaths() []string {
importPath := p.Path("src")
result := make([]string, 0)
filepath.Walk(
importPath,
func(path string, info os.FileInfo, err error) error {
if len(path) > len(importPath) && info.IsDir() {
parse := strings.Split(path[len(importPath)+1:], string(filepath.Separator))
if len(parse) == 3 {
result = append(result, strings.Join(parse, "/"))
return filepath.SkipDir
}
}
return nil
},
)
sort.Strings(result)
return result
}
func (p *IntegrationTestProject) RecordImportPaths() {
p.preImports = p.GetImportPaths()
}
// Compare import paths before and after commands
func (p *IntegrationTestProject) CompareImportPaths() {
wantImportPaths := p.preImports
gotImportPaths := p.GetImportPaths()
if len(gotImportPaths) != len(wantImportPaths) {
p.t.Fatalf("Import path count changed during command: pre %d post %d", len(wantImportPaths), len(gotImportPaths))
}
for ind := range gotImportPaths {
if gotImportPaths[ind] != wantImportPaths[ind] {
p.t.Errorf("Change in import paths during: pre %s post %s", gotImportPaths, wantImportPaths)
}
}
}

Просмотреть файл

@ -24,9 +24,9 @@ import (
)
var (
ExeSuffix string // ".exe" on Windows
mu sync.Mutex
UpdateGolden = flag.Bool("update", false, "update .golden files")
ExeSuffix string // ".exe" on Windows
mu sync.Mutex
PrintLogs *bool = flag.Bool("logs", false, "log stdin/stdout of test commands")
)
func init() {
@ -151,7 +151,9 @@ func (h *Helper) DoRun(args []string) error {
}
}
}
h.t.Logf("running testdep %v", args)
if *PrintLogs {
h.t.Logf("running testdep %v", args)
}
var prog string
if h.wd == "" {
prog = "./testdep" + ExeSuffix
@ -166,13 +168,15 @@ func (h *Helper) DoRun(args []string) error {
cmd.Stderr = &h.stderr
cmd.Env = h.env
status := cmd.Run()
if h.stdout.Len() > 0 {
h.t.Log("standard output:")
h.t.Log(h.stdout.String())
}
if h.stderr.Len() > 0 {
h.t.Log("standard error:")
h.t.Log(h.stderr.String())
if *PrintLogs {
if h.stdout.Len() > 0 {
h.t.Log("standard output:")
h.t.Log(h.stdout.String())
}
if h.stderr.Len() > 0 {
h.t.Log("standard error:")
h.t.Log(h.stderr.String())
}
}
h.ran = true
return status
@ -249,13 +253,15 @@ func (h *Helper) RunGit(dir string, args ...string) {
cmd.Dir = dir
cmd.Env = h.env
status := cmd.Run()
if h.stdout.Len() > 0 {
h.t.Logf("git %v standard output:", args)
h.t.Log(h.stdout.String())
}
if h.stderr.Len() > 0 {
h.t.Logf("git %v standard error:", args)
h.t.Log(h.stderr.String())
if *PrintLogs {
if h.stdout.Len() > 0 {
h.t.Logf("git %v standard output:", args)
h.t.Log(h.stdout.String())
}
if h.stderr.Len() > 0 {
h.t.Logf("git %v standard error:", args)
h.t.Log(h.stderr.String())
}
}
if status != nil {
h.t.Logf("git %v failed unexpectedly: %v", args, status)