github.com/leanovate/gopter@v0.2.9/runner.go (about) 1 package gopter 2 3 import ( 4 "sync" 5 "time" 6 ) 7 8 type shouldStop func() bool 9 10 type worker func(int, shouldStop) *TestResult 11 12 type runner struct { 13 sync.RWMutex 14 parameters *TestParameters 15 worker worker 16 } 17 18 func (r *runner) mergeCheckResults(r1, r2 *TestResult) *TestResult { 19 var result TestResult 20 21 switch { 22 case r1 == nil: 23 return r2 24 case r1.Status != TestPassed && r1.Status != TestExhausted: 25 result = *r1 26 case r2.Status != TestPassed && r2.Status != TestExhausted: 27 result = *r2 28 default: 29 result.Status = TestExhausted 30 31 if r1.Succeeded+r2.Succeeded >= r.parameters.MinSuccessfulTests && 32 float64(r1.Discarded+r2.Discarded) <= float64(r1.Succeeded+r2.Succeeded)*r.parameters.MaxDiscardRatio { 33 result.Status = TestPassed 34 } 35 } 36 37 result.Succeeded = r1.Succeeded + r2.Succeeded 38 result.Discarded = r1.Discarded + r2.Discarded 39 40 return &result 41 } 42 43 func (r *runner) runWorkers() *TestResult { 44 var stopFlag Flag 45 defer stopFlag.Set() 46 47 start := time.Now() 48 if r.parameters.Workers < 2 { 49 result := r.worker(0, stopFlag.Get) 50 result.Time = time.Since(start) 51 return result 52 } 53 var waitGroup sync.WaitGroup 54 waitGroup.Add(r.parameters.Workers) 55 results := make(chan *TestResult, r.parameters.Workers) 56 combinedResult := make(chan *TestResult) 57 58 go func() { 59 var combined *TestResult 60 for result := range results { 61 combined = r.mergeCheckResults(combined, result) 62 } 63 combinedResult <- combined 64 }() 65 for i := 0; i < r.parameters.Workers; i++ { 66 go func(workerIdx int) { 67 defer waitGroup.Done() 68 results <- r.worker(workerIdx, stopFlag.Get) 69 }(i) 70 } 71 waitGroup.Wait() 72 close(results) 73 74 result := <-combinedResult 75 result.Time = time.Since(start) 76 return result 77 }