summaryrefslogtreecommitdiff
path: root/vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go')
-rw-r--r--vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go572
1 files changed, 572 insertions, 0 deletions
diff --git a/vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go b/vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go
new file mode 100644
index 000000000..601c74d66
--- /dev/null
+++ b/vendor/github.com/onsi/ginkgo/reporters/stenographer/stenographer.go
@@ -0,0 +1,572 @@
+/*
+The stenographer is used by Ginkgo's reporters to generate output.
+
+Move along, nothing to see here.
+*/
+
+package stenographer
+
+import (
+ "fmt"
+ "io"
+ "runtime"
+ "strings"
+
+ "github.com/onsi/ginkgo/types"
+)
+
+const defaultStyle = "\x1b[0m"
+const boldStyle = "\x1b[1m"
+const redColor = "\x1b[91m"
+const greenColor = "\x1b[32m"
+const yellowColor = "\x1b[33m"
+const cyanColor = "\x1b[36m"
+const grayColor = "\x1b[90m"
+const lightGrayColor = "\x1b[37m"
+
+type cursorStateType int
+
+const (
+ cursorStateTop cursorStateType = iota
+ cursorStateStreaming
+ cursorStateMidBlock
+ cursorStateEndBlock
+)
+
+type Stenographer interface {
+ AnnounceSuite(description string, randomSeed int64, randomizingAll bool, succinct bool)
+ AnnounceAggregatedParallelRun(nodes int, succinct bool)
+ AnnounceParallelRun(node int, nodes int, succinct bool)
+ AnnounceTotalNumberOfSpecs(total int, succinct bool)
+ AnnounceNumberOfSpecs(specsToRun int, total int, succinct bool)
+ AnnounceSpecRunCompletion(summary *types.SuiteSummary, succinct bool)
+
+ AnnounceSpecWillRun(spec *types.SpecSummary)
+ AnnounceBeforeSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool)
+ AnnounceAfterSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool)
+
+ AnnounceCapturedOutput(output string)
+
+ AnnounceSuccesfulSpec(spec *types.SpecSummary)
+ AnnounceSuccesfulSlowSpec(spec *types.SpecSummary, succinct bool)
+ AnnounceSuccesfulMeasurement(spec *types.SpecSummary, succinct bool)
+
+ AnnouncePendingSpec(spec *types.SpecSummary, noisy bool)
+ AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool)
+
+ AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool)
+ AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool)
+ AnnounceSpecFailed(spec *types.SpecSummary, succinct bool, fullTrace bool)
+
+ SummarizeFailures(summaries []*types.SpecSummary)
+}
+
+func New(color bool, enableFlakes bool, writer io.Writer) Stenographer {
+ denoter := "•"
+ if runtime.GOOS == "windows" {
+ denoter = "+"
+ }
+ return &consoleStenographer{
+ color: color,
+ denoter: denoter,
+ cursorState: cursorStateTop,
+ enableFlakes: enableFlakes,
+ w: writer,
+ }
+}
+
+type consoleStenographer struct {
+ color bool
+ denoter string
+ cursorState cursorStateType
+ enableFlakes bool
+ w io.Writer
+}
+
+var alternatingColors = []string{defaultStyle, grayColor}
+
+func (s *consoleStenographer) AnnounceSuite(description string, randomSeed int64, randomizingAll bool, succinct bool) {
+ if succinct {
+ s.print(0, "[%d] %s ", randomSeed, s.colorize(boldStyle, description))
+ return
+ }
+ s.printBanner(fmt.Sprintf("Running Suite: %s", description), "=")
+ s.print(0, "Random Seed: %s", s.colorize(boldStyle, "%d", randomSeed))
+ if randomizingAll {
+ s.print(0, " - Will randomize all specs")
+ }
+ s.printNewLine()
+}
+
+func (s *consoleStenographer) AnnounceParallelRun(node int, nodes int, succinct bool) {
+ if succinct {
+ s.print(0, "- node #%d ", node)
+ return
+ }
+ s.println(0,
+ "Parallel test node %s/%s.",
+ s.colorize(boldStyle, "%d", node),
+ s.colorize(boldStyle, "%d", nodes),
+ )
+ s.printNewLine()
+}
+
+func (s *consoleStenographer) AnnounceAggregatedParallelRun(nodes int, succinct bool) {
+ if succinct {
+ s.print(0, "- %d nodes ", nodes)
+ return
+ }
+ s.println(0,
+ "Running in parallel across %s nodes",
+ s.colorize(boldStyle, "%d", nodes),
+ )
+ s.printNewLine()
+}
+
+func (s *consoleStenographer) AnnounceNumberOfSpecs(specsToRun int, total int, succinct bool) {
+ if succinct {
+ s.print(0, "- %d/%d specs ", specsToRun, total)
+ s.stream()
+ return
+ }
+ s.println(0,
+ "Will run %s of %s specs",
+ s.colorize(boldStyle, "%d", specsToRun),
+ s.colorize(boldStyle, "%d", total),
+ )
+
+ s.printNewLine()
+}
+
+func (s *consoleStenographer) AnnounceTotalNumberOfSpecs(total int, succinct bool) {
+ if succinct {
+ s.print(0, "- %d specs ", total)
+ s.stream()
+ return
+ }
+ s.println(0,
+ "Will run %s specs",
+ s.colorize(boldStyle, "%d", total),
+ )
+
+ s.printNewLine()
+}
+
+func (s *consoleStenographer) AnnounceSpecRunCompletion(summary *types.SuiteSummary, succinct bool) {
+ if succinct && summary.SuiteSucceeded {
+ s.print(0, " %s %s ", s.colorize(greenColor, "SUCCESS!"), summary.RunTime)
+ return
+ }
+ s.printNewLine()
+ color := greenColor
+ if !summary.SuiteSucceeded {
+ color = redColor
+ }
+ s.println(0, s.colorize(boldStyle+color, "Ran %d of %d Specs in %.3f seconds", summary.NumberOfSpecsThatWillBeRun, summary.NumberOfTotalSpecs, summary.RunTime.Seconds()))
+
+ status := ""
+ if summary.SuiteSucceeded {
+ status = s.colorize(boldStyle+greenColor, "SUCCESS!")
+ } else {
+ status = s.colorize(boldStyle+redColor, "FAIL!")
+ }
+
+ flakes := ""
+ if s.enableFlakes {
+ flakes = " | " + s.colorize(yellowColor+boldStyle, "%d Flaked", summary.NumberOfFlakedSpecs)
+ }
+
+ s.print(0,
+ "%s -- %s | %s | %s | %s\n",
+ status,
+ s.colorize(greenColor+boldStyle, "%d Passed", summary.NumberOfPassedSpecs),
+ s.colorize(redColor+boldStyle, "%d Failed", summary.NumberOfFailedSpecs)+flakes,
+ s.colorize(yellowColor+boldStyle, "%d Pending", summary.NumberOfPendingSpecs),
+ s.colorize(cyanColor+boldStyle, "%d Skipped", summary.NumberOfSkippedSpecs),
+ )
+}
+
+func (s *consoleStenographer) AnnounceSpecWillRun(spec *types.SpecSummary) {
+ s.startBlock()
+ for i, text := range spec.ComponentTexts[1 : len(spec.ComponentTexts)-1] {
+ s.print(0, s.colorize(alternatingColors[i%2], text)+" ")
+ }
+
+ indentation := 0
+ if len(spec.ComponentTexts) > 2 {
+ indentation = 1
+ s.printNewLine()
+ }
+ index := len(spec.ComponentTexts) - 1
+ s.print(indentation, s.colorize(boldStyle, spec.ComponentTexts[index]))
+ s.printNewLine()
+ s.print(indentation, s.colorize(lightGrayColor, spec.ComponentCodeLocations[index].String()))
+ s.printNewLine()
+ s.midBlock()
+}
+
+func (s *consoleStenographer) AnnounceBeforeSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
+ s.announceSetupFailure("BeforeSuite", summary, succinct, fullTrace)
+}
+
+func (s *consoleStenographer) AnnounceAfterSuiteFailure(summary *types.SetupSummary, succinct bool, fullTrace bool) {
+ s.announceSetupFailure("AfterSuite", summary, succinct, fullTrace)
+}
+
+func (s *consoleStenographer) announceSetupFailure(name string, summary *types.SetupSummary, succinct bool, fullTrace bool) {
+ s.startBlock()
+ var message string
+ switch summary.State {
+ case types.SpecStateFailed:
+ message = "Failure"
+ case types.SpecStatePanicked:
+ message = "Panic"
+ case types.SpecStateTimedOut:
+ message = "Timeout"
+ }
+
+ s.println(0, s.colorize(redColor+boldStyle, "%s [%.3f seconds]", message, summary.RunTime.Seconds()))
+
+ indentation := s.printCodeLocationBlock([]string{name}, []types.CodeLocation{summary.CodeLocation}, summary.ComponentType, 0, summary.State, true)
+
+ s.printNewLine()
+ s.printFailure(indentation, summary.State, summary.Failure, fullTrace)
+
+ s.endBlock()
+}
+
+func (s *consoleStenographer) AnnounceCapturedOutput(output string) {
+ if output == "" {
+ return
+ }
+
+ s.startBlock()
+ s.println(0, output)
+ s.midBlock()
+}
+
+func (s *consoleStenographer) AnnounceSuccesfulSpec(spec *types.SpecSummary) {
+ s.print(0, s.colorize(greenColor, s.denoter))
+ s.stream()
+}
+
+func (s *consoleStenographer) AnnounceSuccesfulSlowSpec(spec *types.SpecSummary, succinct bool) {
+ s.printBlockWithMessage(
+ s.colorize(greenColor, "%s [SLOW TEST:%.3f seconds]", s.denoter, spec.RunTime.Seconds()),
+ "",
+ spec,
+ succinct,
+ )
+}
+
+func (s *consoleStenographer) AnnounceSuccesfulMeasurement(spec *types.SpecSummary, succinct bool) {
+ s.printBlockWithMessage(
+ s.colorize(greenColor, "%s [MEASUREMENT]", s.denoter),
+ s.measurementReport(spec, succinct),
+ spec,
+ succinct,
+ )
+}
+
+func (s *consoleStenographer) AnnouncePendingSpec(spec *types.SpecSummary, noisy bool) {
+ if noisy {
+ s.printBlockWithMessage(
+ s.colorize(yellowColor, "P [PENDING]"),
+ "",
+ spec,
+ false,
+ )
+ } else {
+ s.print(0, s.colorize(yellowColor, "P"))
+ s.stream()
+ }
+}
+
+func (s *consoleStenographer) AnnounceSkippedSpec(spec *types.SpecSummary, succinct bool, fullTrace bool) {
+ // Skips at runtime will have a non-empty spec.Failure. All others should be succinct.
+ if succinct || spec.Failure == (types.SpecFailure{}) {
+ s.print(0, s.colorize(cyanColor, "S"))
+ s.stream()
+ } else {
+ s.startBlock()
+ s.println(0, s.colorize(cyanColor+boldStyle, "S [SKIPPING]%s [%.3f seconds]", s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds()))
+
+ indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct)
+
+ s.printNewLine()
+ s.printSkip(indentation, spec.Failure)
+ s.endBlock()
+ }
+}
+
+func (s *consoleStenographer) AnnounceSpecTimedOut(spec *types.SpecSummary, succinct bool, fullTrace bool) {
+ s.printSpecFailure(fmt.Sprintf("%s... Timeout", s.denoter), spec, succinct, fullTrace)
+}
+
+func (s *consoleStenographer) AnnounceSpecPanicked(spec *types.SpecSummary, succinct bool, fullTrace bool) {
+ s.printSpecFailure(fmt.Sprintf("%s! Panic", s.denoter), spec, succinct, fullTrace)
+}
+
+func (s *consoleStenographer) AnnounceSpecFailed(spec *types.SpecSummary, succinct bool, fullTrace bool) {
+ s.printSpecFailure(fmt.Sprintf("%s Failure", s.denoter), spec, succinct, fullTrace)
+}
+
+func (s *consoleStenographer) SummarizeFailures(summaries []*types.SpecSummary) {
+ failingSpecs := []*types.SpecSummary{}
+
+ for _, summary := range summaries {
+ if summary.HasFailureState() {
+ failingSpecs = append(failingSpecs, summary)
+ }
+ }
+
+ if len(failingSpecs) == 0 {
+ return
+ }
+
+ s.printNewLine()
+ s.printNewLine()
+ plural := "s"
+ if len(failingSpecs) == 1 {
+ plural = ""
+ }
+ s.println(0, s.colorize(redColor+boldStyle, "Summarizing %d Failure%s:", len(failingSpecs), plural))
+ for _, summary := range failingSpecs {
+ s.printNewLine()
+ if summary.HasFailureState() {
+ if summary.TimedOut() {
+ s.print(0, s.colorize(redColor+boldStyle, "[Timeout...] "))
+ } else if summary.Panicked() {
+ s.print(0, s.colorize(redColor+boldStyle, "[Panic!] "))
+ } else if summary.Failed() {
+ s.print(0, s.colorize(redColor+boldStyle, "[Fail] "))
+ }
+ s.printSpecContext(summary.ComponentTexts, summary.ComponentCodeLocations, summary.Failure.ComponentType, summary.Failure.ComponentIndex, summary.State, true)
+ s.printNewLine()
+ s.println(0, s.colorize(lightGrayColor, summary.Failure.Location.String()))
+ }
+ }
+}
+
+func (s *consoleStenographer) startBlock() {
+ if s.cursorState == cursorStateStreaming {
+ s.printNewLine()
+ s.printDelimiter()
+ } else if s.cursorState == cursorStateMidBlock {
+ s.printNewLine()
+ }
+}
+
+func (s *consoleStenographer) midBlock() {
+ s.cursorState = cursorStateMidBlock
+}
+
+func (s *consoleStenographer) endBlock() {
+ s.printDelimiter()
+ s.cursorState = cursorStateEndBlock
+}
+
+func (s *consoleStenographer) stream() {
+ s.cursorState = cursorStateStreaming
+}
+
+func (s *consoleStenographer) printBlockWithMessage(header string, message string, spec *types.SpecSummary, succinct bool) {
+ s.startBlock()
+ s.println(0, header)
+
+ indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, types.SpecComponentTypeInvalid, 0, spec.State, succinct)
+
+ if message != "" {
+ s.printNewLine()
+ s.println(indentation, message)
+ }
+
+ s.endBlock()
+}
+
+func (s *consoleStenographer) printSpecFailure(message string, spec *types.SpecSummary, succinct bool, fullTrace bool) {
+ s.startBlock()
+ s.println(0, s.colorize(redColor+boldStyle, "%s%s [%.3f seconds]", message, s.failureContext(spec.Failure.ComponentType), spec.RunTime.Seconds()))
+
+ indentation := s.printCodeLocationBlock(spec.ComponentTexts, spec.ComponentCodeLocations, spec.Failure.ComponentType, spec.Failure.ComponentIndex, spec.State, succinct)
+
+ s.printNewLine()
+ s.printFailure(indentation, spec.State, spec.Failure, fullTrace)
+ s.endBlock()
+}
+
+func (s *consoleStenographer) failureContext(failedComponentType types.SpecComponentType) string {
+ switch failedComponentType {
+ case types.SpecComponentTypeBeforeSuite:
+ return " in Suite Setup (BeforeSuite)"
+ case types.SpecComponentTypeAfterSuite:
+ return " in Suite Teardown (AfterSuite)"
+ case types.SpecComponentTypeBeforeEach:
+ return " in Spec Setup (BeforeEach)"
+ case types.SpecComponentTypeJustBeforeEach:
+ return " in Spec Setup (JustBeforeEach)"
+ case types.SpecComponentTypeAfterEach:
+ return " in Spec Teardown (AfterEach)"
+ }
+
+ return ""
+}
+
+func (s *consoleStenographer) printSkip(indentation int, spec types.SpecFailure) {
+ s.println(indentation, s.colorize(cyanColor, spec.Message))
+ s.printNewLine()
+ s.println(indentation, spec.Location.String())
+}
+
+func (s *consoleStenographer) printFailure(indentation int, state types.SpecState, failure types.SpecFailure, fullTrace bool) {
+ if state == types.SpecStatePanicked {
+ s.println(indentation, s.colorize(redColor+boldStyle, failure.Message))
+ s.println(indentation, s.colorize(redColor, failure.ForwardedPanic))
+ s.println(indentation, failure.Location.String())
+ s.printNewLine()
+ s.println(indentation, s.colorize(redColor, "Full Stack Trace"))
+ s.println(indentation, failure.Location.FullStackTrace)
+ } else {
+ s.println(indentation, s.colorize(redColor, failure.Message))
+ s.printNewLine()
+ s.println(indentation, failure.Location.String())
+ if fullTrace {
+ s.printNewLine()
+ s.println(indentation, s.colorize(redColor, "Full Stack Trace"))
+ s.println(indentation, failure.Location.FullStackTrace)
+ }
+ }
+}
+
+func (s *consoleStenographer) printSpecContext(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int {
+ startIndex := 1
+ indentation := 0
+
+ if len(componentTexts) == 1 {
+ startIndex = 0
+ }
+
+ for i := startIndex; i < len(componentTexts); i++ {
+ if (state.IsFailure() || state == types.SpecStateSkipped) && i == failedComponentIndex {
+ color := redColor
+ if state == types.SpecStateSkipped {
+ color = cyanColor
+ }
+ blockType := ""
+ switch failedComponentType {
+ case types.SpecComponentTypeBeforeSuite:
+ blockType = "BeforeSuite"
+ case types.SpecComponentTypeAfterSuite:
+ blockType = "AfterSuite"
+ case types.SpecComponentTypeBeforeEach:
+ blockType = "BeforeEach"
+ case types.SpecComponentTypeJustBeforeEach:
+ blockType = "JustBeforeEach"
+ case types.SpecComponentTypeAfterEach:
+ blockType = "AfterEach"
+ case types.SpecComponentTypeIt:
+ blockType = "It"
+ case types.SpecComponentTypeMeasure:
+ blockType = "Measurement"
+ }
+ if succinct {
+ s.print(0, s.colorize(color+boldStyle, "[%s] %s ", blockType, componentTexts[i]))
+ } else {
+ s.println(indentation, s.colorize(color+boldStyle, "%s [%s]", componentTexts[i], blockType))
+ s.println(indentation, s.colorize(grayColor, "%s", componentCodeLocations[i]))
+ }
+ } else {
+ if succinct {
+ s.print(0, s.colorize(alternatingColors[i%2], "%s ", componentTexts[i]))
+ } else {
+ s.println(indentation, componentTexts[i])
+ s.println(indentation, s.colorize(grayColor, "%s", componentCodeLocations[i]))
+ }
+ }
+ indentation++
+ }
+
+ return indentation
+}
+
+func (s *consoleStenographer) printCodeLocationBlock(componentTexts []string, componentCodeLocations []types.CodeLocation, failedComponentType types.SpecComponentType, failedComponentIndex int, state types.SpecState, succinct bool) int {
+ indentation := s.printSpecContext(componentTexts, componentCodeLocations, failedComponentType, failedComponentIndex, state, succinct)
+
+ if succinct {
+ if len(componentTexts) > 0 {
+ s.printNewLine()
+ s.print(0, s.colorize(lightGrayColor, "%s", componentCodeLocations[len(componentCodeLocations)-1]))
+ }
+ s.printNewLine()
+ indentation = 1
+ } else {
+ indentation--
+ }
+
+ return indentation
+}
+
+func (s *consoleStenographer) orderedMeasurementKeys(measurements map[string]*types.SpecMeasurement) []string {
+ orderedKeys := make([]string, len(measurements))
+ for key, measurement := range measurements {
+ orderedKeys[measurement.Order] = key
+ }
+ return orderedKeys
+}
+
+func (s *consoleStenographer) measurementReport(spec *types.SpecSummary, succinct bool) string {
+ if len(spec.Measurements) == 0 {
+ return "Found no measurements"
+ }
+
+ message := []string{}
+ orderedKeys := s.orderedMeasurementKeys(spec.Measurements)
+
+ if succinct {
+ message = append(message, fmt.Sprintf("%s samples:", s.colorize(boldStyle, "%d", spec.NumberOfSamples)))
+ for _, key := range orderedKeys {
+ measurement := spec.Measurements[key]
+ message = append(message, fmt.Sprintf(" %s - %s: %s%s, %s: %s%s ± %s%s, %s: %s%s",
+ s.colorize(boldStyle, "%s", measurement.Name),
+ measurement.SmallestLabel,
+ s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
+ measurement.Units,
+ measurement.AverageLabel,
+ s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
+ measurement.Units,
+ s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
+ measurement.Units,
+ measurement.LargestLabel,
+ s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
+ measurement.Units,
+ ))
+ }
+ } else {
+ message = append(message, fmt.Sprintf("Ran %s samples:", s.colorize(boldStyle, "%d", spec.NumberOfSamples)))
+ for _, key := range orderedKeys {
+ measurement := spec.Measurements[key]
+ info := ""
+ if measurement.Info != nil {
+ message = append(message, fmt.Sprintf("%v", measurement.Info))
+ }
+
+ message = append(message, fmt.Sprintf("%s:\n%s %s: %s%s\n %s: %s%s\n %s: %s%s ± %s%s",
+ s.colorize(boldStyle, "%s", measurement.Name),
+ info,
+ measurement.SmallestLabel,
+ s.colorize(greenColor, measurement.PrecisionFmt(), measurement.Smallest),
+ measurement.Units,
+ measurement.LargestLabel,
+ s.colorize(redColor, measurement.PrecisionFmt(), measurement.Largest),
+ measurement.Units,
+ measurement.AverageLabel,
+ s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.Average),
+ measurement.Units,
+ s.colorize(cyanColor, measurement.PrecisionFmt(), measurement.StdDeviation),
+ measurement.Units,
+ ))
+ }
+ }
+
+ return strings.Join(message, "\n")
+}