diff --git a/main.go b/main.go index 446d3a9c..dd79661b 100644 --- a/main.go +++ b/main.go @@ -177,7 +177,7 @@ func Build(pkgName, outpath string, options *compileopts.Options) error { // Test runs the tests in the given package. Returns whether the test passed and // possibly an error if the test failed to run. -func Test(pkgName string, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, outpath string) (bool, error) { +func Test(pkgName string, options *compileopts.Options, testCompileOnly, testVerbose, testShort bool, testRunRegexp string, outpath string) (bool, error) { options.TestConfig.CompileTestBinary = true config, err := builder.NewConfig(options) if err != nil { @@ -203,7 +203,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly, testVer // Run the test. start := time.Now() var err error - passed, err = runPackageTest(config, result, testVerbose, testShort) + passed, err = runPackageTest(config, result, testVerbose, testShort, testRunRegexp) if err != nil { return err } @@ -229,7 +229,7 @@ func Test(pkgName string, options *compileopts.Options, testCompileOnly, testVer // runPackageTest runs a test binary that was previously built. The return // values are whether the test passed and any errors encountered while trying to // run the binary. -func runPackageTest(config *compileopts.Config, result builder.BuildResult, testVerbose, testShort bool) (bool, error) { +func runPackageTest(config *compileopts.Config, result builder.BuildResult, testVerbose, testShort bool, testRunRegexp string) (bool, error) { var cmd *exec.Cmd if len(config.Target.Emulator) == 0 { // Run directly. @@ -240,6 +240,9 @@ func runPackageTest(config *compileopts.Config, result builder.BuildResult, test if testShort { flags = append(flags, "-test.short") } + if testRunRegexp != "" { + flags = append(flags, "-test.run="+testRunRegexp) + } cmd = executeCommand(config.Options, result.Binary, flags...) cmd.Dir = result.MainDir } else { @@ -255,6 +258,9 @@ func runPackageTest(config *compileopts.Config, result builder.BuildResult, test if testShort { args = append(args, "-test.short") } + if testRunRegexp != "" { + args = append(args, "-test.run="+testRunRegexp) + } } cmd = executeCommand(config.Options, config.Target.Emulator[0], args...) } @@ -1150,10 +1156,12 @@ func main() { flag.StringVar(&outpath, "o", "", "output filename") } var testCompileOnlyFlag, testVerboseFlag, testShortFlag *bool + var testRunRegexp *string if command == "help" || command == "test" { testCompileOnlyFlag = flag.Bool("c", false, "compile the test binary but do not run it") testVerboseFlag = flag.Bool("v", false, "verbose: print additional output") testShortFlag = flag.Bool("short", false, "short: run smaller test suite to save time") + testRunRegexp = flag.String("run", "", "run: regexp of tests to run") } // Early command processing, before commands are interpreted by the Go flag @@ -1336,7 +1344,7 @@ func main() { allTestsPassed := true for _, pkgName := range pkgNames { // TODO: parallelize building the test binaries - passed, err := Test(pkgName, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, outpath) + passed, err := Test(pkgName, options, *testCompileOnlyFlag, *testVerboseFlag, *testShortFlag, *testRunRegexp, outpath) handleCompilerError(err) if !passed { allTestsPassed = false diff --git a/src/testing/testing.go b/src/testing/testing.go index 4f12b3d1..fe1fb83d 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -18,8 +18,9 @@ import ( // Testing flags. var ( - flagVerbose bool - flagShort bool + flagVerbose bool + flagShort bool + flagRunRegexp string ) var initRan bool @@ -33,6 +34,7 @@ func Init() { flag.BoolVar(&flagVerbose, "test.v", false, "verbose: print additional output") flag.BoolVar(&flagShort, "test.short", false, "short: run smaller test suite to save time") + flag.StringVar(&flagRunRegexp, "test.run", "", "run: regexp of tests to run") } // common holds the elements common between T and B and @@ -242,19 +244,42 @@ type InternalTest struct { type M struct { // tests is a list of the test names to execute Tests []InternalTest + + deps testDeps } // Run the test suite. func (m *M) Run() int { - if len(m.Tests) == 0 { - fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") - } if !flag.Parsed() { flag.Parse() } failures := 0 + if flagRunRegexp != "" { + var filtered []InternalTest + + // pre-test the regexp; we don't want to bother logging one failure for every test name if the regexp is broken + if _, err := m.deps.MatchString(flagRunRegexp, "some-test-name"); err != nil { + fmt.Println("testing: invalid regexp for -test.run:", err.Error()) + failures++ + } + + // filter the list of tests before we try to run them + for _, test := range m.Tests { + // ignore the error; we already tested that the regexp compiles fine above + if match, _ := m.deps.MatchString(flagRunRegexp, test.Name); match { + filtered = append(filtered, test) + } + } + + m.Tests = filtered + } + + if len(m.Tests) == 0 { + fmt.Fprintln(os.Stderr, "testing: warning: no tests to run") + } + for _, test := range m.Tests { t := &T{ common: common{ @@ -326,10 +351,15 @@ func TestMain(m *M) { os.Exit(m.Run()) } +type testDeps interface { + MatchString(pat, s string) (bool, error) +} + func MainStart(deps interface{}, tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) *M { Init() return &M{ Tests: tests, + deps: deps.(testDeps), } } diff --git a/testdata/testing.go b/testdata/testing.go index ba952f34..6b549da8 100644 --- a/testdata/testing.go +++ b/testdata/testing.go @@ -34,9 +34,13 @@ var benchmarks = []testing.InternalBenchmark{} var examples = []testing.InternalExample{} func main() { - m := testing.MainStart(nil, tests, benchmarks, examples) + m := testing.MainStart(testdeps{}, tests, benchmarks, examples) exitcode := m.Run() if exitcode != 0 { println("exitcode:", exitcode) } } + +type testdeps struct{} + +func (testdeps) MatchString(pat, str string) (bool, error) { return true, nil }