github.com/onsi/ginkgo@v1.16.6-0.20211118180735-4e1925ba4c95/internal/parallel_support/server_handler.go (about)

     1  package parallel_support
     2  
     3  import (
     4  	"io"
     5  	"os"
     6  	"sync"
     7  
     8  	"github.com/onsi/ginkgo/reporters"
     9  	"github.com/onsi/ginkgo/types"
    10  )
    11  
    12  type Void struct{}
    13  
    14  var voidReceiver *Void = &Void{}
    15  var voidSender Void
    16  
    17  // ServerHandler is an RPC-compatible handler that is shared between the http server and the rpc server.
    18  // It handles all the business logic to avoid duplication between the two servers
    19  
    20  type ServerHandler struct {
    21  	done              chan interface{}
    22  	outputDestination io.Writer
    23  	reporter          reporters.Reporter
    24  	alives            []func() bool
    25  	lock              *sync.Mutex
    26  	beforeSuiteState  BeforeSuiteState
    27  	parallelTotal     int
    28  	counter           int
    29  	counterLock       *sync.Mutex
    30  	shouldAbort       bool
    31  
    32  	numSuiteDidBegins int
    33  	numSuiteDidEnds   int
    34  	aggregatedReport  types.Report
    35  	reportHoldingArea []types.SpecReport
    36  }
    37  
    38  func newServerHandler(parallelTotal int, reporter reporters.Reporter) *ServerHandler {
    39  	return &ServerHandler{
    40  		reporter:          reporter,
    41  		lock:              &sync.Mutex{},
    42  		counterLock:       &sync.Mutex{},
    43  		alives:            make([]func() bool, parallelTotal),
    44  		beforeSuiteState:  BeforeSuiteState{Data: nil, State: types.SpecStateInvalid},
    45  		parallelTotal:     parallelTotal,
    46  		outputDestination: os.Stdout,
    47  		done:              make(chan interface{}),
    48  	}
    49  }
    50  
    51  func (handler *ServerHandler) SpecSuiteWillBegin(report types.Report, _ *Void) error {
    52  	handler.lock.Lock()
    53  	defer handler.lock.Unlock()
    54  
    55  	handler.numSuiteDidBegins += 1
    56  
    57  	// all summaries are identical, so it's fine to simply emit the last one of these
    58  	if handler.numSuiteDidBegins == handler.parallelTotal {
    59  		handler.reporter.SuiteWillBegin(report)
    60  
    61  		for _, summary := range handler.reportHoldingArea {
    62  			handler.reporter.WillRun(summary)
    63  			handler.reporter.DidRun(summary)
    64  		}
    65  
    66  		handler.reportHoldingArea = nil
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func (handler *ServerHandler) DidRun(report types.SpecReport, _ *Void) error {
    73  	handler.lock.Lock()
    74  	defer handler.lock.Unlock()
    75  
    76  	if handler.numSuiteDidBegins == handler.parallelTotal {
    77  		handler.reporter.WillRun(report)
    78  		handler.reporter.DidRun(report)
    79  	} else {
    80  		handler.reportHoldingArea = append(handler.reportHoldingArea, report)
    81  	}
    82  
    83  	return nil
    84  }
    85  
    86  func (handler *ServerHandler) SpecSuiteDidEnd(report types.Report, _ *Void) error {
    87  	handler.lock.Lock()
    88  	defer handler.lock.Unlock()
    89  
    90  	handler.numSuiteDidEnds += 1
    91  	if handler.numSuiteDidEnds == 1 {
    92  		handler.aggregatedReport = report
    93  	} else {
    94  		handler.aggregatedReport = handler.aggregatedReport.Add(report)
    95  	}
    96  
    97  	if handler.numSuiteDidEnds == handler.parallelTotal {
    98  		handler.reporter.SuiteDidEnd(handler.aggregatedReport)
    99  		close(handler.done)
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  func (handler *ServerHandler) EmitOutput(output []byte, n *int) error {
   106  	var err error
   107  	*n, err = handler.outputDestination.Write(output)
   108  	return err
   109  }
   110  
   111  func (handler *ServerHandler) registerAlive(proc int, alive func() bool) {
   112  	handler.lock.Lock()
   113  	defer handler.lock.Unlock()
   114  	handler.alives[proc-1] = alive
   115  }
   116  
   117  func (handler *ServerHandler) procIsAlive(proc int) bool {
   118  	handler.lock.Lock()
   119  	defer handler.lock.Unlock()
   120  	alive := handler.alives[proc-1]
   121  	if alive == nil {
   122  		return true
   123  	}
   124  	return alive()
   125  }
   126  
   127  func (handler *ServerHandler) haveNonprimaryProcsFinished() bool {
   128  	for i := 2; i <= handler.parallelTotal; i++ {
   129  		if handler.procIsAlive(i) {
   130  			return false
   131  		}
   132  	}
   133  	return true
   134  }
   135  
   136  func (handler *ServerHandler) BeforeSuiteCompleted(beforeSuiteState BeforeSuiteState, _ *Void) error {
   137  	handler.lock.Lock()
   138  	defer handler.lock.Unlock()
   139  	handler.beforeSuiteState = beforeSuiteState
   140  
   141  	return nil
   142  }
   143  
   144  func (handler *ServerHandler) BeforeSuiteState(_ Void, beforeSuiteState *BeforeSuiteState) error {
   145  	proc1IsAlive := handler.procIsAlive(1)
   146  	handler.lock.Lock()
   147  	defer handler.lock.Unlock()
   148  	if handler.beforeSuiteState.State == types.SpecStateInvalid {
   149  		if proc1IsAlive {
   150  			return ErrorEarly
   151  		} else {
   152  			return ErrorGone
   153  		}
   154  	}
   155  	*beforeSuiteState = handler.beforeSuiteState
   156  	return nil
   157  }
   158  
   159  func (handler *ServerHandler) HaveNonprimaryProcsFinished(_ Void, _ *Void) error {
   160  	if handler.haveNonprimaryProcsFinished() {
   161  		return nil
   162  	} else {
   163  		return ErrorEarly
   164  	}
   165  }
   166  
   167  func (handler *ServerHandler) AggregatedNonprimaryProcsReport(_ Void, report *types.Report) error {
   168  	if handler.haveNonprimaryProcsFinished() {
   169  		handler.lock.Lock()
   170  		defer handler.lock.Unlock()
   171  		if handler.numSuiteDidEnds == handler.parallelTotal-1 {
   172  			*report = handler.aggregatedReport
   173  			return nil
   174  		} else {
   175  			return ErrorGone
   176  		}
   177  	} else {
   178  		return ErrorEarly
   179  	}
   180  }
   181  
   182  func (handler *ServerHandler) Counter(_ Void, counter *int) error {
   183  	handler.counterLock.Lock()
   184  	defer handler.counterLock.Unlock()
   185  	*counter = handler.counter
   186  	handler.counter++
   187  	return nil
   188  }
   189  
   190  func (handler *ServerHandler) Abort(_ Void, _ *Void) error {
   191  	handler.lock.Lock()
   192  	defer handler.lock.Unlock()
   193  	handler.shouldAbort = true
   194  	return nil
   195  }
   196  
   197  func (handler *ServerHandler) ShouldAbort(_ Void, shouldAbort *bool) error {
   198  	handler.lock.Lock()
   199  	defer handler.lock.Unlock()
   200  	*shouldAbort = handler.shouldAbort
   201  	return nil
   202  }