runner

package
v0.0.0-...-93ffe60 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2020 License: MIT Imports: 1 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Deps = []string{
	"bytes",
	"flag",
	"fmt",
	"io",
	"os",
	"os/exec",
	"path",
	"sort",
	"strconv",
	"testing",
	"testing/internal/testdeps",
	"time",
}
View Source
var Template = template.Must(template.New("").Parse(`// Code generated by 'gophertest'. DO NOT EDIT.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path"
	"sort"
	"strconv"
	"testing"
	"testing/internal/testdeps"
	"time"

{{range .Targets}}
{{if .ImportTest}}
	{{.TestName}} {{.ImportPath | printf "%q"}}
{{end}}
{{if .ImportXTest}}
	{{.XTestName}} {{.ImportPath | printf "%s_test" | printf "%q"}}
{{end}}
{{end}}
)

const pkgEnvName = "GOPHERTEST_PKG"
const concurrentEnvName = "GOPHERTEST_CONCURRENT"

type target struct {
	name string
	importPath string
	directory string
	tests []testing.InternalTest
	benchmarks []testing.InternalBenchmark
	examples []testing.InternalExample
	initFunc func()
	xInitFunc func()
	testMain func(*testing.M)
	complexity int64
}

var selectedTarget *target

var targets = []target{
{{range .Targets}}
	target{
		name: {{.Name | printf "%q"}},
		importPath: {{.ImportPath | printf "%q"}},
		directory: {{.Directory | printf "%q"}},

		initFunc: {{.InitFunc}},
		xInitFunc: {{.XInitFunc}},
		testMain: {{.Main}},

		complexity: {{.TestComplexity}},

		tests: []testing.InternalTest{
{{range .Tests}}
			{"{{.Name}}", {{.Package}}.{{.Name}}},
{{end}}
		},

		benchmarks: []testing.InternalBenchmark{
{{range .Benchmarks}}
			{"{{.Name}}", {{.Package}}.{{.Name}}},
{{end}}
		},
	},
{{end}}
}

func init() {
	var err error
	pkg := os.Getenv(pkgEnvName)
	if pkg == "" {
		bin := os.Args[0]
		binDir := path.Dir(bin)
		for _, t := range targets {
			if binDir == t.directory {
				selectedTarget = &t
				break
			}
		}
	}

	if selectedTarget == nil && pkg == "" {
		concurrent := 1
		if s := os.Getenv(concurrentEnvName); s != "" {
			concurrent, err = strconv.Atoi(s)
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing %q: %v", concurrentEnvName, err)
				os.Exit(1)
			}
		}
		fs := flag.NewFlagSet("gophertest", flag.ExitOnError)
		fs.IntVar(&concurrent, "c", concurrent, "test concurrency")
		fs.Usage = func() {
			fmt.Fprintf(fs.Output(), "gophertest: all arguments after -- are passed to the tests\n")
			fs.PrintDefaults()
		}
		fs.Parse(os.Args[1:])
		args := fs.Args()
		if concurrent < 0 {
			concurrent = 1
		}
		if concurrent > 1 {
			sort.Slice(targets, func(i, j int) bool {
				// Sort from most complex to least.
				return targets[i].complexity > targets[j].complexity
			})
		}
		all(concurrent, args)
	}

	if selectedTarget == nil && pkg != "" {
		for _, t := range targets {
			if t.importPath == pkg {
				selectedTarget = &t
				break
			}
		}
	}

	if selectedTarget == nil {
		selectedTarget = &target{
			importPath: pkg,
			initFunc: func(){},
			xInitFunc: func(){},
			testMain: defaultMain,
		}
	}

	testdeps.ImportPath = selectedTarget.importPath
}

func defaultMain(m *testing.M) {
	os.Exit(m.Run())
}

func main() {
	selectedTarget.initFunc()
	selectedTarget.xInitFunc()

	m := testing.MainStart(testdeps.TestDeps{}, selectedTarget.tests, selectedTarget.benchmarks, nil)
	selectedTarget.testMain(m)
}

func all(concurrent int, args []string) {
	bin := os.Args[0]
	if !path.IsAbs(bin) {
		cwd, err := os.Getwd()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		}
		bin = path.Join(cwd, bin)
	}
	slot := make(chan struct{}, concurrent)
	for i := 0; i < concurrent; i++ {
		slot <- struct{}{}
	}
	mutex := make(chan struct{}, 1)
	mutex <- struct{}{}
	exitCode := 0
	for _, v := range targets {
		t := v
		<-slot
		os.Setenv(pkgEnvName, t.importPath)
		cmdArgs := []string{}
		for _, arg := range args {
			cmdArgs = append(cmdArgs, os.ExpandEnv(arg))
		}
		wd, err := os.Stat(t.directory)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		} else if !wd.IsDir() {
			fmt.Fprintf(os.Stderr, "%q is not a directory", t.directory)
			os.Exit(1)
		}
		testBin := path.Join(t.directory, fmt.Sprintf("%s.test", t.name))
		_, err = os.Stat(testBin)
		if os.IsNotExist(err) {
		} else if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		} else {
			err = os.Remove(testBin)
			if err != nil {
				fmt.Fprintf(os.Stderr, "%v", err)
				os.Exit(1)
			}
		}
		err = os.Symlink(bin, testBin)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		}
		cmd := exec.Command(testBin, cmdArgs...)
		cmd.Dir = t.directory
		cmd.Env = os.Environ()
		buffer := &bytes.Buffer{}
		if concurrent == 1 {
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
		} else {
			cmd.Stdout = buffer
			cmd.Stderr = buffer
		}
		go func() {
			defer func() {
				err := os.Remove(testBin)
				if err != nil {
					fmt.Fprintf(os.Stderr, "%v", err)
					os.Exit(1)
				}
			}()
			start := time.Now()
			err := cmd.Run()
			failed := false
			if exitErr, ok := err.(*exec.ExitError); ok {
				failed = exitErr.ExitCode() != 0
			} else if err != nil {
				fmt.Fprintf(os.Stderr, "%v", err)
				os.Exit(1)
			}
			duration := time.Since(start).Round(time.Millisecond)
			<-mutex
			status := "ok"
			if failed {
				status = "fail"
				exitCode++
			}
			_, err = io.Copy(os.Stdout, buffer)
			if err != nil {
				fmt.Fprintf(os.Stderr, "%v", err)
				os.Exit(1)
			}
			fmt.Fprintf(os.Stdout, "%-4s\t%s\t%.3fs\n", status, t.importPath, duration.Seconds())
			mutex <- struct{}{}
			slot <- struct{}{}
		}()
	}
	for i := 0; i < concurrent; i++ {
		<-slot
	}
	os.Exit(exitCode)
}

`))

Functions

This section is empty.

Types

type Context

type Context struct {
	Targets []Target
}

type Target

type Target struct {
	ImportTest  bool
	TestName    string
	ImportXTest bool
	XTestName   string

	Name       string
	ImportPath string
	Directory  string

	InitFunc   string
	XInitFunc  string
	Main       string
	Tests      []Test
	Benchmarks []Test

	TestComplexity int64
}

type Test

type Test struct {
	Package string
	Name    string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL