func TestQueue_EvenNumberOfPushesAndPops_GivesZeroFinalLength(t *testing.T) { underTest := NewQueue("Test") numberOfRounds := 200 for i := 0; i < numberOfRounds; i++ { dummyMessagePayLoad := []byte{byte(i)} dummyMessage := message.NewHeaderlessMessage(&dummyMessagePayLoad) underTest.InputChannel <- dummyMessage } gomega.Eventually(func() int { return underTest.length }).Should(gomega.Equal(numberOfRounds)) for i := 0; i < numberOfRounds; i++ { message := <-underTest.OutputChannel if int((*message.Body)[0]) != i { t.Logf("Expected %d, got %d", i, int((*message.Body)[0])) t.FailNow() } } gomega.Eventually(func() int { return underTest.length }).Should(gomega.Equal(0)) }
// 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 (manager *ConnectionManager) parseClientCommand(commandTokens []string, messageBody *[]byte, client *Client) { if len(commandTokens) == 0 { return } commandTokens[0] = strings.ToUpper(commandTokens[0]) switch commandTokens[0] { case "HELP": manager.sendStringToClient(helpString, client) case "PUB": // TODO: Handle headers message := message.NewHeaderlessMessage(messageBody) manager.qm.Publish(commandTokens[1], message) if client.AckRequested { manager.sendStringToClient("PUBACK\n", client) } case "SUB": manager.qm.Subscribe(commandTokens[1], client) case "DISCONNECT": *client.Closed <- true case "PINGREQ": manager.sendStringToClient("PINGRESP", client) case "SETACK": if strings.ToUpper(commandTokens[1]) == "ON" { client.AckRequested = true } else { client.AckRequested = false } case "CLOSE": manager.qm.CloseQueue(commandTokens[1]) default: manager.sendStringToClient(unrecognisedCommandText, client) } }
func TestQueue_CanSendAndReceiveBasicMessages(t *testing.T) { underTest := NewQueue("TestQueue") testMessagePayload := []byte("TestMessage") underTest.InputChannel <- (message.NewHeaderlessMessage(&testMessagePayload)) receivedMessage := <-underTest.OutputChannel if !bytes.Equal(*receivedMessage.Body, testMessagePayload) { t.Fail() } }
func BenchmarkQueueSendRecv(b *testing.B) { dummyMessagePayLoad := []byte("Test") dummyMessage := message.NewHeaderlessMessage(&dummyMessagePayLoad) underTest := NewQueue("Test") for i := 0; i < b.N; i++ { underTest.InputChannel <- dummyMessage } for i := 0; i < b.N; i++ { _ = <-underTest.OutputChannel } }
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 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() } }