func TestServiceFutureSurvival(t *testing.T) { connect := connectPacket() connect.ClientID = "test" connect.CleanSession = false connack := connackPacket() connack.SessionPresent = true publish1 := packet.NewPublishPacket() publish1.Message.Topic = "test" publish1.Message.Payload = []byte("test") publish1.Message.QOS = 1 publish1.PacketID = 1 publish2 := packet.NewPublishPacket() publish2.Message.Topic = "test" publish2.Message.Payload = []byte("test") publish2.Message.QOS = 1 publish2.Dup = true publish2.PacketID = 1 puback := packet.NewPubackPacket() puback.PacketID = 1 broker1 := tools.NewFlow(). Receive(connect). Send(connack). Receive(publish1). Close() broker2 := tools.NewFlow(). Receive(connect). Send(connack). Receive(publish2). Send(puback). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker1, broker2) config := NewConfigWithClientID("tcp://localhost:"+port, "test") config.CleanSession = false s := NewService() s.Start(config) err := s.Publish("test", []byte("test"), 1, false).Wait() assert.NoError(t, err) s.Stop(true) <-done }
func TestServiceReconnect(t *testing.T) { delay := tools.NewFlow(). Receive(connectPacket()). Delay(55 * time.Millisecond). End() noDelay := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(disconnectPacket()). End() done, port := fakeBroker(t, delay, delay, delay, noDelay) online := make(chan struct{}) offline := make(chan struct{}) s := NewService() s.MinReconnectDelay = 50 * time.Millisecond s.ConnectTimeout = 50 * time.Millisecond i := 0 s.Logger = func(msg string) { if msg == "Next Reconnect" { i++ } } s.OnlineCallback = func(resumed bool) { assert.False(t, resumed) close(online) } s.OfflineCallback = func() { close(offline) } s.Start(NewConfig("tcp://localhost:" + port)) <-online s.Stop(true) <-offline <-done assert.Equal(t, 4, i) }
func TestClientKeepAliveTimeout(t *testing.T) { connect := connectPacket() connect.KeepAlive = 0 pingreq := packet.NewPingreqPacket() broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(pingreq). End() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { assert.Nil(t, msg) assert.Equal(t, ErrClientMissingPong, err) close(wait) } config := NewConfig("tcp://localhost:" + port) config.KeepAlive = "5ms" future, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) <-wait <-done }
func TestReceiveMessage(t *testing.T) { subscribe := packet.NewSubscribePacket() subscribe.PacketID = 1 subscribe.Subscriptions = []packet.Subscription{ {Topic: "test"}, } suback := packet.NewSubackPacket() suback.PacketID = 1 suback.ReturnCodes = []uint8{0} publish := packet.NewPublishPacket() publish.Message = packet.Message{ Topic: "test", Payload: []byte("test"), Retain: true, } broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(subscribe). Send(suback). Send(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) msg, err := ReceiveMessage(NewConfig("tcp://localhost:"+port), "test", 0) assert.NoError(t, err) assert.Equal(t, publish.Message.String(), msg.String()) <-done }
func TestClientConnectWithCredentials(t *testing.T) { connect := connectPacket() connect.Username = "******" connect.Password = "******" broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) future, err := c.Connect(NewConfig(fmt.Sprintf("tcp://*****:*****@localhost:%s/", port))) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) err = c.Disconnect() assert.NoError(t, err) <-done }
func TestClientConnectCustomDialer(t *testing.T) { broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) config := NewConfig("tcp://localhost:" + port) config.Dialer = transport.NewDialer() future, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) err = c.Disconnect() assert.NoError(t, err) <-done }
func TestClientUnexpectedClose(t *testing.T) { broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Close() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { assert.Nil(t, msg) assert.Error(t, err) close(wait) } future, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) <-wait <-done }
func TestClientFutureCancellation(t *testing.T) { publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") publish.Message.QOS = 1 publish.PacketID = 1 broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(publish). Close() done, port := fakeBroker(t, broker) c := New() c.Callback = func(msg *packet.Message, err error) { assert.Nil(t, msg) assert.Error(t, err) } connectFuture, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.NoError(t, connectFuture.Wait()) assert.False(t, connectFuture.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, connectFuture.ReturnCode) publishFuture, err := c.Publish("test", []byte("test"), 1, false) assert.NoError(t, err) assert.Equal(t, ErrFutureCanceled, publishFuture.Wait()) <-done }
func TestStartStopVariations(t *testing.T) { broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) online := make(chan struct{}) offline := make(chan struct{}) s := NewService() s.OnlineCallback = func(resumed bool) { assert.False(t, resumed) close(online) } s.OfflineCallback = func() { close(offline) } s.Start(NewConfig("tcp://localhost:" + port)) s.Start(NewConfig("tcp://localhost:" + port)) // <- does nothing <-online s.Stop(true) s.Stop(true) // <- does nothing <-offline <-done }
func TestServiceCommandsInCallback(t *testing.T) { subscribe := packet.NewSubscribePacket() subscribe.Subscriptions = []packet.Subscription{{Topic: "test"}} subscribe.PacketID = 1 suback := packet.NewSubackPacket() suback.ReturnCodes = []uint8{0} suback.PacketID = 1 publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(subscribe). Send(suback). Receive(publish). Send(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) message := make(chan struct{}) offline := make(chan struct{}) s := NewService() s.OnlineCallback = func(resumed bool) { assert.False(t, resumed) s.Subscribe("test", 0) s.Publish("test", []byte("test"), 0, false) } s.OfflineCallback = func() { close(offline) } s.MessageCallback = func(msg *packet.Message) { assert.Equal(t, "test", msg.Topic) assert.Equal(t, []byte("test"), msg.Payload) assert.Equal(t, uint8(0), msg.QOS) assert.False(t, msg.Retain) close(message) } s.Start(NewConfig("tcp://localhost:" + port)) <-message s.Stop(true) <-offline <-done }
func TestClientLogger(t *testing.T) { subscribe := packet.NewSubscribePacket() subscribe.Subscriptions = []packet.Subscription{{Topic: "test"}} subscribe.PacketID = 1 suback := packet.NewSubackPacket() suback.ReturnCodes = []uint8{0} suback.PacketID = 1 publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(subscribe). Send(suback). Receive(publish). Send(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { close(wait) } var counter uint32 c.Logger = func(msg string) { atomic.AddUint32(&counter, 1) } future, _ := c.Connect(NewConfig("tcp://localhost:" + port)) future.Wait() subscribeFuture, _ := c.Subscribe("test", 0) subscribeFuture.Wait() publishFuture, _ := c.Publish("test", []byte("test"), 0, false) publishFuture.Wait() <-wait c.Disconnect() <-done assert.Equal(t, uint32(8), counter) }
func TestClientKeepAlive(t *testing.T) { connect := connectPacket() connect.KeepAlive = 0 pingreq := packet.NewPingreqPacket() pingresp := packet.NewPingrespPacket() broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(pingreq). Send(pingresp). Receive(pingreq). Send(pingresp). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) var reqCounter int32 var respCounter int32 c.Logger = func(message string) { if strings.Contains(message, "Pingreq") { atomic.AddInt32(&reqCounter, 1) } else if strings.Contains(message, "Pingresp") { atomic.AddInt32(&respCounter, 1) } } config := NewConfig("tcp://localhost:" + port) config.KeepAlive = "100ms" future, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) <-time.After(250 * time.Millisecond) err = c.Disconnect() assert.NoError(t, err) assert.Equal(t, int32(2), atomic.LoadInt32(&reqCounter)) assert.Equal(t, int32(2), atomic.LoadInt32(&respCounter)) <-done }
func TestClientSessionResumption(t *testing.T) { connect := connectPacket() connect.ClientID = "test" connect.CleanSession = false publish1 := packet.NewPublishPacket() publish1.Message.Topic = "test" publish1.Message.Payload = []byte("test") publish1.Message.QOS = 1 publish1.PacketID = 1 puback1 := packet.NewPubackPacket() puback1.PacketID = 1 broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(publish1). Send(puback1). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Session.SavePacket(outgoing, publish1) c.Session.PacketID() c.Callback = errorCallback(t) config := NewConfig("tcp://localhost:" + port) config.ClientID = "test" config.CleanSession = false connectFuture, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, connectFuture.Wait()) assert.False(t, connectFuture.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, connectFuture.ReturnCode) time.Sleep(20 * time.Millisecond) err = c.Disconnect() assert.NoError(t, err) <-done pkts, err := c.Session.AllPackets(outgoing) assert.NoError(t, err) assert.Equal(t, 0, len(pkts)) }
func TestClientDisconnectWithTimeout(t *testing.T) { publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") publish.Message.QOS = 1 publish.PacketID = 1 puback := packet.NewPubackPacket() puback.PacketID = 1 wait := func() { time.Sleep(100 * time.Millisecond) } broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(publish). Run(wait). Send(puback). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) connectFuture, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.NoError(t, connectFuture.Wait()) assert.False(t, connectFuture.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, connectFuture.ReturnCode) publishFuture, err := c.Publish("test", []byte("test"), 1, false) assert.NoError(t, err) assert.NotNil(t, publishFuture) err = c.Disconnect(10 * time.Second) assert.NoError(t, err) <-done assert.NoError(t, publishFuture.Wait()) list, err := c.Session.AllPackets(outgoing) assert.NoError(t, err) assert.Equal(t, 0, len(list)) }
func TestClientHardDisconnect(t *testing.T) { connect := connectPacket() connect.ClientID = "test" connect.CleanSession = false publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") publish.Message.QOS = 1 publish.PacketID = 1 broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) config := NewConfig("tcp://localhost:" + port) config.ClientID = "test" config.CleanSession = false connectFuture, err := c.Connect(config) assert.NoError(t, err) assert.NoError(t, connectFuture.Wait()) assert.False(t, connectFuture.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, connectFuture.ReturnCode) publishFuture, err := c.Publish("test", []byte("test"), 1, false) assert.NoError(t, err) assert.NotNil(t, publishFuture) err = c.Disconnect() assert.NoError(t, err) assert.Equal(t, ErrFutureCanceled, publishFuture.Wait()) <-done list, err := c.Session.AllPackets(outgoing) assert.NoError(t, err) assert.Equal(t, 1, len(list)) }
func TestClearSession(t *testing.T) { connect := connectPacket() connect.ClientID = "test" broker := tools.NewFlow(). Receive(connect). Send(connackPacket()). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) err := ClearSession(NewConfigWithClientID("tcp://localhost:"+port, "test")) assert.NoError(t, err) <-done }
func TestServiceUnsubscribe(t *testing.T) { unsubscribe := packet.NewUnsubscribePacket() unsubscribe.Topics = []string{"test"} unsubscribe.PacketID = 1 unsuback := packet.NewUnsubackPacket() unsuback.PacketID = 1 broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(unsubscribe). Send(unsuback). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) online := make(chan struct{}) offline := make(chan struct{}) s := NewService() s.OnlineCallback = func(resumed bool) { assert.False(t, resumed) close(online) } s.OfflineCallback = func() { close(offline) } s.Start(NewConfig("tcp://localhost:" + port)) <-online s.Unsubscribe("test").Wait() s.Stop(true) <-offline <-done }
func TestClearRetainedMessage(t *testing.T) { publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = nil publish.Message.Retain = true broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) err := ClearRetainedMessage(NewConfig("tcp://localhost:"+port), "test") assert.NoError(t, err) <-done }
func TestPublishMessage(t *testing.T) { publish := packet.NewPublishPacket() publish.Message = packet.Message{ Topic: "test", Payload: []byte("test"), Retain: true, } broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(publish). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) err := PublishMessage(NewConfig("tcp://localhost:"+port), &publish.Message) assert.NoError(t, err) <-done }
func TestClientConnackFutureCancellation(t *testing.T) { broker := tools.NewFlow(). Receive(connectPacket()). Close() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { assert.Nil(t, msg) assert.Error(t, err) close(wait) } future, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.Equal(t, ErrFutureCanceled, future.Wait()) <-wait <-done }
func TestClientUnsubscribe(t *testing.T) { unsubscribe := packet.NewUnsubscribePacket() unsubscribe.Topics = []string{"test"} unsubscribe.PacketID = 1 unsuback := packet.NewUnsubackPacket() unsuback.PacketID = 1 broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(unsubscribe). Send(unsuback). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) c := New() c.Callback = errorCallback(t) future, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) unsubscribeFuture, err := c.Unsubscribe("test") assert.NoError(t, err) assert.NoError(t, unsubscribeFuture.Wait()) err = c.Disconnect() assert.NoError(t, err) <-done }
func TestClientPublishSubscribeQOS2(t *testing.T) { subscribe := packet.NewSubscribePacket() subscribe.Subscriptions = []packet.Subscription{{Topic: "test", QOS: 2}} subscribe.PacketID = 1 suback := packet.NewSubackPacket() suback.ReturnCodes = []uint8{2} suback.PacketID = 1 publish := packet.NewPublishPacket() publish.Message.Topic = "test" publish.Message.Payload = []byte("test") publish.Message.QOS = 2 publish.PacketID = 2 pubrec := packet.NewPubrecPacket() pubrec.PacketID = 2 pubrel := packet.NewPubrelPacket() pubrel.PacketID = 2 pubcomp := packet.NewPubcompPacket() pubcomp.PacketID = 2 broker := tools.NewFlow(). Receive(connectPacket()). Send(connackPacket()). Receive(subscribe). Send(suback). Receive(publish). Send(pubrec). Receive(pubrel). Send(pubcomp). Send(publish). Receive(pubrec). Send(pubrel). Receive(pubcomp). Receive(disconnectPacket()). End() done, port := fakeBroker(t, broker) wait := make(chan struct{}) c := New() c.Callback = func(msg *packet.Message, err error) { assert.NoError(t, err) assert.Equal(t, "test", msg.Topic) assert.Equal(t, []byte("test"), msg.Payload) assert.Equal(t, uint8(2), msg.QOS) assert.False(t, msg.Retain) close(wait) } future, err := c.Connect(NewConfig("tcp://localhost:" + port)) assert.NoError(t, err) assert.NoError(t, future.Wait()) assert.False(t, future.SessionPresent) assert.Equal(t, packet.ConnectionAccepted, future.ReturnCode) subscribeFuture, err := c.Subscribe("test", 2) assert.NoError(t, err) assert.NoError(t, subscribeFuture.Wait()) assert.Equal(t, []uint8{2}, subscribeFuture.ReturnCodes) publishFuture, err := c.Publish("test", []byte("test"), 2, false) assert.NoError(t, err) assert.NoError(t, publishFuture.Wait()) <-wait err = c.Disconnect() assert.NoError(t, err) <-done in, err := c.Session.AllPackets(incoming) assert.NoError(t, err) assert.Equal(t, 0, len(in)) out, err := c.Session.AllPackets(outgoing) assert.NoError(t, err) assert.Equal(t, 0, len(out)) }