You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

875 lines
32 KiB

  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. using MQTTnet.Client;
  3. using MQTTnet.Client.Connecting;
  4. using MQTTnet.Client.Disconnecting;
  5. using MQTTnet.Client.Options;
  6. using MQTTnet.Client.Subscribing;
  7. using MQTTnet.Exceptions;
  8. using MQTTnet.Protocol;
  9. using MQTTnet.Server;
  10. using MQTTnet.Tests.Mockups;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Net.Sockets;
  15. using System.Text;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. using MQTTnet.Client.Receiving;
  19. using MQTTnet.Formatter;
  20. using MQTTnet.Packets;
  21. namespace MQTTnet.Tests
  22. {
  23. [TestClass]
  24. public class Client_Tests
  25. {
  26. public TestContext TestContext { get; set; }
  27. [TestMethod]
  28. public async Task Ensure_Queue_Drain()
  29. {
  30. using (var testEnvironment = new TestEnvironment(TestContext))
  31. {
  32. var server = await testEnvironment.StartServerAsync();
  33. var client = await testEnvironment.ConnectLowLevelClientAsync();
  34. var i = 0;
  35. server.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c =>
  36. {
  37. i++;
  38. });
  39. await client.SendAsync(new MqttConnectPacket
  40. {
  41. ClientId = "Ensure_Queue_Drain_Test"
  42. }, CancellationToken.None);
  43. await client.SendAsync(new MqttPublishPacket
  44. {
  45. Topic = "Test"
  46. }, CancellationToken.None);
  47. await Task.Delay(1000);
  48. // This will simulate a device which closes the connection directly
  49. // after sending the data so do delay is added between send and dispose!
  50. client.Dispose();
  51. await Task.Delay(1000);
  52. Assert.AreEqual(1, i);
  53. }
  54. }
  55. [TestMethod]
  56. public async Task Set_ClientWasConnected_On_ServerDisconnect()
  57. {
  58. using (var testEnvironment = new TestEnvironment(TestContext))
  59. {
  60. var server = await testEnvironment.StartServerAsync();
  61. var client = await testEnvironment.ConnectClientAsync();
  62. Assert.IsTrue(client.IsConnected);
  63. client.UseDisconnectedHandler(e => Assert.IsTrue(e.ClientWasConnected));
  64. await server.StopAsync();
  65. await Task.Delay(4000);
  66. }
  67. }
  68. [TestMethod]
  69. public async Task Set_ClientWasConnected_On_ClientDisconnect()
  70. {
  71. using (var testEnvironment = new TestEnvironment(TestContext))
  72. {
  73. var server = await testEnvironment.StartServerAsync();
  74. var client = await testEnvironment.ConnectClientAsync();
  75. Assert.IsTrue(client.IsConnected);
  76. client.UseDisconnectedHandler(e => Assert.IsTrue(e.ClientWasConnected));
  77. await client.DisconnectAsync();
  78. await Task.Delay(200);
  79. }
  80. }
  81. [TestMethod]
  82. [ExpectedException(typeof(MqttCommunicationTimedOutException))]
  83. public async Task Connect_To_Invalid_Server_Wrong_IP()
  84. {
  85. var client = new MqttFactory().CreateMqttClient();
  86. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("1.2.3.4").WithCommunicationTimeout(TimeSpan.FromSeconds(2)).Build());
  87. }
  88. [TestMethod]
  89. [ExpectedException(typeof(MqttCommunicationException))]
  90. public async Task Connect_To_Invalid_Server_Port_Not_Opened()
  91. {
  92. var client = new MqttFactory().CreateMqttClient();
  93. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", 12345).WithCommunicationTimeout(TimeSpan.FromSeconds(5)).Build());
  94. }
  95. [TestMethod]
  96. [ExpectedException(typeof(MqttCommunicationException))]
  97. public async Task Connect_To_Invalid_Server_Wrong_Protocol()
  98. {
  99. var client = new MqttFactory().CreateMqttClient();
  100. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("http://127.0.0.1", 12345).WithCommunicationTimeout(TimeSpan.FromSeconds(2)).Build());
  101. }
  102. [TestMethod]
  103. public async Task Send_Manual_Ping()
  104. {
  105. using (var testEnvironment = new TestEnvironment(TestContext))
  106. {
  107. await testEnvironment.StartServerAsync();
  108. var client = await testEnvironment.ConnectClientAsync();
  109. await client.PingAsync(CancellationToken.None);
  110. }
  111. }
  112. [TestMethod]
  113. public async Task Send_Reply_In_Message_Handler_For_Same_Client()
  114. {
  115. using (var testEnvironment = new TestEnvironment(TestContext))
  116. {
  117. await testEnvironment.StartServerAsync();
  118. var client = await testEnvironment.ConnectClientAsync();
  119. await client.SubscribeAsync("#");
  120. var replyReceived = false;
  121. client.UseApplicationMessageReceivedHandler(c =>
  122. {
  123. if (c.ApplicationMessage.Topic == "request")
  124. {
  125. #pragma warning disable 4014
  126. Task.Run(() => client.PublishAsync("reply", null, MqttQualityOfServiceLevel.AtLeastOnce));
  127. #pragma warning restore 4014
  128. }
  129. else
  130. {
  131. replyReceived = true;
  132. }
  133. });
  134. await client.PublishAsync("request", null, MqttQualityOfServiceLevel.AtLeastOnce);
  135. SpinWait.SpinUntil(() => replyReceived, TimeSpan.FromSeconds(10));
  136. Assert.IsTrue(replyReceived);
  137. }
  138. }
  139. [TestMethod]
  140. public async Task Send_Reply_In_Message_Handler()
  141. {
  142. using (var testEnvironment = new TestEnvironment())
  143. {
  144. await testEnvironment.StartServerAsync();
  145. var client1 = await testEnvironment.ConnectClientAsync();
  146. var client2 = await testEnvironment.ConnectClientAsync();
  147. await client1.SubscribeAsync("#");
  148. await client2.SubscribeAsync("#");
  149. var replyReceived = false;
  150. client1.UseApplicationMessageReceivedHandler(c =>
  151. {
  152. if (c.ApplicationMessage.Topic == "reply")
  153. {
  154. replyReceived = true;
  155. }
  156. });
  157. client2.UseApplicationMessageReceivedHandler(async c =>
  158. {
  159. if (c.ApplicationMessage.Topic == "request")
  160. {
  161. // Use AtMostOnce here because with QoS 1 or even QoS 2 the process waits for
  162. // the ACK etc. The problem is that the SpinUntil below only waits until the
  163. // flag is set. It does not wait until the client has sent the ACK
  164. await client2.PublishAsync("reply", null, MqttQualityOfServiceLevel.AtMostOnce);
  165. }
  166. });
  167. await client1.PublishAsync("request", null, MqttQualityOfServiceLevel.AtLeastOnce);
  168. await Task.Delay(500);
  169. SpinWait.SpinUntil(() => replyReceived, TimeSpan.FromSeconds(10));
  170. await Task.Delay(500);
  171. Assert.IsTrue(replyReceived);
  172. }
  173. }
  174. [TestMethod]
  175. public async Task Reconnect()
  176. {
  177. using (var testEnvironment = new TestEnvironment(TestContext))
  178. {
  179. var server = await testEnvironment.StartServerAsync();
  180. var client = await testEnvironment.ConnectClientAsync();
  181. await Task.Delay(500);
  182. Assert.IsTrue(client.IsConnected);
  183. await server.StopAsync();
  184. await Task.Delay(500);
  185. Assert.IsFalse(client.IsConnected);
  186. await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
  187. await Task.Delay(500);
  188. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
  189. Assert.IsTrue(client.IsConnected);
  190. }
  191. }
  192. [TestMethod]
  193. public async Task Reconnect_While_Server_Offline()
  194. {
  195. using (var testEnvironment = new TestEnvironment(TestContext))
  196. {
  197. testEnvironment.IgnoreClientLogErrors = true;
  198. var server = await testEnvironment.StartServerAsync();
  199. var client = await testEnvironment.ConnectClientAsync();
  200. await Task.Delay(500);
  201. Assert.IsTrue(client.IsConnected);
  202. await server.StopAsync();
  203. await Task.Delay(500);
  204. Assert.IsFalse(client.IsConnected);
  205. for (var i = 0; i < 5; i++)
  206. {
  207. try
  208. {
  209. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
  210. Assert.Fail("Must fail!");
  211. }
  212. catch
  213. {
  214. }
  215. }
  216. await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
  217. await Task.Delay(500);
  218. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
  219. Assert.IsTrue(client.IsConnected);
  220. }
  221. }
  222. [TestMethod]
  223. public async Task Reconnect_From_Disconnected_Event()
  224. {
  225. using (var testEnvironment = new TestEnvironment(TestContext))
  226. {
  227. testEnvironment.IgnoreClientLogErrors = true;
  228. var client = testEnvironment.CreateClient();
  229. var tries = 0;
  230. var maxTries = 3;
  231. client.UseDisconnectedHandler(async e =>
  232. {
  233. if (tries >= maxTries)
  234. {
  235. return;
  236. }
  237. Interlocked.Increment(ref tries);
  238. await Task.Delay(100);
  239. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
  240. });
  241. try
  242. {
  243. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("127.0.0.1", testEnvironment.ServerPort).Build());
  244. Assert.Fail("Must fail!");
  245. }
  246. catch
  247. {
  248. }
  249. SpinWait.SpinUntil(() => tries >= maxTries, 10000);
  250. Assert.AreEqual(maxTries, tries);
  251. }
  252. }
  253. [TestMethod]
  254. public async Task PacketIdentifier_In_Publish_Result()
  255. {
  256. using (var testEnvironment = new TestEnvironment(TestContext))
  257. {
  258. await testEnvironment.StartServerAsync();
  259. var client = await testEnvironment.ConnectClientAsync();
  260. var result = await client.PublishAsync("a", "a", MqttQualityOfServiceLevel.AtMostOnce);
  261. Assert.AreEqual(null, result.PacketIdentifier);
  262. result = await client.PublishAsync("b", "b", MqttQualityOfServiceLevel.AtMostOnce);
  263. Assert.AreEqual(null, result.PacketIdentifier);
  264. result = await client.PublishAsync("a", "a", MqttQualityOfServiceLevel.AtLeastOnce);
  265. Assert.AreEqual((ushort)1, result.PacketIdentifier);
  266. result = await client.PublishAsync("b", "b", MqttQualityOfServiceLevel.AtLeastOnce);
  267. Assert.AreEqual((ushort)2, result.PacketIdentifier);
  268. result = await client.PublishAsync("a", "a", MqttQualityOfServiceLevel.ExactlyOnce);
  269. Assert.AreEqual((ushort)3, result.PacketIdentifier);
  270. result = await client.PublishAsync("b", "b", MqttQualityOfServiceLevel.ExactlyOnce);
  271. Assert.AreEqual((ushort)4, result.PacketIdentifier);
  272. }
  273. }
  274. [TestMethod]
  275. public async Task Invalid_Connect_Throws_Exception()
  276. {
  277. var factory = new MqttFactory();
  278. using (var client = factory.CreateMqttClient())
  279. {
  280. try
  281. {
  282. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("wrong-server").Build());
  283. Assert.Fail("Must fail!");
  284. }
  285. catch (Exception exception)
  286. {
  287. Assert.IsNotNull(exception);
  288. Assert.IsInstanceOfType(exception, typeof(MqttCommunicationException));
  289. Assert.IsInstanceOfType(exception.InnerException, typeof(SocketException));
  290. }
  291. }
  292. }
  293. [TestMethod]
  294. public async Task ConnectTimeout_Throws_Exception()
  295. {
  296. var factory = new MqttFactory();
  297. using (var client = factory.CreateMqttClient())
  298. {
  299. bool disconnectHandlerCalled = false;
  300. try
  301. {
  302. client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(args =>
  303. {
  304. disconnectHandlerCalled = true;
  305. });
  306. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("1.2.3.4").Build());
  307. Assert.Fail("Must fail!");
  308. }
  309. catch (Exception exception)
  310. {
  311. Assert.IsNotNull(exception);
  312. Assert.IsInstanceOfType(exception, typeof(MqttCommunicationException));
  313. //Assert.IsInstanceOfType(exception.InnerException, typeof(SocketException));
  314. }
  315. await Task.Delay(100); // disconnected handler is called async
  316. Assert.IsTrue(disconnectHandlerCalled);
  317. }
  318. }
  319. [TestMethod]
  320. public async Task Fire_Disconnected_Event_On_Server_Shutdown()
  321. {
  322. using (var testEnvironment = new TestEnvironment(TestContext))
  323. {
  324. var server = await testEnvironment.StartServerAsync();
  325. var client = await testEnvironment.ConnectClientAsync();
  326. var handlerFired = false;
  327. client.UseDisconnectedHandler(e => handlerFired = true);
  328. await server.StopAsync();
  329. await Task.Delay(4000);
  330. Assert.IsTrue(handlerFired);
  331. }
  332. }
  333. [TestMethod]
  334. public async Task Disconnect_Event_Contains_Exception()
  335. {
  336. var factory = new MqttFactory();
  337. using (var client = factory.CreateMqttClient())
  338. {
  339. Exception ex = null;
  340. client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(e =>
  341. {
  342. ex = e.Exception;
  343. });
  344. try
  345. {
  346. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("wrong-server").Build());
  347. }
  348. catch
  349. {
  350. }
  351. await Task.Delay(500);
  352. Assert.IsNotNull(ex);
  353. Assert.IsInstanceOfType(ex, typeof(MqttCommunicationException));
  354. Assert.IsInstanceOfType(ex.InnerException, typeof(SocketException));
  355. }
  356. }
  357. [TestMethod]
  358. public async Task Preserve_Message_Order()
  359. {
  360. // The messages are sent in reverse or to ensure that the delay in the handler
  361. // needs longer for the first messages and later messages may be processed earlier (if there
  362. // is an issue).
  363. const int MessagesCount = 50;
  364. using (var testEnvironment = new TestEnvironment(TestContext))
  365. {
  366. await testEnvironment.StartServerAsync();
  367. var client1 = await testEnvironment.ConnectClientAsync();
  368. await client1.SubscribeAsync("x");
  369. var receivedValues = new List<int>();
  370. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  371. {
  372. var value = int.Parse(eventArgs.ApplicationMessage.ConvertPayloadToString());
  373. await Task.Delay(value);
  374. lock (receivedValues)
  375. {
  376. receivedValues.Add(value);
  377. }
  378. }
  379. client1.UseApplicationMessageReceivedHandler(Handler1);
  380. var client2 = await testEnvironment.ConnectClientAsync();
  381. for (var i = MessagesCount; i > 0; i--)
  382. {
  383. await client2.PublishAsync("x", i.ToString());
  384. }
  385. await Task.Delay(5000);
  386. for (var i = MessagesCount; i > 0; i--)
  387. {
  388. Assert.AreEqual(i, receivedValues[MessagesCount - i]);
  389. }
  390. }
  391. }
  392. [TestMethod]
  393. public async Task Preserve_Message_Order_With_Delayed_Acknowledgement()
  394. {
  395. // The messages are sent in reverse or to ensure that the delay in the handler
  396. // needs longer for the first messages and later messages may be processed earlier (if there
  397. // is an issue).
  398. const int MessagesCount = 50;
  399. using (var testEnvironment = new TestEnvironment(TestContext))
  400. {
  401. await testEnvironment.StartServerAsync();
  402. var client1 = await testEnvironment.ConnectClientAsync();
  403. await client1.SubscribeAsync("x", MqttQualityOfServiceLevel.ExactlyOnce);
  404. var receivedValues = new List<int>();
  405. Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  406. {
  407. var value = int.Parse(eventArgs.ApplicationMessage.ConvertPayloadToString());
  408. eventArgs.AutoAcknowledge = false;
  409. Task.Delay(value).ContinueWith(x => eventArgs.AcknowledgeAsync(CancellationToken.None));
  410. System.Diagnostics.Debug.WriteLine($"received {value}");
  411. lock (receivedValues)
  412. {
  413. receivedValues.Add(value);
  414. }
  415. return Task.CompletedTask;
  416. }
  417. client1.UseApplicationMessageReceivedHandler(Handler1);
  418. var client2 = await testEnvironment.ConnectClientAsync();
  419. for (var i = MessagesCount; i > 0; i--)
  420. {
  421. await client2.PublishAsync("x", i.ToString(), MqttQualityOfServiceLevel.ExactlyOnce);
  422. }
  423. await Task.Delay(5000);
  424. for (var i = MessagesCount; i > 0; i--)
  425. {
  426. Assert.AreEqual(i, receivedValues[MessagesCount - i]);
  427. }
  428. }
  429. }
  430. [TestMethod]
  431. public async Task Send_Reply_For_Any_Received_Message()
  432. {
  433. using (var testEnvironment = new TestEnvironment(TestContext))
  434. {
  435. await testEnvironment.StartServerAsync();
  436. var client1 = await testEnvironment.ConnectClientAsync();
  437. await client1.SubscribeAsync("request/+");
  438. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  439. {
  440. await client1.PublishAsync($"reply/{eventArgs.ApplicationMessage.Topic}");
  441. }
  442. client1.UseApplicationMessageReceivedHandler(Handler1);
  443. var client2 = await testEnvironment.ConnectClientAsync();
  444. await client2.SubscribeAsync("reply/#");
  445. var replies = new List<string>();
  446. void Handler2(MqttApplicationMessageReceivedEventArgs eventArgs)
  447. {
  448. lock (replies)
  449. {
  450. replies.Add(eventArgs.ApplicationMessage.Topic);
  451. }
  452. }
  453. client2.UseApplicationMessageReceivedHandler((Action<MqttApplicationMessageReceivedEventArgs>)Handler2);
  454. await Task.Delay(500);
  455. await client2.PublishAsync("request/a");
  456. await client2.PublishAsync("request/b");
  457. await client2.PublishAsync("request/c");
  458. await Task.Delay(500);
  459. Assert.AreEqual("reply/request/a,reply/request/b,reply/request/c", string.Join(",", replies));
  460. }
  461. }
  462. [TestMethod]
  463. public async Task Publish_With_Correct_Retain_Flag()
  464. {
  465. using (var testEnvironment = new TestEnvironment(TestContext))
  466. {
  467. await testEnvironment.StartServerAsync();
  468. var receivedMessages = new List<MqttApplicationMessage>();
  469. var client1 = await testEnvironment.ConnectClientAsync();
  470. client1.UseApplicationMessageReceivedHandler(c =>
  471. {
  472. lock (receivedMessages)
  473. {
  474. receivedMessages.Add(c.ApplicationMessage);
  475. }
  476. });
  477. await client1.SubscribeAsync("a");
  478. var client2 = await testEnvironment.ConnectClientAsync();
  479. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithRetainFlag().Build();
  480. await client2.PublishAsync(message);
  481. await Task.Delay(500);
  482. Assert.AreEqual(1, receivedMessages.Count);
  483. Assert.IsFalse(receivedMessages.First().Retain); // Must be false even if set above!
  484. }
  485. }
  486. [TestMethod]
  487. public async Task Publish_QoS_1_In_ApplicationMessageReceiveHandler()
  488. {
  489. using (var testEnvironment = new TestEnvironment(TestContext))
  490. {
  491. await testEnvironment.StartServerAsync();
  492. const string client1Topic = "client1/topic";
  493. const string client2Topic = "client2/topic";
  494. const string expectedClient2Message = "hello client2";
  495. var client1 = await testEnvironment.ConnectClientAsync();
  496. client1.UseApplicationMessageReceivedHandler(async c =>
  497. {
  498. await client1.PublishAsync(client2Topic, expectedClient2Message, MqttQualityOfServiceLevel.AtLeastOnce);
  499. });
  500. await client1.SubscribeAsync(client1Topic, MqttQualityOfServiceLevel.AtLeastOnce);
  501. var client2 = await testEnvironment.ConnectClientAsync();
  502. var client2TopicResults = new List<string>();
  503. client2.UseApplicationMessageReceivedHandler(c =>
  504. {
  505. client2TopicResults.Add(Encoding.UTF8.GetString(c.ApplicationMessage.Payload));
  506. });
  507. await client2.SubscribeAsync(client2Topic);
  508. var client3 = await testEnvironment.ConnectClientAsync();
  509. var message = new MqttApplicationMessageBuilder().WithTopic(client1Topic).Build();
  510. await client3.PublishAsync(message);
  511. await client3.PublishAsync(message);
  512. await Task.Delay(500);
  513. Assert.AreEqual(2, client2TopicResults.Count);
  514. Assert.AreEqual(expectedClient2Message, client2TopicResults[0]);
  515. Assert.AreEqual(expectedClient2Message, client2TopicResults[1]);
  516. }
  517. }
  518. [TestMethod]
  519. public async Task Subscribe_In_Callback_Events()
  520. {
  521. using (var testEnvironment = new TestEnvironment(TestContext))
  522. {
  523. await testEnvironment.StartServerAsync();
  524. var receivedMessages = new List<MqttApplicationMessage>();
  525. var client = testEnvironment.CreateClient();
  526. client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(async e =>
  527. {
  528. await client.SubscribeAsync("RCU/P1/H0001/R0003");
  529. var msg = new MqttApplicationMessageBuilder()
  530. .WithPayload("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|")
  531. .WithTopic("RCU/P1/H0001/R0003");
  532. await client.PublishAsync(msg.Build());
  533. });
  534. client.UseApplicationMessageReceivedHandler(c =>
  535. {
  536. lock (receivedMessages)
  537. {
  538. receivedMessages.Add(c.ApplicationMessage);
  539. }
  540. });
  541. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).Build());
  542. await Task.Delay(500);
  543. Assert.AreEqual(1, receivedMessages.Count);
  544. Assert.AreEqual("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|", receivedMessages.First().ConvertPayloadToString());
  545. }
  546. }
  547. [TestMethod]
  548. public async Task Message_Send_Retry()
  549. {
  550. using (var testEnvironment = new TestEnvironment(TestContext))
  551. {
  552. testEnvironment.IgnoreClientLogErrors = true;
  553. testEnvironment.IgnoreServerLogErrors = true;
  554. await testEnvironment.StartServerAsync(
  555. new MqttServerOptionsBuilder()
  556. .WithPersistentSessions()
  557. .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(250)));
  558. var client1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithCleanSession(false));
  559. await client1.SubscribeAsync("x", MqttQualityOfServiceLevel.AtLeastOnce);
  560. var retries = 0;
  561. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  562. {
  563. retries++;
  564. await Task.Delay(1000);
  565. throw new Exception("Broken!");
  566. }
  567. client1.UseApplicationMessageReceivedHandler(Handler1);
  568. var client2 = await testEnvironment.ConnectClientAsync();
  569. await client2.PublishAsync("x");
  570. await Task.Delay(3000);
  571. // The server should disconnect clients which are not responding.
  572. Assert.IsFalse(client1.IsConnected);
  573. await client1.ReconnectAsync().ConfigureAwait(false);
  574. await Task.Delay(1000);
  575. Assert.AreEqual(2, retries);
  576. }
  577. }
  578. [TestMethod]
  579. public async Task NoConnectedHandler_Connect_DoesNotThrowException()
  580. {
  581. using (var testEnvironment = new TestEnvironment(TestContext))
  582. {
  583. await testEnvironment.StartServerAsync();
  584. var client = await testEnvironment.ConnectClientAsync();
  585. Assert.IsTrue(client.IsConnected);
  586. }
  587. }
  588. [TestMethod]
  589. public async Task NoDisconnectedHandler_Disconnect_DoesNotThrowException()
  590. {
  591. using (var testEnvironment = new TestEnvironment(TestContext))
  592. {
  593. await testEnvironment.StartServerAsync();
  594. var client = await testEnvironment.ConnectClientAsync();
  595. Assert.IsTrue(client.IsConnected);
  596. await client.DisconnectAsync();
  597. Assert.IsFalse(client.IsConnected);
  598. }
  599. }
  600. [TestMethod]
  601. public async Task Frequent_Connects()
  602. {
  603. using (var testEnvironment = new TestEnvironment(TestContext))
  604. {
  605. await testEnvironment.StartServerAsync();
  606. var clients = new List<IMqttClient>();
  607. for (var i = 0; i < 100; i++)
  608. {
  609. clients.Add(await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("a")));
  610. }
  611. await Task.Delay(500);
  612. var clientStatus = await testEnvironment.Server.GetClientStatusAsync();
  613. var sessionStatus = await testEnvironment.Server.GetSessionStatusAsync();
  614. for (var i = 0; i < 98; i++)
  615. {
  616. Assert.IsFalse(clients[i].IsConnected, $"clients[{i}] is not connected");
  617. }
  618. Assert.IsTrue(clients[99].IsConnected);
  619. Assert.AreEqual(1, clientStatus.Count);
  620. Assert.AreEqual(1, sessionStatus.Count);
  621. var receiveClient = clients[99];
  622. object receivedPayload = null;
  623. receiveClient.UseApplicationMessageReceivedHandler(e =>
  624. {
  625. receivedPayload = e.ApplicationMessage.ConvertPayloadToString();
  626. });
  627. await receiveClient.SubscribeAsync("x");
  628. var sendClient = await testEnvironment.ConnectClientAsync();
  629. await sendClient.PublishAsync("x", "1");
  630. await Task.Delay(250);
  631. Assert.AreEqual("1", receivedPayload);
  632. }
  633. }
  634. [TestMethod]
  635. public async Task No_Payload()
  636. {
  637. using (var testEnvironment = new TestEnvironment(TestContext))
  638. {
  639. await testEnvironment.StartServerAsync();
  640. var sender = await testEnvironment.ConnectClientAsync();
  641. var receiver = await testEnvironment.ConnectClientAsync();
  642. var message = new MqttApplicationMessageBuilder()
  643. .WithTopic("A");
  644. await receiver.SubscribeAsync(new MqttClientSubscribeOptions
  645. {
  646. TopicFilters = new List<MqttTopicFilter> { new MqttTopicFilter { Topic = "#" } }
  647. }, CancellationToken.None);
  648. MqttApplicationMessage receivedMessage = null;
  649. receiver.UseApplicationMessageReceivedHandler(e => receivedMessage = e.ApplicationMessage);
  650. await sender.PublishAsync(message.Build(), CancellationToken.None);
  651. await Task.Delay(1000);
  652. Assert.IsNotNull(receivedMessage);
  653. Assert.AreEqual("A", receivedMessage.Topic);
  654. Assert.AreEqual(null, receivedMessage.Payload);
  655. }
  656. }
  657. [TestMethod]
  658. public async Task Subscribe_With_QoS2()
  659. {
  660. using (var testEnvironment = new TestEnvironment())
  661. {
  662. await testEnvironment.StartServerAsync();
  663. var client1 = await testEnvironment.ConnectClientAsync(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
  664. var client2 = await testEnvironment.ConnectClientAsync(o => o.WithProtocolVersion(MqttProtocolVersion.V500));
  665. var disconnectedFired = false;
  666. client1.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(c =>
  667. {
  668. disconnectedFired = true;
  669. });
  670. var messageReceived = false;
  671. client1.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c =>
  672. {
  673. messageReceived = true;
  674. });
  675. await client1.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("topic1").WithExactlyOnceQoS().Build());
  676. await Task.Delay(500);
  677. var message = new MqttApplicationMessageBuilder().WithTopic("topic1").WithPayload("Hello World").WithExactlyOnceQoS().WithRetainFlag().Build();
  678. await client2.PublishAsync(message);
  679. await Task.Delay(500);
  680. Assert.IsTrue(messageReceived);
  681. Assert.IsTrue(client1.IsConnected);
  682. Assert.IsFalse(disconnectedFired);
  683. }
  684. }
  685. }
  686. }