mirror of
https://github.com/mainflux/mainflux.git
synced 2025-04-24 13:48:49 +08:00

* Refactor message broker implementation This commit refactors the Nats message broker implementation to include pubsub options. These changes include: - Adding `Option` func that takes in the URL and prefix - Implement `WithStream` option which can create a different stream for nats stream - Implement `WithExchange` option which can create a different exchaange for rabbitmq channel - Implement `WithPrefix` option which allows to you change the publisher prefix These changes improve the organization and readability of the codebase. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Use redis URL to configure username, password and db Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Make event store configurable on dev deployment Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix adds options to messaging `PubSub` interface Adding options to PubSub interface allows the use of messaging package to do es. The changes in this commit ensure that the code handles errors properly and provides more informative error messages when encountering unexpected types. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Add NATS event publisher implementation This commit adds the implementation of the NATS event publisher. The NATS event publisher is responsible for publishing events to a NATS messaging system. It uses the `messaging` package to interact with the messaging system. The implementation includes the following features: - Publishing events to NATS using the `Publish` method. - Marshaling events to JSON before publishing. - Setting the message subject and headers based on the event. - Handling errors during publishing. This implementation is built with the `!rabbitmq` build tag, which means it will only be compiled if the `rabbitmq` build tag is not present. The NATS event publisher is part of the Mainflux events package and provides support for the Mainflux NATS events source service functionality. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Add RabbitMQ event publisher implementation This commit adds the implementation of the RabbitMQ event publisher. The RabbitMQ event publisher is responsible for publishing events to a RabbitMQ messaging system. It uses the `messaging` package to interact with the messaging system. The implementation includes the following features: - Publishing events to RabbitMQ using the `Publish` method. - Marshaling events to JSON before publishing. - Setting the message subject and headers based on the event. - Handling errors during publishing. This implementation is built with the `rabbitmq` build tag, which means it will only be compiled if the `rabbitmq` build tag is present. The RabbitMQ event publisher is part of the Mainflux events package and provides support for the Mainflux RabbitMQ events source service functionality. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Add configurable implementation for events store This commit adds a new file `brokers_*.go` which contains the implementation for the different event store. The file includes functions for creating a new publisher and subscriber using different es store. This commit also includes an `init` function that logs a message indicating that the binary was built using the respective package as the events store. The purpose of this commit is to add support for alternative events store. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix build flags Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Refactor Makefile and Semaphore configuration The Makefile has been refactored to include the `MF_ES_STORE_TYPE` tag in the `go build` command. Additionally, the Semaphore configuration has been updated to include a new task for compiling with Redis as the broker type. This commit addresses the need to compile the codebase with Redis as the event store type and includes the necessary changes in the Makefile and Semaphore configuration. Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Reduced due to memory on testing Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix tests for es Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix grammar Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com> Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix linting Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * feat(docker): update environment variables for message broker The commit updates the environment variable `MF_ES_STORE_TYPE` in the `docker/.env` file. The variable is changed from `${MF_MQTT_BROKER_TYPE}` to `${MF_MESSAGE_BROKER_TYPE}` to accurately reflect the type of message broker being used. This change ensures that the correct message broker is configured for the Event Store. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * feat: Update docker environment variables - Removed the unused MF_ES_URL variable in the .env file - Updated the MF_ES_STORE_TYPE and MF_ES_STORE_URL variables in the .env file to match the MF_MESSAGE_BROKER_TYPE and MF_NATS_URL variables respectively Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Fix after rebase Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Add godocs for option parameters for brokers Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * pass by value exchange and prefix names Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * Rename option functions Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * move variables to constants Signed-off-by: rodneyosodo <blackd0t@protonmail.com> * fix: option example comment Signed-off-by: rodneyosodo <blackd0t@protonmail.com> --------- Signed-off-by: Rodney Osodo <socials@rodneyosodo.com> Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> Signed-off-by: rodneyosodo <blackd0t@protonmail.com> Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
461 lines
13 KiB
Go
461 lines
13 KiB
Go
// Copyright (c) Mainflux
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package rabbitmq_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/mainflux/mainflux/pkg/messaging"
|
|
"github.com/mainflux/mainflux/pkg/messaging/rabbitmq"
|
|
amqp "github.com/rabbitmq/amqp091-go"
|
|
"github.com/stretchr/testify/assert"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const (
|
|
topic = "topic"
|
|
chansPrefix = "channels"
|
|
channel = "9b7b1b3f-b1b0-46a8-a717-b8213f9eda3b"
|
|
subtopic = "engine"
|
|
clientID = "9b7b1b3f-b1b0-46a8-a717-b8213f9eda3b"
|
|
exchangeName = "messages"
|
|
)
|
|
|
|
var (
|
|
msgChan = make(chan *messaging.Message)
|
|
data = []byte("payload")
|
|
)
|
|
|
|
var errFailedHandleMessage = errors.New("failed to handle mainflux message")
|
|
|
|
func TestPublisher(t *testing.T) {
|
|
// Subscribing with topic, and with subtopic, so that we can publish messages.
|
|
conn, ch, err := newConn()
|
|
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
topicChan := subscribe(t, ch, fmt.Sprintf("%s.%s", chansPrefix, topic))
|
|
subtopicChan := subscribe(t, ch, fmt.Sprintf("%s.%s.%s", chansPrefix, topic, subtopic))
|
|
|
|
go rabbitHandler(topicChan, handler{})
|
|
go rabbitHandler(subtopicChan, handler{})
|
|
|
|
t.Cleanup(func() {
|
|
conn.Close()
|
|
ch.Close()
|
|
})
|
|
|
|
cases := []struct {
|
|
desc string
|
|
channel string
|
|
subtopic string
|
|
payload []byte
|
|
}{
|
|
{
|
|
desc: "publish message with nil payload",
|
|
payload: nil,
|
|
},
|
|
{
|
|
desc: "publish message with string payload",
|
|
payload: data,
|
|
},
|
|
{
|
|
desc: "publish message with channel",
|
|
payload: data,
|
|
channel: channel,
|
|
},
|
|
{
|
|
desc: "publish message with subtopic",
|
|
payload: data,
|
|
subtopic: subtopic,
|
|
},
|
|
{
|
|
desc: "publish message with channel and subtopic",
|
|
payload: data,
|
|
channel: channel,
|
|
subtopic: subtopic,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
expectedMsg := messaging.Message{
|
|
Publisher: clientID,
|
|
Channel: tc.channel,
|
|
Subtopic: tc.subtopic,
|
|
Payload: tc.payload,
|
|
}
|
|
err = pubsub.Publish(context.TODO(), topic, &expectedMsg)
|
|
assert.Nil(t, err, fmt.Sprintf("%s: got unexpected error: %s", tc.desc, err))
|
|
|
|
receivedMsg := <-msgChan
|
|
assert.Equal(t, expectedMsg.Channel, receivedMsg.Channel, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Created, receivedMsg.Created, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Protocol, receivedMsg.Protocol, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Publisher, receivedMsg.Publisher, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Subtopic, receivedMsg.Subtopic, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Payload, receivedMsg.Payload, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
}
|
|
}
|
|
|
|
func TestSubscribe(t *testing.T) {
|
|
// Creating rabbitmq connection and channel, so that we can publish messages.
|
|
conn, ch, err := newConn()
|
|
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
t.Cleanup(func() {
|
|
conn.Close()
|
|
ch.Close()
|
|
})
|
|
|
|
cases := []struct {
|
|
desc string
|
|
topic string
|
|
clientID string
|
|
err error
|
|
handler messaging.MessageHandler
|
|
}{
|
|
{
|
|
desc: "Subscribe to a topic with an ID",
|
|
topic: topic,
|
|
clientID: "clientid1",
|
|
err: nil,
|
|
handler: handler{false, "clientid1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to the same topic with a different ID",
|
|
topic: topic,
|
|
clientID: "clientid2",
|
|
err: nil,
|
|
handler: handler{false, "clientid2"},
|
|
},
|
|
{
|
|
desc: "Subscribe to an already subscribed topic with an ID",
|
|
topic: topic,
|
|
clientID: "clientid1",
|
|
err: nil,
|
|
handler: handler{false, "clientid1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to a topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", topic, subtopic),
|
|
clientID: "clientid1",
|
|
err: nil,
|
|
handler: handler{false, "clientid1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to an already subscribed topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", topic, subtopic),
|
|
clientID: "clientid1",
|
|
err: nil,
|
|
handler: handler{false, "clientid1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to an empty topic with an ID",
|
|
topic: "",
|
|
clientID: "clientid1",
|
|
err: rabbitmq.ErrEmptyTopic,
|
|
handler: handler{false, "clientid1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to a topic with empty id",
|
|
topic: topic,
|
|
clientID: "",
|
|
err: rabbitmq.ErrEmptyID,
|
|
handler: handler{false, ""},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
subCfg := messaging.SubscriberConfig{
|
|
ID: tc.clientID,
|
|
Topic: tc.topic,
|
|
Handler: tc.handler,
|
|
}
|
|
err := pubsub.Subscribe(context.TODO(), subCfg)
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected: %s, but got: %s", tc.desc, tc.err, err))
|
|
|
|
if tc.err == nil {
|
|
expectedMsg := messaging.Message{
|
|
Publisher: "CLIENTID",
|
|
Channel: channel,
|
|
Subtopic: subtopic,
|
|
Payload: data,
|
|
}
|
|
|
|
data, err := proto.Marshal(&expectedMsg)
|
|
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
err = ch.PublishWithContext(
|
|
context.Background(),
|
|
exchangeName,
|
|
tc.topic,
|
|
false,
|
|
false,
|
|
amqp.Publishing{
|
|
Headers: amqp.Table{},
|
|
ContentType: "application/octet-stream",
|
|
AppId: "mainflux-publisher",
|
|
Body: data,
|
|
})
|
|
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
|
|
|
receivedMsg := <-msgChan
|
|
assert.Equal(t, expectedMsg.Channel, receivedMsg.Channel, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Created, receivedMsg.Created, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Protocol, receivedMsg.Protocol, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Publisher, receivedMsg.Publisher, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Subtopic, receivedMsg.Subtopic, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Payload, receivedMsg.Payload, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUnsubscribe(t *testing.T) {
|
|
// Test Subscribe and Unsubscribe
|
|
cases := []struct {
|
|
desc string
|
|
topic string
|
|
clientID string
|
|
err error
|
|
subscribe bool // True for subscribe and false for unsubscribe.
|
|
handler messaging.MessageHandler
|
|
}{
|
|
{
|
|
desc: "Subscribe to a topic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "clientid4",
|
|
err: nil,
|
|
subscribe: true,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Subscribe to the same topic with a different ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "clientid9",
|
|
err: nil,
|
|
subscribe: true,
|
|
handler: handler{false, "clientid9"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a topic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "clientid4",
|
|
err: nil,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from same topic with different ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "clientid9",
|
|
err: nil,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid9"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a non-existent topic with an ID",
|
|
topic: "h",
|
|
clientID: "clientid4",
|
|
err: rabbitmq.ErrNotSubscribed,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from an already unsubscribed topic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "clientid4",
|
|
err: rabbitmq.ErrNotSubscribed,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Subscribe to a topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s.%s", chansPrefix, topic, subtopic),
|
|
clientID: "clientidd4",
|
|
err: nil,
|
|
subscribe: true,
|
|
handler: handler{false, "clientidd4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s.%s", chansPrefix, topic, subtopic),
|
|
clientID: "clientidd4",
|
|
err: nil,
|
|
subscribe: false,
|
|
handler: handler{false, "clientidd4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from an already unsubscribed topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s.%s", chansPrefix, topic, subtopic),
|
|
clientID: "clientid4",
|
|
err: rabbitmq.ErrNotSubscribed,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from an empty topic with an ID",
|
|
topic: "",
|
|
clientID: "clientid4",
|
|
err: rabbitmq.ErrEmptyTopic,
|
|
subscribe: false,
|
|
handler: handler{false, "clientid4"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a topic with empty ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic),
|
|
clientID: "",
|
|
err: rabbitmq.ErrEmptyID,
|
|
subscribe: false,
|
|
handler: handler{false, ""},
|
|
},
|
|
{
|
|
desc: "Subscribe to a new topic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic+"2"),
|
|
clientID: "clientid55",
|
|
err: nil,
|
|
subscribe: true,
|
|
handler: handler{true, "clientid5"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a topic with an ID with failing handler",
|
|
topic: fmt.Sprintf("%s.%s", chansPrefix, topic+"2"),
|
|
clientID: "clientid55",
|
|
err: errFailedHandleMessage,
|
|
subscribe: false,
|
|
handler: handler{true, "clientid5"},
|
|
},
|
|
{
|
|
desc: "Subscribe to a new topic with subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s.%s", chansPrefix, topic+"2", subtopic),
|
|
clientID: "clientid55",
|
|
err: nil,
|
|
subscribe: true,
|
|
handler: handler{true, "clientid5"},
|
|
},
|
|
{
|
|
desc: "Unsubscribe from a topic with subtopic with an ID with failing handler",
|
|
topic: fmt.Sprintf("%s.%s.%s", chansPrefix, topic+"2", subtopic),
|
|
clientID: "clientid55",
|
|
err: errFailedHandleMessage,
|
|
subscribe: false,
|
|
handler: handler{true, "clientid5"},
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
subCfg := messaging.SubscriberConfig{
|
|
ID: tc.clientID,
|
|
Topic: tc.topic,
|
|
Handler: tc.handler,
|
|
}
|
|
switch tc.subscribe {
|
|
case true:
|
|
err := pubsub.Subscribe(context.TODO(), subCfg)
|
|
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected: %s, but got: %s", tc.desc, tc.err, err))
|
|
default:
|
|
err := pubsub.Unsubscribe(context.TODO(), tc.clientID, tc.topic)
|
|
assert.Equal(t, err, tc.err, fmt.Sprintf("%s: expected: %s, but got: %s", tc.desc, tc.err, err))
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPubSub(t *testing.T) {
|
|
cases := []struct {
|
|
desc string
|
|
topic string
|
|
clientID string
|
|
err error
|
|
handler messaging.MessageHandler
|
|
}{
|
|
{
|
|
desc: "Subscribe to a topic with an ID",
|
|
topic: topic,
|
|
clientID: clientID,
|
|
err: nil,
|
|
handler: handler{false, clientID},
|
|
},
|
|
{
|
|
desc: "Subscribe to the same topic with a different ID",
|
|
topic: topic,
|
|
clientID: clientID + "1",
|
|
err: nil,
|
|
handler: handler{false, clientID + "1"},
|
|
},
|
|
{
|
|
desc: "Subscribe to a topic with a subtopic with an ID",
|
|
topic: fmt.Sprintf("%s.%s", topic, subtopic),
|
|
clientID: clientID + "2",
|
|
err: nil,
|
|
handler: handler{false, clientID + "2"},
|
|
},
|
|
{
|
|
desc: "Subscribe to an empty topic with an ID",
|
|
topic: "",
|
|
clientID: clientID,
|
|
err: rabbitmq.ErrEmptyTopic,
|
|
handler: handler{false, clientID},
|
|
},
|
|
{
|
|
desc: "Subscribe to a topic with empty id",
|
|
topic: topic,
|
|
clientID: "",
|
|
err: rabbitmq.ErrEmptyID,
|
|
handler: handler{false, ""},
|
|
},
|
|
}
|
|
for _, tc := range cases {
|
|
subject := ""
|
|
if tc.topic != "" {
|
|
subject = fmt.Sprintf("%s.%s", chansPrefix, tc.topic)
|
|
}
|
|
subCfg := messaging.SubscriberConfig{
|
|
ID: tc.clientID,
|
|
Topic: subject,
|
|
Handler: tc.handler,
|
|
}
|
|
err := pubsub.Subscribe(context.TODO(), subCfg)
|
|
|
|
switch tc.err {
|
|
case nil:
|
|
// If no error, publish message, and receive after subscribing.
|
|
expectedMsg := messaging.Message{
|
|
Channel: channel,
|
|
Payload: data,
|
|
}
|
|
|
|
err = pubsub.Publish(context.TODO(), tc.topic, &expectedMsg)
|
|
assert.Nil(t, err, fmt.Sprintf("%s got unexpected error: %s", tc.desc, err))
|
|
|
|
receivedMsg := <-msgChan
|
|
assert.Equal(t, expectedMsg.Channel, receivedMsg.Channel, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
assert.Equal(t, expectedMsg.Payload, receivedMsg.Payload, fmt.Sprintf("%s: expected %+v got %+v\n", tc.desc, &expectedMsg, receivedMsg))
|
|
|
|
err = pubsub.Unsubscribe(context.TODO(), tc.clientID, fmt.Sprintf("%s.%s", chansPrefix, tc.topic))
|
|
assert.Nil(t, err, fmt.Sprintf("%s got unexpected error: %s", tc.desc, err))
|
|
default:
|
|
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected: %s, but got: %s", tc.desc, err, tc.err))
|
|
}
|
|
}
|
|
}
|
|
|
|
type handler struct {
|
|
fail bool
|
|
publisher string
|
|
}
|
|
|
|
func (h handler) Handle(msg *messaging.Message) error {
|
|
if msg.Publisher != h.publisher {
|
|
msgChan <- msg
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (h handler) Cancel() error {
|
|
if h.fail {
|
|
return errFailedHandleMessage
|
|
}
|
|
return nil
|
|
}
|