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)
}
|