// Ensure a replica can connect and stream messages. func TestHandler_stream(t *testing.T) { s := NewServer() defer s.Close() // Create replica. s.Handler.Broker().CreateReplica(2000) // Send request to stream the replica. resp, err := http.Get(s.URL + `/messaging/messages?replicaID=2000`) defer resp.Body.Close() if err != nil { t.Fatalf("unexpected error: %s", err) } else if resp.StatusCode != http.StatusOK { t.Fatalf("unexpected status: %d: %s", resp.StatusCode, resp.Header.Get("X-Broker-Error")) } time.Sleep(10 * time.Millisecond) // Decode from body. var m messaging.Message dec := messaging.NewMessageDecoder(resp.Body) if err := dec.Decode(&m); err != nil { t.Fatalf("decode error: %s", err) } else if m.Index != 2 && m.Type != messaging.CreateReplicaMessageType { t.Fatalf("unexpected index/type: %d / %x", m.Index, m.Type) } }
// MustReadAll reads all available messages for a replica. Panic on error. func (b *Broker) MustReadAll(replicaID uint64) (a []*messaging.Message) { // Read message from the replica. var buf bytes.Buffer go func() { if _, err := b.Replica(replicaID).WriteTo(&buf); err != nil { panic("write to: " + err.Error()) } }() time.Sleep(10 * time.Millisecond) // Read out the config messages first. dec := messaging.NewMessageDecoder(&buf) for { m := &messaging.Message{} if err := dec.Decode(m); err == io.EOF { break } else if err != nil { panic("decode: " + err.Error()) } a = append(a, m) } return }
// Ensure a handler can publish a message. func TestHandler_publish(t *testing.T) { s := NewServer() defer s.Close() // Stream subscription for a replica. var m messaging.Message s.Handler.Broker().CreateReplica(2000) s.Handler.Broker().Subscribe(2000, 200) go func() { resp, _ := http.Get(s.URL + `/messaging/messages?replicaID=2000`) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("unexpected response code: %d", resp.StatusCode) } dec := messaging.NewMessageDecoder(resp.Body) for { if err := dec.Decode(&m); err != nil { return } } }() // Send request to the broker. resp, _ := http.Post(s.URL+`/messaging/messages?type=100&topicID=200`, "application/octet-stream", strings.NewReader(`abc`)) defer resp.Body.Close() if resp.StatusCode != http.StatusOK { t.Fatalf("unexpected status: %d: %s", resp.StatusCode, resp.Header.Get("X-Broker-Error")) } s.Handler.Broker().Sync(4) // Check if the last message received is our new message. time.Sleep(10 * time.Millisecond) if !reflect.DeepEqual(&m, &messaging.Message{Type: 100, Index: 4, TopicID: 200, Data: []byte("abc")}) { t.Fatalf("unexpected message: %#v", &m) } }
// Ensure the broker can write messages to the appropriate topics. func TestBroker_Publish(t *testing.T) { b := NewBroker(nil) defer b.Close() // Create a new named replica. if err := b.CreateReplica(2000); err != nil { t.Fatalf("create replica: %s", err) } // Subscribe replica to a topic. if err := b.Subscribe(2000, 20); err != nil { t.Fatalf("subscribe: %s", err) } // Write a message to the broker. index, err := b.Publish(&messaging.Message{Type: 100, TopicID: 20, Data: []byte("0000")}) if err != nil { t.Fatalf("unexpected error: %s", err) } else if index != 4 { t.Fatalf("unexpected index: %d", index) } if err := b.Sync(index); err != nil { t.Fatalf("sync error: %s", err) } // Read message from the replica. var buf bytes.Buffer go func() { if _, err := b.Replica(2000).WriteTo(&buf); err != nil { t.Fatalf("write to: %s", err) } }() time.Sleep(10 * time.Millisecond) // Read out the config messages first. var m messaging.Message dec := messaging.NewMessageDecoder(&buf) if err := dec.Decode(&m); err != nil || m.Type != messaging.CreateReplicaMessageType { t.Fatalf("decode(create replica): %x (%v)", m.Type, err) } if err := dec.Decode(&m); err != nil || m.Type != messaging.SubscribeMessageType { t.Fatalf("decode(subscribe): %x (%v)", m.Type, err) } // Read out the published message. if err := dec.Decode(&m); err != nil { t.Fatalf("decode: %s", err) } else if !reflect.DeepEqual(&m, &messaging.Message{Type: 100, TopicID: 20, Index: 4, Data: []byte("0000")}) { t.Fatalf("unexpected message: %#v", &m) } // Unsubscribe replica from the topic. if err := b.Unsubscribe(2000, 20); err != nil { 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) // Read unsubscribe. if err := dec.Decode(&m); err != nil || m.Type != messaging.UnsubscribeMessageType { 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) } }