mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-19 11:35:10 +00:00
65aaa607ab
Change made by: - running "gvt fetch" on each of the packages mentioned in Godeps/Godeps.json - `rm -rf Godeps` - tweaking the build scripts to not mention Godeps - tweaking the build scripts to test `./lib/...`, `./cmd/...` explicitly (to avoid testing vendor) - tweaking the build scripts to not juggle GOPATH for Godeps and instead set GO15VENDOREXPERIMENT. This also results in some updated packages at the same time I bet. Building with Go 1.3 and 1.4 still *works* but won't use our vendored dependencies - the user needs to have the actual packages in their GOPATH then, which they'll get with a normal "go get". Building with Go 1.6+ will get our vendored dependencies by default even when not using our build script, which is nice. By doing this we gain some freedom in that we can pick and choose manually what to include in vendor, as it's not based on just dependency analysis of our own code. This is also a risk as we might pick up dependencies we are unaware of, as the build may work locally with those packages present in GOPATH. On the other hand the build server will detect this as it has no packages in it's GOPATH beyond what is included in the repo. Recommended tool to manage dependencies is github.com/FiloSottile/gvt.
205 lines
5.7 KiB
Go
205 lines
5.7 KiB
Go
/*
|
|
|
|
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"
|
|
"github.com/onsi/ginkgo/config"
|
|
"github.com/onsi/ginkgo/reporters"
|
|
"github.com/onsi/ginkgo/types"
|
|
"io/ioutil"
|
|
"net"
|
|
"net/http"
|
|
"sync"
|
|
)
|
|
|
|
/*
|
|
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
|
|
}
|
|
|
|
//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{nil, 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)
|
|
|
|
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)
|
|
}
|