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.

MqttClient_Tests.cs 31 KiB

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