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.
 
 
 
 

1426 lines
52 KiB

  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. using MQTTnet.Adapter;
  3. using MQTTnet.Client;
  4. using MQTTnet.Client.Connecting;
  5. using MQTTnet.Client.Disconnecting;
  6. using MQTTnet.Client.Options;
  7. using MQTTnet.Client.Receiving;
  8. using MQTTnet.Client.Subscribing;
  9. using MQTTnet.Protocol;
  10. using MQTTnet.Server;
  11. using MQTTnet.Tests.Mockups;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Linq;
  15. using System.Text;
  16. using System.Threading;
  17. using System.Threading.Tasks;
  18. using MQTTnet.Diagnostics;
  19. using MQTTnet.Formatter;
  20. namespace MQTTnet.Tests
  21. {
  22. [TestClass]
  23. public sealed class Server_Tests
  24. {
  25. public TestContext TestContext { get; set; }
  26. [TestMethod]
  27. public async Task Use_Empty_Client_ID()
  28. {
  29. using (var testEnvironment = new TestEnvironment(TestContext))
  30. {
  31. await testEnvironment.StartServerAsync();
  32. var client = testEnvironment.CreateClient();
  33. var clientOptions = new MqttClientOptionsBuilder()
  34. .WithTcpServer("localhost", testEnvironment.ServerPort)
  35. .WithClientId(string.Empty)
  36. .Build();
  37. var connectResult = await client.ConnectAsync(clientOptions);
  38. Assert.IsFalse(connectResult.IsSessionPresent);
  39. Assert.IsTrue(client.IsConnected);
  40. }
  41. }
  42. [TestMethod]
  43. public async Task Publish_At_Most_Once_0x00()
  44. {
  45. await TestPublishAsync(
  46. "A/B/C",
  47. MqttQualityOfServiceLevel.AtMostOnce,
  48. "A/B/C",
  49. MqttQualityOfServiceLevel.AtMostOnce,
  50. 1,
  51. TestContext);
  52. }
  53. [TestMethod]
  54. public async Task Publish_At_Least_Once_0x01()
  55. {
  56. await TestPublishAsync(
  57. "A/B/C",
  58. MqttQualityOfServiceLevel.AtLeastOnce,
  59. "A/B/C",
  60. MqttQualityOfServiceLevel.AtLeastOnce,
  61. 1,
  62. TestContext);
  63. }
  64. [TestMethod]
  65. public async Task Publish_Exactly_Once_0x02()
  66. {
  67. await TestPublishAsync(
  68. "A/B/C",
  69. MqttQualityOfServiceLevel.ExactlyOnce,
  70. "A/B/C",
  71. MqttQualityOfServiceLevel.ExactlyOnce,
  72. 1,
  73. TestContext);
  74. }
  75. [TestMethod]
  76. public async Task Use_Clean_Session()
  77. {
  78. using (var testEnvironment = new TestEnvironment(TestContext))
  79. {
  80. await testEnvironment.StartServerAsync();
  81. var client = testEnvironment.CreateClient();
  82. var connectResult = await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).WithCleanSession().Build());
  83. Assert.IsFalse(connectResult.IsSessionPresent);
  84. }
  85. }
  86. [TestMethod]
  87. public async Task Will_Message_Do_Not_Send()
  88. {
  89. using (var testEnvironment = new TestEnvironment(TestContext))
  90. {
  91. var receivedMessagesCount = 0;
  92. await testEnvironment.StartServerAsync();
  93. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  94. var clientOptions = new MqttClientOptionsBuilder().WithWillMessage(willMessage);
  95. var c1 = await testEnvironment.ConnectClientAsync();
  96. c1.ApplicationMessageReceivedHandler = new MqttApplicationMessageReceivedHandlerDelegate(c => Interlocked.Increment(ref receivedMessagesCount));
  97. await c1.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("#").Build());
  98. var c2 = await testEnvironment.ConnectClientAsync(clientOptions);
  99. await c2.DisconnectAsync().ConfigureAwait(false);
  100. await Task.Delay(1000);
  101. Assert.AreEqual(0, receivedMessagesCount);
  102. }
  103. }
  104. [TestMethod]
  105. public async Task Will_Message_Send()
  106. {
  107. using (var testEnvironment = new TestEnvironment(TestContext))
  108. {
  109. var receivedMessagesCount = 0;
  110. await testEnvironment.StartServerAsync();
  111. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  112. var clientOptions = new MqttClientOptionsBuilder().WithWillMessage(willMessage);
  113. var c1 = await testEnvironment.ConnectClientAsync();
  114. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  115. await c1.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("#").Build());
  116. var c2 = await testEnvironment.ConnectClientAsync(clientOptions);
  117. c2.Dispose(); // Dispose will not send a DISCONNECT pattern first so the will message must be sent.
  118. await Task.Delay(1000);
  119. Assert.AreEqual(1, receivedMessagesCount);
  120. }
  121. }
  122. [TestMethod]
  123. public async Task Intercept_Subscription()
  124. {
  125. using (var testEnvironment = new TestEnvironment(TestContext))
  126. {
  127. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(
  128. c =>
  129. {
  130. // Set the topic to "a" regards what the client wants to subscribe.
  131. c.TopicFilter.Topic = "a";
  132. }));
  133. var topicAReceived = false;
  134. var topicBReceived = false;
  135. var client = await testEnvironment.ConnectClientAsync();
  136. client.UseApplicationMessageReceivedHandler(c =>
  137. {
  138. if (c.ApplicationMessage.Topic == "a")
  139. {
  140. topicAReceived = true;
  141. }
  142. else if (c.ApplicationMessage.Topic == "b")
  143. {
  144. topicBReceived = true;
  145. }
  146. });
  147. await client.SubscribeAsync("b");
  148. await client.PublishAsync("a");
  149. await Task.Delay(500);
  150. Assert.IsTrue(topicAReceived);
  151. Assert.IsFalse(topicBReceived);
  152. }
  153. }
  154. [TestMethod]
  155. public async Task Subscribe_Unsubscribe()
  156. {
  157. using (var testEnvironment = new TestEnvironment(TestContext))
  158. {
  159. var receivedMessagesCount = 0;
  160. var server = await testEnvironment.StartServerAsync();
  161. var c1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("c1"));
  162. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  163. var c2 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("c2"));
  164. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  165. await c2.PublishAsync(message);
  166. await Task.Delay(500);
  167. Assert.AreEqual(0, receivedMessagesCount);
  168. var subscribeEventCalled = false;
  169. server.ClientSubscribedTopicHandler = new MqttServerClientSubscribedHandlerDelegate(e =>
  170. {
  171. subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == c1.Options.ClientId;
  172. });
  173. await c1.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  174. await Task.Delay(250);
  175. Assert.IsTrue(subscribeEventCalled, "Subscribe event not called.");
  176. await c2.PublishAsync(message);
  177. await Task.Delay(250);
  178. Assert.AreEqual(1, receivedMessagesCount);
  179. var unsubscribeEventCalled = false;
  180. server.ClientUnsubscribedTopicHandler = new MqttServerClientUnsubscribedTopicHandlerDelegate(e =>
  181. {
  182. unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == c1.Options.ClientId;
  183. });
  184. await c1.UnsubscribeAsync("a");
  185. await Task.Delay(250);
  186. Assert.IsTrue(unsubscribeEventCalled, "Unsubscribe event not called.");
  187. await c2.PublishAsync(message);
  188. await Task.Delay(500);
  189. Assert.AreEqual(1, receivedMessagesCount);
  190. await Task.Delay(500);
  191. Assert.AreEqual(1, receivedMessagesCount);
  192. }
  193. }
  194. [TestMethod]
  195. public async Task Subscribe_Multiple_In_Single_Request()
  196. {
  197. using (var testEnvironment = new TestEnvironment(TestContext))
  198. {
  199. var receivedMessagesCount = 0;
  200. await testEnvironment.StartServerAsync();
  201. var c1 = await testEnvironment.ConnectClientAsync();
  202. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  203. await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
  204. .WithTopicFilter("a")
  205. .WithTopicFilter("b")
  206. .WithTopicFilter("c")
  207. .Build());
  208. var c2 = await testEnvironment.ConnectClientAsync();
  209. await c2.PublishAsync("a");
  210. await Task.Delay(100);
  211. Assert.AreEqual(receivedMessagesCount, 1);
  212. await c2.PublishAsync("b");
  213. await Task.Delay(100);
  214. Assert.AreEqual(receivedMessagesCount, 2);
  215. await c2.PublishAsync("c");
  216. await Task.Delay(100);
  217. Assert.AreEqual(receivedMessagesCount, 3);
  218. }
  219. }
  220. [TestMethod]
  221. public async Task Subscribe_Lots_In_Single_Request()
  222. {
  223. using (var testEnvironment = new TestEnvironment(TestContext))
  224. {
  225. var receivedMessagesCount = 0;
  226. await testEnvironment.StartServerAsync();
  227. var c1 = await testEnvironment.ConnectClientAsync();
  228. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  229. var optionsBuilder = new MqttClientSubscribeOptionsBuilder();
  230. for (var i = 0; i < 500; i++)
  231. {
  232. optionsBuilder.WithTopicFilter(i.ToString(), MqttQualityOfServiceLevel.AtMostOnce);
  233. }
  234. await c1.SubscribeAsync(optionsBuilder.Build()).ConfigureAwait(false);
  235. var c2 = await testEnvironment.ConnectClientAsync();
  236. var messageBuilder = new MqttApplicationMessageBuilder();
  237. for (var i = 0; i < 500; i++)
  238. {
  239. messageBuilder.WithTopic(i.ToString());
  240. await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
  241. }
  242. SpinWait.SpinUntil(() => receivedMessagesCount == 500, 5000);
  243. Assert.AreEqual(500, receivedMessagesCount);
  244. }
  245. }
  246. [TestMethod]
  247. public async Task Subscribe_Lots_In_Multiple_Requests()
  248. {
  249. using (var testEnvironment = new TestEnvironment(TestContext))
  250. {
  251. var receivedMessagesCount = 0;
  252. await testEnvironment.StartServerAsync();
  253. var c1 = await testEnvironment.ConnectClientAsync();
  254. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  255. for (var i = 0; i < 500; i++)
  256. {
  257. var so = new MqttClientSubscribeOptionsBuilder()
  258. .WithTopicFilter(i.ToString()).Build();
  259. await c1.SubscribeAsync(so).ConfigureAwait(false);
  260. await Task.Delay(10);
  261. }
  262. var c2 = await testEnvironment.ConnectClientAsync();
  263. var messageBuilder = new MqttApplicationMessageBuilder();
  264. for (var i = 0; i < 500; i++)
  265. {
  266. messageBuilder.WithTopic(i.ToString());
  267. await c2.PublishAsync(messageBuilder.Build()).ConfigureAwait(false);
  268. await Task.Delay(10);
  269. }
  270. SpinWait.SpinUntil(() => receivedMessagesCount == 500, 5000);
  271. Assert.AreEqual(500, receivedMessagesCount);
  272. }
  273. }
  274. [TestMethod]
  275. public async Task Subscribe_Multiple_In_Multiple_Request()
  276. {
  277. using (var testEnvironment = new TestEnvironment(TestContext))
  278. {
  279. var receivedMessagesCount = 0;
  280. await testEnvironment.StartServerAsync();
  281. var c1 = await testEnvironment.ConnectClientAsync();
  282. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  283. await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
  284. .WithTopicFilter("a")
  285. .Build());
  286. await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
  287. .WithTopicFilter("b")
  288. .Build());
  289. await c1.SubscribeAsync(new MqttClientSubscribeOptionsBuilder()
  290. .WithTopicFilter("c")
  291. .Build());
  292. var c2 = await testEnvironment.ConnectClientAsync();
  293. await c2.PublishAsync("a");
  294. await Task.Delay(100);
  295. Assert.AreEqual(receivedMessagesCount, 1);
  296. await c2.PublishAsync("b");
  297. await Task.Delay(100);
  298. Assert.AreEqual(receivedMessagesCount, 2);
  299. await c2.PublishAsync("c");
  300. await Task.Delay(100);
  301. Assert.AreEqual(receivedMessagesCount, 3);
  302. }
  303. }
  304. [TestMethod]
  305. public async Task Publish_From_Server()
  306. {
  307. using (var testEnvironment = new TestEnvironment(TestContext))
  308. {
  309. var server = await testEnvironment.StartServerAsync();
  310. var receivedMessagesCount = 0;
  311. var client = await testEnvironment.ConnectClientAsync();
  312. client.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  313. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  314. await client.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  315. await server.PublishAsync(message);
  316. await Task.Delay(1000);
  317. Assert.AreEqual(1, receivedMessagesCount);
  318. }
  319. }
  320. [TestMethod]
  321. public async Task Publish_Multiple_Clients()
  322. {
  323. var receivedMessagesCount = 0;
  324. using (var testEnvironment = new TestEnvironment(TestContext))
  325. {
  326. await testEnvironment.StartServerAsync();
  327. var c1 = await testEnvironment.ConnectClientAsync();
  328. var c2 = await testEnvironment.ConnectClientAsync();
  329. var c3 = await testEnvironment.ConnectClientAsync();
  330. c2.UseApplicationMessageReceivedHandler(c =>
  331. {
  332. Interlocked.Increment(ref receivedMessagesCount);
  333. });
  334. c3.UseApplicationMessageReceivedHandler(c =>
  335. {
  336. Interlocked.Increment(ref receivedMessagesCount);
  337. });
  338. await c2.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }).ConfigureAwait(false);
  339. await c3.SubscribeAsync(new MqttTopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce }).ConfigureAwait(false);
  340. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  341. for (var i = 0; i < 500; i++)
  342. {
  343. await c1.PublishAsync(message).ConfigureAwait(false);
  344. }
  345. SpinWait.SpinUntil(() => receivedMessagesCount == 1000, TimeSpan.FromSeconds(10));
  346. Assert.AreEqual(1000, receivedMessagesCount);
  347. }
  348. }
  349. [TestMethod]
  350. public async Task Session_Takeover()
  351. {
  352. using (var testEnvironment = new TestEnvironment(TestContext))
  353. {
  354. await testEnvironment.StartServerAsync();
  355. var options = new MqttClientOptionsBuilder()
  356. .WithCleanSession(false)
  357. .WithProtocolVersion(MqttProtocolVersion.V500) // Disconnect reason is only available in MQTT 5+
  358. .WithClientId("a");
  359. var client1 = await testEnvironment.ConnectClientAsync(options);
  360. await Task.Delay(500);
  361. MqttClientDisconnectReason disconnectReason = MqttClientDisconnectReason.NormalDisconnection;
  362. client1.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(c =>
  363. {
  364. disconnectReason = c.Reason;
  365. });
  366. var client2 = await testEnvironment.ConnectClientAsync(options);
  367. await Task.Delay(500);
  368. Assert.IsFalse(client1.IsConnected);
  369. Assert.IsTrue(client2.IsConnected);
  370. Assert.AreEqual(MqttClientDisconnectReason.SessionTakenOver, disconnectReason);
  371. }
  372. }
  373. [TestMethod]
  374. public async Task No_Messages_If_No_Subscription()
  375. {
  376. using (var testEnvironment = new TestEnvironment(TestContext))
  377. {
  378. await testEnvironment.StartServerAsync();
  379. var client = await testEnvironment.ConnectClientAsync();
  380. var receivedMessages = new List<MqttApplicationMessage>();
  381. client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(async e =>
  382. {
  383. await client.PublishAsync("Connected");
  384. });
  385. client.UseApplicationMessageReceivedHandler(c =>
  386. {
  387. lock (receivedMessages)
  388. {
  389. receivedMessages.Add(c.ApplicationMessage);
  390. }
  391. });
  392. await Task.Delay(500);
  393. await client.PublishAsync("Hello");
  394. await Task.Delay(500);
  395. Assert.AreEqual(0, receivedMessages.Count);
  396. }
  397. }
  398. [TestMethod]
  399. public async Task Set_Subscription_At_Server()
  400. {
  401. using (var testEnvironment = new TestEnvironment(TestContext))
  402. {
  403. var server = await testEnvironment.StartServerAsync();
  404. server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(e => server.SubscribeAsync(e.ClientId, "topic1"));
  405. var client = await testEnvironment.ConnectClientAsync();
  406. var receivedMessages = new List<MqttApplicationMessage>();
  407. client.UseApplicationMessageReceivedHandler(c =>
  408. {
  409. lock (receivedMessages)
  410. {
  411. receivedMessages.Add(c.ApplicationMessage);
  412. }
  413. });
  414. await Task.Delay(500);
  415. await client.PublishAsync("Hello");
  416. await Task.Delay(100);
  417. Assert.AreEqual(0, receivedMessages.Count);
  418. await client.PublishAsync("topic1");
  419. await Task.Delay(100);
  420. Assert.AreEqual(1, receivedMessages.Count);
  421. }
  422. }
  423. [TestMethod]
  424. public async Task Shutdown_Disconnects_Clients_Gracefully()
  425. {
  426. using (var testEnvironment = new TestEnvironment(TestContext))
  427. {
  428. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  429. var disconnectCalled = 0;
  430. var c1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder());
  431. c1.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(e => disconnectCalled++);
  432. await Task.Delay(100);
  433. await server.StopAsync();
  434. await Task.Delay(100);
  435. Assert.AreEqual(1, disconnectCalled);
  436. }
  437. }
  438. [TestMethod]
  439. public async Task Handle_Clean_Disconnect()
  440. {
  441. using (var testEnvironment = new TestEnvironment(TestContext))
  442. {
  443. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  444. var clientConnectedCalled = 0;
  445. var clientDisconnectedCalled = 0;
  446. server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ => Interlocked.Increment(ref clientConnectedCalled));
  447. server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ => Interlocked.Increment(ref clientDisconnectedCalled));
  448. var c1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder());
  449. Assert.AreEqual(1, clientConnectedCalled);
  450. Assert.AreEqual(0, clientDisconnectedCalled);
  451. await Task.Delay(500);
  452. await c1.DisconnectAsync();
  453. await Task.Delay(500);
  454. Assert.AreEqual(1, clientConnectedCalled);
  455. Assert.AreEqual(1, clientDisconnectedCalled);
  456. }
  457. }
  458. [TestMethod]
  459. public async Task Client_Disconnect_Without_Errors()
  460. {
  461. using (var testEnvironment = new TestEnvironment(TestContext))
  462. {
  463. bool clientWasConnected;
  464. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  465. try
  466. {
  467. var client = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder());
  468. clientWasConnected = true;
  469. await client.DisconnectAsync();
  470. await Task.Delay(500);
  471. }
  472. finally
  473. {
  474. await server.StopAsync();
  475. }
  476. Assert.IsTrue(clientWasConnected);
  477. testEnvironment.ThrowIfLogErrors();
  478. }
  479. }
  480. [TestMethod]
  481. public async Task Handle_Lots_Of_Parallel_Retained_Messages()
  482. {
  483. const int ClientCount = 50;
  484. using (var testEnvironment = new TestEnvironment(TestContext))
  485. {
  486. var server = await testEnvironment.StartServerAsync();
  487. var tasks = new List<Task>();
  488. for (var i = 0; i < ClientCount; i++)
  489. {
  490. var i2 = i;
  491. var testEnvironment2 = testEnvironment;
  492. tasks.Add(Task.Run(async () =>
  493. {
  494. try
  495. {
  496. using (var client = await testEnvironment2.ConnectClientAsync())
  497. {
  498. // Clear retained message.
  499. await client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i2)
  500. .WithPayload(new byte[0]).WithRetainFlag().WithQualityOfServiceLevel(1).Build());
  501. // Set retained message.
  502. await client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i2)
  503. .WithPayload("value").WithRetainFlag().WithQualityOfServiceLevel(1).Build());
  504. await client.DisconnectAsync();
  505. }
  506. }
  507. catch (Exception exception)
  508. {
  509. testEnvironment2.TrackException(exception);
  510. }
  511. }));
  512. await Task.Delay(10);
  513. }
  514. await Task.WhenAll(tasks);
  515. await Task.Delay(1000);
  516. var retainedMessages = await server.GetRetainedApplicationMessagesAsync();
  517. Assert.AreEqual(ClientCount, retainedMessages.Count);
  518. for (var i = 0; i < ClientCount; i++)
  519. {
  520. Assert.IsTrue(retainedMessages.Any(m => m.Topic == "r" + i));
  521. }
  522. }
  523. }
  524. [TestMethod]
  525. public async Task Retained_Messages_Flow()
  526. {
  527. using (var testEnvironment = new TestEnvironment(TestContext))
  528. {
  529. var retainedMessage = new MqttApplicationMessageBuilder().WithTopic("r").WithPayload("r").WithRetainFlag().Build();
  530. await testEnvironment.StartServerAsync();
  531. var c1 = await testEnvironment.ConnectClientAsync();
  532. var receivedMessages = 0;
  533. var c2 = await testEnvironment.ConnectClientAsync();
  534. c2.UseApplicationMessageReceivedHandler(c =>
  535. {
  536. Interlocked.Increment(ref receivedMessages);
  537. });
  538. await c1.PublishAsync(retainedMessage);
  539. await c1.DisconnectAsync();
  540. await Task.Delay(500);
  541. for (var i = 0; i < 5; i++)
  542. {
  543. await c2.UnsubscribeAsync("r");
  544. await Task.Delay(100);
  545. Assert.AreEqual(i, receivedMessages);
  546. await c2.SubscribeAsync("r");
  547. await Task.Delay(100);
  548. Assert.AreEqual(i + 1, receivedMessages);
  549. }
  550. await c2.DisconnectAsync();
  551. }
  552. }
  553. [TestMethod]
  554. public async Task Receive_No_Retained_Message_After_Subscribe()
  555. {
  556. using (var testEnvironment = new TestEnvironment(TestContext))
  557. {
  558. await testEnvironment.StartServerAsync();
  559. var c1 = await testEnvironment.ConnectClientAsync();
  560. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  561. await c1.DisconnectAsync();
  562. var receivedMessagesCount = 0;
  563. var c2 = await testEnvironment.ConnectClientAsync();
  564. c2.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  565. await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained_other").Build());
  566. await Task.Delay(500);
  567. Assert.AreEqual(0, receivedMessagesCount);
  568. }
  569. }
  570. [TestMethod]
  571. public async Task Receive_Retained_Message_After_Subscribe()
  572. {
  573. using (var testEnvironment = new TestEnvironment(TestContext))
  574. {
  575. await testEnvironment.StartServerAsync();
  576. var c1 = await testEnvironment.ConnectClientAsync();
  577. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  578. await c1.DisconnectAsync();
  579. var receivedMessages = new List<MqttApplicationMessage>();
  580. var c2 = await testEnvironment.ConnectClientAsync();
  581. c2.UseApplicationMessageReceivedHandler(c =>
  582. {
  583. lock (receivedMessages)
  584. {
  585. receivedMessages.Add(c.ApplicationMessage);
  586. }
  587. });
  588. await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("retained").Build());
  589. await Task.Delay(500);
  590. Assert.AreEqual(1, receivedMessages.Count);
  591. Assert.IsTrue(receivedMessages.First().Retain);
  592. }
  593. }
  594. [TestMethod]
  595. public async Task Clear_Retained_Message_With_Empty_Payload()
  596. {
  597. using (var testEnvironment = new TestEnvironment(TestContext))
  598. {
  599. var receivedMessagesCount = 0;
  600. await testEnvironment.StartServerAsync();
  601. var c1 = await testEnvironment.ConnectClientAsync();
  602. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  603. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
  604. await c1.DisconnectAsync();
  605. var c2 = await testEnvironment.ConnectClientAsync();
  606. c2.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  607. await Task.Delay(200);
  608. await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  609. await Task.Delay(500);
  610. Assert.AreEqual(0, receivedMessagesCount);
  611. }
  612. }
  613. [TestMethod]
  614. public async Task Clear_Retained_Message_With_Null_Payload()
  615. {
  616. using (var testEnvironment = new TestEnvironment(TestContext))
  617. {
  618. var receivedMessagesCount = 0;
  619. await testEnvironment.StartServerAsync();
  620. var c1 = await testEnvironment.ConnectClientAsync();
  621. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  622. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload((byte[])null).WithRetainFlag().Build());
  623. await c1.DisconnectAsync();
  624. var c2 = await testEnvironment.ConnectClientAsync();
  625. c2.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  626. await Task.Delay(200);
  627. await c2.SubscribeAsync(new MqttTopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  628. await Task.Delay(500);
  629. Assert.AreEqual(0, receivedMessagesCount);
  630. }
  631. }
  632. [TestMethod]
  633. public async Task Intercept_Application_Message()
  634. {
  635. using (var testEnvironment = new TestEnvironment(TestContext))
  636. {
  637. await testEnvironment.StartServerAsync(
  638. new MqttServerOptionsBuilder().WithApplicationMessageInterceptor(
  639. c => { c.ApplicationMessage = new MqttApplicationMessage { Topic = "new_topic" }; }));
  640. string receivedTopic = null;
  641. var c1 = await testEnvironment.ConnectClientAsync();
  642. await c1.SubscribeAsync("#");
  643. c1.UseApplicationMessageReceivedHandler(a => { receivedTopic = a.ApplicationMessage.Topic; });
  644. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("original_topic").Build());
  645. await Task.Delay(500);
  646. Assert.AreEqual("new_topic", receivedTopic);
  647. }
  648. }
  649. [TestMethod]
  650. public async Task Persist_Retained_Message()
  651. {
  652. var serverStorage = new TestServerStorage();
  653. using (var testEnvironment = new TestEnvironment(TestContext))
  654. {
  655. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithStorage(serverStorage));
  656. var c1 = await testEnvironment.ConnectClientAsync();
  657. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  658. await Task.Delay(500);
  659. Assert.AreEqual(1, serverStorage.Messages.Count);
  660. }
  661. }
  662. [TestMethod]
  663. public async Task Publish_After_Client_Connects()
  664. {
  665. using (var testEnvironment = new TestEnvironment(TestContext))
  666. {
  667. var server = await testEnvironment.StartServerAsync();
  668. server.UseClientConnectedHandler(async e =>
  669. {
  670. await server.PublishAsync("/test/1", "true", MqttQualityOfServiceLevel.ExactlyOnce, false);
  671. });
  672. string receivedTopic = null;
  673. var c1 = await testEnvironment.ConnectClientAsync();
  674. c1.UseApplicationMessageReceivedHandler(e => { receivedTopic = e.ApplicationMessage.Topic; });
  675. await c1.SubscribeAsync("#");
  676. await testEnvironment.ConnectClientAsync();
  677. await testEnvironment.ConnectClientAsync();
  678. await testEnvironment.ConnectClientAsync();
  679. await testEnvironment.ConnectClientAsync();
  680. await Task.Delay(500);
  681. Assert.AreEqual("/test/1", receivedTopic);
  682. }
  683. }
  684. [TestMethod]
  685. public async Task Intercept_Message()
  686. {
  687. void Interceptor(MqttApplicationMessageInterceptorContext context)
  688. {
  689. context.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
  690. }
  691. using (var testEnvironment = new TestEnvironment(TestContext))
  692. {
  693. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithApplicationMessageInterceptor(Interceptor));
  694. var c1 = await testEnvironment.ConnectClientAsync();
  695. var c2 = await testEnvironment.ConnectClientAsync();
  696. await c2.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("test").Build());
  697. var isIntercepted = false;
  698. c2.UseApplicationMessageReceivedHandler(c =>
  699. {
  700. isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(c.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
  701. });
  702. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("test").Build());
  703. await c1.DisconnectAsync();
  704. await Task.Delay(500);
  705. Assert.IsTrue(isIntercepted);
  706. }
  707. }
  708. [TestMethod]
  709. public async Task Send_Long_Body()
  710. {
  711. using (var testEnvironment = new TestEnvironment(TestContext))
  712. {
  713. const int PayloadSizeInMB = 30;
  714. const int CharCount = PayloadSizeInMB * 1024 * 1024;
  715. var longBody = new byte[CharCount];
  716. byte @char = 32;
  717. for (long i = 0; i < PayloadSizeInMB * 1024L * 1024L; i++)
  718. {
  719. longBody[i] = @char;
  720. @char++;
  721. if (@char > 126)
  722. {
  723. @char = 32;
  724. }
  725. }
  726. byte[] receivedBody = null;
  727. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  728. var client1 = await testEnvironment.ConnectClientAsync();
  729. client1.UseApplicationMessageReceivedHandler(c =>
  730. {
  731. receivedBody = c.ApplicationMessage.Payload;
  732. });
  733. await client1.SubscribeAsync("string");
  734. var client2 = await testEnvironment.ConnectClientAsync();
  735. await client2.PublishAsync("string", longBody);
  736. await Task.Delay(500);
  737. Assert.IsTrue(longBody.SequenceEqual(receivedBody ?? new byte[0]));
  738. }
  739. }
  740. [TestMethod]
  741. public async Task Deny_Connection()
  742. {
  743. var serverOptions = new MqttServerOptionsBuilder().WithConnectionValidator(context =>
  744. {
  745. context.ReasonCode = MqttConnectReasonCode.NotAuthorized;
  746. });
  747. using (var testEnvironment = new TestEnvironment(TestContext))
  748. {
  749. testEnvironment.IgnoreClientLogErrors = true;
  750. await testEnvironment.StartServerAsync(serverOptions);
  751. var connectingFailedException = await Assert.ThrowsExceptionAsync<MqttConnectingFailedException>(() => testEnvironment.ConnectClientAsync());
  752. Assert.AreEqual(MqttClientConnectResultCode.NotAuthorized, connectingFailedException.ResultCode);
  753. }
  754. }
  755. Dictionary<string, bool> _connected;
  756. private void ConnectionValidationHandler(MqttConnectionValidatorContext eventArgs)
  757. {
  758. if (_connected.ContainsKey(eventArgs.ClientId))
  759. {
  760. eventArgs.ReasonCode = MqttConnectReasonCode.BadUserNameOrPassword;
  761. return;
  762. }
  763. _connected[eventArgs.ClientId] = true;
  764. eventArgs.ReasonCode = MqttConnectReasonCode.Success;
  765. return;
  766. }
  767. [TestMethod]
  768. public async Task Same_Client_Id_Refuse_Connection()
  769. {
  770. using (var testEnvironment = new TestEnvironment(TestContext))
  771. {
  772. testEnvironment.IgnoreClientLogErrors = true;
  773. _connected = new Dictionary<string, bool>();
  774. var options = new MqttServerOptionsBuilder();
  775. options.WithConnectionValidator(e => ConnectionValidationHandler(e));
  776. var server = await testEnvironment.StartServerAsync(options);
  777. var events = new List<string>();
  778. server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ =>
  779. {
  780. lock (events)
  781. {
  782. events.Add("c");
  783. }
  784. });
  785. server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ =>
  786. {
  787. lock (events)
  788. {
  789. events.Add("d");
  790. }
  791. });
  792. var clientOptions = new MqttClientOptionsBuilder()
  793. .WithClientId("same_id");
  794. // c
  795. var c1 = await testEnvironment.ConnectClientAsync(clientOptions);
  796. c1.UseDisconnectedHandler(_ =>
  797. {
  798. lock (events)
  799. {
  800. events.Add("x");
  801. }
  802. });
  803. c1.UseApplicationMessageReceivedHandler(_ =>
  804. {
  805. lock (events)
  806. {
  807. events.Add("r");
  808. }
  809. });
  810. c1.SubscribeAsync("topic").Wait();
  811. await Task.Delay(500);
  812. c1.PublishAsync("topic").Wait();
  813. await Task.Delay(500);
  814. var flow = string.Join(string.Empty, events);
  815. Assert.AreEqual("cr", flow);
  816. try
  817. {
  818. await testEnvironment.ConnectClientAsync(clientOptions);
  819. Assert.Fail("same id connection is expected to fail");
  820. }
  821. catch
  822. {
  823. //same id connection is expected to fail
  824. }
  825. await Task.Delay(500);
  826. flow = string.Join(string.Empty, events);
  827. Assert.AreEqual("cr", flow);
  828. c1.PublishAsync("topic").Wait();
  829. await Task.Delay(500);
  830. flow = string.Join(string.Empty, events);
  831. Assert.AreEqual("crr", flow);
  832. }
  833. }
  834. [TestMethod]
  835. public async Task Same_Client_Id_Connect_Disconnect_Event_Order()
  836. {
  837. using (var testEnvironment = new TestEnvironment())
  838. {
  839. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  840. var events = new List<string>();
  841. server.ClientConnectedHandler = new MqttServerClientConnectedHandlerDelegate(_ =>
  842. {
  843. lock (events)
  844. {
  845. events.Add("c");
  846. }
  847. });
  848. server.ClientDisconnectedHandler = new MqttServerClientDisconnectedHandlerDelegate(_ =>
  849. {
  850. lock (events)
  851. {
  852. events.Add("d");
  853. }
  854. });
  855. var clientOptionsBuilder = new MqttClientOptionsBuilder()
  856. .WithClientId(Guid.NewGuid().ToString());
  857. // c
  858. var c1 = await testEnvironment.ConnectClientAsync(clientOptionsBuilder);
  859. await Task.Delay(500);
  860. var flow = string.Join(string.Empty, events);
  861. Assert.AreEqual("c", flow);
  862. // dc
  863. // Connect client with same client ID. Should disconnect existing client.
  864. var c2 = await testEnvironment.ConnectClientAsync(clientOptionsBuilder);
  865. await Task.Delay(500);
  866. flow = string.Join(string.Empty, events);
  867. Assert.AreEqual("cdc", flow);
  868. c2.UseApplicationMessageReceivedHandler(_ =>
  869. {
  870. lock (events)
  871. {
  872. events.Add("r");
  873. }
  874. });
  875. await c2.SubscribeAsync("topic");
  876. // r
  877. await c2.PublishAsync("topic");
  878. await Task.Delay(500);
  879. flow = string.Join(string.Empty, events);
  880. Assert.AreEqual("cdcr", flow);
  881. // nothing
  882. Assert.AreEqual(false, c1.IsConnected);
  883. await c1.DisconnectAsync();
  884. Assert.AreEqual(false, c1.IsConnected);
  885. await Task.Delay(500);
  886. // d
  887. Assert.AreEqual(true, c2.IsConnected);
  888. await c2.DisconnectAsync();
  889. await Task.Delay(500);
  890. await server.StopAsync();
  891. flow = string.Join(string.Empty, events);
  892. Assert.AreEqual("cdcrd", flow);
  893. }
  894. }
  895. [TestMethod]
  896. public async Task Remove_Session()
  897. {
  898. using (var testEnvironment = new TestEnvironment(TestContext))
  899. {
  900. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  901. var clientOptions = new MqttClientOptionsBuilder();
  902. var c1 = await testEnvironment.ConnectClientAsync(clientOptions);
  903. await Task.Delay(500);
  904. Assert.AreEqual(1, (await server.GetClientStatusAsync()).Count);
  905. await c1.DisconnectAsync();
  906. await Task.Delay(500);
  907. Assert.AreEqual(0, (await server.GetClientStatusAsync()).Count);
  908. }
  909. }
  910. [TestMethod]
  911. public async Task Stop_And_Restart()
  912. {
  913. using (var testEnvironment = new TestEnvironment(TestContext))
  914. {
  915. testEnvironment.IgnoreClientLogErrors = true;
  916. var server = await testEnvironment.StartServerAsync();
  917. await testEnvironment.ConnectClientAsync();
  918. await server.StopAsync();
  919. try
  920. {
  921. await testEnvironment.ConnectClientAsync();
  922. Assert.Fail("Connecting should fail.");
  923. }
  924. catch (Exception)
  925. {
  926. }
  927. await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultEndpointPort(testEnvironment.ServerPort).Build());
  928. await testEnvironment.ConnectClientAsync();
  929. }
  930. }
  931. [TestMethod]
  932. public async Task Do_Not_Send_Retained_Messages_For_Denied_Subscription()
  933. {
  934. using (var testEnvironment = new TestEnvironment(TestContext))
  935. {
  936. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithSubscriptionInterceptor(c =>
  937. {
  938. // This should lead to no subscriptions for "n" at all. So also no sending of retained messages.
  939. if (c.TopicFilter.Topic == "n")
  940. {
  941. c.AcceptSubscription = false;
  942. }
  943. }));
  944. // Prepare some retained messages.
  945. var client1 = await testEnvironment.ConnectClientAsync();
  946. await client1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("y").WithPayload("x").WithRetainFlag().Build());
  947. await client1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("n").WithPayload("x").WithRetainFlag().Build());
  948. await client1.DisconnectAsync();
  949. await Task.Delay(500);
  950. // Subscribe to all retained message types.
  951. // It is important to do this in a range of filters to ensure that a subscription is not "hidden".
  952. var client2 = await testEnvironment.ConnectClientAsync();
  953. var buffer = new StringBuilder();
  954. client2.UseApplicationMessageReceivedHandler(c =>
  955. {
  956. lock (buffer)
  957. {
  958. buffer.Append(c.ApplicationMessage.Topic);
  959. }
  960. });
  961. await client2.SubscribeAsync(new MqttTopicFilter { Topic = "y" }, new MqttTopicFilter { Topic = "n" });
  962. await Task.Delay(500);
  963. Assert.AreEqual("y", buffer.ToString());
  964. }
  965. }
  966. [TestMethod]
  967. public async Task Collect_Messages_In_Disconnected_Session()
  968. {
  969. using (var testEnvironment = new TestEnvironment(TestContext))
  970. {
  971. var server = await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder().WithPersistentSessions());
  972. // Create the session including the subscription.
  973. var client1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("a"));
  974. await client1.SubscribeAsync("x");
  975. await client1.DisconnectAsync();
  976. await Task.Delay(500);
  977. var clientStatus = await server.GetClientStatusAsync();
  978. Assert.AreEqual(0, clientStatus.Count);
  979. var client2 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("b"));
  980. await client2.PublishAsync("x", "1");
  981. await client2.PublishAsync("x", "2");
  982. await client2.PublishAsync("x", "3");
  983. await client2.DisconnectAsync();
  984. await Task.Delay(500);
  985. clientStatus = await server.GetClientStatusAsync();
  986. var sessionStatus = await server.GetSessionStatusAsync();
  987. Assert.AreEqual(0, clientStatus.Count);
  988. Assert.AreEqual(2, sessionStatus.Count);
  989. Assert.AreEqual(3, sessionStatus.First(s => s.ClientId == client1.Options.ClientId).PendingApplicationMessagesCount);
  990. }
  991. }
  992. private static async Task TestPublishAsync(
  993. string topic,
  994. MqttQualityOfServiceLevel qualityOfServiceLevel,
  995. string topicFilter,
  996. MqttQualityOfServiceLevel filterQualityOfServiceLevel,
  997. int expectedReceivedMessagesCount,
  998. TestContext testContext)
  999. {
  1000. using (var testEnvironment = new TestEnvironment(testContext))
  1001. {
  1002. var receivedMessagesCount = 0;
  1003. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder());
  1004. var c1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("receiver"));
  1005. c1.UseApplicationMessageReceivedHandler(c => Interlocked.Increment(ref receivedMessagesCount));
  1006. await c1.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
  1007. var c2 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithClientId("sender"));
  1008. await c2.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
  1009. await c2.DisconnectAsync().ConfigureAwait(false);
  1010. await Task.Delay(500);
  1011. await c1.UnsubscribeAsync(topicFilter);
  1012. await Task.Delay(500);
  1013. Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
  1014. }
  1015. }
  1016. [TestMethod]
  1017. public async Task Intercept_Undelivered()
  1018. {
  1019. using (var testEnvironment = new TestEnvironment())
  1020. {
  1021. var undeliverd = string.Empty;
  1022. var options = new MqttServerOptionsBuilder().WithUndeliveredMessageInterceptor(
  1023. context =>
  1024. {
  1025. undeliverd = context.ApplicationMessage.Topic;
  1026. });
  1027. await testEnvironment.StartServerAsync(options);
  1028. var client = await testEnvironment.ConnectClientAsync();
  1029. await client.SubscribeAsync("b");
  1030. await client.PublishAsync("a", null, MqttQualityOfServiceLevel.ExactlyOnce);
  1031. await Task.Delay(500);
  1032. Assert.AreEqual("a", undeliverd);
  1033. }
  1034. }
  1035. [TestMethod]
  1036. public async Task Intercept_ClientMessageQueue()
  1037. {
  1038. using (var testEnvironment = new TestEnvironment(TestContext))
  1039. {
  1040. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder()
  1041. .WithClientMessageQueueInterceptor(c => c.ApplicationMessage.Topic = "a"));
  1042. var topicAReceived = false;
  1043. var topicBReceived = false;
  1044. var client = await testEnvironment.ConnectClientAsync();
  1045. client.UseApplicationMessageReceivedHandler(c =>
  1046. {
  1047. if (c.ApplicationMessage.Topic == "a")
  1048. {
  1049. topicAReceived = true;
  1050. }
  1051. else if (c.ApplicationMessage.Topic == "b")
  1052. {
  1053. topicBReceived = true;
  1054. }
  1055. });
  1056. await client.SubscribeAsync("a");
  1057. await client.SubscribeAsync("b");
  1058. await client.PublishAsync("b");
  1059. await Task.Delay(500);
  1060. Assert.IsTrue(topicAReceived);
  1061. Assert.IsFalse(topicBReceived);
  1062. }
  1063. }
  1064. [TestMethod]
  1065. public async Task Intercept_ClientMessageQueue_Different_QoS_Of_Subscription_And_Message()
  1066. {
  1067. const string topic = "a";
  1068. using (var testEnvironment = new TestEnvironment(TestContext))
  1069. {
  1070. await testEnvironment.StartServerAsync(new MqttServerOptionsBuilder()
  1071. .WithClientMessageQueueInterceptor(c => { })); // Interceptor does nothing but has to be present.
  1072. bool receivedMessage = false;
  1073. var client = await testEnvironment.ConnectClientAsync();
  1074. client.UseApplicationMessageReceivedHandler(c =>
  1075. {
  1076. receivedMessage = true;
  1077. });
  1078. await client.SubscribeAsync(topic, MqttQualityOfServiceLevel.AtLeastOnce);
  1079. await client.PublishAsync(new MqttApplicationMessage { Topic = topic, QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  1080. await Task.Delay(500);
  1081. Assert.IsTrue(receivedMessage);
  1082. }
  1083. }
  1084. }
  1085. }