Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

942 řádky
31 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Sockets;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Microsoft.VisualStudio.TestTools.UnitTesting;
  9. using MQTTnet.Adapter;
  10. using MQTTnet.Client;
  11. using MQTTnet.Client.Options;
  12. using MQTTnet.Diagnostics;
  13. using MQTTnet.Implementations;
  14. using MQTTnet.Protocol;
  15. using MQTTnet.Server;
  16. namespace MQTTnet.Tests
  17. {
  18. [TestClass]
  19. public class MqttServerTests
  20. {
  21. [TestMethod]
  22. public void MqttServer_PublishSimple_AtMostOnce()
  23. {
  24. TestPublishAsync(
  25. "A/B/C",
  26. MqttQualityOfServiceLevel.AtMostOnce,
  27. "A/B/C",
  28. MqttQualityOfServiceLevel.AtMostOnce,
  29. 1).Wait();
  30. }
  31. [TestMethod]
  32. public void MqttServer_PublishSimple_AtLeastOnce()
  33. {
  34. TestPublishAsync(
  35. "A/B/C",
  36. MqttQualityOfServiceLevel.AtLeastOnce,
  37. "A/B/C",
  38. MqttQualityOfServiceLevel.AtLeastOnce,
  39. 1).Wait();
  40. }
  41. [TestMethod]
  42. public void MqttServer_PublishSimple_ExactlyOnce()
  43. {
  44. TestPublishAsync(
  45. "A/B/C",
  46. MqttQualityOfServiceLevel.ExactlyOnce,
  47. "A/B/C",
  48. MqttQualityOfServiceLevel.ExactlyOnce,
  49. 1).Wait();
  50. }
  51. [TestMethod]
  52. public async Task MqttServer_Will_Message()
  53. {
  54. var serverAdapter = new TestMqttServerAdapter();
  55. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  56. var receivedMessagesCount = 0;
  57. try
  58. {
  59. await s.StartAsync(new MqttServerOptions());
  60. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  61. var c1 = await serverAdapter.ConnectTestClient("c1");
  62. var c2 = await serverAdapter.ConnectTestClient("c2", willMessage);
  63. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  64. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic("#").Build());
  65. await c2.DisconnectAsync();
  66. await Task.Delay(1000);
  67. await c1.DisconnectAsync();
  68. }
  69. finally
  70. {
  71. await s.StopAsync();
  72. }
  73. Assert.AreEqual(0, receivedMessagesCount);
  74. }
  75. [TestMethod]
  76. public async Task MqttServer_Subscribe_Unsubscribe()
  77. {
  78. var serverAdapter = new TestMqttServerAdapter();
  79. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  80. var receivedMessagesCount = 0;
  81. try
  82. {
  83. await s.StartAsync(new MqttServerOptions());
  84. var c1 = await serverAdapter.ConnectTestClient("c1");
  85. var c2 = await serverAdapter.ConnectTestClient("c2");
  86. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  87. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  88. await c2.PublishAsync(message);
  89. await Task.Delay(1000);
  90. Assert.AreEqual(0, receivedMessagesCount);
  91. var subscribeEventCalled = false;
  92. s.ClientSubscribedTopic += (_, e) =>
  93. {
  94. subscribeEventCalled = e.TopicFilter.Topic == "a" && e.ClientId == "c1";
  95. };
  96. await c1.SubscribeAsync(new TopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  97. await Task.Delay(500);
  98. Assert.IsTrue(subscribeEventCalled, "Subscribe event not called.");
  99. await c2.PublishAsync(message);
  100. await Task.Delay(500);
  101. Assert.AreEqual(1, receivedMessagesCount);
  102. var unsubscribeEventCalled = false;
  103. s.ClientUnsubscribedTopic += (_, e) =>
  104. {
  105. unsubscribeEventCalled = e.TopicFilter == "a" && e.ClientId == "c1";
  106. };
  107. await c1.UnsubscribeAsync("a");
  108. await Task.Delay(500);
  109. Assert.IsTrue(unsubscribeEventCalled, "Unsubscribe event not called.");
  110. await c2.PublishAsync(message);
  111. await Task.Delay(1000);
  112. Assert.AreEqual(1, receivedMessagesCount);
  113. }
  114. finally
  115. {
  116. await s.StopAsync();
  117. }
  118. await Task.Delay(500);
  119. Assert.AreEqual(1, receivedMessagesCount);
  120. }
  121. [TestMethod]
  122. public async Task MqttServer_Publish()
  123. {
  124. var serverAdapter = new TestMqttServerAdapter();
  125. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  126. var receivedMessagesCount = 0;
  127. try
  128. {
  129. await s.StartAsync(new MqttServerOptions());
  130. var c1 = await serverAdapter.ConnectTestClient("c1");
  131. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  132. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  133. await c1.SubscribeAsync(new TopicFilter { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  134. await s.PublishAsync(message);
  135. await Task.Delay(500);
  136. }
  137. finally
  138. {
  139. await s.StopAsync();
  140. }
  141. Assert.AreEqual(1, receivedMessagesCount);
  142. }
  143. [TestMethod]
  144. public async Task MqttServer_Publish_MultipleClients()
  145. {
  146. var s = new MqttFactory().CreateMqttServer();
  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 { Topic = "a", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  178. await c2.SubscribeAsync(new TopicFilter { Topic = "a", QualityOfServiceLevel = 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_Session_Takeover()
  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_Handle_Clean_Disconnect()
  241. {
  242. var s = new MqttFactory().CreateMqttServer();
  243. try
  244. {
  245. var clientConnectedCalled = 0;
  246. var clientDisconnectedCalled = 0;
  247. s.ClientConnected += (_, __) => clientConnectedCalled++;
  248. s.ClientDisconnected += (_, __) => clientDisconnectedCalled++;
  249. var clientOptions = new MqttClientOptionsBuilder()
  250. .WithTcpServer("localhost")
  251. .Build();
  252. await s.StartAsync(new MqttServerOptions());
  253. var c1 = new MqttFactory().CreateMqttClient();
  254. await c1.ConnectAsync(clientOptions);
  255. await Task.Delay(100);
  256. await c1.DisconnectAsync();
  257. await Task.Delay(100);
  258. await s.StopAsync();
  259. await Task.Delay(100);
  260. Assert.AreEqual(clientConnectedCalled, clientDisconnectedCalled);
  261. }
  262. finally
  263. {
  264. await s.StopAsync();
  265. }
  266. }
  267. [TestMethod]
  268. public async Task MqttServer_Client_Disconnect_Without_Errors()
  269. {
  270. var errors = 0;
  271. MqttNetGlobalLogger.LogMessagePublished += (_, e) =>
  272. {
  273. System.Diagnostics.Debug.WriteLine($"[{e.TraceMessage.Timestamp:s}] {e.TraceMessage.Source} {e.TraceMessage.Message}");
  274. if (e.TraceMessage.Level == MqttNetLogLevel.Error)
  275. {
  276. errors++;
  277. }
  278. };
  279. bool clientWasConnected;
  280. var server = new MqttFactory().CreateMqttServer();
  281. try
  282. {
  283. var options = new MqttServerOptionsBuilder().Build();
  284. await server.StartAsync(options);
  285. var client = new MqttFactory().CreateMqttClient();
  286. var clientOptions = new MqttClientOptionsBuilder()
  287. .WithTcpServer("localhost")
  288. .Build();
  289. await client.ConnectAsync(clientOptions);
  290. clientWasConnected = true;
  291. await client.DisconnectAsync();
  292. await Task.Delay(500);
  293. }
  294. finally
  295. {
  296. await server.StopAsync();
  297. }
  298. Assert.IsTrue(clientWasConnected);
  299. Assert.AreEqual(0, errors);
  300. }
  301. [TestMethod]
  302. public async Task MqttServer_LotsOfRetainedMessages()
  303. {
  304. const int ClientCount = 100;
  305. var server = new MqttFactory().CreateMqttServer();
  306. try
  307. {
  308. await server.StartAsync(new MqttServerOptionsBuilder().Build());
  309. Parallel.For(
  310. 0,
  311. ClientCount,
  312. new ParallelOptions { MaxDegreeOfParallelism = 10 },
  313. i =>
  314. {
  315. using (var client = new MqttFactory().CreateMqttClient())
  316. {
  317. client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build())
  318. .GetAwaiter().GetResult();
  319. for (var j = 0; j < 10; j++)
  320. {
  321. // Clear retained message.
  322. client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
  323. .WithPayload(new byte[0]).WithRetainFlag().Build()).GetAwaiter().GetResult();
  324. // Set retained message.
  325. client.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("r" + i)
  326. .WithPayload("value" + j).WithRetainFlag().Build()).GetAwaiter().GetResult();
  327. }
  328. Thread.Sleep(100);
  329. client.DisconnectAsync().GetAwaiter().GetResult();
  330. }
  331. });
  332. await Task.Delay(1000);
  333. var retainedMessages = server.GetRetainedMessages();
  334. Assert.AreEqual(ClientCount, retainedMessages.Count);
  335. for (var i = 0; i < ClientCount; i++)
  336. {
  337. Assert.IsTrue(retainedMessages.Any(m => m.Topic == "r" + i));
  338. }
  339. }
  340. finally
  341. {
  342. await server.StopAsync();
  343. }
  344. }
  345. [TestMethod]
  346. public async Task MqttServer_Retained_Messages_Flow()
  347. {
  348. var retainedMessage = new MqttApplicationMessageBuilder().WithTopic("r").WithPayload("r").WithRetainFlag().Build();
  349. var serverAdapter = new TestMqttServerAdapter();
  350. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  351. await s.StartAsync(new MqttServerOptions());
  352. var c1 = await serverAdapter.ConnectTestClient("c1");
  353. await c1.PublishAsync(retainedMessage);
  354. await Task.Delay(500);
  355. await c1.DisconnectAsync();
  356. await Task.Delay(500);
  357. var receivedMessages = 0;
  358. var c2 = await serverAdapter.ConnectTestClient("c2");
  359. c2.ApplicationMessageReceived += (_, e) =>
  360. {
  361. receivedMessages++;
  362. };
  363. for (var i = 0; i < 5; i++)
  364. {
  365. await c2.UnsubscribeAsync("r");
  366. await Task.Delay(500);
  367. Assert.AreEqual(i, receivedMessages);
  368. await c2.SubscribeAsync("r");
  369. await Task.Delay(500);
  370. Assert.AreEqual(i + 1, receivedMessages);
  371. }
  372. await c2.DisconnectAsync();
  373. await s.StopAsync();
  374. }
  375. [TestMethod]
  376. public async Task MqttServer_No_Retained_Message()
  377. {
  378. var serverAdapter = new TestMqttServerAdapter();
  379. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  380. var receivedMessagesCount = 0;
  381. try
  382. {
  383. await s.StartAsync(new MqttServerOptions());
  384. var c1 = await serverAdapter.ConnectTestClient("c1");
  385. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[3]));
  386. await c1.DisconnectAsync();
  387. var c2 = await serverAdapter.ConnectTestClient("c2");
  388. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  389. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  390. await Task.Delay(500);
  391. }
  392. finally
  393. {
  394. await s.StopAsync();
  395. }
  396. Assert.AreEqual(0, receivedMessagesCount);
  397. }
  398. [TestMethod]
  399. public async Task MqttServer_Retained_Message()
  400. {
  401. var serverAdapter = new TestMqttServerAdapter();
  402. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  403. var receivedMessages = new List<MqttApplicationMessage>();
  404. try
  405. {
  406. await s.StartAsync(new MqttServerOptions());
  407. var c1 = await serverAdapter.ConnectTestClient("c1");
  408. await c1.PublishAndWaitForAsync(s, new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  409. await c1.DisconnectAsync();
  410. var c2 = await serverAdapter.ConnectTestClient("c2");
  411. c2.ApplicationMessageReceived += (_, e) =>
  412. {
  413. lock (receivedMessages)
  414. {
  415. receivedMessages.Add(e.ApplicationMessage);
  416. }
  417. };
  418. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  419. await Task.Delay(500);
  420. }
  421. finally
  422. {
  423. await s.StopAsync();
  424. }
  425. Assert.AreEqual(1, receivedMessages.Count);
  426. Assert.IsTrue(receivedMessages.First().Retain);
  427. }
  428. [TestMethod]
  429. public async Task MqttServer_Clear_Retained_Message()
  430. {
  431. var serverAdapter = new TestMqttServerAdapter();
  432. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  433. var receivedMessagesCount = 0;
  434. try
  435. {
  436. await s.StartAsync(new MqttServerOptions());
  437. var c1 = await serverAdapter.ConnectTestClient("c1");
  438. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag());
  439. await c1.PublishAsync(builder => builder.WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag());
  440. await c1.DisconnectAsync();
  441. var c2 = await serverAdapter.ConnectTestClient("c2");
  442. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  443. await Task.Delay(200);
  444. await c2.SubscribeAsync(new TopicFilter { Topic = "retained", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  445. await Task.Delay(500);
  446. }
  447. finally
  448. {
  449. await s.StopAsync();
  450. }
  451. Assert.AreEqual(0, receivedMessagesCount);
  452. }
  453. [TestMethod]
  454. public async Task MqttServer_Persist_Retained_Message()
  455. {
  456. var storage = new TestStorage();
  457. var serverAdapter = new TestMqttServerAdapter();
  458. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  459. try
  460. {
  461. var options = new MqttServerOptions { Storage = storage };
  462. await s.StartAsync(options);
  463. var c1 = await serverAdapter.ConnectTestClient("c1");
  464. await c1.PublishAndWaitForAsync(s, new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  465. await Task.Delay(250);
  466. await c1.DisconnectAsync();
  467. }
  468. finally
  469. {
  470. await s.StopAsync();
  471. }
  472. Assert.AreEqual(1, storage.Messages.Count);
  473. s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  474. var receivedMessagesCount = 0;
  475. try
  476. {
  477. var options = new MqttServerOptions { Storage = storage };
  478. await s.StartAsync(options);
  479. var c2 = await serverAdapter.ConnectTestClient("c2");
  480. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  481. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("retained").Build());
  482. await Task.Delay(250);
  483. }
  484. finally
  485. {
  486. await s.StopAsync();
  487. }
  488. Assert.AreEqual(1, receivedMessagesCount);
  489. }
  490. [TestMethod]
  491. public async Task MqttServer_InterceptMessage()
  492. {
  493. void Interceptor(MqttApplicationMessageInterceptorContext context)
  494. {
  495. context.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
  496. }
  497. var serverAdapter = new TestMqttServerAdapter();
  498. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  499. try
  500. {
  501. var options = new MqttServerOptions { ApplicationMessageInterceptor = new MqttServerApplicationMessageInterceptorDelegate(c => Interceptor(c)) };
  502. await s.StartAsync(options);
  503. var c1 = await serverAdapter.ConnectTestClient("c1");
  504. var c2 = await serverAdapter.ConnectTestClient("c2");
  505. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("test").Build());
  506. var isIntercepted = false;
  507. c2.ApplicationMessageReceived += (sender, args) =>
  508. {
  509. isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(args.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
  510. };
  511. await c1.PublishAsync(builder => builder.WithTopic("test"));
  512. await c1.DisconnectAsync();
  513. await Task.Delay(500);
  514. Assert.IsTrue(isIntercepted);
  515. }
  516. finally
  517. {
  518. await s.StopAsync();
  519. }
  520. }
  521. [TestMethod]
  522. public async Task MqttServer_Body()
  523. {
  524. var serverAdapter = new TestMqttServerAdapter();
  525. var s = new MqttFactory().CreateMqttServer(new[] { serverAdapter }, new MqttNetLogger());
  526. var bodyIsMatching = false;
  527. try
  528. {
  529. await s.StartAsync(new MqttServerOptions());
  530. var c1 = await serverAdapter.ConnectTestClient("c1");
  531. var c2 = await serverAdapter.ConnectTestClient("c2");
  532. c1.ApplicationMessageReceived += (_, e) =>
  533. {
  534. if (Encoding.UTF8.GetString(e.ApplicationMessage.Payload) == "The body")
  535. {
  536. bodyIsMatching = true;
  537. }
  538. };
  539. await c1.SubscribeAsync("A", MqttQualityOfServiceLevel.AtMostOnce);
  540. await c2.PublishAsync(builder => builder.WithTopic("A").WithPayload(Encoding.UTF8.GetBytes("The body")));
  541. await Task.Delay(1000);
  542. }
  543. finally
  544. {
  545. await s.StopAsync();
  546. }
  547. Assert.IsTrue(bodyIsMatching);
  548. }
  549. [TestMethod]
  550. public async Task MqttServer_Connection_Denied()
  551. {
  552. var server = new MqttFactory().CreateMqttServer();
  553. var client = new MqttFactory().CreateMqttClient();
  554. try
  555. {
  556. var options = new MqttServerOptionsBuilder().WithConnectionValidator(context =>
  557. {
  558. context.ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized;
  559. }).Build();
  560. await server.StartAsync(options);
  561. var clientOptions = new MqttClientOptionsBuilder()
  562. .WithTcpServer("localhost").Build();
  563. try
  564. {
  565. await client.ConnectAsync(clientOptions);
  566. Assert.Fail("An exception should be raised.");
  567. }
  568. catch (Exception exception)
  569. {
  570. if (exception is MqttConnectingFailedException)
  571. {
  572. }
  573. else
  574. {
  575. Assert.Fail("Wrong exception.");
  576. }
  577. }
  578. }
  579. finally
  580. {
  581. await client.DisconnectAsync();
  582. await server.StopAsync();
  583. client.Dispose();
  584. }
  585. }
  586. [TestMethod]
  587. public async Task MqttServer_SameClientIdConnectDisconnectEventOrder()
  588. {
  589. var s = new MqttFactory().CreateMqttServer();
  590. var events = new List<string>();
  591. s.ClientConnected += (_, __) =>
  592. {
  593. lock (events)
  594. {
  595. events.Add("c");
  596. }
  597. };
  598. s.ClientDisconnected += (_, __) =>
  599. {
  600. lock (events)
  601. {
  602. events.Add("d");
  603. }
  604. };
  605. var clientOptions = new MqttClientOptionsBuilder()
  606. .WithTcpServer("localhost")
  607. .WithClientId("same_id")
  608. .Build();
  609. await s.StartAsync(new MqttServerOptions());
  610. var c1 = new MqttFactory().CreateMqttClient();
  611. var c2 = new MqttFactory().CreateMqttClient();
  612. await c1.ConnectAsync(clientOptions);
  613. await Task.Delay(250);
  614. await c2.ConnectAsync(clientOptions);
  615. await Task.Delay(250);
  616. await c1.DisconnectAsync();
  617. await Task.Delay(250);
  618. await c2.DisconnectAsync();
  619. await Task.Delay(250);
  620. await s.StopAsync();
  621. var flow = string.Join(string.Empty, events);
  622. Assert.AreEqual("cdcd", flow);
  623. }
  624. [TestMethod]
  625. public async Task MqttServer_StopAndRestart()
  626. {
  627. var server = new MqttFactory().CreateMqttServer();
  628. await server.StartAsync(new MqttServerOptions());
  629. var client = new MqttFactory().CreateMqttClient();
  630. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  631. await server.StopAsync();
  632. try
  633. {
  634. var client2 = new MqttFactory().CreateMqttClient();
  635. await client2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  636. Assert.Fail("Connecting should fail.");
  637. }
  638. catch (Exception)
  639. {
  640. }
  641. await server.StartAsync(new MqttServerOptions());
  642. var client3 = new MqttFactory().CreateMqttClient();
  643. await client3.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  644. await server.StopAsync();
  645. }
  646. [TestMethod]
  647. public async Task MqttServer_Close_Idle_Connection()
  648. {
  649. var server = new MqttFactory().CreateMqttServer();
  650. try
  651. {
  652. await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(4)).Build());
  653. var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  654. await client.ConnectAsync("localhost", 1883);
  655. // Don't send anything. The server should close the connection.
  656. await Task.Delay(TimeSpan.FromSeconds(5));
  657. try
  658. {
  659. await client.ReceiveAsync(new ArraySegment<byte>(new byte[10]), SocketFlags.Partial);
  660. Assert.Fail("Receive should throw an exception.");
  661. }
  662. catch (SocketException)
  663. {
  664. }
  665. }
  666. finally
  667. {
  668. await server.StopAsync();
  669. }
  670. }
  671. [TestMethod]
  672. public async Task MqttServer_Send_Garbage()
  673. {
  674. var server = new MqttFactory().CreateMqttServer();
  675. try
  676. {
  677. await server.StartAsync(new MqttServerOptionsBuilder().WithDefaultCommunicationTimeout(TimeSpan.FromSeconds(4)).Build());
  678. var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  679. await client.ConnectAsync("localhost", 1883);
  680. await client.SendAsync(Encoding.UTF8.GetBytes("Garbage"), SocketFlags.None);
  681. await Task.Delay(TimeSpan.FromSeconds(5));
  682. try
  683. {
  684. await client.ReceiveAsync(new ArraySegment<byte>(new byte[10]), SocketFlags.Partial);
  685. Assert.Fail("Receive should throw an exception.");
  686. }
  687. catch (SocketException)
  688. {
  689. }
  690. }
  691. finally
  692. {
  693. await server.StopAsync();
  694. }
  695. }
  696. private class TestStorage : IMqttServerStorage
  697. {
  698. public IList<MqttApplicationMessage> Messages = new List<MqttApplicationMessage>();
  699. public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
  700. {
  701. Messages = messages;
  702. return Task.CompletedTask;
  703. }
  704. public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
  705. {
  706. return Task.FromResult(Messages);
  707. }
  708. }
  709. private static async Task TestPublishAsync(
  710. string topic,
  711. MqttQualityOfServiceLevel qualityOfServiceLevel,
  712. string topicFilter,
  713. MqttQualityOfServiceLevel filterQualityOfServiceLevel,
  714. int expectedReceivedMessagesCount)
  715. {
  716. var s = new MqttFactory().CreateMqttServer();
  717. var receivedMessagesCount = 0;
  718. try
  719. {
  720. await s.StartAsync(new MqttServerOptions());
  721. var c1 = new MqttFactory().CreateMqttClient();
  722. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  723. await c1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  724. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
  725. var c2 = new MqttFactory().CreateMqttClient();
  726. await c2.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost").Build());
  727. await c2.PublishAsync(builder => builder.WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel));
  728. await Task.Delay(500);
  729. await c1.UnsubscribeAsync(topicFilter);
  730. await Task.Delay(500);
  731. }
  732. finally
  733. {
  734. await s.StopAsync();
  735. }
  736. Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
  737. }
  738. }
  739. }