25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

335 lines
12 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading.Tasks;
  5. using Microsoft.VisualStudio.TestTools.UnitTesting;
  6. using MQTTnet.Core.Adapter;
  7. using MQTTnet.Core.Client;
  8. using MQTTnet.Core.Protocol;
  9. using MQTTnet.Core.Server;
  10. using Microsoft.Extensions.DependencyInjection;
  11. namespace MQTTnet.Core.Tests
  12. {
  13. [TestClass]
  14. public class MqttServerTests
  15. {
  16. [TestMethod]
  17. public void MqttServer_PublishSimple_AtMostOnce()
  18. {
  19. TestPublishAsync(
  20. "A/B/C",
  21. MqttQualityOfServiceLevel.AtMostOnce,
  22. "A/B/C",
  23. MqttQualityOfServiceLevel.AtMostOnce,
  24. 1).Wait();
  25. }
  26. [TestMethod]
  27. public void MqttServer_PublishSimple_AtLeastOnce()
  28. {
  29. TestPublishAsync(
  30. "A/B/C",
  31. MqttQualityOfServiceLevel.AtLeastOnce,
  32. "A/B/C",
  33. MqttQualityOfServiceLevel.AtLeastOnce,
  34. 1).Wait();
  35. }
  36. [TestMethod]
  37. public void MqttServer_PublishSimple_ExactlyOnce()
  38. {
  39. TestPublishAsync(
  40. "A/B/C",
  41. MqttQualityOfServiceLevel.ExactlyOnce,
  42. "A/B/C",
  43. MqttQualityOfServiceLevel.ExactlyOnce,
  44. 1).Wait();
  45. }
  46. [TestMethod]
  47. public async Task MqttServer_WillMessage()
  48. {
  49. var serverAdapter = new TestMqttServerAdapter();
  50. var s = new MqttFactory().CreateMqttServer();
  51. await s.StartAsync();
  52. var willMessage = new MqttApplicationMessageBuilder().WithTopic("My/last/will").WithAtMostOnceQoS().Build();
  53. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  54. var c2 = await serverAdapter.ConnectTestClient(s, "c2", willMessage);
  55. var receivedMessagesCount = 0;
  56. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  57. await c1.SubscribeAsync(new TopicFilter("#", MqttQualityOfServiceLevel.AtMostOnce));
  58. await c2.DisconnectAsync();
  59. await Task.Delay(1000);
  60. await s.StopAsync();
  61. Assert.AreEqual(1, receivedMessagesCount);
  62. }
  63. [TestMethod]
  64. public async Task MqttServer_Unsubscribe()
  65. {
  66. var serverAdapter = new TestMqttServerAdapter();
  67. var s = new MqttFactory().CreateMqttServer();
  68. await s.StartAsync();
  69. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  70. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  71. var receivedMessagesCount = 0;
  72. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  73. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  74. await c2.PublishAsync(message);
  75. Assert.AreEqual(0, receivedMessagesCount);
  76. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  77. await c2.PublishAsync(message);
  78. await Task.Delay(500);
  79. Assert.AreEqual(1, receivedMessagesCount);
  80. await c1.UnsubscribeAsync("a");
  81. await c2.PublishAsync(message);
  82. await Task.Delay(500);
  83. Assert.AreEqual(1, receivedMessagesCount);
  84. await s.StopAsync();
  85. await Task.Delay(500);
  86. Assert.AreEqual(1, receivedMessagesCount);
  87. }
  88. [TestMethod]
  89. public async Task MqttServer_Publish()
  90. {
  91. var serverAdapter = new TestMqttServerAdapter();
  92. var s = new MqttFactory().CreateMqttServer();
  93. await s.StartAsync();
  94. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  95. var receivedMessagesCount = 0;
  96. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  97. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithAtLeastOnceQoS().Build();
  98. await c1.SubscribeAsync(new TopicFilter("a", MqttQualityOfServiceLevel.AtLeastOnce));
  99. s.PublishAsync(message).Wait();
  100. await Task.Delay(500);
  101. await s.StopAsync();
  102. Assert.AreEqual(1, receivedMessagesCount);
  103. }
  104. [TestMethod]
  105. public async Task MqttServer_NoRetainedMessage()
  106. {
  107. var serverAdapter = new TestMqttServerAdapter();
  108. var s = new MqttFactory().CreateMqttServer();
  109. await s.StartAsync();
  110. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  111. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).Build());
  112. await c1.DisconnectAsync();
  113. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  114. var receivedMessagesCount = 0;
  115. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  116. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  117. await Task.Delay(500);
  118. await s.StopAsync();
  119. Assert.AreEqual(0, receivedMessagesCount);
  120. }
  121. [TestMethod]
  122. public async Task MqttServer_RetainedMessage()
  123. {
  124. var serverAdapter = new TestMqttServerAdapter();
  125. var s = new MqttFactory().CreateMqttServer();
  126. await s.StartAsync();
  127. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  128. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  129. await c1.DisconnectAsync();
  130. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  131. var receivedMessagesCount = 0;
  132. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  133. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  134. await Task.Delay(500);
  135. await s.StopAsync();
  136. Assert.AreEqual(1, receivedMessagesCount);
  137. }
  138. [TestMethod]
  139. public async Task MqttServer_ClearRetainedMessage()
  140. {
  141. var serverAdapter = new TestMqttServerAdapter();
  142. var services = new ServiceCollection()
  143. .AddLogging()
  144. .AddMqttServer() // TODO: Is there maybe an easier way for the library user to set the options?
  145. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  146. .BuildServiceProvider();
  147. var s = new MqttFactory(services).CreateMqttServer();
  148. await s.StartAsync();
  149. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  150. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  151. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[0]).WithRetainFlag().Build());
  152. await c1.DisconnectAsync();
  153. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  154. var receivedMessagesCount = 0;
  155. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  156. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  157. await Task.Delay(500);
  158. await s.StopAsync();
  159. Assert.AreEqual(0, receivedMessagesCount);
  160. }
  161. [TestMethod]
  162. public async Task MqttServer_PersistRetainedMessage()
  163. {
  164. var storage = new TestStorage();
  165. var serverAdapter = new TestMqttServerAdapter();
  166. var services = new ServiceCollection()
  167. .AddLogging()
  168. .AddMqttServer(options => options.Storage = storage) // TODO: Is there maybe an easier way for the library user to set the options?
  169. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  170. .BuildServiceProvider();
  171. var s = new MqttFactory(services).CreateMqttServer(); // TODO: Like here?
  172. await s.StartAsync();
  173. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  174. await c1.PublishAsync(new MqttApplicationMessageBuilder().WithTopic("retained").WithPayload(new byte[3]).WithRetainFlag().Build());
  175. await c1.DisconnectAsync();
  176. await s.StopAsync();
  177. s = services.GetRequiredService<IMqttServer>();
  178. await s.StartAsync();
  179. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  180. var receivedMessagesCount = 0;
  181. c2.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  182. await c2.SubscribeAsync(new TopicFilter("retained", MqttQualityOfServiceLevel.AtMostOnce));
  183. await Task.Delay(500);
  184. await s.StopAsync();
  185. Assert.AreEqual(1, receivedMessagesCount);
  186. }
  187. [TestMethod]
  188. public async Task MqttServer_InterceptMessage()
  189. {
  190. MqttApplicationMessage Interceptor(MqttApplicationMessage message)
  191. {
  192. message.Payload = Encoding.ASCII.GetBytes("extended");
  193. return message;
  194. }
  195. var serverAdapter = new TestMqttServerAdapter();
  196. var services = new ServiceCollection()
  197. .AddLogging()
  198. .AddMqttServer(options => options.ApplicationMessageInterceptor = Interceptor)
  199. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  200. .BuildServiceProvider();
  201. var s = services.GetRequiredService<IMqttServer>();
  202. await s.StartAsync();
  203. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  204. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  205. await c2.SubscribeAsync(new TopicFilterBuilder().WithTopic("test").Build());
  206. var isIntercepted = false;
  207. c2.ApplicationMessageReceived += (sender, args) =>
  208. {
  209. isIntercepted = string.Compare("extended", Encoding.UTF8.GetString(args.ApplicationMessage.Payload), StringComparison.Ordinal) == 0;
  210. };
  211. var m = new MqttApplicationMessageBuilder().WithTopic("test").Build();
  212. await c1.PublishAsync(m);
  213. await c1.DisconnectAsync();
  214. await Task.Delay(500);
  215. Assert.IsTrue(isIntercepted);
  216. }
  217. private class TestStorage : IMqttServerStorage
  218. {
  219. private IList<MqttApplicationMessage> _messages = new List<MqttApplicationMessage>();
  220. public Task SaveRetainedMessagesAsync(IList<MqttApplicationMessage> messages)
  221. {
  222. _messages = messages;
  223. return Task.CompletedTask;
  224. }
  225. public Task<IList<MqttApplicationMessage>> LoadRetainedMessagesAsync()
  226. {
  227. return Task.FromResult(_messages);
  228. }
  229. }
  230. private static async Task TestPublishAsync(
  231. string topic,
  232. MqttQualityOfServiceLevel qualityOfServiceLevel,
  233. string topicFilter,
  234. MqttQualityOfServiceLevel filterQualityOfServiceLevel,
  235. int expectedReceivedMessagesCount)
  236. {
  237. var serverAdapter = new TestMqttServerAdapter();
  238. var services = new ServiceCollection()
  239. .AddMqttServer()
  240. .AddSingleton<IMqttServerAdapter>(serverAdapter)
  241. .BuildServiceProvider();
  242. var s = services.GetRequiredService<IMqttServer>();
  243. await s.StartAsync();
  244. var c1 = await serverAdapter.ConnectTestClient(s, "c1");
  245. var c2 = await serverAdapter.ConnectTestClient(s, "c2");
  246. var receivedMessagesCount = 0;
  247. c1.ApplicationMessageReceived += (_, __) => receivedMessagesCount++;
  248. await c1.SubscribeAsync(new TopicFilterBuilder().WithTopic(topicFilter).WithQualityOfServiceLevel(filterQualityOfServiceLevel).Build());
  249. await c2.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(new byte[0]).WithQualityOfServiceLevel(qualityOfServiceLevel).Build());
  250. await Task.Delay(500);
  251. await c1.UnsubscribeAsync(topicFilter);
  252. await Task.Delay(500);
  253. await s.StopAsync();
  254. Assert.AreEqual(expectedReceivedMessagesCount, receivedMessagesCount);
  255. }
  256. }
  257. }