Moved base concurrency support to the basefmt

Этот коммит содержится в:
Fredrik Lönnblad 2020-02-29 14:55:27 -03:00
родитель 3f817c89de
коммит 9b86360854
7 изменённых файлов: 93 добавлений и 155 удалений

66
fmt.go
Просмотреть файл

@ -9,6 +9,7 @@ import (
"regexp"
"strconv"
"strings"
"sync"
"text/template"
"time"
"unicode"
@ -221,6 +222,16 @@ func (f stepResult) scenarioLine() string {
return f.line() // was not expecting different owner
}
func newBaseFmt(suite string, out io.Writer) *basefmt {
return &basefmt{
suiteName: suite,
started: timeNowFunc(),
indent: 2,
out: out,
lock: new(sync.Mutex),
}
}
type basefmt struct {
suiteName string
@ -235,9 +246,14 @@ type basefmt struct {
skipped []*stepResult
undefined []*stepResult
pending []*stepResult
lock *sync.Mutex
}
func (f *basefmt) Node(n interface{}) {
f.lock.Lock()
defer f.lock.Unlock()
switch t := n.(type) {
case *gherkin.Scenario:
f.owner = t
@ -265,14 +281,21 @@ func (f *basefmt) Node(n interface{}) {
}
func (f *basefmt) Defined(*gherkin.Step, *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
}
func (f *basefmt) Feature(ft *gherkin.Feature, p string, c []byte) {
f.lock.Lock()
defer f.lock.Unlock()
f.features = append(f.features, &feature{Path: p, Feature: ft, time: timeNowFunc()})
}
func (f *basefmt) Passed(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
s := &stepResult{
owner: f.owner,
feature: f.features[len(f.features)-1],
@ -287,6 +310,9 @@ func (f *basefmt) Passed(step *gherkin.Step, match *StepDef) {
}
func (f *basefmt) Skipped(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
s := &stepResult{
owner: f.owner,
feature: f.features[len(f.features)-1],
@ -301,6 +327,9 @@ func (f *basefmt) Skipped(step *gherkin.Step, match *StepDef) {
}
func (f *basefmt) Undefined(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
s := &stepResult{
owner: f.owner,
feature: f.features[len(f.features)-1],
@ -315,6 +344,9 @@ func (f *basefmt) Undefined(step *gherkin.Step, match *StepDef) {
}
func (f *basefmt) Failed(step *gherkin.Step, match *StepDef, err error) {
f.lock.Lock()
defer f.lock.Unlock()
s := &stepResult{
owner: f.owner,
feature: f.features[len(f.features)-1],
@ -330,6 +362,9 @@ func (f *basefmt) Failed(step *gherkin.Step, match *StepDef, err error) {
}
func (f *basefmt) Pending(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
s := &stepResult{
owner: f.owner,
feature: f.features[len(f.features)-1],
@ -438,6 +473,35 @@ func (f *basefmt) Summary() {
}
}
func (f *basefmt) Sync(cf ConcurrentFormatter) {
if source, ok := cf.(*basefmt); ok {
f.lock = source.lock
}
}
func (f *basefmt) Copy(cf ConcurrentFormatter) {
if source, ok := cf.(*basefmt); ok {
for _, v := range source.features {
f.features = append(f.features, v)
}
for _, v := range source.failed {
f.failed = append(f.failed, v)
}
for _, v := range source.passed {
f.passed = append(f.passed, v)
}
for _, v := range source.skipped {
f.skipped = append(f.skipped, v)
}
for _, v := range source.undefined {
f.undefined = append(f.undefined, v)
}
for _, v := range source.pending {
f.pending = append(f.pending, v)
}
}
}
func (s *undefinedSnippet) Args() (ret string) {
var (
args []string

Просмотреть файл

@ -27,15 +27,7 @@ func init() {
}
func cucumberFunc(suite string, out io.Writer) Formatter {
formatter := &cukefmt{
basefmt: basefmt{
started: timeNowFunc(),
indent: 2,
out: out,
},
}
return formatter
return &cukefmt{basefmt: newBaseFmt(suite, out)}
}
// Replace spaces with - This function is used to create the "id" fields of the cucumber output.
@ -108,7 +100,7 @@ type cukeFeatureJSON struct {
}
type cukefmt struct {
basefmt
*basefmt
// currently running feature path, to be part of id.
// this is sadly not passed by gherkin nodes.

Просмотреть файл

@ -16,13 +16,7 @@ func init() {
}
func eventsFunc(suite string, out io.Writer) Formatter {
formatter := &events{
basefmt: basefmt{
started: timeNowFunc(),
indent: 2,
out: out,
},
}
formatter := &events{basefmt: newBaseFmt(suite, out)}
formatter.event(&struct {
Event string `json:"event"`
@ -40,7 +34,7 @@ func eventsFunc(suite string, out io.Writer) Formatter {
}
type events struct {
basefmt
*basefmt
// currently running feature path, to be part of id.
// this is sadly not passed by gherkin nodes.

Просмотреть файл

@ -7,10 +7,7 @@ import (
"os"
"sort"
"strconv"
"sync"
"time"
"github.com/cucumber/godog/gherkin"
)
func init() {
@ -18,32 +15,11 @@ func init() {
}
func junitFunc(suite string, out io.Writer) Formatter {
return &junitFormatter{
basefmt: basefmt{
suiteName: suite,
started: timeNowFunc(),
indent: 2,
out: out,
},
lock: new(sync.Mutex),
}
return &junitFormatter{basefmt: newBaseFmt(suite, out)}
}
type junitFormatter struct {
basefmt
lock *sync.Mutex
}
func (f *junitFormatter) Node(n interface{}) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Node(n)
}
func (f *junitFormatter) Feature(ft *gherkin.Feature, p string, c []byte) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Feature(ft, p, c)
*basefmt
}
func (f *junitFormatter) Summary() {
@ -61,62 +37,15 @@ func (f *junitFormatter) Summary() {
}
}
func (f *junitFormatter) Passed(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Passed(step, match)
}
func (f *junitFormatter) Skipped(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Skipped(step, match)
}
func (f *junitFormatter) Undefined(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Undefined(step, match)
}
func (f *junitFormatter) Failed(step *gherkin.Step, match *StepDef, err error) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Failed(step, match, err)
}
func (f *junitFormatter) Pending(step *gherkin.Step, match *StepDef) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Pending(step, match)
}
func (f *junitFormatter) Sync(cf ConcurrentFormatter) {
if source, ok := cf.(*junitFormatter); ok {
f.lock = source.lock
f.basefmt.Sync(source.basefmt)
}
}
func (f *junitFormatter) Copy(cf ConcurrentFormatter) {
if source, ok := cf.(*junitFormatter); ok {
for _, v := range source.features {
f.features = append(f.features, v)
}
for _, v := range source.failed {
f.failed = append(f.failed, v)
}
for _, v := range source.passed {
f.passed = append(f.passed, v)
}
for _, v := range source.skipped {
f.skipped = append(f.skipped, v)
}
for _, v := range source.undefined {
f.undefined = append(f.undefined, v)
}
for _, v := range source.pending {
f.pending = append(f.pending, v)
}
f.basefmt.Copy(source.basefmt)
}
}

Просмотреть файл

@ -17,20 +17,14 @@ func init() {
}
func prettyFunc(suite string, out io.Writer) Formatter {
return &pretty{
basefmt: basefmt{
started: timeNowFunc(),
indent: 2,
out: out,
},
}
return &pretty{basefmt: newBaseFmt(suite, out)}
}
var outlinePlaceholderRegexp = regexp.MustCompile("<[^>]+>")
// a built in default pretty formatter
type pretty struct {
basefmt
*basefmt
// currently processed
feature *gherkin.Feature

Просмотреть файл

@ -5,7 +5,6 @@ import (
"io"
"math"
"strings"
"sync"
"github.com/cucumber/godog/gherkin"
)
@ -17,36 +16,18 @@ func init() {
func progressFunc(suite string, out io.Writer) Formatter {
steps := 0
return &progress{
basefmt: basefmt{
started: timeNowFunc(),
indent: 2,
out: out,
},
basefmt: newBaseFmt(suite, out),
stepsPerRow: 70,
lock: new(sync.Mutex),
steps: &steps,
}
}
type progress struct {
basefmt
lock *sync.Mutex
*basefmt
stepsPerRow int
steps *int
}
func (f *progress) Node(n interface{}) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Node(n)
}
func (f *progress) Feature(ft *gherkin.Feature, p string, c []byte) {
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Feature(ft, p, c)
}
func (f *progress) Summary() {
left := math.Mod(float64(*f.steps), float64(f.stepsPerRow))
if left != 0 {
@ -82,73 +63,63 @@ func (f *progress) step(res *stepResult) {
case pending:
fmt.Fprint(f.out, yellow("P"))
}
*f.steps++
if math.Mod(float64(*f.steps), float64(f.stepsPerRow)) == 0 {
fmt.Fprintf(f.out, " %d\n", *f.steps)
}
}
func (f *progress) Passed(step *gherkin.Step, match *StepDef) {
f.basefmt.Passed(step, match)
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Passed(step, match)
f.step(f.passed[len(f.passed)-1])
}
func (f *progress) Skipped(step *gherkin.Step, match *StepDef) {
f.basefmt.Skipped(step, match)
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Skipped(step, match)
f.step(f.skipped[len(f.skipped)-1])
}
func (f *progress) Undefined(step *gherkin.Step, match *StepDef) {
f.basefmt.Undefined(step, match)
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Undefined(step, match)
f.step(f.undefined[len(f.undefined)-1])
}
func (f *progress) Failed(step *gherkin.Step, match *StepDef, err error) {
f.basefmt.Failed(step, match, err)
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Failed(step, match, err)
f.step(f.failed[len(f.failed)-1])
}
func (f *progress) Pending(step *gherkin.Step, match *StepDef) {
f.basefmt.Pending(step, match)
f.lock.Lock()
defer f.lock.Unlock()
f.basefmt.Pending(step, match)
f.step(f.pending[len(f.pending)-1])
}
func (f *progress) Sync(cf ConcurrentFormatter) {
if source, ok := cf.(*progress); ok {
f.lock = source.lock
f.basefmt.Sync(source.basefmt)
f.steps = source.steps
}
}
func (f *progress) Copy(cf ConcurrentFormatter) {
if source, ok := cf.(*progress); ok {
for _, v := range source.features {
f.features = append(f.features, v)
}
for _, v := range source.failed {
f.failed = append(f.failed, v)
}
for _, v := range source.passed {
f.passed = append(f.passed, v)
}
for _, v := range source.skipped {
f.skipped = append(f.skipped, v)
}
for _, v := range source.undefined {
f.undefined = append(f.undefined, v)
}
for _, v := range source.pending {
f.pending = append(f.pending, v)
}
f.basefmt.Copy(source.basefmt)
}
}

Просмотреть файл

@ -529,18 +529,12 @@ func (s *suiteContext) theRenderXMLWillBe(docstring *gherkin.DocString) error {
}
type testFormatter struct {
basefmt
*basefmt
scenarios []interface{}
}
func testFormatterFunc(suite string, out io.Writer) Formatter {
return &testFormatter{
basefmt: basefmt{
started: timeNowFunc(),
indent: 2,
out: out,
},
}
return &testFormatter{basefmt: newBaseFmt(suite, out)}
}
func (f *testFormatter) Node(node interface{}) {