package remote_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/internal/remote" . "github.com/onsi/gomega" "github.com/onsi/ginkgo/config" "github.com/onsi/ginkgo/reporters" "github.com/onsi/ginkgo/types" "bytes" "encoding/json" "net/http" ) var _ = Describe("Server", func() { var ( server *Server ) BeforeEach(func() { var err error server, err = NewServer(3) Ω(err).ShouldNot(HaveOccurred()) server.Start() }) AfterEach(func() { server.Close() }) Describe("Streaming endpoints", func() { var ( reporterA, reporterB *reporters.FakeReporter forwardingReporter *ForwardingReporter suiteSummary *types.SuiteSummary setupSummary *types.SetupSummary specSummary *types.SpecSummary ) BeforeEach(func() { reporterA = reporters.NewFakeReporter() reporterB = reporters.NewFakeReporter() server.RegisterReporters(reporterA, reporterB) forwardingReporter = NewForwardingReporter(server.Address(), &http.Client{}, &fakeOutputInterceptor{}) suiteSummary = &types.SuiteSummary{ SuiteDescription: "My Test Suite", } setupSummary = &types.SetupSummary{ State: types.SpecStatePassed, } specSummary = &types.SpecSummary{ ComponentTexts: []string{"My", "Spec"}, State: types.SpecStatePassed, } }) It("should make its address available", func() { Ω(server.Address()).Should(MatchRegexp(`http://127.0.0.1:\d{2,}`)) }) Describe("/SpecSuiteWillBegin", func() { It("should decode and forward the Ginkgo config and suite summary", func(done Done) { forwardingReporter.SpecSuiteWillBegin(config.GinkgoConfig, suiteSummary) Ω(reporterA.Config).Should(Equal(config.GinkgoConfig)) Ω(reporterB.Config).Should(Equal(config.GinkgoConfig)) Ω(reporterA.BeginSummary).Should(Equal(suiteSummary)) Ω(reporterB.BeginSummary).Should(Equal(suiteSummary)) close(done) }) }) Describe("/BeforeSuiteDidRun", func() { It("should decode and forward the setup summary", func() { forwardingReporter.BeforeSuiteDidRun(setupSummary) Ω(reporterA.BeforeSuiteSummary).Should(Equal(setupSummary)) Ω(reporterB.BeforeSuiteSummary).Should(Equal(setupSummary)) }) }) Describe("/AfterSuiteDidRun", func() { It("should decode and forward the setup summary", func() { forwardingReporter.AfterSuiteDidRun(setupSummary) Ω(reporterA.AfterSuiteSummary).Should(Equal(setupSummary)) Ω(reporterB.AfterSuiteSummary).Should(Equal(setupSummary)) }) }) Describe("/SpecWillRun", func() { It("should decode and forward the spec summary", func(done Done) { forwardingReporter.SpecWillRun(specSummary) Ω(reporterA.SpecWillRunSummaries[0]).Should(Equal(specSummary)) Ω(reporterB.SpecWillRunSummaries[0]).Should(Equal(specSummary)) close(done) }) }) Describe("/SpecDidComplete", func() { It("should decode and forward the spec summary", func(done Done) { forwardingReporter.SpecDidComplete(specSummary) Ω(reporterA.SpecSummaries[0]).Should(Equal(specSummary)) Ω(reporterB.SpecSummaries[0]).Should(Equal(specSummary)) close(done) }) }) Describe("/SpecSuiteDidEnd", func() { It("should decode and forward the suite summary", func(done Done) { forwardingReporter.SpecSuiteDidEnd(suiteSummary) Ω(reporterA.EndSummary).Should(Equal(suiteSummary)) Ω(reporterB.EndSummary).Should(Equal(suiteSummary)) close(done) }) }) }) Describe("Synchronization endpoints", func() { Describe("GETting and POSTing BeforeSuiteState", func() { getBeforeSuite := func() types.RemoteBeforeSuiteData { resp, err := http.Get(server.Address() + "/BeforeSuiteState") Ω(err).ShouldNot(HaveOccurred()) Ω(resp.StatusCode).Should(Equal(http.StatusOK)) r := types.RemoteBeforeSuiteData{} decoder := json.NewDecoder(resp.Body) err = decoder.Decode(&r) Ω(err).ShouldNot(HaveOccurred()) return r } postBeforeSuite := func(r types.RemoteBeforeSuiteData) { resp, err := http.Post(server.Address()+"/BeforeSuiteState", "application/json", bytes.NewReader(r.ToJSON())) Ω(err).ShouldNot(HaveOccurred()) Ω(resp.StatusCode).Should(Equal(http.StatusOK)) } Context("when the first node's Alive has not been registered yet", func() { It("should return pending", func() { state := getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStatePending})) state = getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStatePending})) }) }) Context("when the first node is Alive but has not responded yet", func() { BeforeEach(func() { server.RegisterAlive(1, func() bool { return true }) }) It("should return pending", func() { state := getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStatePending})) state = getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStatePending})) }) }) Context("when the first node has responded", func() { var state types.RemoteBeforeSuiteData BeforeEach(func() { server.RegisterAlive(1, func() bool { return false }) state = types.RemoteBeforeSuiteData{ Data: []byte("my data"), State: types.RemoteBeforeSuiteStatePassed, } postBeforeSuite(state) }) It("should return the passed in state", func() { returnedState := getBeforeSuite() Ω(returnedState).Should(Equal(state)) }) }) Context("when the first node is no longer Alive and has not responded yet", func() { BeforeEach(func() { server.RegisterAlive(1, func() bool { return false }) }) It("should return disappeared", func() { state := getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStateDisappeared})) state = getBeforeSuite() Ω(state).Should(Equal(types.RemoteBeforeSuiteData{nil, types.RemoteBeforeSuiteStateDisappeared})) }) }) }) Describe("GETting RemoteAfterSuiteData", func() { getRemoteAfterSuiteData := func() bool { resp, err := http.Get(server.Address() + "/RemoteAfterSuiteData") Ω(err).ShouldNot(HaveOccurred()) Ω(resp.StatusCode).Should(Equal(http.StatusOK)) a := types.RemoteAfterSuiteData{} decoder := json.NewDecoder(resp.Body) err = decoder.Decode(&a) Ω(err).ShouldNot(HaveOccurred()) return a.CanRun } Context("when there are unregistered nodes", func() { BeforeEach(func() { server.RegisterAlive(2, func() bool { return false }) }) It("should return false", func() { Ω(getRemoteAfterSuiteData()).Should(BeFalse()) }) }) Context("when all none-node-1 nodes are still running", func() { BeforeEach(func() { server.RegisterAlive(2, func() bool { return true }) server.RegisterAlive(3, func() bool { return false }) }) It("should return false", func() { Ω(getRemoteAfterSuiteData()).Should(BeFalse()) }) }) Context("when all none-1 nodes are done", func() { BeforeEach(func() { server.RegisterAlive(2, func() bool { return false }) server.RegisterAlive(3, func() bool { return false }) }) It("should return true", func() { Ω(getRemoteAfterSuiteData()).Should(BeTrue()) }) }) }) }) })