vendor update for E2E framework

Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
Madhu Rajanna
2019-05-31 15:15:11 +05:30
parent 9bb23e4e32
commit d300da19b7
2149 changed files with 598692 additions and 14107 deletions

View File

@ -0,0 +1,249 @@
/*
Aggregator is a reporter used by the Ginkgo CLI to aggregate and present parallel test output
coherently as tests complete. You shouldn't need to use this in your code. To run tests in parallel:
ginkgo -nodes=N
where N is the number of nodes you desire.
*/
package remote
import (
"time"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/reporters/stenographer"
"github.com/onsi/ginkgo/types"
)
type configAndSuite struct {
config config.GinkgoConfigType
summary *types.SuiteSummary
}
type Aggregator struct {
nodeCount int
config config.DefaultReporterConfigType
stenographer stenographer.Stenographer
result chan bool
suiteBeginnings chan configAndSuite
aggregatedSuiteBeginnings []configAndSuite
beforeSuites chan *types.SetupSummary
aggregatedBeforeSuites []*types.SetupSummary
afterSuites chan *types.SetupSummary
aggregatedAfterSuites []*types.SetupSummary
specCompletions chan *types.SpecSummary
completedSpecs []*types.SpecSummary
suiteEndings chan *types.SuiteSummary
aggregatedSuiteEndings []*types.SuiteSummary
specs []*types.SpecSummary
startTime time.Time
}
func NewAggregator(nodeCount int, result chan bool, config config.DefaultReporterConfigType, stenographer stenographer.Stenographer) *Aggregator {
aggregator := &Aggregator{
nodeCount: nodeCount,
result: result,
config: config,
stenographer: stenographer,
suiteBeginnings: make(chan configAndSuite, 0),
beforeSuites: make(chan *types.SetupSummary, 0),
afterSuites: make(chan *types.SetupSummary, 0),
specCompletions: make(chan *types.SpecSummary, 0),
suiteEndings: make(chan *types.SuiteSummary, 0),
}
go aggregator.mux()
return aggregator
}
func (aggregator *Aggregator) SpecSuiteWillBegin(config config.GinkgoConfigType, summary *types.SuiteSummary) {
aggregator.suiteBeginnings <- configAndSuite{config, summary}
}
func (aggregator *Aggregator) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
aggregator.beforeSuites <- setupSummary
}
func (aggregator *Aggregator) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
aggregator.afterSuites <- setupSummary
}
func (aggregator *Aggregator) SpecWillRun(specSummary *types.SpecSummary) {
//noop
}
func (aggregator *Aggregator) SpecDidComplete(specSummary *types.SpecSummary) {
aggregator.specCompletions <- specSummary
}
func (aggregator *Aggregator) SpecSuiteDidEnd(summary *types.SuiteSummary) {
aggregator.suiteEndings <- summary
}
func (aggregator *Aggregator) mux() {
loop:
for {
select {
case configAndSuite := <-aggregator.suiteBeginnings:
aggregator.registerSuiteBeginning(configAndSuite)
case setupSummary := <-aggregator.beforeSuites:
aggregator.registerBeforeSuite(setupSummary)
case setupSummary := <-aggregator.afterSuites:
aggregator.registerAfterSuite(setupSummary)
case specSummary := <-aggregator.specCompletions:
aggregator.registerSpecCompletion(specSummary)
case suite := <-aggregator.suiteEndings:
finished, passed := aggregator.registerSuiteEnding(suite)
if finished {
aggregator.result <- passed
break loop
}
}
}
}
func (aggregator *Aggregator) registerSuiteBeginning(configAndSuite configAndSuite) {
aggregator.aggregatedSuiteBeginnings = append(aggregator.aggregatedSuiteBeginnings, configAndSuite)
if len(aggregator.aggregatedSuiteBeginnings) == 1 {
aggregator.startTime = time.Now()
}
if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
return
}
aggregator.stenographer.AnnounceSuite(configAndSuite.summary.SuiteDescription, configAndSuite.config.RandomSeed, configAndSuite.config.RandomizeAllSpecs, aggregator.config.Succinct)
totalNumberOfSpecs := 0
if len(aggregator.aggregatedSuiteBeginnings) > 0 {
totalNumberOfSpecs = configAndSuite.summary.NumberOfSpecsBeforeParallelization
}
aggregator.stenographer.AnnounceTotalNumberOfSpecs(totalNumberOfSpecs, aggregator.config.Succinct)
aggregator.stenographer.AnnounceAggregatedParallelRun(aggregator.nodeCount, aggregator.config.Succinct)
aggregator.flushCompletedSpecs()
}
func (aggregator *Aggregator) registerBeforeSuite(setupSummary *types.SetupSummary) {
aggregator.aggregatedBeforeSuites = append(aggregator.aggregatedBeforeSuites, setupSummary)
aggregator.flushCompletedSpecs()
}
func (aggregator *Aggregator) registerAfterSuite(setupSummary *types.SetupSummary) {
aggregator.aggregatedAfterSuites = append(aggregator.aggregatedAfterSuites, setupSummary)
aggregator.flushCompletedSpecs()
}
func (aggregator *Aggregator) registerSpecCompletion(specSummary *types.SpecSummary) {
aggregator.completedSpecs = append(aggregator.completedSpecs, specSummary)
aggregator.specs = append(aggregator.specs, specSummary)
aggregator.flushCompletedSpecs()
}
func (aggregator *Aggregator) flushCompletedSpecs() {
if len(aggregator.aggregatedSuiteBeginnings) != aggregator.nodeCount {
return
}
for _, setupSummary := range aggregator.aggregatedBeforeSuites {
aggregator.announceBeforeSuite(setupSummary)
}
for _, specSummary := range aggregator.completedSpecs {
aggregator.announceSpec(specSummary)
}
for _, setupSummary := range aggregator.aggregatedAfterSuites {
aggregator.announceAfterSuite(setupSummary)
}
aggregator.aggregatedBeforeSuites = []*types.SetupSummary{}
aggregator.completedSpecs = []*types.SpecSummary{}
aggregator.aggregatedAfterSuites = []*types.SetupSummary{}
}
func (aggregator *Aggregator) announceBeforeSuite(setupSummary *types.SetupSummary) {
aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
if setupSummary.State != types.SpecStatePassed {
aggregator.stenographer.AnnounceBeforeSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
}
}
func (aggregator *Aggregator) announceAfterSuite(setupSummary *types.SetupSummary) {
aggregator.stenographer.AnnounceCapturedOutput(setupSummary.CapturedOutput)
if setupSummary.State != types.SpecStatePassed {
aggregator.stenographer.AnnounceAfterSuiteFailure(setupSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
}
}
func (aggregator *Aggregator) announceSpec(specSummary *types.SpecSummary) {
if aggregator.config.Verbose && specSummary.State != types.SpecStatePending && specSummary.State != types.SpecStateSkipped {
aggregator.stenographer.AnnounceSpecWillRun(specSummary)
}
aggregator.stenographer.AnnounceCapturedOutput(specSummary.CapturedOutput)
switch specSummary.State {
case types.SpecStatePassed:
if specSummary.IsMeasurement {
aggregator.stenographer.AnnounceSuccesfulMeasurement(specSummary, aggregator.config.Succinct)
} else if specSummary.RunTime.Seconds() >= aggregator.config.SlowSpecThreshold {
aggregator.stenographer.AnnounceSuccesfulSlowSpec(specSummary, aggregator.config.Succinct)
} else {
aggregator.stenographer.AnnounceSuccesfulSpec(specSummary)
}
case types.SpecStatePending:
aggregator.stenographer.AnnouncePendingSpec(specSummary, aggregator.config.NoisyPendings && !aggregator.config.Succinct)
case types.SpecStateSkipped:
aggregator.stenographer.AnnounceSkippedSpec(specSummary, aggregator.config.Succinct || !aggregator.config.NoisySkippings, aggregator.config.FullTrace)
case types.SpecStateTimedOut:
aggregator.stenographer.AnnounceSpecTimedOut(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
case types.SpecStatePanicked:
aggregator.stenographer.AnnounceSpecPanicked(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
case types.SpecStateFailed:
aggregator.stenographer.AnnounceSpecFailed(specSummary, aggregator.config.Succinct, aggregator.config.FullTrace)
}
}
func (aggregator *Aggregator) registerSuiteEnding(suite *types.SuiteSummary) (finished bool, passed bool) {
aggregator.aggregatedSuiteEndings = append(aggregator.aggregatedSuiteEndings, suite)
if len(aggregator.aggregatedSuiteEndings) < aggregator.nodeCount {
return false, false
}
aggregatedSuiteSummary := &types.SuiteSummary{}
aggregatedSuiteSummary.SuiteSucceeded = true
for _, suiteSummary := range aggregator.aggregatedSuiteEndings {
if suiteSummary.SuiteSucceeded == false {
aggregatedSuiteSummary.SuiteSucceeded = false
}
aggregatedSuiteSummary.NumberOfSpecsThatWillBeRun += suiteSummary.NumberOfSpecsThatWillBeRun
aggregatedSuiteSummary.NumberOfTotalSpecs += suiteSummary.NumberOfTotalSpecs
aggregatedSuiteSummary.NumberOfPassedSpecs += suiteSummary.NumberOfPassedSpecs
aggregatedSuiteSummary.NumberOfFailedSpecs += suiteSummary.NumberOfFailedSpecs
aggregatedSuiteSummary.NumberOfPendingSpecs += suiteSummary.NumberOfPendingSpecs
aggregatedSuiteSummary.NumberOfSkippedSpecs += suiteSummary.NumberOfSkippedSpecs
aggregatedSuiteSummary.NumberOfFlakedSpecs += suiteSummary.NumberOfFlakedSpecs
}
aggregatedSuiteSummary.RunTime = time.Since(aggregator.startTime)
aggregator.stenographer.SummarizeFailures(aggregator.specs)
aggregator.stenographer.AnnounceSpecRunCompletion(aggregatedSuiteSummary, aggregator.config.Succinct)
return true, aggregatedSuiteSummary.SuiteSucceeded
}

View File

@ -0,0 +1,147 @@
package remote
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"github.com/onsi/ginkgo/internal/writer"
"github.com/onsi/ginkgo/reporters"
"github.com/onsi/ginkgo/reporters/stenographer"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/types"
)
//An interface to net/http's client to allow the injection of fakes under test
type Poster interface {
Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error)
}
/*
The ForwardingReporter is a Ginkgo reporter that forwards information to
a Ginkgo remote server.
When streaming parallel test output, this repoter is automatically installed by Ginkgo.
This is accomplished by passing in the GINKGO_REMOTE_REPORTING_SERVER environment variable to `go test`, the Ginkgo test runner
detects this environment variable (which should contain the host of the server) and automatically installs a ForwardingReporter
in place of Ginkgo's DefaultReporter.
*/
type ForwardingReporter struct {
serverHost string
poster Poster
outputInterceptor OutputInterceptor
debugMode bool
debugFile *os.File
nestedReporter *reporters.DefaultReporter
}
func NewForwardingReporter(config config.DefaultReporterConfigType, serverHost string, poster Poster, outputInterceptor OutputInterceptor, ginkgoWriter *writer.Writer, debugFile string) *ForwardingReporter {
reporter := &ForwardingReporter{
serverHost: serverHost,
poster: poster,
outputInterceptor: outputInterceptor,
}
if debugFile != "" {
var err error
reporter.debugMode = true
reporter.debugFile, err = os.Create(debugFile)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
if !config.Verbose {
//if verbose is true then the GinkgoWriter emits to stdout. Don't _also_ redirect GinkgoWriter output as that will result in duplication.
ginkgoWriter.AndRedirectTo(reporter.debugFile)
}
outputInterceptor.StreamTo(reporter.debugFile) //This is not working
stenographer := stenographer.New(false, true, reporter.debugFile)
config.Succinct = false
config.Verbose = true
config.FullTrace = true
reporter.nestedReporter = reporters.NewDefaultReporter(config, stenographer)
}
return reporter
}
func (reporter *ForwardingReporter) post(path string, data interface{}) {
encoded, _ := json.Marshal(data)
buffer := bytes.NewBuffer(encoded)
reporter.poster.Post(reporter.serverHost+path, "application/json", buffer)
}
func (reporter *ForwardingReporter) SpecSuiteWillBegin(conf config.GinkgoConfigType, summary *types.SuiteSummary) {
data := struct {
Config config.GinkgoConfigType `json:"config"`
Summary *types.SuiteSummary `json:"suite-summary"`
}{
conf,
summary,
}
reporter.outputInterceptor.StartInterceptingOutput()
if reporter.debugMode {
reporter.nestedReporter.SpecSuiteWillBegin(conf, summary)
reporter.debugFile.Sync()
}
reporter.post("/SpecSuiteWillBegin", data)
}
func (reporter *ForwardingReporter) BeforeSuiteDidRun(setupSummary *types.SetupSummary) {
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
reporter.outputInterceptor.StartInterceptingOutput()
setupSummary.CapturedOutput = output
if reporter.debugMode {
reporter.nestedReporter.BeforeSuiteDidRun(setupSummary)
reporter.debugFile.Sync()
}
reporter.post("/BeforeSuiteDidRun", setupSummary)
}
func (reporter *ForwardingReporter) SpecWillRun(specSummary *types.SpecSummary) {
if reporter.debugMode {
reporter.nestedReporter.SpecWillRun(specSummary)
reporter.debugFile.Sync()
}
reporter.post("/SpecWillRun", specSummary)
}
func (reporter *ForwardingReporter) SpecDidComplete(specSummary *types.SpecSummary) {
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
reporter.outputInterceptor.StartInterceptingOutput()
specSummary.CapturedOutput = output
if reporter.debugMode {
reporter.nestedReporter.SpecDidComplete(specSummary)
reporter.debugFile.Sync()
}
reporter.post("/SpecDidComplete", specSummary)
}
func (reporter *ForwardingReporter) AfterSuiteDidRun(setupSummary *types.SetupSummary) {
output, _ := reporter.outputInterceptor.StopInterceptingAndReturnOutput()
reporter.outputInterceptor.StartInterceptingOutput()
setupSummary.CapturedOutput = output
if reporter.debugMode {
reporter.nestedReporter.AfterSuiteDidRun(setupSummary)
reporter.debugFile.Sync()
}
reporter.post("/AfterSuiteDidRun", setupSummary)
}
func (reporter *ForwardingReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) {
reporter.outputInterceptor.StopInterceptingAndReturnOutput()
if reporter.debugMode {
reporter.nestedReporter.SpecSuiteDidEnd(summary)
reporter.debugFile.Sync()
}
reporter.post("/SpecSuiteDidEnd", summary)
}

View File

@ -0,0 +1,13 @@
package remote
import "os"
/*
The OutputInterceptor is used by the ForwardingReporter to
intercept and capture all stdin and stderr output during a test run.
*/
type OutputInterceptor interface {
StartInterceptingOutput() error
StopInterceptingAndReturnOutput() (string, error)
StreamTo(*os.File)
}

View File

@ -0,0 +1,83 @@
// +build freebsd openbsd netbsd dragonfly darwin linux solaris
package remote
import (
"errors"
"io/ioutil"
"os"
"github.com/hpcloud/tail"
)
func NewOutputInterceptor() OutputInterceptor {
return &outputInterceptor{}
}
type outputInterceptor struct {
redirectFile *os.File
streamTarget *os.File
intercepting bool
tailer *tail.Tail
doneTailing chan bool
}
func (interceptor *outputInterceptor) StartInterceptingOutput() error {
if interceptor.intercepting {
return errors.New("Already intercepting output!")
}
interceptor.intercepting = true
var err error
interceptor.redirectFile, err = ioutil.TempFile("", "ginkgo-output")
if err != nil {
return err
}
// Call a function in ./syscall_dup_*.go
// If building for everything other than linux_arm64,
// use a "normal" syscall.Dup2(oldfd, newfd) call. If building for linux_arm64 (which doesn't have syscall.Dup2)
// call syscall.Dup3(oldfd, newfd, 0). They are nearly identical, see: http://linux.die.net/man/2/dup3
syscallDup(int(interceptor.redirectFile.Fd()), 1)
syscallDup(int(interceptor.redirectFile.Fd()), 2)
if interceptor.streamTarget != nil {
interceptor.tailer, _ = tail.TailFile(interceptor.redirectFile.Name(), tail.Config{Follow: true})
interceptor.doneTailing = make(chan bool)
go func() {
for line := range interceptor.tailer.Lines {
interceptor.streamTarget.Write([]byte(line.Text + "\n"))
}
close(interceptor.doneTailing)
}()
}
return nil
}
func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) {
if !interceptor.intercepting {
return "", errors.New("Not intercepting output!")
}
interceptor.redirectFile.Close()
output, err := ioutil.ReadFile(interceptor.redirectFile.Name())
os.Remove(interceptor.redirectFile.Name())
interceptor.intercepting = false
if interceptor.streamTarget != nil {
interceptor.tailer.Stop()
interceptor.tailer.Cleanup()
<-interceptor.doneTailing
interceptor.streamTarget.Sync()
}
return string(output), err
}
func (interceptor *outputInterceptor) StreamTo(out *os.File) {
interceptor.streamTarget = out
}

View File

@ -0,0 +1,36 @@
// +build windows
package remote
import (
"errors"
"os"
)
func NewOutputInterceptor() OutputInterceptor {
return &outputInterceptor{}
}
type outputInterceptor struct {
intercepting bool
}
func (interceptor *outputInterceptor) StartInterceptingOutput() error {
if interceptor.intercepting {
return errors.New("Already intercepting output!")
}
interceptor.intercepting = true
// not working on windows...
return nil
}
func (interceptor *outputInterceptor) StopInterceptingAndReturnOutput() (string, error) {
// not working on windows...
interceptor.intercepting = false
return "", nil
}
func (interceptor *outputInterceptor) StreamTo(*os.File) {}

224
vendor/github.com/onsi/ginkgo/internal/remote/server.go generated vendored Normal file
View File

@ -0,0 +1,224 @@
/*
The remote package provides the pieces to allow Ginkgo test suites to report to remote listeners.
This is used, primarily, to enable streaming parallel test output but has, in principal, broader applications (e.g. streaming test output to a browser).
*/
package remote
import (
"encoding/json"
"io/ioutil"
"net"
"net/http"
"sync"
"github.com/onsi/ginkgo/internal/spec_iterator"
"github.com/onsi/ginkgo/config"
"github.com/onsi/ginkgo/reporters"
"github.com/onsi/ginkgo/types"
)
/*
Server spins up on an automatically selected port and listens for communication from the forwarding reporter.
It then forwards that communication to attached reporters.
*/
type Server struct {
listener net.Listener
reporters []reporters.Reporter
alives []func() bool
lock *sync.Mutex
beforeSuiteData types.RemoteBeforeSuiteData
parallelTotal int
counter int
}
//Create a new server, automatically selecting a port
func NewServer(parallelTotal int) (*Server, error) {
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return nil, err
}
return &Server{
listener: listener,
lock: &sync.Mutex{},
alives: make([]func() bool, parallelTotal),
beforeSuiteData: types.RemoteBeforeSuiteData{Data: nil, State: types.RemoteBeforeSuiteStatePending},
parallelTotal: parallelTotal,
}, nil
}
//Start the server. You don't need to `go s.Start()`, just `s.Start()`
func (server *Server) Start() {
httpServer := &http.Server{}
mux := http.NewServeMux()
httpServer.Handler = mux
//streaming endpoints
mux.HandleFunc("/SpecSuiteWillBegin", server.specSuiteWillBegin)
mux.HandleFunc("/BeforeSuiteDidRun", server.beforeSuiteDidRun)
mux.HandleFunc("/AfterSuiteDidRun", server.afterSuiteDidRun)
mux.HandleFunc("/SpecWillRun", server.specWillRun)
mux.HandleFunc("/SpecDidComplete", server.specDidComplete)
mux.HandleFunc("/SpecSuiteDidEnd", server.specSuiteDidEnd)
//synchronization endpoints
mux.HandleFunc("/BeforeSuiteState", server.handleBeforeSuiteState)
mux.HandleFunc("/RemoteAfterSuiteData", server.handleRemoteAfterSuiteData)
mux.HandleFunc("/counter", server.handleCounter)
mux.HandleFunc("/has-counter", server.handleHasCounter) //for backward compatibility
go httpServer.Serve(server.listener)
}
//Stop the server
func (server *Server) Close() {
server.listener.Close()
}
//The address the server can be reached it. Pass this into the `ForwardingReporter`.
func (server *Server) Address() string {
return "http://" + server.listener.Addr().String()
}
//
// Streaming Endpoints
//
//The server will forward all received messages to Ginkgo reporters registered with `RegisterReporters`
func (server *Server) readAll(request *http.Request) []byte {
defer request.Body.Close()
body, _ := ioutil.ReadAll(request.Body)
return body
}
func (server *Server) RegisterReporters(reporters ...reporters.Reporter) {
server.reporters = reporters
}
func (server *Server) specSuiteWillBegin(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var data struct {
Config config.GinkgoConfigType `json:"config"`
Summary *types.SuiteSummary `json:"suite-summary"`
}
json.Unmarshal(body, &data)
for _, reporter := range server.reporters {
reporter.SpecSuiteWillBegin(data.Config, data.Summary)
}
}
func (server *Server) beforeSuiteDidRun(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var setupSummary *types.SetupSummary
json.Unmarshal(body, &setupSummary)
for _, reporter := range server.reporters {
reporter.BeforeSuiteDidRun(setupSummary)
}
}
func (server *Server) afterSuiteDidRun(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var setupSummary *types.SetupSummary
json.Unmarshal(body, &setupSummary)
for _, reporter := range server.reporters {
reporter.AfterSuiteDidRun(setupSummary)
}
}
func (server *Server) specWillRun(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var specSummary *types.SpecSummary
json.Unmarshal(body, &specSummary)
for _, reporter := range server.reporters {
reporter.SpecWillRun(specSummary)
}
}
func (server *Server) specDidComplete(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var specSummary *types.SpecSummary
json.Unmarshal(body, &specSummary)
for _, reporter := range server.reporters {
reporter.SpecDidComplete(specSummary)
}
}
func (server *Server) specSuiteDidEnd(writer http.ResponseWriter, request *http.Request) {
body := server.readAll(request)
var suiteSummary *types.SuiteSummary
json.Unmarshal(body, &suiteSummary)
for _, reporter := range server.reporters {
reporter.SpecSuiteDidEnd(suiteSummary)
}
}
//
// Synchronization Endpoints
//
func (server *Server) RegisterAlive(node int, alive func() bool) {
server.lock.Lock()
defer server.lock.Unlock()
server.alives[node-1] = alive
}
func (server *Server) nodeIsAlive(node int) bool {
server.lock.Lock()
defer server.lock.Unlock()
alive := server.alives[node-1]
if alive == nil {
return true
}
return alive()
}
func (server *Server) handleBeforeSuiteState(writer http.ResponseWriter, request *http.Request) {
if request.Method == "POST" {
dec := json.NewDecoder(request.Body)
dec.Decode(&(server.beforeSuiteData))
} else {
beforeSuiteData := server.beforeSuiteData
if beforeSuiteData.State == types.RemoteBeforeSuiteStatePending && !server.nodeIsAlive(1) {
beforeSuiteData.State = types.RemoteBeforeSuiteStateDisappeared
}
enc := json.NewEncoder(writer)
enc.Encode(beforeSuiteData)
}
}
func (server *Server) handleRemoteAfterSuiteData(writer http.ResponseWriter, request *http.Request) {
afterSuiteData := types.RemoteAfterSuiteData{
CanRun: true,
}
for i := 2; i <= server.parallelTotal; i++ {
afterSuiteData.CanRun = afterSuiteData.CanRun && !server.nodeIsAlive(i)
}
enc := json.NewEncoder(writer)
enc.Encode(afterSuiteData)
}
func (server *Server) handleCounter(writer http.ResponseWriter, request *http.Request) {
c := spec_iterator.Counter{}
server.lock.Lock()
c.Index = server.counter
server.counter = server.counter + 1
server.lock.Unlock()
json.NewEncoder(writer).Encode(c)
}
func (server *Server) handleHasCounter(writer http.ResponseWriter, request *http.Request) {
writer.Write([]byte(""))
}

View File

@ -0,0 +1,11 @@
// +build linux,arm64
package remote
import "syscall"
// linux_arm64 doesn't have syscall.Dup2 which ginkgo uses, so
// use the nearly identical syscall.Dup3 instead
func syscallDup(oldfd int, newfd int) (err error) {
return syscall.Dup3(oldfd, newfd, 0)
}

View File

@ -0,0 +1,9 @@
// +build solaris
package remote
import "golang.org/x/sys/unix"
func syscallDup(oldfd int, newfd int) (err error) {
return unix.Dup2(oldfd, newfd)
}

View File

@ -0,0 +1,11 @@
// +build !linux !arm64
// +build !windows
// +build !solaris
package remote
import "syscall"
func syscallDup(oldfd int, newfd int) (err error) {
return syscall.Dup2(oldfd, newfd)
}