File: packages_test.go

package info (click to toggle)
golang-github-mmcloughlin-avo 0.0~git20200523.4439b6b-6
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 8,304 kB
  • sloc: xml: 71,029; asm: 13,138; sh: 179; makefile: 35
file content (161 lines) | stat: -rw-r--r-- 3,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package thirdparty

import (
	"flag"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"testing"

	"github.com/mmcloughlin/avo/internal/test"
)

// Custom flags.
var (
	pkgsfilename = flag.String("pkgs", "", "packages configuration")
	preserve     = flag.Bool("preserve", false, "preserve working directories")
	latest       = flag.Bool("latest", false, "use latest versions of each package")
)

// TestPackages runs integration tests on all packages specified by packages
// file given on the command line.
func TestPackages(t *testing.T) {
	// Load packages.
	if *pkgsfilename == "" {
		t.Skip("no packages specified")
	}

	pkgs, err := LoadPackagesFile(*pkgsfilename)
	if err != nil {
		t.Fatal(err)
	}

	for _, pkg := range pkgs {
		pkg := pkg // scopelint
		t.Run(pkg.Name(), func(t *testing.T) {
			dir, clean := test.TempDir(t)
			if !*preserve {
				defer clean()
			} else {
				t.Logf("working directory: %s", dir)
			}
			pt := PackageTest{
				T:       t,
				Package: pkg,
				WorkDir: dir,
				Latest:  *latest,
			}
			pt.Run()
		})
	}
}

// PackageTest executes an integration test based on a given third-party package.
type PackageTest struct {
	*testing.T
	Package

	WorkDir string // working directory for the test
	Latest  bool   // use latest version of the package

	repopath string // path the repo is cloned to
}

// Run the test.
func (t *PackageTest) Run() {
	t.checkout()
	t.modinit()
	t.replaceavo()
	t.diff()
	t.generate()
	t.diff()
	t.test()
}

// checkout the code at the specified version.
func (t *PackageTest) checkout() {
	// Clone repo.
	dst := filepath.Join(t.WorkDir, t.Name())
	t.git("clone", "--quiet", t.CloneURL(), dst)
	t.repopath = dst

	// Checkout specific version.
	if t.Latest {
		t.Log("using latest version")
		return
	}
	t.git("-C", t.repopath, "checkout", "--quiet", t.Version)
}

// modinit initializes the repo as a go module if it isn't one already.
func (t *PackageTest) modinit() {
	// Check if module path already exists.
	gomod := filepath.Join(t.repopath, "go.mod")
	if _, err := os.Stat(gomod); err == nil {
		t.Logf("already a module")
		return
	}

	// Initialize the module.
	t.gotool("mod", "init", t.ImportPath)
}

// replaceavo points all avo dependencies to the local version.
func (t *PackageTest) replaceavo() {
	// Determine the path to avo.
	_, self, _, ok := runtime.Caller(1)
	if !ok {
		t.Fatal("failed to determine path to avo")
	}
	avodir := filepath.Join(filepath.Dir(self), "..", "..")

	// Edit all go.mod files in the repo.
	err := filepath.Walk(t.repopath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if filepath.Base(path) != "go.mod" {
			return nil
		}
		t.gotool("mod", "edit", "-replace=github.com/mmcloughlin/avo="+avodir, path)
		return nil
	})
	if err != nil {
		t.Fatal(err)
	}
}

// generate runs generate commands.
func (t *PackageTest) generate() {
	if len(t.Generate) == 0 {
		t.Fatal("no commands specified")
	}
	for _, args := range t.Generate {
		cmd := exec.Command(args[0], args[1:]...)
		cmd.Dir = filepath.Join(t.repopath, t.Dir)
		test.ExecCommand(t.T, cmd)
	}
}

// diff runs git diff on the repository.
func (t *PackageTest) diff() {
	t.git("-C", t.repopath, "diff")
}

// test runs go test.
func (t *PackageTest) test() {
	t.gotool("test", t.TestPath())
}

// git runs a git command.
func (t *PackageTest) git(arg ...string) {
	test.Exec(t.T, "git", arg...)
}

// gotool runs a go command.
func (t *PackageTest) gotool(arg ...string) {
	cmd := exec.Command(test.GoTool(), arg...)
	cmd.Dir = t.repopath
	test.ExecCommand(t.T, cmd)
}