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  }