cloudflared-mirror/vendor/github.com/onsi/ginkgo/ginkgo/watch_command.go

176 lines
5.4 KiB
Go

package main
import (
"flag"
"fmt"
"regexp"
"time"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/ginkgo/interrupthandler"
"github.com/onsi/ginkgo/ginkgo/testrunner"
"github.com/onsi/ginkgo/ginkgo/testsuite"
"github.com/onsi/ginkgo/ginkgo/watch"
colorable "github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable"
)
func BuildWatchCommand() *Command {
commandFlags := NewWatchCommandFlags(flag.NewFlagSet("watch", flag.ExitOnError))
interruptHandler := interrupthandler.NewInterruptHandler()
notifier := NewNotifier(commandFlags)
watcher := &SpecWatcher{
commandFlags: commandFlags,
notifier: notifier,
interruptHandler: interruptHandler,
suiteRunner: NewSuiteRunner(notifier, interruptHandler),
}
return &Command{
Name: "watch",
FlagSet: commandFlags.FlagSet,
UsageCommand: "ginkgo watch <FLAGS> <PACKAGES> -- <PASS-THROUGHS>",
Usage: []string{
"Watches the tests in the passed in <PACKAGES> and runs them when changes occur.",
"Any arguments after -- will be passed to the test.",
},
Command: watcher.WatchSpecs,
SuppressFlagDocumentation: true,
FlagDocSubstitute: []string{
"Accepts all the flags that the ginkgo command accepts except for --keepGoing and --untilItFails",
},
}
}
type SpecWatcher struct {
commandFlags *RunWatchAndBuildCommandFlags
notifier *Notifier
interruptHandler *interrupthandler.InterruptHandler
suiteRunner *SuiteRunner
}
func (w *SpecWatcher) WatchSpecs(args []string, additionalArgs []string) {
w.commandFlags.computeNodes()
w.notifier.VerifyNotificationsAreAvailable()
w.WatchSuites(args, additionalArgs)
}
func (w *SpecWatcher) runnersForSuites(suites []testsuite.TestSuite, additionalArgs []string) []*testrunner.TestRunner {
runners := []*testrunner.TestRunner{}
for _, suite := range suites {
runners = append(runners, testrunner.New(suite, w.commandFlags.NumCPU, w.commandFlags.ParallelStream, w.commandFlags.Timeout, w.commandFlags.GoOpts, additionalArgs))
}
return runners
}
func (w *SpecWatcher) WatchSuites(args []string, additionalArgs []string) {
suites, _ := findSuites(args, w.commandFlags.Recurse, w.commandFlags.SkipPackage, false)
if len(suites) == 0 {
complainAndQuit("Found no test suites")
}
fmt.Printf("Identified %d test %s. Locating dependencies to a depth of %d (this may take a while)...\n", len(suites), pluralizedWord("suite", "suites", len(suites)), w.commandFlags.Depth)
deltaTracker := watch.NewDeltaTracker(w.commandFlags.Depth, regexp.MustCompile(w.commandFlags.WatchRegExp))
delta, errors := deltaTracker.Delta(suites)
fmt.Printf("Watching %d %s:\n", len(delta.NewSuites), pluralizedWord("suite", "suites", len(delta.NewSuites)))
for _, suite := range delta.NewSuites {
fmt.Println(" " + suite.Description())
}
for suite, err := range errors {
fmt.Printf("Failed to watch %s: %s\n", suite.PackageName, err)
}
if len(suites) == 1 {
runners := w.runnersForSuites(suites, additionalArgs)
w.suiteRunner.RunSuites(runners, w.commandFlags.NumCompilers, true, nil)
runners[0].CleanUp()
}
ticker := time.NewTicker(time.Second)
for {
select {
case <-ticker.C:
suites, _ := findSuites(args, w.commandFlags.Recurse, w.commandFlags.SkipPackage, false)
delta, _ := deltaTracker.Delta(suites)
coloredStream := colorable.NewColorableStdout()
suitesToRun := []testsuite.TestSuite{}
if len(delta.NewSuites) > 0 {
fmt.Fprintf(coloredStream, greenColor+"Detected %d new %s:\n"+defaultStyle, len(delta.NewSuites), pluralizedWord("suite", "suites", len(delta.NewSuites)))
for _, suite := range delta.NewSuites {
suitesToRun = append(suitesToRun, suite.Suite)
fmt.Fprintln(coloredStream, " "+suite.Description())
}
}
modifiedSuites := delta.ModifiedSuites()
if len(modifiedSuites) > 0 {
fmt.Fprintln(coloredStream, greenColor+"\nDetected changes in:"+defaultStyle)
for _, pkg := range delta.ModifiedPackages {
fmt.Fprintln(coloredStream, " "+pkg)
}
fmt.Fprintf(coloredStream, greenColor+"Will run %d %s:\n"+defaultStyle, len(modifiedSuites), pluralizedWord("suite", "suites", len(modifiedSuites)))
for _, suite := range modifiedSuites {
suitesToRun = append(suitesToRun, suite.Suite)
fmt.Fprintln(coloredStream, " "+suite.Description())
}
fmt.Fprintln(coloredStream, "")
}
if len(suitesToRun) > 0 {
w.UpdateSeed()
w.ComputeSuccinctMode(len(suitesToRun))
runners := w.runnersForSuites(suitesToRun, additionalArgs)
result, _ := w.suiteRunner.RunSuites(runners, w.commandFlags.NumCompilers, true, func(suite testsuite.TestSuite) {
deltaTracker.WillRun(suite)
})
for _, runner := range runners {
runner.CleanUp()
}
if !w.interruptHandler.WasInterrupted() {
color := redColor
if result.Passed {
color = greenColor
}
fmt.Fprintln(coloredStream, color+"\nDone. Resuming watch..."+defaultStyle)
}
}
case <-w.interruptHandler.C:
return
}
}
}
func (w *SpecWatcher) ComputeSuccinctMode(numSuites int) {
if config.DefaultReporterConfig.Verbose {
config.DefaultReporterConfig.Succinct = false
return
}
if w.commandFlags.wasSet("succinct") {
return
}
if numSuites == 1 {
config.DefaultReporterConfig.Succinct = false
}
if numSuites > 1 {
config.DefaultReporterConfig.Succinct = true
}
}
func (w *SpecWatcher) UpdateSeed() {
if !w.commandFlags.wasSet("seed") {
config.GinkgoConfig.RandomSeed = time.Now().Unix()
}
}