fix for progress formatter summary in concurrency mode

see: https://github.com/DATA-DOG/godog/issues/161
Этот коммит содержится в:
funvit 2019-08-31 17:40:34 +03:00
родитель 96731eaefa
коммит b730b9fd4b

54
run.go
Просмотреть файл

@ -8,6 +8,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"github.com/DATA-DOG/godog/colors"
)
@ -28,11 +29,22 @@ type runner struct {
initializer initializer
}
func (r *runner) concurrent(rate int) (failed bool) {
func (r *runner) concurrent(rate int, formatterFn func() Formatter) (failed bool) {
var useFmtCopy bool
var copyLock sync.Mutex
// special mode for progress-formatter
if _, ok := r.fmt.(*progress); ok {
useFmtCopy = true
}
queue := make(chan int, rate)
for i, ft := range r.features {
queue <- i // reserve space in queue
ft := *ft
go func(fail *bool, feat *feature) {
var fmtCopy Formatter
defer func() {
<-queue // free a space in queue
}()
@ -46,12 +58,48 @@ func (r *runner) concurrent(rate int) (failed bool) {
strict: r.strict,
features: []*feature{feat},
}
if useFmtCopy {
fmtCopy = formatterFn()
suite.fmt = fmtCopy
} else {
suite.fmt = r.fmt
}
r.initializer(suite)
suite.run()
if suite.failed {
*fail = true
}
}(&failed, ft)
if useFmtCopy {
copyLock.Lock()
if d, ok := r.fmt.(*progress); ok {
if s, ok := fmtCopy.(*progress); ok {
func(source *progress, dest *progress) {
for _, v := range source.features {
dest.features = append(dest.features, v)
}
for _, v := range source.failed {
dest.failed = append(dest.failed, v)
}
for _, v := range source.passed {
dest.passed = append(dest.passed, v)
}
for _, v := range source.skipped {
dest.skipped = append(dest.skipped, v)
}
for _, v := range source.undefined {
dest.undefined = append(dest.undefined, v)
}
for _, v := range source.pending {
dest.pending = append(dest.pending, v)
}
}(s, d)
}
}
copyLock.Unlock()
}
}(&failed, &ft)
}
// wait until last are processed
for i := 0; i < rate; i++ {
@ -168,7 +216,7 @@ func RunWithOptions(suite string, contextInitializer func(suite *Suite), opt Opt
var failed bool
if opt.Concurrency > 1 {
failed = r.concurrent(opt.Concurrency)
failed = r.concurrent(opt.Concurrency, func() Formatter { return formatter(suite, output) })
} else {
failed = r.run()
}