Commit 129b3a1e authored by Daniel Smith's avatar Daniel Smith

bump ginkgo

parent e60df085
...@@ -31,6 +31,7 @@ type GinkgoConfigType struct { ...@@ -31,6 +31,7 @@ type GinkgoConfigType struct {
SkipMeasurements bool SkipMeasurements bool
FailOnPending bool FailOnPending bool
FailFast bool FailFast bool
FlakeAttempts int
EmitSpecProgress bool EmitSpecProgress bool
DryRun bool DryRun bool
...@@ -75,6 +76,8 @@ func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) { ...@@ -75,6 +76,8 @@ func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) {
flagSet.BoolVar(&(GinkgoConfig.RegexScansFilePath), prefix+"regexScansFilePath", false, "If set, ginkgo regex matching also will look at the file path (code location).") flagSet.BoolVar(&(GinkgoConfig.RegexScansFilePath), prefix+"regexScansFilePath", false, "If set, ginkgo regex matching also will look at the file path (code location).")
flagSet.IntVar(&(GinkgoConfig.FlakeAttempts), prefix+"flakeAttempts", 1, "Make up to this many attempts to run each spec. Please note that if any of the attempts succeed, the suite will not be failed. But any failures will still be recorded.")
flagSet.BoolVar(&(GinkgoConfig.EmitSpecProgress), prefix+"progress", false, "If set, ginkgo will emit progress information as each spec runs to the GinkgoWriter.") flagSet.BoolVar(&(GinkgoConfig.EmitSpecProgress), prefix+"progress", false, "If set, ginkgo will emit progress information as each spec runs to the GinkgoWriter.")
if includeParallelFlags { if includeParallelFlags {
...@@ -128,6 +131,10 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor ...@@ -128,6 +131,10 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor
result = append(result, fmt.Sprintf("--%sskip=%s", prefix, ginkgo.SkipString)) result = append(result, fmt.Sprintf("--%sskip=%s", prefix, ginkgo.SkipString))
} }
if ginkgo.FlakeAttempts > 1 {
result = append(result, fmt.Sprintf("--%sflakeAttempts=%d", prefix, ginkgo.FlakeAttempts))
}
if ginkgo.EmitSpecProgress { if ginkgo.EmitSpecProgress {
result = append(result, fmt.Sprintf("--%sprogress", prefix)) result = append(result, fmt.Sprintf("--%sprogress", prefix))
} }
......
...@@ -9,7 +9,7 @@ func BuildHelpCommand() *Command { ...@@ -9,7 +9,7 @@ func BuildHelpCommand() *Command {
return &Command{ return &Command{
Name: "help", Name: "help",
FlagSet: flag.NewFlagSet("help", flag.ExitOnError), FlagSet: flag.NewFlagSet("help", flag.ExitOnError),
UsageCommand: "ginkgo help <COMAND>", UsageCommand: "ginkgo help <COMMAND>",
Usage: []string{ Usage: []string{
"Print usage information. If a command is passed in, print usage information just for that command.", "Print usage information. If a command is passed in, print usage information just for that command.",
}, },
......
// +build freebsd openbsd netbsd dragonfly darwin linux // +build freebsd openbsd netbsd dragonfly darwin linux solaris
package interrupthandler package interrupthandler
......
...@@ -51,7 +51,7 @@ func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, race bool, ...@@ -51,7 +51,7 @@ func New(suite testsuite.TestSuite, numCPU int, parallelStream bool, race bool,
if !suite.Precompiled { if !suite.Precompiled {
dir, err := ioutil.TempDir("", "ginkgo") dir, err := ioutil.TempDir("", "ginkgo")
if err != nil { if err != nil {
panic(fmt.Sprintf("coulnd't create temporary directory... might be time to rm -rf:\n%s", err.Error())) panic(fmt.Sprintf("couldn't create temporary directory... might be time to rm -rf:\n%s", err.Error()))
} }
runner.compilationTargetPath = filepath.Join(dir, suite.PackageName+".test") runner.compilationTargetPath = filepath.Join(dir, suite.PackageName+".test")
} }
......
...@@ -168,6 +168,8 @@ func CurrentGinkgoTestDescription() GinkgoTestDescription { ...@@ -168,6 +168,8 @@ func CurrentGinkgoTestDescription() GinkgoTestDescription {
// //
//You use the Time() function to time how long the passed in body function takes to run //You use the Time() function to time how long the passed in body function takes to run
//You use the RecordValue() function to track arbitrary numerical measurements. //You use the RecordValue() function to track arbitrary numerical measurements.
//The RecordValueWithPrecision() function can be used alternatively to provide the unit
//and resolution of the numeric measurement.
//The optional info argument is passed to the test reporter and can be used to //The optional info argument is passed to the test reporter and can be used to
// provide the measurement data to a custom reporter with context. // provide the measurement data to a custom reporter with context.
// //
...@@ -175,6 +177,7 @@ func CurrentGinkgoTestDescription() GinkgoTestDescription { ...@@ -175,6 +177,7 @@ func CurrentGinkgoTestDescription() GinkgoTestDescription {
type Benchmarker interface { type Benchmarker interface {
Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration) Time(name string, body func(), info ...interface{}) (elapsedTime time.Duration)
RecordValue(name string, value float64, info ...interface{}) RecordValue(name string, value float64, info ...interface{})
RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{})
} }
//RunSpecs is the entry point for the Ginkgo test runner. //RunSpecs is the entry point for the Ginkgo test runner.
......
...@@ -28,20 +28,27 @@ func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elaps ...@@ -28,20 +28,27 @@ func (b *benchmarker) Time(name string, body func(), info ...interface{}) (elaps
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", info...) measurement := b.getMeasurement(name, "Fastest Time", "Slowest Time", "Average Time", "s", 3, info...)
measurement.Results = append(measurement.Results, elapsedTime.Seconds()) measurement.Results = append(measurement.Results, elapsedTime.Seconds())
return return
} }
func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) { func (b *benchmarker) RecordValue(name string, value float64, info ...interface{}) {
measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", info...) measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", "", 3, info...)
b.mu.Lock() b.mu.Lock()
defer b.mu.Unlock() defer b.mu.Unlock()
measurement.Results = append(measurement.Results, value) measurement.Results = append(measurement.Results, value)
} }
func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, info ...interface{}) *types.SpecMeasurement { func (b *benchmarker) RecordValueWithPrecision(name string, value float64, units string, precision int, info ...interface{}) {
measurement := b.getMeasurement(name, "Smallest", " Largest", " Average", units, precision, info...)
b.mu.Lock()
defer b.mu.Unlock()
measurement.Results = append(measurement.Results, value)
}
func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestLabel string, averageLabel string, units string, precision int, info ...interface{}) *types.SpecMeasurement {
measurement, ok := b.measurements[name] measurement, ok := b.measurements[name]
if !ok { if !ok {
var computedInfo interface{} var computedInfo interface{}
...@@ -57,6 +64,7 @@ func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestL ...@@ -57,6 +64,7 @@ func (b *benchmarker) getMeasurement(name string, smallestLabel string, largestL
LargestLabel: largestLabel, LargestLabel: largestLabel,
AverageLabel: averageLabel, AverageLabel: averageLabel,
Units: units, Units: units,
Precision: precision,
Results: make([]float64, 0), Results: make([]float64, 0),
} }
b.measurements[name] = measurement b.measurements[name] = measurement
......
// +build freebsd openbsd netbsd dragonfly darwin linux // +build freebsd openbsd netbsd dragonfly darwin linux solaris
package remote package remote
......
// +build solaris
package remote
import "golang.org/x/sys/unix"
func syscallDup(oldfd int, newfd int) (err error) {
return unix.Dup2(oldfd, newfd)
}
// +build !linux !arm64 // +build !linux !arm64
// +build !windows // +build !windows
// +build !solaris
package remote package remote
......
...@@ -17,9 +17,10 @@ type Spec struct { ...@@ -17,9 +17,10 @@ type Spec struct {
containers []*containernode.ContainerNode containers []*containernode.ContainerNode
state types.SpecState state types.SpecState
runTime time.Duration runTime time.Duration
failure types.SpecFailure failure types.SpecFailure
previousFailures bool
} }
func New(subject leafnodes.SubjectNode, containers []*containernode.ContainerNode, announceProgress bool) *Spec { func New(subject leafnodes.SubjectNode, containers []*containernode.ContainerNode, announceProgress bool) *Spec {
...@@ -58,6 +59,10 @@ func (spec *Spec) Passed() bool { ...@@ -58,6 +59,10 @@ func (spec *Spec) Passed() bool {
return spec.state == types.SpecStatePassed return spec.state == types.SpecStatePassed
} }
func (spec *Spec) Flaked() bool {
return spec.state == types.SpecStatePassed && spec.previousFailures
}
func (spec *Spec) Pending() bool { func (spec *Spec) Pending() bool {
return spec.state == types.SpecStatePending return spec.state == types.SpecStatePending
} }
...@@ -109,6 +114,10 @@ func (spec *Spec) ConcatenatedString() string { ...@@ -109,6 +114,10 @@ func (spec *Spec) ConcatenatedString() string {
} }
func (spec *Spec) Run(writer io.Writer) { func (spec *Spec) Run(writer io.Writer) {
if spec.state == types.SpecStateFailed {
spec.previousFailures = true
}
startTime := time.Now() startTime := time.Now()
defer func() { defer func() {
spec.runTime = time.Since(startTime) spec.runTime = time.Since(startTime)
......
...@@ -137,21 +137,20 @@ func (runner *SpecRunner) runSpecs() bool { ...@@ -137,21 +137,20 @@ func (runner *SpecRunner) runSpecs() bool {
if skipRemainingSpecs { if skipRemainingSpecs {
spec.Skip() spec.Skip()
} }
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
if !spec.Skipped() && !spec.Pending() { if !spec.Skipped() && !spec.Pending() {
runner.runningSpec = spec if passed := runner.runSpec(spec); !passed {
spec.Run(runner.writer)
runner.runningSpec = nil
if spec.Failed() {
suiteFailed = true suiteFailed = true
} }
} else if spec.Pending() && runner.config.FailOnPending { } else if spec.Pending() && runner.config.FailOnPending {
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
suiteFailed = true suiteFailed = true
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
} else {
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
} }
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
if spec.Failed() && runner.config.FailFast { if spec.Failed() && runner.config.FailFast {
skipRemainingSpecs = true skipRemainingSpecs = true
} }
...@@ -160,6 +159,26 @@ func (runner *SpecRunner) runSpecs() bool { ...@@ -160,6 +159,26 @@ func (runner *SpecRunner) runSpecs() bool {
return !suiteFailed return !suiteFailed
} }
func (runner *SpecRunner) runSpec(spec *spec.Spec) (passed bool) {
maxAttempts := 1
if runner.config.FlakeAttempts > 0 {
// uninitialized configs count as 1
maxAttempts = runner.config.FlakeAttempts
}
for i := 0; i < maxAttempts; i++ {
runner.reportSpecWillRun(spec.Summary(runner.suiteID))
runner.runningSpec = spec
spec.Run(runner.writer)
runner.runningSpec = nil
runner.reportSpecDidComplete(spec.Summary(runner.suiteID), spec.Failed())
if !spec.Failed() {
return true
}
}
return false
}
func (runner *SpecRunner) CurrentSpecSummary() (*types.SpecSummary, bool) { func (runner *SpecRunner) CurrentSpecSummary() (*types.SpecSummary, bool) {
if runner.runningSpec == nil { if runner.runningSpec == nil {
return nil, false return nil, false
...@@ -300,6 +319,10 @@ func (runner *SpecRunner) summary(success bool) *types.SuiteSummary { ...@@ -300,6 +319,10 @@ func (runner *SpecRunner) summary(success bool) *types.SuiteSummary {
return ex.Passed() return ex.Passed()
}) })
numberOfFlakedSpecs := runner.countSpecsSatisfying(func(ex *spec.Spec) bool {
return ex.Flaked()
})
numberOfFailedSpecs := runner.countSpecsSatisfying(func(ex *spec.Spec) bool { numberOfFailedSpecs := runner.countSpecsSatisfying(func(ex *spec.Spec) bool {
return ex.Failed() return ex.Failed()
}) })
...@@ -320,5 +343,6 @@ func (runner *SpecRunner) summary(success bool) *types.SuiteSummary { ...@@ -320,5 +343,6 @@ func (runner *SpecRunner) summary(success bool) *types.SuiteSummary {
NumberOfSkippedSpecs: numberOfSkippedSpecs, NumberOfSkippedSpecs: numberOfSkippedSpecs,
NumberOfPassedSpecs: numberOfPassedSpecs, NumberOfPassedSpecs: numberOfPassedSpecs,
NumberOfFailedSpecs: numberOfFailedSpecs, NumberOfFailedSpecs: numberOfFailedSpecs,
NumberOfFlakedSpecs: numberOfFlakedSpecs,
} }
} }
...@@ -506,15 +506,15 @@ func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinc ...@@ -506,15 +506,15 @@ func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinc
message = append(message, fmt.Sprintf(" %s - %s: %s%s, %s: %s%s ± %s%s, %s: %s%s", message = append(message, fmt.Sprintf(" %s - %s: %s%s, %s: %s%s ± %s%s, %s: %s%s",
s.colorize(boldStyle, "%s", measurement.Name), s.colorize(boldStyle, "%s", measurement.Name),
measurement.SmallestLabel, measurement.SmallestLabel,
s.colorize(greenColor, "%.3f", measurement.Smallest), s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
measurement.Units, measurement.Units,
measurement.AverageLabel, measurement.AverageLabel,
s.colorize(cyanColor, "%.3f", measurement.Average), s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
measurement.Units, measurement.Units,
s.colorize(cyanColor, "%.3f", measurement.StdDeviation), s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
measurement.Units, measurement.Units,
measurement.LargestLabel, measurement.LargestLabel,
s.colorize(redColor, "%.3f", measurement.Largest), s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
measurement.Units, measurement.Units,
)) ))
} }
...@@ -531,15 +531,15 @@ func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinc ...@@ -531,15 +531,15 @@ func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinc
s.colorize(boldStyle, "%s", measurement.Name), s.colorize(boldStyle, "%s", measurement.Name),
info, info,
measurement.SmallestLabel, measurement.SmallestLabel,
s.colorize(greenColor, "%.3f", measurement.Smallest), s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
measurement.Units, measurement.Units,
measurement.LargestLabel, measurement.LargestLabel,
s.colorize(redColor, "%.3f", measurement.Largest), s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
measurement.Units, measurement.Units,
measurement.AverageLabel, measurement.AverageLabel,
s.colorize(cyanColor, "%.3f", measurement.Average), s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
measurement.Units, measurement.Units,
s.colorize(cyanColor, "%.3f", measurement.StdDeviation), s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
measurement.Units, measurement.Units,
)) ))
} }
......
package types package types
import "time" import (
"strconv"
"time"
)
const GINKGO_FOCUS_EXIT_CODE = 197 const GINKGO_FOCUS_EXIT_CODE = 197
...@@ -16,7 +19,10 @@ type SuiteSummary struct { ...@@ -16,7 +19,10 @@ type SuiteSummary struct {
NumberOfSkippedSpecs int NumberOfSkippedSpecs int
NumberOfPassedSpecs int NumberOfPassedSpecs int
NumberOfFailedSpecs int NumberOfFailedSpecs int
RunTime time.Duration // Flaked specs are those that failed initially, but then passed on a
// subsequent try.
NumberOfFlakedSpecs int
RunTime time.Duration
} }
type SpecSummary struct { type SpecSummary struct {
...@@ -100,6 +106,17 @@ type SpecMeasurement struct { ...@@ -100,6 +106,17 @@ type SpecMeasurement struct {
LargestLabel string LargestLabel string
AverageLabel string AverageLabel string
Units string Units string
Precision int
}
func (s SpecMeasurement) PrecisionFmt() string {
if s.Precision == 0 {
return "%f"
}
str := strconv.Itoa(s.Precision)
return "%." + str + "f"
} }
type SpecState uint type SpecState uint
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment