2014-10-21 02:42:03 +00:00
|
|
|
package messaging_test
|
2014-10-03 03:13:42 +00:00
|
|
|
|
|
|
|
import (
|
2014-10-04 17:27:12 +00:00
|
|
|
"bytes"
|
2014-10-12 18:05:03 +00:00
|
|
|
"fmt"
|
2014-10-15 03:42:40 +00:00
|
|
|
"io"
|
2014-10-03 03:13:42 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2014-10-04 17:27:12 +00:00
|
|
|
"reflect"
|
2014-10-03 03:13:42 +00:00
|
|
|
"testing"
|
2014-10-04 17:27:12 +00:00
|
|
|
"time"
|
2014-10-03 03:13:42 +00:00
|
|
|
|
2014-10-21 02:42:03 +00:00
|
|
|
"github.com/influxdb/influxdb/messaging"
|
2014-10-03 03:13:42 +00:00
|
|
|
)
|
|
|
|
|
2014-10-12 18:05:03 +00:00
|
|
|
// Ensure that opening a broker without a path returns an error.
|
|
|
|
func TestBroker_Open_ErrPathRequired(t *testing.T) {
|
2014-10-21 02:42:03 +00:00
|
|
|
b := messaging.NewBroker()
|
2014-12-19 22:07:10 +00:00
|
|
|
if err := b.Open("", "http://127.0.0.1:8080"); err != messaging.ErrPathRequired {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that opening a broker without a connection address returns an error.
|
|
|
|
func TestBroker_Open_ErrAddressRequired(t *testing.T) {
|
|
|
|
b := messaging.NewBroker()
|
|
|
|
f := tempfile()
|
|
|
|
defer os.Remove(f)
|
|
|
|
|
|
|
|
if err := b.Open(f, ""); err != messaging.ErrConnectionAddressRequired {
|
2014-10-12 18:05:03 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that closing an already closed broker returns an error.
|
|
|
|
func TestBroker_Close_ErrClosed(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
b.Close()
|
2014-10-21 02:42:03 +00:00
|
|
|
if err := b.Broker.Close(); err != messaging.ErrClosed {
|
2014-10-12 18:05:03 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-03 03:13:42 +00:00
|
|
|
// Ensure the broker can write messages to the appropriate topics.
|
2014-10-15 03:42:40 +00:00
|
|
|
func TestBroker_Publish(t *testing.T) {
|
2014-10-03 03:13:42 +00:00
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
|
|
|
|
2014-10-13 23:32:12 +00:00
|
|
|
// Create a new named replica.
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.CreateReplica(2000); err != nil {
|
2014-10-13 23:32:12 +00:00
|
|
|
t.Fatalf("create replica: %s", err)
|
2014-10-12 18:05:03 +00:00
|
|
|
}
|
|
|
|
|
2014-10-24 04:22:52 +00:00
|
|
|
// Subscribe replica to a topic.
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.Subscribe(2000, 20); err != nil {
|
2014-10-12 18:05:03 +00:00
|
|
|
t.Fatalf("subscribe: %s", err)
|
|
|
|
}
|
|
|
|
|
2014-10-03 03:13:42 +00:00
|
|
|
// Write a message to the broker.
|
2014-10-24 04:22:52 +00:00
|
|
|
index, err := b.Publish(&messaging.Message{Type: 100, TopicID: 20, Data: []byte("0000")})
|
2014-10-03 03:13:42 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
2014-10-24 04:22:52 +00:00
|
|
|
} else if index != 4 {
|
2014-10-03 03:13:42 +00:00
|
|
|
t.Fatalf("unexpected index: %d", index)
|
|
|
|
}
|
2014-10-24 04:22:52 +00:00
|
|
|
if err := b.Sync(index); err != nil {
|
|
|
|
t.Fatalf("sync error: %s", err)
|
2014-10-03 03:13:42 +00:00
|
|
|
}
|
|
|
|
|
2014-10-13 23:32:12 +00:00
|
|
|
// Read message from the replica.
|
2014-10-04 17:27:12 +00:00
|
|
|
var buf bytes.Buffer
|
|
|
|
go func() {
|
2014-12-24 00:01:06 +00:00
|
|
|
if _, err := b.Replica(2000).WriteTo(&buf); err != nil {
|
2014-10-04 17:27:12 +00:00
|
|
|
t.Fatalf("write to: %s", err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
2014-10-12 18:05:03 +00:00
|
|
|
// Read out the config messages first.
|
2014-10-21 02:42:03 +00:00
|
|
|
var m messaging.Message
|
|
|
|
dec := messaging.NewMessageDecoder(&buf)
|
|
|
|
if err := dec.Decode(&m); err != nil || m.Type != messaging.CreateReplicaMessageType {
|
2014-10-13 23:32:12 +00:00
|
|
|
t.Fatalf("decode(create replica): %x (%v)", m.Type, err)
|
2014-10-12 18:05:03 +00:00
|
|
|
}
|
2014-10-21 02:42:03 +00:00
|
|
|
if err := dec.Decode(&m); err != nil || m.Type != messaging.SubscribeMessageType {
|
2014-10-12 18:05:03 +00:00
|
|
|
t.Fatalf("decode(subscribe): %x (%v)", m.Type, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read out the published message.
|
2014-10-04 17:27:12 +00:00
|
|
|
if err := dec.Decode(&m); err != nil {
|
|
|
|
t.Fatalf("decode: %s", err)
|
2014-10-24 04:22:52 +00:00
|
|
|
} else if !reflect.DeepEqual(&m, &messaging.Message{Type: 100, TopicID: 20, Index: 4, Data: []byte("0000")}) {
|
2014-10-04 17:27:12 +00:00
|
|
|
t.Fatalf("unexpected message: %#v", &m)
|
|
|
|
}
|
2014-10-15 03:42:40 +00:00
|
|
|
|
2014-10-24 04:22:52 +00:00
|
|
|
// Unsubscribe replica from the topic.
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.Unsubscribe(2000, 20); err != nil {
|
2014-10-24 04:22:52 +00:00
|
|
|
t.Fatalf("unsubscribe: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write another message (that shouldn't be read).
|
|
|
|
if _, err := b.Publish(&messaging.Message{Type: 101, TopicID: 20}); err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
2014-10-15 03:42:40 +00:00
|
|
|
// Read unsubscribe.
|
2014-10-21 02:42:03 +00:00
|
|
|
if err := dec.Decode(&m); err != nil || m.Type != messaging.UnsubscribeMessageType {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("decode(unsubscribe): %x (%v)", m.Type, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// EOF
|
|
|
|
if err := dec.Decode(&m); err != io.EOF {
|
|
|
|
t.Fatalf("decode(eof): %x (%v)", m.Type, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that creating a duplicate replica will return an error.
|
|
|
|
func TestBroker_CreateReplica_ErrReplicaExists(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
|
|
|
|
|
|
|
// Create a replica twice.
|
2014-12-24 00:01:06 +00:00
|
|
|
b.CreateReplica(2000)
|
|
|
|
if err := b.CreateReplica(2000); err != messaging.ErrReplicaExists {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the broker can remove an existing replica.
|
|
|
|
func TestBroker_DeleteReplica(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
|
|
|
|
|
|
|
// Create a new named replica.
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.CreateReplica(2000); err != nil {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("create replica: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attach a replica writer.
|
|
|
|
var buf bytes.Buffer
|
|
|
|
var closed bool
|
|
|
|
go func() {
|
2014-12-24 00:01:06 +00:00
|
|
|
if _, err := b.Replica(2000).WriteTo(&buf); err != nil {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("write to: %s", err)
|
|
|
|
}
|
|
|
|
closed = true
|
|
|
|
}()
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
|
|
|
// Delete the replica.
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.DeleteReplica(2000); err != nil {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("delete replica: %s", err)
|
|
|
|
}
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
|
|
|
|
// Ensure the writer was closed.
|
|
|
|
if !closed {
|
|
|
|
t.Fatal("replica writer did not close")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure the replica no longer exists.
|
2014-12-24 00:01:06 +00:00
|
|
|
if r := b.Replica(2000); r != nil {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatal("replica still exists")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure an error is returned when deleting a non-existent replica.
|
|
|
|
func TestBroker_DeleteReplica_ErrReplicaNotFound(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.DeleteReplica(0); err != messaging.ErrReplicaNotFound {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that subscribing to a missing replica returns an error.
|
|
|
|
func TestBroker_Subscribe_ErrReplicaNotFound(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
2014-12-24 00:01:06 +00:00
|
|
|
b.CreateReplica(2000)
|
|
|
|
if err := b.Subscribe(3000, 20); err != messaging.ErrReplicaNotFound {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure that unsubscribing from a missing replica returns an error.
|
|
|
|
func TestBroker_Unsubscribe_ErrReplicaNotFound(t *testing.T) {
|
|
|
|
b := NewBroker()
|
|
|
|
defer b.Close()
|
2014-12-24 00:01:06 +00:00
|
|
|
if err := b.Unsubscribe(0, 20); err != messaging.ErrReplicaNotFound {
|
2014-10-15 03:42:40 +00:00
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
2014-10-03 03:13:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Broker is a wrapper for broker.Broker that creates the broker in a temporary location.
|
|
|
|
type Broker struct {
|
2014-10-21 02:42:03 +00:00
|
|
|
*messaging.Broker
|
2014-10-03 03:13:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewBroker returns a new open tempoarary broker.
|
|
|
|
func NewBroker() *Broker {
|
2014-10-21 02:42:03 +00:00
|
|
|
b := messaging.NewBroker()
|
2014-12-19 22:07:10 +00:00
|
|
|
if err := b.Open(tempfile(), "http://127.0.0.1:8080"); err != nil {
|
2014-10-03 03:13:42 +00:00
|
|
|
panic("open: " + err.Error())
|
|
|
|
}
|
|
|
|
if err := b.Initialize(); err != nil {
|
|
|
|
panic("initialize: " + err.Error())
|
|
|
|
}
|
|
|
|
return &Broker{b}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Close closes and deletes the temporary broker.
|
|
|
|
func (b *Broker) Close() {
|
|
|
|
defer os.RemoveAll(b.Path())
|
|
|
|
b.Broker.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
// tempfile returns a temporary path.
|
|
|
|
func tempfile() string {
|
2014-10-21 02:42:03 +00:00
|
|
|
f, _ := ioutil.TempFile("", "influxdb-messaging-")
|
2014-10-03 03:13:42 +00:00
|
|
|
path := f.Name()
|
|
|
|
f.Close()
|
|
|
|
os.Remove(path)
|
|
|
|
return path
|
|
|
|
}
|
2014-10-12 18:05:03 +00:00
|
|
|
|
|
|
|
func warn(v ...interface{}) { fmt.Fprintln(os.Stderr, v...) }
|
|
|
|
func warnf(msg string, v ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", v...) }
|