diff options
Diffstat (limited to 'vendor/github.com/smartystreets/goconvey/convey/reporting')
13 files changed, 817 insertions, 0 deletions
diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go new file mode 100644 index 0000000..7bf67db --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/console.go @@ -0,0 +1,16 @@ +package reporting + +import ( + "fmt" + "io" +) + +type console struct{} + +func (self *console) Write(p []byte) (n int, err error) { + return fmt.Print(string(p)) +} + +func NewConsole() io.Writer { + return new(console) +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go new file mode 100644 index 0000000..a37d001 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/doc.go @@ -0,0 +1,5 @@ +// Package reporting contains internal functionality related +// to console reporting and output. Although this package has +// exported names is not intended for public consumption. See the +// examples package for how to use this project. +package reporting diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go new file mode 100644 index 0000000..47d57c6 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/dot.go @@ -0,0 +1,40 @@ +package reporting + +import "fmt" + +type dot struct{ out *Printer } + +func (self *dot) BeginStory(story *StoryReport) {} + +func (self *dot) Enter(scope *ScopeReport) {} + +func (self *dot) Report(report *AssertionResult) { + if report.Error != nil { + fmt.Print(redColor) + self.out.Insert(dotError) + } else if report.Failure != "" { + fmt.Print(yellowColor) + self.out.Insert(dotFailure) + } else if report.Skipped { + fmt.Print(yellowColor) + self.out.Insert(dotSkip) + } else { + fmt.Print(greenColor) + self.out.Insert(dotSuccess) + } + fmt.Print(resetColor) +} + +func (self *dot) Exit() {} + +func (self *dot) EndStory() {} + +func (self *dot) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewDotReporter(out *Printer) *dot { + self := new(dot) + self.out = out + return self +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go new file mode 100644 index 0000000..c396e16 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/gotest.go @@ -0,0 +1,33 @@ +package reporting + +type gotestReporter struct{ test T } + +func (self *gotestReporter) BeginStory(story *StoryReport) { + self.test = story.Test +} + +func (self *gotestReporter) Enter(scope *ScopeReport) {} + +func (self *gotestReporter) Report(r *AssertionResult) { + if !passed(r) { + self.test.Fail() + } +} + +func (self *gotestReporter) Exit() {} + +func (self *gotestReporter) EndStory() { + self.test = nil +} + +func (self *gotestReporter) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewGoTestReporter() *gotestReporter { + return new(gotestReporter) +} + +func passed(r *AssertionResult) bool { + return r.Error == nil && r.Failure == "" +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go new file mode 100644 index 0000000..99c3bd6 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/init.go @@ -0,0 +1,94 @@ +package reporting + +import ( + "os" + "runtime" + "strings" +) + +func init() { + if !isColorableTerminal() { + monochrome() + } + + if runtime.GOOS == "windows" { + success, failure, error_ = dotSuccess, dotFailure, dotError + } +} + +func BuildJsonReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewJsonReporter(out)) +} +func BuildDotReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewDotReporter(out), + NewProblemReporter(out), + consoleStatistics) +} +func BuildStoryReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewStoryReporter(out), + NewProblemReporter(out), + consoleStatistics) +} +func BuildSilentReporter() Reporter { + out := NewPrinter(NewConsole()) + return NewReporters( + NewGoTestReporter(), + NewSilentProblemReporter(out)) +} + +var ( + newline = "\n" + success = "✔" + failure = "✘" + error_ = "🔥" + skip = "⚠" + dotSuccess = "." + dotFailure = "x" + dotError = "E" + dotSkip = "S" + errorTemplate = "* %s \nLine %d: - %v \n%s\n" + failureTemplate = "* %s \nLine %d:\n%s\n%s\n" +) + +var ( + greenColor = "\033[32m" + yellowColor = "\033[33m" + redColor = "\033[31m" + resetColor = "\033[0m" +) + +var consoleStatistics = NewStatisticsReporter(NewPrinter(NewConsole())) + +func SuppressConsoleStatistics() { consoleStatistics.Suppress() } +func PrintConsoleStatistics() { consoleStatistics.PrintSummary() } + +// QuietMode disables all console output symbols. This is only meant to be used +// for tests that are internal to goconvey where the output is distracting or +// otherwise not needed in the test output. +func QuietMode() { + success, failure, error_, skip, dotSuccess, dotFailure, dotError, dotSkip = "", "", "", "", "", "", "", "" +} + +func monochrome() { + greenColor, yellowColor, redColor, resetColor = "", "", "", "" +} + +func isColorableTerminal() bool { + return strings.Contains(os.Getenv("TERM"), "color") +} + +// This interface allows us to pass the *testing.T struct +// throughout the internals of this tool without ever +// having to import the "testing" package. +type T interface { + Fail() +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go new file mode 100644 index 0000000..f852697 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/json.go @@ -0,0 +1,88 @@ +// TODO: under unit test + +package reporting + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" +) + +type JsonReporter struct { + out *Printer + currentKey []string + current *ScopeResult + index map[string]*ScopeResult + scopes []*ScopeResult +} + +func (self *JsonReporter) depth() int { return len(self.currentKey) } + +func (self *JsonReporter) BeginStory(story *StoryReport) {} + +func (self *JsonReporter) Enter(scope *ScopeReport) { + self.currentKey = append(self.currentKey, scope.Title) + ID := strings.Join(self.currentKey, "|") + if _, found := self.index[ID]; !found { + next := newScopeResult(scope.Title, self.depth(), scope.File, scope.Line) + self.scopes = append(self.scopes, next) + self.index[ID] = next + } + self.current = self.index[ID] +} + +func (self *JsonReporter) Report(report *AssertionResult) { + self.current.Assertions = append(self.current.Assertions, report) +} + +func (self *JsonReporter) Exit() { + self.currentKey = self.currentKey[:len(self.currentKey)-1] +} + +func (self *JsonReporter) EndStory() { + self.report() + self.reset() +} +func (self *JsonReporter) report() { + scopes := []string{} + for _, scope := range self.scopes { + serialized, err := json.Marshal(scope) + if err != nil { + self.out.Println(jsonMarshalFailure) + panic(err) + } + var buffer bytes.Buffer + json.Indent(&buffer, serialized, "", " ") + scopes = append(scopes, buffer.String()) + } + self.out.Print(fmt.Sprintf("%s\n%s,\n%s\n", OpenJson, strings.Join(scopes, ","), CloseJson)) +} +func (self *JsonReporter) reset() { + self.scopes = []*ScopeResult{} + self.index = map[string]*ScopeResult{} + self.currentKey = nil +} + +func (self *JsonReporter) Write(content []byte) (written int, err error) { + self.current.Output += string(content) + return len(content), nil +} + +func NewJsonReporter(out *Printer) *JsonReporter { + self := new(JsonReporter) + self.out = out + self.reset() + return self +} + +const OpenJson = ">->->OPEN-JSON->->->" // "⌦" +const CloseJson = "<-<-<-CLOSE-JSON<-<-<" // "⌫" +const jsonMarshalFailure = ` + +GOCONVEY_JSON_MARSHALL_FAILURE: There was an error when attempting to convert test results to JSON. +Please file a bug report and reference the code that caused this failure if possible. + +Here's the panic: + +` diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go new file mode 100644 index 0000000..3dac0d4 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/printer.go @@ -0,0 +1,60 @@ +package reporting + +import ( + "fmt" + "io" + "strings" +) + +type Printer struct { + out io.Writer + prefix string +} + +func (self *Printer) Println(message string, values ...interface{}) { + formatted := self.format(message, values...) + newline + self.out.Write([]byte(formatted)) +} + +func (self *Printer) Print(message string, values ...interface{}) { + formatted := self.format(message, values...) + self.out.Write([]byte(formatted)) +} + +func (self *Printer) Insert(text string) { + self.out.Write([]byte(text)) +} + +func (self *Printer) format(message string, values ...interface{}) string { + var formatted string + if len(values) == 0 { + formatted = self.prefix + message + } else { + formatted = self.prefix + fmt_Sprintf(message, values...) + } + indented := strings.Replace(formatted, newline, newline+self.prefix, -1) + return strings.TrimRight(indented, space) +} + +// Extracting fmt.Sprintf to a separate variable circumvents go vet, which, as of go 1.10 is run with go test. +var fmt_Sprintf = fmt.Sprintf + +func (self *Printer) Indent() { + self.prefix += pad +} + +func (self *Printer) Dedent() { + if len(self.prefix) >= padLength { + self.prefix = self.prefix[:len(self.prefix)-padLength] + } +} + +func NewPrinter(out io.Writer) *Printer { + self := new(Printer) + self.out = out + return self +} + +const space = " " +const pad = space + space +const padLength = len(pad) diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go new file mode 100644 index 0000000..33d5e14 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/problems.go @@ -0,0 +1,80 @@ +package reporting + +import "fmt" + +type problem struct { + silent bool + out *Printer + errors []*AssertionResult + failures []*AssertionResult +} + +func (self *problem) BeginStory(story *StoryReport) {} + +func (self *problem) Enter(scope *ScopeReport) {} + +func (self *problem) Report(report *AssertionResult) { + if report.Error != nil { + self.errors = append(self.errors, report) + } else if report.Failure != "" { + self.failures = append(self.failures, report) + } +} + +func (self *problem) Exit() {} + +func (self *problem) EndStory() { + self.show(self.showErrors, redColor) + self.show(self.showFailures, yellowColor) + self.prepareForNextStory() +} +func (self *problem) show(display func(), color string) { + if !self.silent { + fmt.Print(color) + } + display() + if !self.silent { + fmt.Print(resetColor) + } + self.out.Dedent() +} +func (self *problem) showErrors() { + for i, e := range self.errors { + if i == 0 { + self.out.Println("\nErrors:\n") + self.out.Indent() + } + self.out.Println(errorTemplate, e.File, e.Line, e.Error, e.StackTrace) + } +} +func (self *problem) showFailures() { + for i, f := range self.failures { + if i == 0 { + self.out.Println("\nFailures:\n") + self.out.Indent() + } + self.out.Println(failureTemplate, f.File, f.Line, f.Failure, f.StackTrace) + } +} + +func (self *problem) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewProblemReporter(out *Printer) *problem { + self := new(problem) + self.out = out + self.prepareForNextStory() + return self +} + +func NewSilentProblemReporter(out *Printer) *problem { + self := NewProblemReporter(out) + self.silent = true + return self +} + +func (self *problem) prepareForNextStory() { + self.errors = []*AssertionResult{} + self.failures = []*AssertionResult{} +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go new file mode 100644 index 0000000..cce6c5e --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporter.go @@ -0,0 +1,39 @@ +package reporting + +import "io" + +type Reporter interface { + BeginStory(story *StoryReport) + Enter(scope *ScopeReport) + Report(r *AssertionResult) + Exit() + EndStory() + io.Writer +} + +type reporters struct{ collection []Reporter } + +func (self *reporters) BeginStory(s *StoryReport) { self.foreach(func(r Reporter) { r.BeginStory(s) }) } +func (self *reporters) Enter(s *ScopeReport) { self.foreach(func(r Reporter) { r.Enter(s) }) } +func (self *reporters) Report(a *AssertionResult) { self.foreach(func(r Reporter) { r.Report(a) }) } +func (self *reporters) Exit() { self.foreach(func(r Reporter) { r.Exit() }) } +func (self *reporters) EndStory() { self.foreach(func(r Reporter) { r.EndStory() }) } + +func (self *reporters) Write(contents []byte) (written int, err error) { + self.foreach(func(r Reporter) { + written, err = r.Write(contents) + }) + return written, err +} + +func (self *reporters) foreach(action func(Reporter)) { + for _, r := range self.collection { + action(r) + } +} + +func NewReporters(collection ...Reporter) *reporters { + self := new(reporters) + self.collection = collection + return self +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey new file mode 100644 index 0000000..7998285 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reporting.goconvey @@ -0,0 +1,2 @@ +#ignore +-timeout=1s diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go new file mode 100644 index 0000000..712e6ad --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/reports.go @@ -0,0 +1,179 @@ +package reporting + +import ( + "encoding/json" + "fmt" + "runtime" + "strings" + + "github.com/smartystreets/goconvey/convey/gotest" +) + +////////////////// ScopeReport //////////////////// + +type ScopeReport struct { + Title string + File string + Line int +} + +func NewScopeReport(title string) *ScopeReport { + file, line, _ := gotest.ResolveExternalCaller() + self := new(ScopeReport) + self.Title = title + self.File = file + self.Line = line + return self +} + +////////////////// ScopeResult //////////////////// + +type ScopeResult struct { + Title string + File string + Line int + Depth int + Assertions []*AssertionResult + Output string +} + +func newScopeResult(title string, depth int, file string, line int) *ScopeResult { + self := new(ScopeResult) + self.Title = title + self.Depth = depth + self.File = file + self.Line = line + self.Assertions = []*AssertionResult{} + return self +} + +/////////////////// StoryReport ///////////////////// + +type StoryReport struct { + Test T + Name string + File string + Line int +} + +func NewStoryReport(test T) *StoryReport { + file, line, name := gotest.ResolveExternalCaller() + name = removePackagePath(name) + self := new(StoryReport) + self.Test = test + self.Name = name + self.File = file + self.Line = line + return self +} + +// name comes in looking like "github.com/smartystreets/goconvey/examples.TestName". +// We only want the stuff after the last '.', which is the name of the test function. +func removePackagePath(name string) string { + parts := strings.Split(name, ".") + return parts[len(parts)-1] +} + +/////////////////// FailureView //////////////////////// + +// This struct is also declared in github.com/smartystreets/assertions. +// The json struct tags should be equal in both declarations. +type FailureView struct { + Message string `json:"Message"` + Expected string `json:"Expected"` + Actual string `json:"Actual"` +} + +////////////////////AssertionResult ////////////////////// + +type AssertionResult struct { + File string + Line int + Expected string + Actual string + Failure string + Error interface{} + StackTrace string + Skipped bool +} + +func NewFailureReport(failure string) *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = stackTrace() + parseFailure(failure, report) + return report +} +func parseFailure(failure string, report *AssertionResult) { + view := new(FailureView) + err := json.Unmarshal([]byte(failure), view) + if err == nil { + report.Failure = view.Message + report.Expected = view.Expected + report.Actual = view.Actual + } else { + report.Failure = failure + } +} +func NewErrorReport(err interface{}) *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = fullStackTrace() + report.Error = fmt.Sprintf("%v", err) + return report +} +func NewSuccessReport() *AssertionResult { + return new(AssertionResult) +} +func NewSkipReport() *AssertionResult { + report := new(AssertionResult) + report.File, report.Line = caller() + report.StackTrace = fullStackTrace() + report.Skipped = true + return report +} + +func caller() (file string, line int) { + file, line, _ = gotest.ResolveExternalCaller() + return +} + +func stackTrace() string { + buffer := make([]byte, 1024*64) + n := runtime.Stack(buffer, false) + return removeInternalEntries(string(buffer[:n])) +} +func fullStackTrace() string { + buffer := make([]byte, 1024*64) + n := runtime.Stack(buffer, true) + return removeInternalEntries(string(buffer[:n])) +} +func removeInternalEntries(stack string) string { + lines := strings.Split(stack, newline) + filtered := []string{} + for _, line := range lines { + if !isExternal(line) { + filtered = append(filtered, line) + } + } + return strings.Join(filtered, newline) +} +func isExternal(line string) bool { + for _, p := range internalPackages { + if strings.Contains(line, p) { + return true + } + } + return false +} + +// NOTE: any new packages that host goconvey packages will need to be added here! +// An alternative is to scan the goconvey directory and then exclude stuff like +// the examples package but that's nasty too. +var internalPackages = []string{ + "goconvey/assertions", + "goconvey/convey", + "goconvey/execution", + "goconvey/gotest", + "goconvey/reporting", +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go new file mode 100644 index 0000000..c3ccd05 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/statistics.go @@ -0,0 +1,108 @@ +package reporting + +import ( + "fmt" + "sync" +) + +func (self *statistics) BeginStory(story *StoryReport) {} + +func (self *statistics) Enter(scope *ScopeReport) {} + +func (self *statistics) Report(report *AssertionResult) { + self.Lock() + defer self.Unlock() + + if !self.failing && report.Failure != "" { + self.failing = true + } + if !self.erroring && report.Error != nil { + self.erroring = true + } + if report.Skipped { + self.skipped += 1 + } else { + self.total++ + } +} + +func (self *statistics) Exit() {} + +func (self *statistics) EndStory() { + self.Lock() + defer self.Unlock() + + if !self.suppressed { + self.printSummaryLocked() + } +} + +func (self *statistics) Suppress() { + self.Lock() + defer self.Unlock() + self.suppressed = true +} + +func (self *statistics) PrintSummary() { + self.Lock() + defer self.Unlock() + self.printSummaryLocked() +} + +func (self *statistics) printSummaryLocked() { + self.reportAssertionsLocked() + self.reportSkippedSectionsLocked() + self.completeReportLocked() +} +func (self *statistics) reportAssertionsLocked() { + self.decideColorLocked() + self.out.Print("\n%d total %s", self.total, plural("assertion", self.total)) +} +func (self *statistics) decideColorLocked() { + if self.failing && !self.erroring { + fmt.Print(yellowColor) + } else if self.erroring { + fmt.Print(redColor) + } else { + fmt.Print(greenColor) + } +} +func (self *statistics) reportSkippedSectionsLocked() { + if self.skipped > 0 { + fmt.Print(yellowColor) + self.out.Print(" (one or more sections skipped)") + } +} +func (self *statistics) completeReportLocked() { + fmt.Print(resetColor) + self.out.Print("\n") + self.out.Print("\n") +} + +func (self *statistics) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewStatisticsReporter(out *Printer) *statistics { + self := statistics{} + self.out = out + return &self +} + +type statistics struct { + sync.Mutex + + out *Printer + total int + failing bool + erroring bool + skipped int + suppressed bool +} + +func plural(word string, count int) string { + if count == 1 { + return word + } + return word + "s" +} diff --git a/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go b/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go new file mode 100644 index 0000000..9e73c97 --- /dev/null +++ b/vendor/github.com/smartystreets/goconvey/convey/reporting/story.go @@ -0,0 +1,73 @@ +// TODO: in order for this reporter to be completely honest +// we need to retrofit to be more like the json reporter such that: +// 1. it maintains ScopeResult collections, which count assertions +// 2. it reports only after EndStory(), so that all tick marks +// are placed near the appropriate title. +// 3. Under unit test + +package reporting + +import ( + "fmt" + "strings" +) + +type story struct { + out *Printer + titlesById map[string]string + currentKey []string +} + +func (self *story) BeginStory(story *StoryReport) {} + +func (self *story) Enter(scope *ScopeReport) { + self.out.Indent() + + self.currentKey = append(self.currentKey, scope.Title) + ID := strings.Join(self.currentKey, "|") + + if _, found := self.titlesById[ID]; !found { + self.out.Println("") + self.out.Print(scope.Title) + self.out.Insert(" ") + self.titlesById[ID] = scope.Title + } +} + +func (self *story) Report(report *AssertionResult) { + if report.Error != nil { + fmt.Print(redColor) + self.out.Insert(error_) + } else if report.Failure != "" { + fmt.Print(yellowColor) + self.out.Insert(failure) + } else if report.Skipped { + fmt.Print(yellowColor) + self.out.Insert(skip) + } else { + fmt.Print(greenColor) + self.out.Insert(success) + } + fmt.Print(resetColor) +} + +func (self *story) Exit() { + self.out.Dedent() + self.currentKey = self.currentKey[:len(self.currentKey)-1] +} + +func (self *story) EndStory() { + self.titlesById = make(map[string]string) + self.out.Println("\n") +} + +func (self *story) Write(content []byte) (written int, err error) { + return len(content), nil // no-op +} + +func NewStoryReporter(out *Printer) *story { + self := new(story) + self.out = out + self.titlesById = make(map[string]string) + return self +} |