public async Task when_client_disconnects_unexpectedly_then_will_message_is_sent() { var client1 = await GetClientAsync(); var client2 = await GetClientAsync(); var client3 = await GetClientAsync(); var topic = Guid.NewGuid().ToString(); var qos = MqttQualityOfService.ExactlyOnce; var retain = true; var willMessage = new FooWillMessage { Message = "Client 1 has been disconnected unexpectedly" }; var willMessagePayload = willMessage.GetPayload(); var will = new MqttLastWill(topic, qos, retain, willMessagePayload); await client1.ConnectAsync(new MqttClientCredentials(GetClientId()), will); await client2.ConnectAsync(new MqttClientCredentials(GetClientId())); await client3.ConnectAsync(new MqttClientCredentials(GetClientId())); await client2.SubscribeAsync(topic, MqttQualityOfService.AtMostOnce); await client3.SubscribeAsync(topic, MqttQualityOfService.AtLeastOnce); var willReceivedSignal = new ManualResetEventSlim(initialState: false); var willApplicationMessage = default(MqttApplicationMessage); client2.MessageStream.Subscribe((Action <MqttApplicationMessage>)(m => { if (m.Topic == topic) { willApplicationMessage = m; willReceivedSignal.Set(); } })); client3.MessageStream.Subscribe((Action <MqttApplicationMessage>)(m => { if (m.Topic == topic) { willApplicationMessage = m; willReceivedSignal.Set(); } })); //Forces socket disconnection without using protocol Disconnect (Disconnect or Dispose Client method) (client1 as MqttClientImpl).Channel.Dispose(); var willReceived = willReceivedSignal.Wait(2000); Assert.True(willReceived); Assert.NotNull(willMessage); Assert.Equal(topic, willApplicationMessage.Topic); Assert.Equal(willMessage.Message, FooWillMessage.GetMessage(willApplicationMessage.Payload).Message); client2.Dispose(); client3.Dispose(); }
public async Task when_client_disconnects_by_protocol_then_will_message_is_not_sent() { var client1 = await GetClientAsync(); var client2 = await GetClientAsync(); var client3 = await GetClientAsync(); var topic = Guid.NewGuid().ToString(); var qos = MqttQualityOfService.ExactlyOnce; var retain = true; var willMessage = new FooWillMessage { Message = "Client 1 has been disconnected unexpectedly" }; var will = new MqttLastWill(topic, qos, retain, willMessage.GetPayload()); await client1.ConnectAsync(new MqttClientCredentials(GetClientId()), will); await client2.ConnectAsync(new MqttClientCredentials(GetClientId())); await client3.ConnectAsync(new MqttClientCredentials(GetClientId())); await client2.SubscribeAsync(topic, MqttQualityOfService.AtMostOnce); await client3.SubscribeAsync(topic, MqttQualityOfService.AtLeastOnce); var willReceivedSignal = new ManualResetEventSlim(initialState: false); client2.MessageStream.Subscribe(m => { if (m.Topic == topic) { willReceivedSignal.Set(); } }); client3.MessageStream.Subscribe(m => { if (m.Topic == topic) { willReceivedSignal.Set(); } }); await client1.DisconnectAsync(); var willReceived = willReceivedSignal.Wait(2000); Assert.False(willReceived); client1.Dispose(); client2.Dispose(); client3.Dispose(); }
public async Task when_sending_connect_with_will_then_will_is_created_and_ack_is_sent() { IMqttAuthenticationProvider authenticationProvider = Mock.Of <IMqttAuthenticationProvider>(p => p.Authenticate(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>()) == true); Mock <IRepository <ClientSession> > sessionRepository = new Mock <IRepository <ClientSession> >(); Mock <IRepository <ConnectionWill> > willRepository = new Mock <IRepository <ConnectionWill> >(); Mock <IPublishSenderFlow> senderFlow = new Mock <IPublishSenderFlow>(); string clientId = Guid.NewGuid().ToString(); Connect connect = new Connect(clientId, cleanSession: true, MqttProtocol.SupportedLevel); FooWillMessage willMessage = new FooWillMessage { Message = "Foo Will Message" }; MqttLastWill will = new MqttLastWill("foo/bar", MqttQualityOfService.AtLeastOnce, retain: true, payload: willMessage.GetPayload()); connect.Will = will; Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >(); IPacket sentPacket = default; channel.Setup(c => c.SendAsync(It.IsAny <IPacket>())) .Callback <IPacket>(packet => sentPacket = packet) .Returns(Task.Delay(0)); Mock <IConnectionProvider> connectionProvider = new Mock <IConnectionProvider>(); connectionProvider .Setup(p => p.GetConnection(It.Is <string>(c => c == clientId))) .Returns(channel.Object); ServerConnectFlow flow = new ServerConnectFlow(authenticationProvider, sessionRepository.Object, willRepository.Object, senderFlow.Object); await flow.ExecuteAsync(clientId, connect, channel.Object); ConnectAck connectAck = sentPacket as ConnectAck; sessionRepository.Verify(r => r.Delete(It.IsAny <string>()), Times.Never); sessionRepository.Verify(r => r.Create(It.Is <ClientSession>(s => s.Id == clientId && s.Clean == true))); willRepository.Verify(r => r.Create(It.Is <ConnectionWill>(w => w.Id == clientId && w.Will == will))); Assert.NotNull(connectAck); connectAck.Type.Should().Be(MqttPacketType.ConnectAck); connectAck.Status.Should().Be(MqttConnectionStatus.Accepted); Assert.False(connectAck.SessionPresent); }