Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

875 rader
29 KiB

  1. using Microsoft.VisualStudio.TestTools.UnitTesting;
  2. using MQTTnet.Client;
  3. using MQTTnet.Diagnostics;
  4. using MQTTnet.Protocol;
  5. using MQTTnet.Server;
  6. using System;
  7. using System.Collections.Concurrent;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. using MQTTnet.Adapter;
  14. using MQTTnet.Implementations;
  15. namespace MQTTnet.Core.Tests
  16. {
  17. [TestClass]
  18. public class MqttServerTests
  19. {
  20. [TestMethod]
  21. public void MqttServer_PublishSimple_AtMostOnce()
  22. {
  23. TestPublishAsync(
  24. "A/B/C",
  25. MqttQualityOfServiceLevel.AtMostOnce,
  26. "A/B/C",
  27. MqttQualityOfServiceLevel.AtMostOnce,
  28. 1).Wait();
  29. }
  30. [TestMethod]
  31. public void MqttServer_PublishSimple_AtLeastOnce()
  32. {
  33. TestPublishAsync(
  34. "A/B/C",
  35. MqttQualityOfServiceLevel.AtLeastOnce,
  36. "A/B/C",
  37. MqttQualityOfServiceLevel.AtLeastOnce,
  38. 1).Wait();
  39. }
  40. [TestMethod]
  41. public void MqttServer_PublishSimple_ExactlyOnce()
  42. {
  43. TestPublishAsync(
  44. "A/B/C",
  45. MqttQualityOfServiceLevel.ExactlyOnce,
  46. "A/B/C",
  47. MqttQualityOfServiceLevel.ExactlyOnce,
  48. 1).Wait();
  49. }
  50. [TestMethod]
  51. public async Task MqttServer_WillMessage()
  52. {
  53. var serverAdapter = new TestMqttServerAdapter();
  54. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  55. var receivedMessagesCount = 0;
  56. try
  57. {
  58. await s.StartAsync(new MqttServerOptions());
  59. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  60. var c1 = await serverAdapter.ConnectTestClient("c1");
  61. var c2 = await serverAdapter.ConnectTestClient("c2", willMessage);
  62. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  63. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic("#").Build());
  64. await c2.DisconnectAsync();
  65. await Task.Delay(1000);
  66. await c1.DisconnectAsync();
  67. }
  68. finally
  69. {
  70. await s.StopAsync();
  71. }
  72. Assert.AreEqual(0, receivedMessagesCount);
  73. }
  74. [TestMethod]
  75. public async Task MqttServer_SubscribeUnsubscribe()
  76. {
  77. var serverAdapter = new TestMqttServerAdapter();
  78. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  79. var receivedMessagesCount = 0;
  80. try
  81. {
  82. await s.StartAsync(new MqttServerOptions());
  83. var c1 = await serverAdapter.ConnectTestClient("c1");
  84. var c2 = await serverAdapter.ConnectTestClient("c2");
  85. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  86. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  87. await c2.PublishAsync(message);
  88. await Task.Delay(1000);
  89. Assert.AreEqual(0, receivedMessagesCount);
  90. var subscribeEventCalled = false;
  91. s.ClientSubscribedTopic += (_, e) =>
  92. {
  93. subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == "c1";
  94. };
  95. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  96. await Task.Delay(500);
  97. Assert.IsTrue(subscribeEventCalled, "Subscribe event not called.");
  98. await c2.PublishAsync(message);
  99. await Task.Delay(500);
  100. Assert.AreEqual(1, receivedMessagesCount);
  101. var unsubscribeEventCalled = false;
  102. s.ClientUnsubscribedTopic += (_, e) =>
  103. {
  104. unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == "c1";
  105. };
  106. await c1.UnsubscribeAsync("a");
  107. await Task.Delay(500);
  108. Assert.IsTrue(unsubscribeEventCalled, "Unsubscribe event not called.");
  109. await c2.PublishAsync(message);
  110. await Task.Delay(1000);
  111. Assert.AreEqual(1, receivedMessagesCount);
  112. }
  113. finally
  114. {
  115. await s.StopAsync();
  116. }
  117. await Task.Delay(500);
  118. Assert.AreEqual(1, receivedMessagesCount);
  119. }
  120. [TestMethod]
  121. public async Task MqttServer_Publish()
  122. {
  123. var serverAdapter = new TestMqttServerAdapter();
  124. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  125. var receivedMessagesCount = 0;
  126. try
  127. {
  128. await s.StartAsync(new MqttServerOptions());
  129. var c1 = await serverAdapter.ConnectTestClient("c1");
  130. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  131. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  132. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  133. await s.PublishAsync(message);
  134. await Task.Delay(500);
  135. }
  136. finally
  137. {
  138. await s.StopAsync();
  139. }
  140. Assert.AreEqual(1, receivedMessagesCount);
  141. }
  142. [TestMethod]
  143. public async Task MqttServer_Publish_MultipleClients()
  144. {
  145. var serverAdapter = new MqttTcpServerAdapter(new MqttNetLogger().CreateChildLogger());
  146. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  147. var receivedMessagesCount = 0;
  148. var locked = new object();
  149. var clientOptions = new MqttClientOptionsBuilder()
  150. .WithTcpServer("localhost")
  151. .Build();
  152. var clientOptions2 = new MqttClientOptionsBuilder()
  153. .WithTcpServer("localhost")
  154. .Build();
  155. try
  156. {
  157. await s.StartAsync(new MqttServerOptions());
  158. var c1 = new MqttFactory().CreateMqttClient();
  159. var c2 = new MqttFactory().CreateMqttClient();
  160. await c1.ConnectAsync(clientOptions);
  161. await c2.ConnectAsync(clientOptions2);
  162. c1.ApplicationMessageReceived += (_, __) =>
  163. {
  164. lock (locked)
  165. {
  166. receivedMessagesCount++;
  167. }
  168. };
  169. c2.ApplicationMessageReceived += (_, __) =>
  170. {
  171. lock (locked)
  172. {
  173. receivedMessagesCount++;
  174. }
  175. };
  176. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  177. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  178. await c2.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  179. //await Task.WhenAll(Publish(c1, message), Publish(c2, message));
  180. await Publish(c1, message);
  181. await Task.Delay(500);
  182. }
  183. finally
  184. {
  185. await s.StopAsync();
  186. }
  187. Assert.AreEqual(2000, receivedMessagesCount);
  188. }
  189. [TestMethod]
  190. public async Task MqttServer_SessionTakeover()
  191. {
  192. var server = new MqttFactory().CreateMqttServer();
  193. try
  194. {
  195. await server.StartAsync(new MqttServerOptions());
  196. var client1 = new MqttFactory().CreateMqttClient();
  197. var client2 = new MqttFactory().CreateMqttClient();
  198. var options = new MqttClientOptionsBuilder()
  199. .WithTcpServer("localhost")
  200. .WithCleanSession(false)
  201. .WithClientId("a").Build();
  202. await client1.ConnectAsync(options);
  203. await Task.Delay(500);
  204. await client2.ConnectAsync(options);
  205. await Task.Delay(500);
  206. Assert.IsFalse(client1.IsConnected);
  207. Assert.IsTrue(client2.IsConnected);
  208. }
  209. finally
  210. {
  211. await server.StopAsync();
  212. }
  213. }
  214. private static async Task Publish(IMqttClient c1, MqttApplicationMessage message)
  215. {
  216. for (int i = 0; i < 1000; i++)
  217. {
  218. await c1.PublishAsync(message);
  219. }
  220. }
  221. [TestMethod]
  222. public async Task MqttServer_ShutdownDisconnectsClientsGracefully()
  223. {
  224. var serverAdapter = new MqttTcpServerAdapter(new MqttNetLogger().CreateChildLogger());
  225. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  226. var clientOptions = new MqttClientOptionsBuilder()
  227. .WithTcpServer("localhost")
  228. .Build();
  229. var disconnectCalled = 0;
  230. await s.StartAsync(new MqttServerOptions());
  231. var c1 = new MqttFactory().CreateMqttClient();
  232. c1.Disconnected += (sender, args) => disconnectCalled++;
  233. await c1.ConnectAsync(clientOptions);
  234. await Task.Delay(100);
  235. await s.StopAsync();
  236. await Task.Delay(100);
  237. Assert.AreEqual(1, disconnectCalled);
  238. }
  239. [TestMethod]
  240. public async Task MqttServer_HandleCleanDisconnect()
  241. {
  242. var serverAdapter = new MqttTcpServerAdapter(new MqttNetLogger().CreateChildLogger());
  243. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  244. var clientConnectedCalled = 0;
  245. var clientDisconnectedCalled = 0;
  246. s.ClientConnected += (_, __) => clientConnectedCalled++;
  247. s.ClientDisconnected += (_, __) => clientDisconnectedCalled++;
  248. var clientOptions = new MqttClientOptionsBuilder()
  249. .WithTcpServer("localhost")
  250. .Build();
  251. await s.StartAsync(new MqttServerOptions());
  252. var c1 = new MqttFactory().CreateMqttClient();
  253. await c1.ConnectAsync(clientOptions);
  254. await Task.Delay(100);
  255. await c1.DisconnectAsync();
  256. await Task.Delay(100);
  257. await s.StopAsync();
  258. await Task.Delay(100);
  259. Assert.AreEqual(clientConnectedCalled, clientDisconnectedCalled);
  260. }
  261. [TestMethod]
  262. public async Task MqttServer_Client_Disconnect_Without_Errors()
  263. {
  264. var errors = 0;
  265. MqttNetGlobalLogger.LogMessagePublished += (_, e) =>
  266. {
  267. System.Diagnostics.Debug.WriteLine($"[{e.TraceMessage.Timestamp:s}] {e.TraceMessage.Source} {e.TraceMessage.Message}");
  268. if (e.TraceMessage.Level == MqttNetLogLevel.Error)
  269. {
  270. errors++;
  271. }
  272. };
  273. bool clientWasConnected;
  274. var server = new MqttFactory().CreateMqttServer();
  275. try
  276. {
  277. var options = new MqttServerOptionsBuilder().Build();
  278. await server.StartAsync(options);
  279. var client = new MqttFactory().CreateMqttClient();
  280. var clientOptions = new MqttClientOptionsBuilder()
  281. .WithTcpServer("localhost")
  282. .Build();
  283. await client.ConnectAsync(clientOptions);
  284. clientWasConnected = true;
  285. await client.DisconnectAsync();
  286. await Task.Delay(500);
  287. }
  288. finally
  289. {
  290. await server.StopAsync();
  291. }
  292. Assert.IsTrue(clientWasConnected);
  293. Assert.AreEqual(0, errors);
  294. }
  295. [TestMethod]
  296. public async Task MqttServer_LotsOfRetainedMessages()
  297. {
  298. const int ClientCount = 100;
  299. var server = new MqttFactory().CreateMqttServer();
  300. try
  301. {
  302. await server.StartAsync(new MqttServerOptionsBuilder().Build());
  303. Parallel.For(
  304. 0,
  305. ClientCount,
  306. new ParallelOptions { MaxDegreeOfParallelism = 10 },
  307. i =>
  308. {
  309. using (var client = new MqttFactory().CreateMqttClient())
  310. {
  311. client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build())
  312. .GetAwaiter().GetResult();
  313. for (var j = 0; j < 10; j++)
  314. {
  315. // Clear retained message.
  316. client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
  317. .WithPayload(new byte[0]).WithRetainFlag().Build()).GetAwaiter().GetResult();
  318. // Set retained message.
  319. client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
  320. .WithPayload("value" + j).WithRetainFlag().Build()).GetAwaiter().GetResult();
  321. }
  322. client.DisconnectAsync().GetAwaiter().GetResult();
  323. }
  324. });
  325. await Task.Delay(100);
  326. var retainedMessages = server.GetRetainedMessages();
  327. Assert.AreEqual(ClientCount, retainedMessages.Count);
  328. for (var i = 0; i < ClientCount; i++)
  329. {
  330. Assert.IsTrue(retainedMessages.Any(m => m.Topic == "r" + i));
  331. }
  332. }
  333. finally
  334. {
  335. await server.StopAsync();
  336. }
  337. }
  338. [TestMethod]
  339. public async Task MqttServer_RetainedMessagesFlow()
  340. {
  341. var retainedMessage = new MqttApplicationMessageBuilder().WithTopic("r").WithPayload("r").WithRetainFlag().Build();
  342. var serverAdapter = new TestMqttServerAdapter();
  343. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  344. await s.StartAsync(new MqttServerOptions());
  345. var c1 = await serverAdapter.ConnectTestClient("c1");
  346. await c1.PublishAsync(retainedMessage);
  347. Thread.Sleep(500);
  348. await c1.DisconnectAsync();
  349. Thread.Sleep(500);
  350. var receivedMessages = 0;
  351. var c2 = await serverAdapter.ConnectTestClient("c2");
  352. c2.ApplicationMessageReceived += (_, e) =>
  353. {
  354. receivedMessages++;
  355. };
  356. for (var i = 0; i < 5; i++)
  357. {
  358. await c2.UnsubscribeAsync("r");
  359. await Task.Delay(500);
  360. Assert.AreEqual(i, receivedMessages);
  361. await c2.SubscribeAsync("r");
  362. await Task.Delay(500);
  363. Assert.AreEqual(i + 1, receivedMessages);
  364. }
  365. await c2.DisconnectAsync();
  366. await s.StopAsync();
  367. }
  368. [TestMethod]
  369. public async Task MqttServer_NoRetainedMessage()
  370. {
  371. var serverAdapter = new TestMqttServerAdapter();
  372. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  373. var receivedMessagesCount = 0;
  374. try
  375. {
  376. await s.StartAsync(new MqttServerOptions());
  377. var c1 = await serverAdapter.ConnectTestClient("c1");
  378. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[3]));
  379. await c1.DisconnectAsync();
  380. var c2 = await serverAdapter.ConnectTestClient("c2");
  381. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  382. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  383. await Task.Delay(500);
  384. }
  385. finally
  386. {
  387. await s.StopAsync();
  388. }
  389. Assert.AreEqual(0, receivedMessagesCount);
  390. }
  391. [TestMethod]
  392. public async Task MqttServer_RetainedMessage()
  393. {
  394. var serverAdapter = new TestMqttServerAdapter();
  395. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  396. var receivedMessages = new List<MqttApplicationMessage>();
  397. try
  398. {
  399. await s.StartAsync(new MqttServerOptions());
  400. var c1 = await serverAdapter.ConnectTestClient("c1");
  401. await c1.PublishAndWaitForAsync(s, new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  402. await c1.DisconnectAsync();
  403. var c2 = await serverAdapter.ConnectTestClient("c2");
  404. c2.ApplicationMessageReceived += (_, e) =>
  405. {
  406. lock (receivedMessages)
  407. {
  408. receivedMessages.Add(e.ApplicationMessage);
  409. }
  410. };
  411. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  412. await Task.Delay(500);
  413. }
  414. finally
  415. {
  416. await s.StopAsync();
  417. }
  418. Assert.AreEqual(1, receivedMessages.Count);
  419. Assert.IsTrue(receivedMessages.First().Retain);
  420. }
  421. [TestMethod]
  422. public async Task MqttServer_ClearRetainedMessage()
  423. {
  424. var serverAdapter = new TestMqttServerAdapter();
  425. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  426. var receivedMessagesCount = 0;
  427. try
  428. {
  429. await s.StartAsync(new MqttServerOptions());
  430. var c1 = await serverAdapter.ConnectTestClient("c1");
  431. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag());
  432. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag());
  433. await c1.DisconnectAsync();
  434. var c2 = await serverAdapter.ConnectTestClient("c2");
  435. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  436. await Task.Delay(200);
  437. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  438. await Task.Delay(500);
  439. }
  440. finally
  441. {
  442. await s.StopAsync();
  443. }
  444. Assert.AreEqual(0, receivedMessagesCount);
  445. }
  446. [TestMethod]
  447. public async Task MqttServer_PersistRetainedMessage()
  448. {
  449. var storage = new TestStorage();
  450. var serverAdapter = new TestMqttServerAdapter();
  451. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  452. try
  453. {
  454. var options = new MqttServerOptions { Storage = storage };
  455. await s.StartAsync(options);
  456. var c1 = await serverAdapter.ConnectTestClient("c1");
  457. await c1.PublishAndWaitForAsync(s, new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  458. await Task.Delay(250);
  459. await c1.DisconnectAsync();
  460. }
  461. finally
  462. {
  463. await s.StopAsync();
  464. }
  465. Assert.AreEqual(1, storage.Messages.Count);
  466. s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  467. var receivedMessagesCount = 0;
  468. try
  469. {
  470. var options = new MqttServerOptions { Storage = storage };
  471. await s.StartAsync(options);
  472. var c2 = await serverAdapter.ConnectTestClient("c2");
  473. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  474. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  475. await Task.Delay(250);
  476. }
  477. finally
  478. {
  479. await s.StopAsync();
  480. }
  481. Assert.AreEqual(1, receivedMessagesCount);
  482. }
  483. [TestMethod]
  484. public async Task MqttServer_InterceptMessage()
  485. {
  486. void Interceptor(MqttApplicationMessageInterceptorContext context)
  487. {
  488. context.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
  489. }
  490. var serverAdapter = new TestMqttServerAdapter();
  491. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  492. try
  493. {
  494. var options = new MqttServerOptions { ApplicationMessageInterceptor = Interceptor };
  495. await s.StartAsync(options);
  496. var c1 = await serverAdapter.ConnectTestClient("c1");
  497. var c2 = await serverAdapter.ConnectTestClient("c2");
  498. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("test").Build());
  499. var isIntercepted = false;
  500. c2.ApplicationMessageReceived += (sender, args) =>
  501. {
  502. isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(args.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
  503. };
  504. await c1.PublishAsync(builder => builder.WithTopic("test"));
  505. await c1.DisconnectAsync();
  506. await Task.Delay(500);
  507. Assert.IsTrue(isIntercepted);
  508. }
  509. finally
  510. {
  511. await s.StopAsync();
  512. }
  513. }
  514. [TestMethod]
  515. public async Task MqttServer_Body()
  516. {
  517. var serverAdapter = new TestMqttServerAdapter();
  518. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  519. var bodyIsMatching = false;
  520. try
  521. {
  522. await s.StartAsync(new MqttServerOptions());
  523. var c1 = await serverAdapter.ConnectTestClient("c1");
  524. var c2 = await serverAdapter.ConnectTestClient("c2");
  525. c1.ApplicationMessageReceived += (_, e) =>
  526. {
  527. if (Encoding.UTF8.GetString(e.ApplicationMessage.Payload) == "The body")
  528. {
  529. bodyIsMatching = true;
  530. }
  531. };
  532. await c1.SubscribeAsync("A", MqttQualityOfServiceLevel.AtMostOnce);
  533. await c2.PublishAsync(builder => builder.WithTopic("A").WithPayload(Encoding.UTF8.GetBytes("The body")));
  534. await Task.Delay(1000);
  535. }
  536. finally
  537. {
  538. await s.StopAsync();
  539. }
  540. Assert.IsTrue(bodyIsMatching);
  541. }
  542. [TestMethod]
  543. public async Task MqttServer_ConnectionDenied()
  544. {
  545. var server = new MqttFactory().CreateMqttServer();
  546. var client = new MqttFactory().CreateMqttClient();
  547. try
  548. {
  549. var options = new MqttServerOptionsBuilder().WithConnectionValidator(context =>
  550. {
  551. context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized;
  552. }).Build();
  553. await server.StartAsync(options);
  554. var clientOptions = new MqttClientOptionsBuilder()
  555. .WithTcpServer("localhost").Build();
  556. try
  557. {
  558. await client.ConnectAsync(clientOptions);
  559. Assert.Fail("An exception should be raised.");
  560. }
  561. catch (Exception exception)
  562. {
  563. if (exception is MqttConnectingFailedException)
  564. {
  565. }
  566. else
  567. {
  568. Assert.Fail("Wrong exception.");
  569. }
  570. }
  571. }
  572. finally
  573. {
  574. await client.DisconnectAsync();
  575. await server.StopAsync();
  576. client.Dispose();
  577. }
  578. }
  579. [TestMethod]
  580. public async Task MqttServer_SameClientIdConnectDisconnectEventOrder()
  581. {
  582. var s = new MqttFactory().CreateMqttServer();
  583. var events = new List<string>();
  584. s.ClientConnected += (_, __) =>
  585. {
  586. lock (events)
  587. {
  588. events.Add("c");
  589. }
  590. };
  591. s.ClientDisconnected += (_, __) =>
  592. {
  593. lock (events)
  594. {
  595. events.Add("d");
  596. }
  597. };
  598. var clientOptions = new MqttClientOptionsBuilder()
  599. .WithTcpServer("localhost")
  600. .WithClientId("same_id")
  601. .Build();
  602. await s.StartAsync(new MqttServerOptions());
  603. var c1 = new MqttFactory().CreateMqttClient();
  604. var c2 = new MqttFactory().CreateMqttClient();
  605. await c1.ConnectAsync(clientOptions);
  606. await Task.Delay(250);
  607. await c2.ConnectAsync(clientOptions);
  608. await Task.Delay(250);
  609. await c1.DisconnectAsync();
  610. await Task.Delay(250);
  611. await c2.DisconnectAsync();
  612. await Task.Delay(250);
  613. await s.StopAsync();
  614. var flow = string.Join(string.Empty, events);
  615. Assert.AreEqual("cdcd", flow);
  616. }
  617. [TestMethod]
  618. public async Task MqttServer_StopAndRestart()
  619. {
  620. var server = new MqttFactory().CreateMqttServer();
  621. await server.StartAsync(new MqttServerOptions());
  622. var client = new MqttFactory().CreateMqttClient();
  623. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  624. await server.StopAsync();
  625. try
  626. {
  627. var client2 = new MqttFactory().CreateMqttClient();
  628. await client2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  629. Assert.Fail("Connecting should fail.");
  630. }
  631. catch (Exception)
  632. {
  633. }
  634. await server.StartAsync(new MqttServerOptions());
  635. var client3 = new MqttFactory().CreateMqttClient();
  636. await client3.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  637. await server.StopAsync();
  638. }
  639. private class TestStorage : IMqttServerStorage
  640. {
  641. public IList<MqttApplicationMessage> Messages = new List<MqttApplicationMessage>();
  642. public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
  643. {
  644. Messages = messages;
  645. return Task.CompletedTask;
  646. }
  647. public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
  648. {
  649. return Task.FromResult(Messages);
  650. }
  651. }
  652. private static async Task TestPublishAsync(
  653. string topic,
  654. MqttQualityOfServiceLevel qualityOfServiceLevel,
  655. string topicFilter,
  656. MqttQualityOfServiceLevel filterQualityOfServiceLevel,
  657. int expectedReceivedMessagesCount)
  658. {
  659. var s = new MqttFactory().CreateMqttServer();
  660. var receivedMessagesCount = 0;
  661. try
  662. {
  663. await s.StartAsync(new MqttServerOptions());
  664. var c1 = new MqttFactory().CreateMqttClient();
  665. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  666. await c1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  667. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
  668. var c2 = new MqttFactory().CreateMqttClient();
  669. await c2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  670. await c2.PublishAsync(builder => builder.WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel));
  671. await Task.Delay(500);
  672. await c1.UnsubscribeAsync(topicFilter);
  673. await Task.Delay(500);
  674. }
  675. finally
  676. {
  677. await s.StopAsync();
  678. }
  679. Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
  680. }
  681. }
  682. }