func TestDumpWithLotsOfDumps(t *testing.T) { runtime.GOMAXPROCS(runtime.NumCPU()) testDump := dump.NewDumpSink("myApp", 5, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() for i := 0; i < 10; i++ { logMessage := messagetesthelpers.NewMessage(t, strconv.Itoa(i), "appId") inputChan <- logMessage } close(inputChan) <-dumpRunnerDone for i := 0; i < 200; i++ { go func() { logMessages := testDump.Dump() assert.Equal(t, len(logMessages), 5) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "5") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "6") }() } }
func TestDumpAlwaysReturnsTheNewestMessages(t *testing.T) { testDump := dump.NewDumpSink("myApp", 2, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage := messagetesthelpers.NewMessage(t, "1", "appId") inputChan <- logMessage logMessage = messagetesthelpers.NewMessage(t, "2", "appId") inputChan <- logMessage logMessage = messagetesthelpers.NewMessage(t, "3", "appId") inputChan <- logMessage close(inputChan) <-dumpRunnerDone logMessages := testDump.Dump() assert.Equal(t, len(logMessages), 2) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "2") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "3") }
func (sinkManager *SinkManager) ensureRecentLogsSinkFor(appId string) { if sinkManager.sinks.DumpFor(appId) != nil { return } s := dump.NewDumpSink(appId, sinkManager.recentLogCount, sinkManager.logger, time.Hour) sinkManager.RegisterSink(s) }
func TestDumpWithLotsOfMessagesAndLargeBuffer(t *testing.T) { testDump := dump.NewDumpSink("myApp", 200, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() for i := 0; i < 1000; i++ { logMessage := messagetesthelpers.NewMessage(t, strconv.Itoa(i), "appId") inputChan <- logMessage } close(inputChan) <-dumpRunnerDone logMessages := testDump.Dump() assert.Equal(t, len(logMessages), 200) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "800") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "801") dumpRunnerDone = make(chan struct{}) inputChan = make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() for i := 1000; i < 2000; i++ { logMessage := messagetesthelpers.NewMessage(t, strconv.Itoa(i), "appId") inputChan <- logMessage } close(inputChan) <-dumpRunnerDone logMessages = testDump.Dump() assert.Equal(t, len(logMessages), 200) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "1800") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "1801") logMessages = testDump.Dump() assert.Equal(t, len(logMessages), 200) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "1800") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "1801") }
func TestDumpSinkClosesItselfAfterPeriodOfInactivity(t *testing.T) { testDump := dump.NewDumpSink("myApp", 5, loggertesthelper.Logger(), 2*time.Microsecond) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() select { case <-dumpRunnerDone: // OK case <-time.After(200 * time.Millisecond): assert.Fail(t, "Should have timeouted the dump") } }
func TestDumpReturnsAllRecentMessagesToMultipleDumpRequestsWithMessagesCloningInInTheMeantime(t *testing.T) { testDump := dump.NewDumpSink("myApp", 2, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage := messagetesthelpers.NewMessage(t, "1", "appId") inputChan <- logMessage logMessage = messagetesthelpers.NewMessage(t, "2", "appId") inputChan <- logMessage logMessage = messagetesthelpers.NewMessage(t, "3", "appId") inputChan <- logMessage close(inputChan) <-dumpRunnerDone logMessages := testDump.Dump() assert.Equal(t, len(logMessages), 2) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "2") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "3") dumpRunnerDone = make(chan struct{}) inputChan = make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage = messagetesthelpers.NewMessage(t, "4", "appId") inputChan <- logMessage logMessages = testDump.Dump() assert.Equal(t, len(logMessages), 2) assert.Equal(t, string(logMessages[0].GetLogMessage().GetMessage()), "3") assert.Equal(t, string(logMessages[1].GetLogMessage().GetMessage()), "4") }
func TestTheDumpSinkNeverFillsUp(t *testing.T) { bufferSize := uint32(3) testDump := dump.NewDumpSink("myApp", bufferSize, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage := messagetesthelpers.NewMessage(t, "hi", "appId") for i := uint32(0); i < bufferSize+1; i++ { inputChan <- logMessage } close(inputChan) <-dumpRunnerDone }
func xTestDumpSinkClosingTimeIsResetWhenAMessageArrives(t *testing.T) { testDump := dump.NewDumpSink("myApp", 5, loggertesthelper.Logger(), 10*time.Millisecond) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage := messagetesthelpers.NewMessage(t, "0", "appId") inputChan <- logMessage select { case sink := <-dumpRunnerDone: assert.Equal(t, sink, testDump) case <-time.After(5 * time.Millisecond): assert.Fail(t, "Should have closed") } }
func TestDumpForOneMessage(t *testing.T) { testDump := dump.NewDumpSink("myApp", 1, loggertesthelper.Logger(), time.Second) dumpRunnerDone := make(chan struct{}) inputChan := make(chan *logmessage.Message) go func() { testDump.Run(inputChan) close(dumpRunnerDone) }() logMessage := messagetesthelpers.NewMessage(t, "hi", "appId") inputChan <- logMessage close(inputChan) <-dumpRunnerDone data := testDump.Dump() assert.Equal(t, len(data), 1) assert.Equal(t, string(data[0].GetLogMessage().GetMessage()), "hi") }
Expect(otherInputChan).To(HaveLen(0)) close(done) }) It("should not block when sending to an appId that has no sinks", func(done Done) { appId := "NonExistantApp" msg := NewMessage("test message", appId) groupedSinks.BroadCast(appId, msg) close(done) }) }) Describe("BroadCastError", func() { It("should send message to all registered sinks that match the appId", func(done Done) { appId := "123" appSink := dump.NewDumpSink(appId, 10, loggertesthelper.Logger(), time.Second, fakeTimeProvider) otherInputChan := make(chan *logmessage.Message) groupedSinks.Register(otherInputChan, appSink) appId = "789" appSink = dump.NewDumpSink(appId, 10, loggertesthelper.Logger(), time.Second, fakeTimeProvider) groupedSinks.Register(inputChan, appSink) msg := NewMessage("error message", appId) go groupedSinks.BroadCastError(appId, msg) Expect(<-inputChan).To(Equal(msg)) Expect(otherInputChan).To(HaveLen(0)) close(done) })
Eventually(numSyslogSinks).Should(Equal(initialNumSinks)) }) It("Should handle a delete for a nonexistent sink", func() { initialNumSinks := numSyslogSinks() deletedAppServiceChan <- domain.AppService{AppId: "aptastic", Url: "https://localhost:884"} Eventually(numSyslogSinks).Should(Equal(initialNumSinks)) }) }) }) Context("When a dump sink times out", func() { BeforeEach(func() { newAppServiceChan <- domain.AppService{AppId: "appId", Url: "https://localhost:884"} }) It("should remove the app from etcd", func(done Done) { dumpSink := dump.NewDumpSink("appId", 0, loggertesthelper.Logger(), 1*time.Second, &easyReturn{}) sinkManager.RegisterSink(dumpSink) Expect(<-appServicesChan).To(Equal(domain.AppServices{AppId: "appId"})) close(done) }) }) })
deletedAppServiceChan <- domain.AppService{AppId: "aptastic", Url: "syslog://127.0.1.1:886"} Eventually(numSyslogSinks).Should(Equal(initialNumSinks)) }) }) }) Context("When a dump sink times out", func() { BeforeEach(func() { newAppServiceChan <- domain.AppService{AppId: "appId", Url: "syslog://127.0.1.1:887"} }) It("should remove the app from etcd", func(done Done) { dumpSink := dump.NewDumpSink("appId", 1, loggertesthelper.Logger(), 1*time.Millisecond) sinkManager.RegisterSink(dumpSink) Expect(<-appServicesChan).To(Equal(domain.AppServices{AppId: "appId"})) close(done) }) }) Describe("UnregisterSink", func() { Context("with a DumpSink", func() { var dumpSink *dump.DumpSink BeforeEach(func() { dumpSink = dump.NewDumpSink("appId", 1, loggertesthelper.Logger(), time.Hour) sinkManager.RegisterSink(dumpSink)