arnaucube
arnaucube/mirror-to-giteaPublic Self-hosted repository
mirror-to-gitea/vendor/github.com/onsi/ginkgo/internal/remote/aggregator.go
vendor/github.com/onsi/ginkgo/internal/remote/aggregator.goRaw
  1/*
  2
  3Aggregator is a reporter used by the Ginkgo CLI to aggregate and present parallel test output
  4coherently as tests complete.  You shouldn't need to use this in your code.  To run tests in parallel:
  5
  6	ginkgo -nodes=N
  7
  8where N is the number of nodes you desire.
  9*/
 10package remote
 11
 12import (
 13	"time"
 14
 15	"github.com/onsi/ginkgo/config"
 16	"github.com/onsi/ginkgo/reporters/stenographer"
 17	"github.com/onsi/ginkgo/types"
 18)
 19
 20type configAndSuite struct {
 21	config  config.GinkgoConfigType
 22	summary *types.SuiteSummary
 23}
 24
 25type Aggregator struct {
 26	nodeCount    int
 27	config       config.DefaultReporterConfigType
 28	stenographer stenographer.Stenographer
 29	result       chan bool
 30
 31	suiteBeginnings           chan configAndSuite
 32	aggregatedSuiteBeginnings []configAndSuite
 33
 34	beforeSuites           chan *types.SetupSummary
 35	aggregatedBeforeSuites []*types.SetupSummary
 36
 37	afterSuites           chan *types.SetupSummary
 38	aggregatedAfterSuites []*types.SetupSummary
 39
 40	specCompletions chan *types.SpecSummary
 41	completedSpecs  []*types.SpecSummary
 42
 43	suiteEndings           chan *types.SuiteSummary
 44	aggregatedSuiteEndings []*types.SuiteSummary
 45	specs                  []*types.SpecSummary
 46
 47	startTime time.Time
 48}
 49
 50func NewAggregator(nodeCount int, result chan bool, config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *Aggregator {
 51	aggregator := &Aggregator{
 52		nodeCount:    nodeCount,
 53		result:       result,
 54		config:       config,
 55		stenographer: stenographer,
 56
 57		suiteBeginnings: make(chan configAndSuite),
 58		beforeSuites:    make(chan *types.SetupSummary),
 59		afterSuites:     make(chan *types.SetupSummary),
 60		specCompletions: make(chan *types.SpecSummary),
 61		suiteEndings:    make(chan *types.SuiteSummary),
 62	}
 63
 64	go aggregator.mux()
 65
 66	return aggregator
 67}
 68
 69func (aggregator *Aggregator) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
 70	aggregator.suiteBeginnings <- configAndSuite{config, summary}
 71}
 72
 73func (aggregator *Aggregator) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
 74	aggregator.beforeSuites <- setupSummary
 75}
 76
 77func (aggregator *Aggregator) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
 78	aggregator.afterSuites <- setupSummary
 79}
 80
 81func (aggregator *Aggregator) SpecWillRun(specSummary *types.SpecSummary) {
 82	//noop
 83}
 84
 85func (aggregator *Aggregator) SpecDidComplete(specSummary *types.SpecSummary) {
 86	aggregator.specCompletions <- specSummary
 87}
 88
 89func (aggregator *Aggregator) SpecSuiteDidEnd(summary *types.SuiteSummary) {
 90	aggregator.suiteEndings <- summary
 91}
 92
 93func (aggregator *Aggregator) mux() {
 94loop:
 95	for {
 96		select {
 97		case configAndSuite := <-aggregator.suiteBeginnings:
 98			aggregator.registerSuiteBeginning(configAndSuite)
 99		case setupSummary := <-aggregator.beforeSuites:
100			aggregator.registerBeforeSuite(setupSummary)
101		case setupSummary := <-aggregator.afterSuites:
102			aggregator.registerAfterSuite(setupSummary)
103		case specSummary := <-aggregator.specCompletions:
104			aggregator.registerSpecCompletion(specSummary)
105		case suite := <-aggregator.suiteEndings:
106			finished, passed := aggregator.registerSuiteEnding(suite)
107			if finished {
108				aggregator.result <- passed
109				break loop
110			}
111		}
112	}
113}
114
115func (aggregator *Aggregator) registerSuiteBeginning(configAndSuite configAndSuite) {
116	aggregator.aggregatedSuiteBeginnings = append(aggregator.aggregatedSuiteBeginnings, configAndSuite)
117
118	if len(aggregator.aggregatedSuiteBeginnings) == 1 {
119		aggregator.startTime = time.Now()
120	}
121
122	if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
123		return
124	}
125
126	aggregator.stenographer.AnnounceSuite(configAndSuite.summary.SuiteDescription, configAndSuite.config.RandomSeed, configAndSuite.config.RandomizeAllSpecs, aggregator.config.Succinct)
127
128	totalNumberOfSpecs := 0
129	if len(aggregator.aggregatedSuiteBeginnings) > 0 {
130		totalNumberOfSpecs = configAndSuite.summary.NumberOfSpecsBeforeParallelization
131	}
132
133	aggregator.stenographer.AnnounceTotalNumberOfSpecs(totalNumberOfSpecs, aggregator.config.Succinct)
134	aggregator.stenographer.AnnounceAggregatedParallelRun(aggregator.nodeCount, aggregator.config.Succinct)
135	aggregator.flushCompletedSpecs()
136}
137
138func (aggregator *Aggregator) registerBeforeSuite(setupSummary *types.SetupSummary) {
139	aggregator.aggregatedBeforeSuites = append(aggregator.aggregatedBeforeSuites, setupSummary)
140	aggregator.flushCompletedSpecs()
141}
142
143func (aggregator *Aggregator) registerAfterSuite(setupSummary *types.SetupSummary) {
144	aggregator.aggregatedAfterSuites = append(aggregator.aggregatedAfterSuites, setupSummary)
145	aggregator.flushCompletedSpecs()
146}
147
148func (aggregator *Aggregator) registerSpecCompletion(specSummary *types.SpecSummary) {
149	aggregator.completedSpecs = append(aggregator.completedSpecs, specSummary)
150	aggregator.specs = append(aggregator.specs, specSummary)
151	aggregator.flushCompletedSpecs()
152}
153
154func (aggregator *Aggregator) flushCompletedSpecs() {
155	if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
156		return
157	}
158
159	for _, setupSummary := range aggregator.aggregatedBeforeSuites {
160		aggregator.announceBeforeSuite(setupSummary)
161	}
162
163	for _, specSummary := range aggregator.completedSpecs {
164		aggregator.announceSpec(specSummary)
165	}
166
167	for _, setupSummary := range aggregator.aggregatedAfterSuites {
168		aggregator.announceAfterSuite(setupSummary)
169	}
170
171	aggregator.aggregatedBeforeSuites = []*types.SetupSummary{}
172	aggregator.completedSpecs = []*types.SpecSummary{}
173	aggregator.aggregatedAfterSuites = []*types.SetupSummary{}
174}
175
176func (aggregator *Aggregator) announceBeforeSuite(setupSummary *types.SetupSummary) {
177	aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
178	if setupSummary.State != types.SpecStatePassed {
179		aggregator.stenographer.AnnounceBeforeSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
180	}
181}
182
183func (aggregator *Aggregator) announceAfterSuite(setupSummary *types.SetupSummary) {
184	aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
185	if setupSummary.State != types.SpecStatePassed {
186		aggregator.stenographer.AnnounceAfterSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
187	}
188}
189
190func (aggregator *Aggregator) announceSpec(specSummary *types.SpecSummary) {
191	if aggregator.config.Verbose && specSummary.State != types.SpecStatePending && specSummary.State != types.SpecStateSkipped {
192		aggregator.stenographer.AnnounceSpecWillRun(specSummary)
193	}
194
195	aggregator.stenographer.AnnounceCapturedOutput(specSummary.CapturedOutput)
196
197	switch specSummary.State {
198	case types.SpecStatePassed:
199		if specSummary.IsMeasurement {
200			aggregator.stenographer.AnnounceSuccessfulMeasurement(specSummary, aggregator.config.Succinct)
201		} else if specSummary.RunTime.Seconds() >= aggregator.config.SlowSpecThreshold {
202			aggregator.stenographer.AnnounceSuccessfulSlowSpec(specSummary, aggregator.config.Succinct)
203		} else {
204			aggregator.stenographer.AnnounceSuccessfulSpec(specSummary)
205		}
206
207	case types.SpecStatePending:
208		aggregator.stenographer.AnnouncePendingSpec(specSummary, aggregator.config.NoisyPendings && !aggregator.config.Succinct)
209	case types.SpecStateSkipped:
210		aggregator.stenographer.AnnounceSkippedSpec(specSummary, aggregator.config.Succinct || !aggregator.config.NoisySkippings, aggregator.config.FullTrace)
211	case types.SpecStateTimedOut:
212		aggregator.stenographer.AnnounceSpecTimedOut(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
213	case types.SpecStatePanicked:
214		aggregator.stenographer.AnnounceSpecPanicked(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
215	case types.SpecStateFailed:
216		aggregator.stenographer.AnnounceSpecFailed(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
217	}
218}
219
220func (aggregator *Aggregator) registerSuiteEnding(suite *types.SuiteSummary) (finished bool, passed bool) {
221	aggregator.aggregatedSuiteEndings = append(aggregator.aggregatedSuiteEndings, suite)
222	if len(aggregator.aggregatedSuiteEndings) < aggregator.nodeCount {
223		return false, false
224	}
225
226	aggregatedSuiteSummary := &types.SuiteSummary{}
227	aggregatedSuiteSummary.SuiteSucceeded = true
228
229	for _, suiteSummary := range aggregator.aggregatedSuiteEndings {
230		if !suiteSummary.SuiteSucceeded {
231			aggregatedSuiteSummary.SuiteSucceeded = false
232		}
233
234		aggregatedSuiteSummary.NumberOfSpecsThatWillBeRun += suiteSummary.NumberOfSpecsThatWillBeRun
235		aggregatedSuiteSummary.NumberOfTotalSpecs += suiteSummary.NumberOfTotalSpecs
236		aggregatedSuiteSummary.NumberOfPassedSpecs += suiteSummary.NumberOfPassedSpecs
237		aggregatedSuiteSummary.NumberOfFailedSpecs += suiteSummary.NumberOfFailedSpecs
238		aggregatedSuiteSummary.NumberOfPendingSpecs += suiteSummary.NumberOfPendingSpecs
239		aggregatedSuiteSummary.NumberOfSkippedSpecs += suiteSummary.NumberOfSkippedSpecs
240		aggregatedSuiteSummary.NumberOfFlakedSpecs += suiteSummary.NumberOfFlakedSpecs
241	}
242
243	aggregatedSuiteSummary.RunTime = time.Since(aggregator.startTime)
244
245	aggregator.stenographer.SummarizeFailures(aggregator.specs)
246	aggregator.stenographer.AnnounceSpecRunCompletion(aggregatedSuiteSummary, aggregator.config.Succinct)
247
248	return true, aggregatedSuiteSummary.SuiteSucceeded
249}