Пример #1
0
        public async Task ManagedClients_Will_Message_Send()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                var receivedMessagesCount = 0;

                await testEnvironment.StartServerAsync();

                var willMessage   = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort)
                                    .WithWillMessage(willMessage);
                var dyingClient        = testEnvironment.CreateClient();
                var dyingManagedClient = new ManagedMqttClient(dyingClient, testEnvironment.ClientLogger);
                await dyingManagedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                                    .WithClientOptions(clientOptions)
                                                    .Build());

                var recievingClient = await testEnvironment.ConnectClientAsync();

                await recievingClient.SubscribeAsync("My/last/will");

                recievingClient.UseApplicationMessageReceivedHandler(context => Interlocked.Increment(ref receivedMessagesCount));

                dyingManagedClient.Dispose();

                await Task.Delay(1000);

                Assert.AreEqual(1, receivedMessagesCount);
            }
        }
Пример #2
0
        public async Task Start_Stop()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                var server = await testEnvironment.StartServerAsync();

                var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger());
                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort);

                var connected = GetConnectedTask(managedClient);

                await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                               .WithClientOptions(clientOptions)
                                               .Build());

                await connected;

                await managedClient.StopAsync();

                await Task.Delay(500);

                Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count);
            }
        }
Пример #3
0
        public async Task Start_Stop()
        {
            using (var testEnvironment = new TestEnvironment())
            {
                var factory = new MqttFactory();

                var server = await testEnvironment.StartServerAsync();

                var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger().CreateChildLogger());
                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort);

                TaskCompletionSource <bool> connected = new TaskCompletionSource <bool>();
                managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e => { connected.SetResult(true); });

                await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                               .WithClientOptions(clientOptions)
                                               .Build());

                await connected.Task;

                await managedClient.StopAsync();

                Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count);
            }
        }
Пример #4
0
        async Task <ManagedMqttClient> CreateManagedClientAsync(
            TestEnvironment testEnvironment,
            IMqttClient underlyingClient     = null,
            TimeSpan?connectionCheckInterval = null)
        {
            await testEnvironment.StartServerAsync();

            var clientOptions = new MqttClientOptionsBuilder()
                                .WithTcpServer("localhost", testEnvironment.ServerPort);

            var managedOptions = new ManagedMqttClientOptionsBuilder()
                                 .WithClientOptions(clientOptions)
                                 .Build();

            // Use a short connection check interval so that subscription operations are performed quickly
            // in order to verify against a previous implementation that performed subscriptions only
            // at connection check intervals
            managedOptions.ConnectionCheckInterval = connectionCheckInterval ?? TimeSpan.FromSeconds(0.1);

            var managedClient = new ManagedMqttClient(underlyingClient ?? testEnvironment.CreateClient(), new MqttNetLogger());

            var connected = GetConnectedTask(managedClient);

            await managedClient.StartAsync(managedOptions);

            await connected;

            return(managedClient);
        }
Пример #5
0
        public async Task Storage_Queue_Drains()
        {
            using (var testEnvironment = new TestEnvironment())
            {
                testEnvironment.IgnoreClientLogErrors = true;
                testEnvironment.IgnoreServerLogErrors = true;

                var factory = new MqttFactory();

                var server = await testEnvironment.StartServerAsync();

                var managedClient = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger().CreateChildLogger());
                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort);
                var storage = new ManagedMqttClientTestStorage();

                TaskCompletionSource <bool> connected = new TaskCompletionSource <bool>();
                managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e =>
                {
                    managedClient.ConnectedHandler = null;
                    connected.SetResult(true);
                });

                await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                               .WithClientOptions(clientOptions)
                                               .WithStorage(storage)
                                               .WithAutoReconnectDelay(System.TimeSpan.FromSeconds(5))
                                               .Build());

                await connected.Task;

                await testEnvironment.Server.StopAsync();

                await managedClient.PublishAsync(new MqttApplicationMessage { Topic = "1" });

                //Message should have been added to the storage queue in PublishAsync,
                //and we are awaiting PublishAsync, so the message should already be
                //in storage at this point (i.e. no waiting).
                Assert.AreEqual(1, storage.GetMessageCount());

                connected = new TaskCompletionSource <bool>();
                managedClient.ConnectedHandler = new MqttClientConnectedHandlerDelegate(e =>
                {
                    managedClient.ConnectedHandler = null;
                    connected.SetResult(true);
                });

                await testEnvironment.Server.StartAsync(new MqttServerOptionsBuilder()
                                                        .WithDefaultEndpointPort(testEnvironment.ServerPort).Build());

                await connected.Task;

                //Wait 500ms here so the client has time to publish the queued message
                await Task.Delay(500);

                Assert.AreEqual(0, storage.GetMessageCount());

                await managedClient.StopAsync();
            }
        }
Пример #6
0
        public async Task Connect_With_AssignedClientId()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                string serverConnectedClientId    = null;
                string serverDisconnectedClientId = null;
                string clientAssignedClientId     = null;

                // Arrange server
                var disconnectedMre = new ManualResetEventSlim();
                var serverOptions   = new MqttServerOptionsBuilder()
                                      .WithConnectionValidator((context) =>
                {
                    if (string.IsNullOrEmpty(context.ClientId))
                    {
                        context.AssignedClientIdentifier = "test123";
                        context.ReasonCode = MqttConnectReasonCode.Success;
                    }
                });
                await testEnvironment.StartServerAsync(serverOptions);

                testEnvironment.Server.UseClientConnectedHandler((args) =>
                {
                    serverConnectedClientId = args.ClientId;
                });
                testEnvironment.Server.UseClientDisconnectedHandler((args) =>
                {
                    serverDisconnectedClientId = args.ClientId;
                    disconnectedMre.Set();
                });

                // Arrange client
                var client = testEnvironment.CreateClient();
                client.UseConnectedHandler((args) =>
                {
                    clientAssignedClientId = args.AuthenticateResult.AssignedClientIdentifier;
                });

                // Act
                await client.ConnectAsync(new MqttClientOptionsBuilder()
                                          .WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
                                          .WithProtocolVersion(MqttProtocolVersion.V500)
                                          .WithClientId(null)
                                          .Build());

                await client.DisconnectAsync();

                // Wait for ClientDisconnectedHandler to trigger
                disconnectedMre.Wait(500);

                // Assert
                Assert.IsNotNull(serverConnectedClientId);
                Assert.IsNotNull(serverDisconnectedClientId);
                Assert.IsNotNull(clientAssignedClientId);
                Assert.AreEqual("test123", serverConnectedClientId);
                Assert.AreEqual("test123", serverDisconnectedClientId);
                Assert.AreEqual("test123", clientAssignedClientId);
            }
        }
Пример #7
0
        public async Task Use_Clean_Session()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                await testEnvironment.StartServerAsync();

                var client        = testEnvironment.CreateClient();
                var connectResult = await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).WithCleanSession().Build());

                Assert.IsFalse(connectResult.IsSessionPresent);
            }
        }
Пример #8
0
        public async Task Clean_Session_Persistence()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                // Create server with persistent sessions enabled

                await testEnvironment.StartServer(o => o.WithPersistentSessions());

                const string ClientId = "Client1";

                // Create client with clean session and long session expiry interval

                var client1 = await testEnvironment.ConnectClient(o => o
                                                                  .WithProtocolVersion(Formatter.MqttProtocolVersion.V311)
                                                                  .WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
                                                                  .WithSessionExpiryInterval(9999) // not relevant for v311 but testing impact
                                                                  .WithCleanSession(true)          // start and end with clean session
                                                                  .WithClientId(ClientId)
                                                                  .Build()
                                                                  );

                // Disconnect; empty session should be removed from server

                await client1.DisconnectAsync();

                // Simulate some time delay between connections

                await Task.Delay(1000);

                // Reconnect the same client ID without clean session

                var client2 = testEnvironment.CreateClient();
                var options = testEnvironment.Factory.CreateClientOptionsBuilder()
                              .WithProtocolVersion(Formatter.MqttProtocolVersion.V311)
                              .WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
                              .WithSessionExpiryInterval(9999) // not relevant for v311 but testing impact
                              .WithCleanSession(false)         // see if there is a session
                              .WithClientId(ClientId)
                              .Build();


                var result = await client2.ConnectAsync(options).ConfigureAwait(false);

                await client2.DisconnectAsync();

                // Session should NOT be present for MQTT v311 and initial CleanSession == true

                Assert.IsTrue(!result.IsSessionPresent, "Session present");
            }
        }
Пример #9
0
        public async Task Validate_IsSessionPresent()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                // Create server with persistent sessions enabled

                await testEnvironment.StartServer(o => o.WithPersistentSessions());

                const string ClientId = "Client1";

                // Create client without clean session and long session expiry interval

                var client1 = await testEnvironment.ConnectClient(o => o
                                                                  .WithProtocolVersion(MqttProtocolVersion.V500)
                                                                  .WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
                                                                  .WithSessionExpiryInterval(9999)
                                                                  .WithCleanSession(false)
                                                                  .WithClientId(ClientId)
                                                                  .Build()
                                                                  );

                // Disconnect; empty session should remain on server

                await client1.DisconnectAsync();

                // Simulate some time delay between connections

                await Task.Delay(1000);

                // Reconnect the same client ID to existing session

                var client2 = testEnvironment.CreateClient();
                var options = testEnvironment.Factory.CreateClientOptionsBuilder()
                              .WithProtocolVersion(MqttProtocolVersion.V500)
                              .WithTcpServer("127.0.0.1", testEnvironment.ServerPort)
                              .WithSessionExpiryInterval(9999)
                              .WithCleanSession(false)
                              .WithClientId(ClientId)
                              .Build();


                var result = await client2.ConnectAsync(options).ConfigureAwait(false);

                await client2.DisconnectAsync();

                // Session should be present

                Assert.IsTrue(result.IsSessionPresent, "Session not present");
            }
        }
Пример #10
0
        public async Task Use_Empty_Client_ID()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                await testEnvironment.StartServerAsync();

                var client = testEnvironment.CreateClient();

                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort)
                                    .WithClientId(string.Empty)
                                    .Build();

                var connectResult = await client.ConnectAsync(clientOptions);

                Assert.IsFalse(connectResult.IsSessionPresent);
                Assert.IsTrue(client.IsConnected);
            }
        }
Пример #11
0
        public async Task Use_Admissible_Credentials(string username, string password)
        {
            using (var testEnvironment = new TestEnvironment())
            {
                await testEnvironment.StartServer();

                var client = testEnvironment.CreateClient();

                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort)
                                    .WithCredentials(username, password)
                                    .Build();

                var connectResult = await client.ConnectAsync(clientOptions);

                Assert.IsFalse(connectResult.IsSessionPresent);
                Assert.IsTrue(client.IsConnected);
            }
        }
Пример #12
0
        public async Task Reconnect_From_Disconnected_Event()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                testEnvironment.IgnoreClientLogErrors = true;

                var client = testEnvironment.CreateClient();

                var tries    = 0;
                var maxTries = 3;

                client.DisconnectedAsync += async e =>
                {
                    if (tries >= maxTries)
                    {
                        return;
                    }

                    Interlocked.Increment(ref tries);

                    await Task.Delay(100);

                    await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
                };

                try
                {
                    await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());

                    Assert.Fail("Must fail!");
                }
                catch
                {
                }

                SpinWait.SpinUntil(() => tries >= maxTries, 10000);

                Assert.AreEqual(maxTries, tries);
            }
        }
Пример #13
0
        public async Task Subscribe_In_Callback_Events()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                await testEnvironment.StartServer();

                var receivedMessages = new List <MqttApplicationMessage>();

                var client = testEnvironment.CreateClient();

                client.ConnectedAsync += async e =>
                {
                    await client.SubscribeAsync("RCU/P1/H0001/R0003");

                    var msg = new MqttApplicationMessageBuilder().WithPayload("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|")
                              .WithTopic("RCU/P1/H0001/R0003");

                    await client.PublishAsync(msg.Build());
                };

                client.ApplicationMessageReceivedAsync += e =>
                {
                    lock (receivedMessages)
                    {
                        receivedMessages.Add(e.ApplicationMessage);
                    }

                    return(PlatformAbstractionLayer.CompletedTask);
                };

                await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).Build());

                await Task.Delay(500);

                Assert.AreEqual(1, receivedMessages.Count);
                Assert.AreEqual("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|", receivedMessages.First().ConvertPayloadToString());
            }
        }
Пример #14
0
        public async Task Subscriptions_Are_Cleared_At_Logout()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                await testEnvironment.StartServerAsync().ConfigureAwait(false);

                var sendingClient = await testEnvironment.ConnectClientAsync().ConfigureAwait(false);

                await sendingClient.PublishAsync(new MqttApplicationMessage
                {
                    Topic   = "topic",
                    Payload = new byte[] { 1 },
                    Retain  = true
                });

                // Wait a bit for the retained message to be available
                await Task.Delay(500);

                await sendingClient.DisconnectAsync();

                // Now use the managed client and check if subscriptions get cleared properly.

                var clientOptions = new MqttClientOptionsBuilder()
                                    .WithTcpServer("localhost", testEnvironment.ServerPort);

                var receivedManagedMessages = new List <MqttApplicationMessage>();
                var managedClient           = new ManagedMqttClient(testEnvironment.CreateClient(), new MqttNetLogger());
                managedClient.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c =>
                {
                    receivedManagedMessages.Add(c.ApplicationMessage);
                });

                await managedClient.SubscribeAsync("topic");

                await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                               .WithClientOptions(clientOptions)
                                               .WithAutoReconnectDelay(TimeSpan.FromSeconds(1))
                                               .Build());

                await Task.Delay(500);

                Assert.AreEqual(1, receivedManagedMessages.Count);

                await managedClient.StopAsync();

                await Task.Delay(500);

                await managedClient.StartAsync(new ManagedMqttClientOptionsBuilder()
                                               .WithClientOptions(clientOptions)
                                               .WithAutoReconnectDelay(TimeSpan.FromSeconds(1))
                                               .Build());

                await Task.Delay(1000);

                // After reconnect and then some delay, the retained message must not be received,
                // showing that the subscriptions were cleared
                Assert.AreEqual(1, receivedManagedMessages.Count);

                // Make sure that it gets received after subscribing again.
                await managedClient.SubscribeAsync("topic");

                await Task.Delay(500);

                Assert.AreEqual(2, receivedManagedMessages.Count);
            }
        }
Пример #15
0
        public async Task Subscriptions_And_Unsubscriptions_Are_Made_And_Reestablished_At_Reconnect()
        {
            using (var testEnvironment = new TestEnvironment(TestContext))
            {
                var unmanagedClient = testEnvironment.CreateClient();
                var managedClient   = await CreateManagedClientAsync(testEnvironment, unmanagedClient);

                var received = SetupReceivingOfMessages(managedClient, 2);

                // Perform some opposing subscriptions and unsubscriptions to verify
                // that these conflicting subscriptions are handled correctly
                await managedClient.SubscribeAsync("keptSubscribed");

                await managedClient.SubscribeAsync("subscribedThenUnsubscribed");

                await managedClient.UnsubscribeAsync("subscribedThenUnsubscribed");

                await managedClient.UnsubscribeAsync("unsubscribedThenSubscribed");

                await managedClient.SubscribeAsync("unsubscribedThenSubscribed");

                //wait a bit for the subscriptions to become established before the messages are published
                await Task.Delay(500);

                var sendingClient = await testEnvironment.ConnectClientAsync();

                async Task PublishMessages()
                {
                    await sendingClient.PublishAsync("keptSubscribed", new byte[] { 1 });

                    await sendingClient.PublishAsync("subscribedThenUnsubscribed", new byte[] { 1 });

                    await sendingClient.PublishAsync("unsubscribedThenSubscribed", new byte[] { 1 });
                }

                await PublishMessages();

                async Task AssertMessagesReceived()
                {
                    var messages = await received;

                    Assert.AreEqual("keptSubscribed", messages[0].Topic);
                    Assert.AreEqual("unsubscribedThenSubscribed", messages[1].Topic);
                }

                await AssertMessagesReceived();

                var connected = GetConnectedTask(managedClient);

                await unmanagedClient.DisconnectAsync();

                // the managed client has to reconnect by itself
                await connected;

                // wait a bit so that the managed client can reestablish the subscriptions
                await Task.Delay(500);

                received = SetupReceivingOfMessages(managedClient, 2);

                await PublishMessages();

                // and then the same subscriptions need to exist again
                await AssertMessagesReceived();
            }
        }