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.
 
 
 
 

455 lines
16 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using MQTTnet.Core.Adapter;
  8. using MQTTnet.Core.Client;
  9. using MQTTnet.Core.Protocol;
  10. using MQTTnet.Core.Server;
  11. using Microsoft.Extensions.DependencyInjection;
  12. using MQTTnet.Core.Internal;
  13. using MQTTnet.Core.Packets;
  14. namespace MQTTnet.Core.Tests
  15. {
  16. [TestClass]
  17. public class MqttServerTests
  18. {
  19. [TestMethod]
  20. public void MqttServer_PublishSimple_AtMostOnce()
  21. {
  22. TestPublishAsync(
  23. "A/B/C",
  24. MqttQualityOfServiceLevel.AtMostOnce,
  25. "A/B/C",
  26. MqttQualityOfServiceLevel.AtMostOnce,
  27. 1).Wait();
  28. }
  29. [TestMethod]
  30. public void MqttServer_PublishSimple_AtLeastOnce()
  31. {
  32. TestPublishAsync(
  33. "A/B/C",
  34. MqttQualityOfServiceLevel.AtLeastOnce,
  35. "A/B/C",
  36. MqttQualityOfServiceLevel.AtLeastOnce,
  37. 1).Wait();
  38. }
  39. [TestMethod]
  40. public void MqttServer_PublishSimple_ExactlyOnce()
  41. {
  42. TestPublishAsync(
  43. "A/B/C",
  44. MqttQualityOfServiceLevel.ExactlyOnce,
  45. "A/B/C",
  46. MqttQualityOfServiceLevel.ExactlyOnce,
  47. 1).Wait();
  48. }
  49. [TestMethod]
  50. public async Task MqttServer_WillMessage()
  51. {
  52. var serverAdapter = new TestMqttServerAdapter();
  53. var services = new ServiceCollection()
  54. .AddLogging()
  55. .AddMqttServer()
  56. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  57. .BuildServiceProvider();
  58. var s = new MqttFactory(services).CreateMqttServer();
  59. var receivedMessagesCount = 0;
  60. try
  61. {
  62. await s.StartAsync();
  63. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  64. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  65. var c2 = await serverAdapter.ConnectTestClient(s, "c2", willMessage);
  66. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  67. await c1.SubscribeAsync(new TopicFilter("#"));
  68. await c2.DisconnectAsync();
  69. await Task.Delay(1000);
  70. await c1.DisconnectAsync();
  71. }
  72. finally
  73. {
  74. await s.StopAsync();
  75. }
  76. Assert.AreEqual(1, receivedMessagesCount);
  77. }
  78. [TestMethod]
  79. public async Task MqttServer_Unsubscribe()
  80. {
  81. var serverAdapter = new TestMqttServerAdapter();
  82. var services = new ServiceCollection()
  83. .AddLogging()
  84. .AddMqttServer()
  85. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  86. .BuildServiceProvider();
  87. var s = new MqttFactory(services).CreateMqttServer();
  88. var receivedMessagesCount = 0;
  89. try
  90. {
  91. await s.StartAsync();
  92. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  93. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  94. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  95. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  96. await c2.PublishAsync(message);
  97. Assert.AreEqual(0, receivedMessagesCount);
  98. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  99. await c2.PublishAsync(message);
  100. await Task.Delay(500);
  101. Assert.AreEqual(1, receivedMessagesCount);
  102. await c1.UnsubscribeAsync("a");
  103. await c2.PublishAsync(message);
  104. await Task.Delay(500);
  105. Assert.AreEqual(1, receivedMessagesCount);
  106. }
  107. finally
  108. {
  109. await s.StopAsync();
  110. }
  111. await Task.Delay(500);
  112. Assert.AreEqual(1, receivedMessagesCount);
  113. }
  114. [TestMethod]
  115. public async Task MqttServer_Publish()
  116. {
  117. var serverAdapter = new TestMqttServerAdapter();
  118. var services = new ServiceCollection()
  119. .AddLogging()
  120. .AddMqttServer()
  121. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  122. .BuildServiceProvider();
  123. var s = new MqttFactory(services).CreateMqttServer();
  124. var receivedMessagesCount = 0;
  125. try
  126. {
  127. await s.StartAsync();
  128. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  129. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  130. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  131. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  132. s.PublishAsync(message).Wait();
  133. await Task.Delay(500);
  134. }
  135. finally
  136. {
  137. await s.StopAsync();
  138. }
  139. Assert.AreEqual(1, receivedMessagesCount);
  140. }
  141. [TestMethod]
  142. public async Task MqttServer_NoRetainedMessage()
  143. {
  144. var serverAdapter = new TestMqttServerAdapter();
  145. var services = new ServiceCollection()
  146. .AddLogging()
  147. .AddMqttServer()
  148. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  149. .BuildServiceProvider();
  150. var s = new MqttFactory(services).CreateMqttServer();
  151. var receivedMessagesCount = 0;
  152. try
  153. {
  154. await s.StartAsync();
  155. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  156. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).Build());
  157. await c1.DisconnectAsync();
  158. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  159. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  160. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  161. await Task.Delay(500);
  162. }
  163. finally
  164. {
  165. await s.StopAsync();
  166. }
  167. Assert.AreEqual(0, receivedMessagesCount);
  168. }
  169. [TestMethod]
  170. public async Task MqttServer_RetainedMessage()
  171. {
  172. var serverAdapter = new TestMqttServerAdapter();
  173. var services = new ServiceCollection()
  174. .AddLogging()
  175. .AddMqttServer()
  176. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  177. .BuildServiceProvider();
  178. var s = new MqttFactory(services).CreateMqttServer();
  179. var receivedMessagesCount = 0;
  180. try
  181. {
  182. await s.StartAsync();
  183. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  184. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  185. await c1.DisconnectAsync();
  186. await services.WaitForRetainedMessage("retained").TimeoutAfter(TimeSpan.FromSeconds(5));
  187. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  188. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  189. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  190. await Task.Delay(500);
  191. }
  192. finally
  193. {
  194. await s.StopAsync();
  195. }
  196. Assert.AreEqual(1, receivedMessagesCount);
  197. }
  198. [TestMethod]
  199. public async Task MqttServer_ClearRetainedMessage()
  200. {
  201. var serverAdapter = new TestMqttServerAdapter();
  202. var services = new ServiceCollection()
  203. .AddLogging()
  204. .AddMqttServer()
  205. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  206. .BuildServiceProvider();
  207. var s = new MqttFactory(services).CreateMqttServer();
  208. var receivedMessagesCount = 0;
  209. try
  210. {
  211. await s.StartAsync();
  212. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  213. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  214. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
  215. await c1.DisconnectAsync();
  216. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  217. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  218. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  219. await Task.Delay(500);
  220. }
  221. finally
  222. {
  223. await s.StopAsync();
  224. }
  225. Assert.AreEqual(0, receivedMessagesCount);
  226. }
  227. [TestMethod]
  228. public async Task MqttServer_PersistRetainedMessage()
  229. {
  230. var storage = new TestStorage();
  231. var serverAdapter = new TestMqttServerAdapter();
  232. var services = new ServiceCollection()
  233. .AddLogging()
  234. .AddMqttServer()
  235. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  236. .BuildServiceProvider();
  237. var s = new MqttFactory(services).CreateMqttServer(options => options.Storage = storage);
  238. try
  239. {
  240. await s.StartAsync();
  241. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  242. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  243. await c1.DisconnectAsync();
  244. }
  245. finally
  246. {
  247. await s.StopAsync();
  248. }
  249. await services.WaitForRetainedMessage("retained").TimeoutAfter(TimeSpan.FromSeconds(5));
  250. s = new MqttFactory(services).CreateMqttServer(options => options.Storage = storage);
  251. var receivedMessagesCount = 0;
  252. try
  253. {
  254. await s.StartAsync();
  255. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  256. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  257. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  258. await Task.Delay(500);
  259. }
  260. finally
  261. {
  262. await s.StopAsync();
  263. }
  264. Assert.AreEqual(1, receivedMessagesCount);
  265. }
  266. [TestMethod]
  267. public async Task MqttServer_InterceptMessage()
  268. {
  269. void Interceptor(MqttApplicationMessageInterceptorContext context)
  270. {
  271. context.ApplicationMessage.Payload = Encoding.ASCII.GetBytes("extended");
  272. }
  273. var serverAdapter = new TestMqttServerAdapter();
  274. var services = new ServiceCollection()
  275. .AddLogging()
  276. .AddMqttServer()
  277. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  278. .BuildServiceProvider();
  279. var s = new MqttFactory(services).CreateMqttServer(options => options.ApplicationMessageInterceptor = Interceptor);
  280. try
  281. {
  282. await s.StartAsync();
  283. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  284. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  285. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("test").Build());
  286. var isIntercepted = false;
  287. c2.ApplicationMessageReceived += (sender, args) =>
  288. {
  289. isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(args.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
  290. };
  291. var m = new MqttApplicationMessageBuilder().WithTopic("test").Build();
  292. await c1.PublishAsync(m);
  293. await c1.DisconnectAsync();
  294. await Task.Delay(500);
  295. Assert.IsTrue(isIntercepted);
  296. }
  297. finally
  298. {
  299. await s.StopAsync();
  300. }
  301. }
  302. private class TestStorage : IMqttServerStorage
  303. {
  304. private IList<MqttApplicationMessage> _messages = new List<MqttApplicationMessage>();
  305. public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
  306. {
  307. _messages = messages;
  308. return Task.CompletedTask;
  309. }
  310. public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
  311. {
  312. return Task.FromResult(_messages);
  313. }
  314. }
  315. private static async Task TestPublishAsync(
  316. string topic,
  317. MqttQualityOfServiceLevel qualityOfServiceLevel,
  318. string topicFilter,
  319. MqttQualityOfServiceLevel filterQualityOfServiceLevel,
  320. int expectedReceivedMessagesCount)
  321. {
  322. var serverAdapter = new TestMqttServerAdapter();
  323. var services = new ServiceCollection()
  324. .AddMqttServer()
  325. .AddLogging()
  326. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  327. .BuildServiceProvider();
  328. var s = services.GetRequiredService<IMqttServer>();
  329. var receivedMessagesCount = 0;
  330. try
  331. {
  332. await s.StartAsync();
  333. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  334. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  335. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  336. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
  337. await c2.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
  338. await Task.Delay(500);
  339. await c1.UnsubscribeAsync(topicFilter);
  340. await Task.Delay(500);
  341. }
  342. finally
  343. {
  344. await s.StopAsync();
  345. }
  346. Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
  347. }
  348. }
  349. public static class TestExtensions
  350. {
  351. public static async Task WaitForRetainedMessage(this IServiceProvider services, string topic)
  352. {
  353. var retainMessagemanager = services.GetRequiredService<IMqttClientRetainedMessageManager>();
  354. var subscribe = new MqttSubscribePacket()
  355. {
  356. TopicFilters = new List<TopicFilter>()
  357. {
  358. new TopicFilter(topic, MqttQualityOfServiceLevel.AtMostOnce)
  359. }
  360. };
  361. while (!(await retainMessagemanager.GetSubscribedMessagesAsync(subscribe)).Any())
  362. {
  363. await Task.Delay(TimeSpan.FromMilliseconds(10));
  364. }
  365. }
  366. }
  367. }