// A unsubscribing client should not be considered for message delivery func TestQueue_sendMessageAfterUnsubscribe_messageReceivedSuccessfully(t *testing.T) { // Need gomega for async testing gomega.RegisterTestingT(t) testMessagePayload := []byte("Testing!") expectedMessagePayload := []byte("Testing!\r\n.\r\n") testMessage := message.NewHeaderlessMessage(&testMessagePayload) dummyMetricsPipe := make(chan<- *Metric, 10) dummyClosingPipe := make(chan<- *string) underTest := newMessageQueue(TEST_QUEUE_NAME, dummyMetricsPipe, dummyClosingPipe) writerBuffer1 := new(bytes.Buffer) dummyWriter1 := bufio.NewWriter(writerBuffer1) closedChannel1 := make(chan bool) dummyClient1 := Client{Name: "Test1", Writer: dummyWriter1, Closed: &closedChannel1} writerBuffer2 := new(bytes.Buffer) dummyWriter2 := bufio.NewWriter(writerBuffer2) closedChannel2 := make(chan bool) dummyClient2 := Client{Name: "Test2", Writer: dummyWriter2, Closed: &closedChannel2} // Add the subscription underTest.AddSubscriber(&dummyClient1) underTest.AddSubscriber(&dummyClient2) // Queue the message underTest.Publish(testMessage) // Bit of a hack - only one of the subscribers will get the message, // and we don't know which one gomega.Eventually(func() []byte { if writerBuffer1.String() == "" { return writerBuffer2.Bytes() } else { return writerBuffer1.Bytes() } }).Should(gomega.Equal(expectedMessagePayload)) // We'll be reusing these buffers writerBuffer1.Reset() writerBuffer2.Reset() // Close one client *dummyClient1.Closed <- true // Should remove the client from the map gomega.Eventually(func() bool { return underTest.subscribers[dummyClient1.Name] == nil }).Should(gomega.BeTrue()) // Now send a message - the remaining client should receive it without issue underTest.Publish(testMessage) gomega.Eventually(func() []byte { return writerBuffer2.Bytes() }).Should(gomega.Equal(expectedMessagePayload)) }
// Check that messages sent to a queue are eventually sent to consumers func TestQueue_sendMessage_messageReceivedSuccessfully(t *testing.T) { // Need gomega for async testing gomega.RegisterTestingT(t) testMessagePayload := []byte("Testing!") expectedMessagePayload := []byte("Testing!\r\n.\r\n") testMessage := message.NewHeaderlessMessage(&testMessagePayload) dummyMetricsPipe := make(chan<- *Metric) dummyClosingPipe := make(chan<- *string) underTest := newMessageQueue(TEST_QUEUE_NAME, dummyMetricsPipe, dummyClosingPipe) writerBuffer := new(bytes.Buffer) dummyWriter := bufio.NewWriter(writerBuffer) closedChannel := make(chan bool) dummyClient := Client{Name: "Test", Writer: dummyWriter, Closed: &closedChannel} // Add the subscription underTest.AddSubscriber(&dummyClient) // Queue the message underTest.Publish(testMessage) gomega.Eventually(func() []byte { return writerBuffer.Bytes() }).Should(gomega.Equal(expectedMessagePayload)) }
func TestQueue_xPendingMetrics_producesCorrectMetric(t *testing.T) { // Need gomega for async testing gomega.RegisterTestingT(t) numberOfMessagesToSend := 10 testMessagePayload := []byte("Testing!") testMessage := message.NewHeaderlessMessage(&testMessagePayload) dummyMetricsPipe := make(chan *Metric) dummyClosingPipe := make(chan *string) underTest := newMessageQueue(TEST_QUEUE_NAME, dummyMetricsPipe, dummyClosingPipe) for i := 0; i < numberOfMessagesToSend; i++ { underTest.Publish(testMessage) } // Eventually, we should see `numberOfMessagesToSend` pending messages gomega.Eventually(func() int { metric := <-dummyMetricsPipe if strings.Contains(metric.Name, "pending") { return int(metric.Value) } else { return -1 } }, "5s").Should(gomega.Equal(numberOfMessagesToSend)) }
func TestConnectionManager_whenInitialized_acceptsConnectionsCorrectly(t *testing.T) { gomega.RegisterTestingT(t) // Choose a high port, so we don't need sudo to run tests config := Config{} config.Port = 55555 SetConfig(&config) underTest := NewConnectionManager() go underTest.Start() gomega.Eventually(func() net.Listener { return underTest.tcpLn }).ShouldNot(gomega.BeNil()) testConn, err := net.Dial("tcp", "localhost:55555") if err != nil || testConn == nil { t.Fail() } fmt.Fprintf(testConn, "PINGREQ\n") response, err := bufio.NewReader(testConn).ReadString('\n') if err != nil || response != "PINGRESP\n" { t.Fail() } testConn.Close() }
func TestQueue_CloseQueueImmediately_ThrowsNoErrors(t *testing.T) { gomega.RegisterTestingT(t) underTest := NewQueue("Test") close(underTest.InputChannel) gomega.Eventually(func() bool { _, open := <-underTest.OutputChannel return open }).Should(gomega.BeFalse()) }
func TestTokenRefresh(t *testing.T) { gomega.RegisterTestingT(t) Convey("Test making request", t, func() { setup(MockRoute{"GET", "/v2/organizations", listOrgsPayload}) c := &Config{ ApiAddress: server.URL, LoginAddress: fakeUAAServer.URL, Username: "******", Password: "******", } client := NewClient(c) gomega.Consistently(client.GetToken()).Should(gomega.Equal("bearer foobar2")) gomega.Eventually(client.GetToken(), "3s").Should(gomega.Equal("bearer foobar3")) }) }
func TestQueue_sendMessage_generatesMetrics(t *testing.T) { // More async testing gomega.RegisterTestingT(t) // We should receive metrics ending in these names from a queue during // normal operation expectedMetricNames := [...]string{"messagerate", "subscribers", "pending"} // Mocking dummyMetricsChannel := make(chan *Metric) dummyClosingChannel := make(chan *string) underTest := newMessageQueue(TEST_QUEUE_NAME, dummyMetricsChannel, dummyClosingChannel) // After a subscriber is added, we should start receiving metrics dummySubscriber := Client{Closed: new(chan bool)} underTest.AddSubscriber(&dummySubscriber) seenMetricNames := make(map[string]bool) go func() { for { metric := <-dummyMetricsChannel metricNameChunks := strings.Split(metric.Name, ".") finalMetricName := metricNameChunks[len(metricNameChunks)-1] seenMetricNames[finalMetricName] = true } }() // Check we've received metrics ending in all the expected names // NOTE: It might take longer than the default gomega 1 second timeout to // receive all the metrics we're expecting gomega.Eventually(func() bool { toReturn := true for _, metricName := range expectedMetricNames { if !seenMetricNames[metricName] { toReturn = false } } return toReturn }, "5s").Should(gomega.BeTrue()) // Timeout upped to 5 seconds }
func TestMessageShipper_SuccessfullyForwardsMessages(t *testing.T) { gomega.RegisterTestingT(t) inputChannel := make(chan *message.Message, 0) writerBuffer := new(bytes.Buffer) dummyWriter := bufio.NewWriter(writerBuffer) closedChannel := make(chan bool) dummyClient := Client{Name: "Test", Writer: dummyWriter, Closed: &closedChannel} dummyMetricsChannel := make(chan *Metric) underTest := newMessageShipper(inputChannel, &dummyClient, dummyMetricsChannel, "test") testMessagePayload := []byte("This is a test!") expectedMessagePayload := []byte("This is a test!\r\n.\r\n") testMessage := message.NewHeaderlessMessage(&testMessagePayload) underTest.messageChannel <- testMessage gomega.Eventually(func() []byte { return writerBuffer.Bytes() }).Should(gomega.Equal(expectedMessagePayload)) }
func TestConnectionManager_disconnectCommand_removesClient(t *testing.T) { gomega.RegisterTestingT(t) underTest := ConnectionManager{} buf := new(bytes.Buffer) bufWriter := bufio.NewWriter(buf) mockClient := NewClient("Mock", bufWriter, nil) closedChannel := make(chan bool, 1) mockClient.Closed = &closedChannel t.Log("Disconnecting") var emptyMessage []byte underTest.parseClientCommand([]string{"disconnect"}, &emptyMessage, mockClient) gomega.Eventually(func() bool { closed := <-*(mockClient.Closed) return closed }).Should(gomega.BeTrue()) }
func TestQueue_ReceiveBeforeSend_ReturnsExpectedResult(t *testing.T) { gomega.RegisterTestingT(t) underTest := NewQueue("TestQueue") var receivedMessage *message.Message go func() { receivedMessage = <-underTest.OutputChannel }() time.Sleep(time.Millisecond * 10) testMessagePayload := []byte("TestMessage") underTest.InputChannel <- (message.NewHeaderlessMessage(&testMessagePayload)) gomega.Eventually(func() *message.Message { return receivedMessage }).Should(gomega.Not(gomega.BeNil())) if !bytes.Equal(*receivedMessage.Body, testMessagePayload) { t.Fail() } }
func TestVersionStaging(t *testing.T) { gomega.RegisterTestingT(t) stor := testutil.NewStorage() defer stor.Close() s, err := newSession(stor, nil) if err != nil { t.Fatal(err) } v := newVersion(s) v.newStaging() tmp := make([]byte, 4) mik := func(i uint64) []byte { binary.BigEndian.PutUint32(tmp, uint32(i)) return []byte(makeInternalKey(nil, tmp, 0, keyTypeVal)) } for i, x := range []struct { add, del []testFileRec levels [][]int64 }{ { add: []testFileRec{ {1, 1}, }, levels: [][]int64{ {}, {1}, }, }, { add: []testFileRec{ {1, 1}, }, levels: [][]int64{ {}, {1}, }, }, { del: []testFileRec{ {1, 1}, }, levels: [][]int64{}, }, { add: []testFileRec{ {0, 1}, {0, 3}, {0, 2}, {2, 5}, {1, 4}, }, levels: [][]int64{ {3, 2, 1}, {4}, {5}, }, }, { add: []testFileRec{ {1, 6}, {2, 5}, }, del: []testFileRec{ {0, 1}, {0, 4}, }, levels: [][]int64{ {3, 2}, {4, 6}, {5}, }, }, { del: []testFileRec{ {0, 3}, {0, 2}, {1, 4}, {1, 6}, {2, 5}, }, levels: [][]int64{}, }, { add: []testFileRec{ {0, 1}, }, levels: [][]int64{ {1}, }, }, { add: []testFileRec{ {1, 2}, }, levels: [][]int64{ {1}, {2}, }, }, { add: []testFileRec{ {0, 3}, }, levels: [][]int64{ {3, 1}, {2}, }, }, { add: []testFileRec{ {6, 9}, }, levels: [][]int64{ {3, 1}, {2}, {}, {}, {}, {}, {9}, }, }, { del: []testFileRec{ {6, 9}, }, levels: [][]int64{ {3, 1}, {2}, }, }, } { rec := &sessionRecord{} for _, f := range x.add { ik := mik(uint64(f.num)) rec.addTable(f.level, f.num, 1, ik, ik) } for _, f := range x.del { rec.delTable(f.level, f.num) } vs := v.newStaging() vs.commit(rec) v = vs.finish() if len(v.levels) != len(x.levels) { t.Fatalf("#%d: invalid level count: want=%d got=%d", i, len(x.levels), len(v.levels)) } for j, want := range x.levels { tables := v.levels[j] if len(want) != len(tables) { t.Fatalf("#%d.%d: invalid tables count: want=%d got=%d", i, j, len(want), len(tables)) } got := make([]int64, len(tables)) for k, t := range tables { got[k] = t.fd.Num } if !reflect.DeepEqual(want, got) { t.Fatalf("#%d.%d: invalid tables: want=%v got=%v", i, j, want, got) } } } }
func TestMetricsManager_ReceivesBasicMetric_PublishesDownstreamAndSendsToStatsD(t *testing.T) { gomega.RegisterTestingT(t) // Listen on UDP var statsDBuffer [2048]byte var udpPacketsReceived int udpAddr, _ := net.ResolveUDPAddr("udp", ":0") udpConn, _ := net.ListenUDP("udp", udpAddr) // Don't care about the contents of the received messages - just the fact // that we received them. We trust the StatsD library go func() { for i := 0; i < 3; i++ { _, _, _ = udpConn.ReadFromUDP(statsDBuffer[0:]) udpPacketsReceived++ } }() config := Config{StatsDEndpoint: fmt.Sprintf("localhost:%d", udpConn.LocalAddr().(*net.UDPAddr).Port)} SetConfig(&config) qm := newQueueManager() // Listen to metrics queue writerBuffer := new(bytes.Buffer) dummyWriter := bufio.NewWriter(writerBuffer) closedChannel := make(chan bool) dummyClient := Client{Name: "Test", Writer: dummyWriter, Closed: &closedChannel} qm.Subscribe("metrics", &dummyClient) // Log one of each metric // Check we've received metrics both via UDP - and on the metrics channel testMetric := NewMetric("test", "guage", 123) qm.metricsManager.metricsChannel <- testMetric gomega.Eventually(func() int { return udpPacketsReceived }, "2s").Should(gomega.Equal(1)) gomega.Eventually(func() []byte { return writerBuffer.Bytes() }).ShouldNot(gomega.BeNil()) writerBuffer.Reset() testMetric2 := NewMetric("test", "counter", 123) qm.metricsManager.metricsChannel <- testMetric2 gomega.Eventually(func() int { return udpPacketsReceived }, "2s").Should(gomega.Equal(2)) gomega.Eventually(func() []byte { return writerBuffer.Bytes() }).ShouldNot(gomega.BeNil()) writerBuffer.Reset() testMetric3 := NewMetric("test", "timing", 123) qm.metricsManager.metricsChannel <- testMetric3 gomega.Eventually(func() int { return udpPacketsReceived }, "2s").Should(gomega.Equal(3)) gomega.Eventually(func() []byte { return writerBuffer.Bytes() }).ShouldNot(gomega.BeNil()) writerBuffer.Reset() }