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.
 
 
 
 

300 lines
10 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net.Sockets;
  5. using System.Threading.Tasks;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using MQTTnet.Client;
  8. using MQTTnet.Client.Connecting;
  9. using MQTTnet.Client.Disconnecting;
  10. using MQTTnet.Client.Options;
  11. using MQTTnet.Exceptions;
  12. using MQTTnet.Protocol;
  13. using MQTTnet.Server;
  14. using MQTTnet.Tests.Mockups;
  15. namespace MQTTnet.Tests
  16. {
  17. [TestClass]
  18. public class Client_Tests
  19. {
  20. [TestMethod]
  21. public async Task Invalid_Connect_Throws_Exception()
  22. {
  23. var factory = new MqttFactory();
  24. using (var client = factory.CreateMqttClient())
  25. {
  26. try
  27. {
  28. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("wrong-server").Build());
  29. Assert.Fail("Must fail!");
  30. }
  31. catch (Exception exception)
  32. {
  33. Assert.IsNotNull(exception);
  34. Assert.IsInstanceOfType(exception, typeof(MqttCommunicationException));
  35. Assert.IsInstanceOfType(exception.InnerException, typeof(SocketException));
  36. }
  37. }
  38. }
  39. [TestMethod]
  40. public async Task Disconnect_Event_Contains_Exception()
  41. {
  42. var factory = new MqttFactory();
  43. using (var client = factory.CreateMqttClient())
  44. {
  45. Exception ex = null;
  46. client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(e =>
  47. {
  48. ex = e.Exception;
  49. });
  50. try
  51. {
  52. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("wrong-server").Build());
  53. }
  54. catch
  55. {
  56. }
  57. Assert.IsNotNull(ex);
  58. Assert.IsInstanceOfType(ex, typeof(MqttCommunicationException));
  59. Assert.IsInstanceOfType(ex.InnerException, typeof(SocketException));
  60. }
  61. }
  62. [TestMethod]
  63. public async Task Preserve_Message_Order()
  64. {
  65. // The messages are sent in reverse or to ensure that the delay in the handler
  66. // needs longer for the first messages and later messages may be processed earlier (if there
  67. // is an issue).
  68. const int MessagesCount = 50;
  69. using (var testEnvironment = new TestEnvironment())
  70. {
  71. await testEnvironment.StartServerAsync();
  72. var client1 = await testEnvironment.ConnectClientAsync();
  73. await client1.SubscribeAsync("x");
  74. var receivedValues = new List<int>();
  75. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  76. {
  77. var value = int.Parse(eventArgs.ApplicationMessage.ConvertPayloadToString());
  78. await Task.Delay(value);
  79. lock (receivedValues)
  80. {
  81. receivedValues.Add(value);
  82. }
  83. }
  84. client1.UseApplicationMessageReceivedHandler(Handler1);
  85. var client2 = await testEnvironment.ConnectClientAsync();
  86. for (var i = MessagesCount; i > 0; i--)
  87. {
  88. await client2.PublishAsync("x", i.ToString());
  89. }
  90. await Task.Delay(5000);
  91. for (var i = MessagesCount; i > 0; i--)
  92. {
  93. Assert.AreEqual(i, receivedValues[MessagesCount - i]);
  94. }
  95. }
  96. }
  97. [TestMethod]
  98. public async Task Send_Reply_For_Any_Received_Message()
  99. {
  100. using (var testEnvironment = new TestEnvironment())
  101. {
  102. await testEnvironment.StartServerAsync();
  103. var client1 = await testEnvironment.ConnectClientAsync();
  104. await client1.SubscribeAsync("request/+");
  105. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  106. {
  107. await client1.PublishAsync($"reply/{eventArgs.ApplicationMessage.Topic}");
  108. }
  109. client1.UseApplicationMessageReceivedHandler(Handler1);
  110. var client2 = await testEnvironment.ConnectClientAsync();
  111. await client2.SubscribeAsync("reply/#");
  112. var replies = new List<string>();
  113. void Handler2(MqttApplicationMessageReceivedEventArgs eventArgs)
  114. {
  115. lock (replies)
  116. {
  117. replies.Add(eventArgs.ApplicationMessage.Topic);
  118. }
  119. }
  120. client2.UseApplicationMessageReceivedHandler((Action<MqttApplicationMessageReceivedEventArgs>)Handler2);
  121. await Task.Delay(500);
  122. await client2.PublishAsync("request/a");
  123. await client2.PublishAsync("request/b");
  124. await client2.PublishAsync("request/c");
  125. await Task.Delay(500);
  126. Assert.AreEqual("reply/request/a,reply/request/b,reply/request/c", string.Join(",", replies));
  127. }
  128. }
  129. [TestMethod]
  130. public async Task Publish_With_Correct_Retain_Flag()
  131. {
  132. using (var testEnvironment = new TestEnvironment())
  133. {
  134. await testEnvironment.StartServerAsync();
  135. var receivedMessages = new List<MqttApplicationMessage>();
  136. var client1 = await testEnvironment.ConnectClientAsync();
  137. client1.UseApplicationMessageReceivedHandler(c =>
  138. {
  139. lock (receivedMessages)
  140. {
  141. receivedMessages.Add(c.ApplicationMessage);
  142. }
  143. });
  144. await client1.SubscribeAsync("a");
  145. var client2 = await testEnvironment.ConnectClientAsync();
  146. var message = new MqttApplicationMessageBuilder().WithTopic("a").WithRetainFlag().Build();
  147. await client2.PublishAsync(message);
  148. await Task.Delay(500);
  149. Assert.AreEqual(1, receivedMessages.Count);
  150. Assert.IsFalse(receivedMessages.First().Retain); // Must be false even if set above!
  151. }
  152. }
  153. [TestMethod]
  154. public async Task Subscribe_In_Callback_Events()
  155. {
  156. using (var testEnvironment = new TestEnvironment())
  157. {
  158. await testEnvironment.StartServerAsync();
  159. var receivedMessages = new List<MqttApplicationMessage>();
  160. var client = testEnvironment.CreateClient();
  161. client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(async e =>
  162. {
  163. await client.SubscribeAsync("RCU/P1/H0001/R0003");
  164. var msg = new MqttApplicationMessageBuilder()
  165. .WithPayload("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|")
  166. .WithTopic("RCU/P1/H0001/R0003");
  167. await client.PublishAsync(msg.Build());
  168. });
  169. client.UseApplicationMessageReceivedHandler(c =>
  170. {
  171. lock (receivedMessages)
  172. {
  173. receivedMessages.Add(c.ApplicationMessage);
  174. }
  175. });
  176. await client.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer("localhost", testEnvironment.ServerPort).Build());
  177. await Task.Delay(500);
  178. Assert.AreEqual(1, receivedMessages.Count);
  179. Assert.AreEqual("DA|18RS00SC00XI0000RV00R100R200R300R400L100L200L300L400Y100Y200AC0102031800BELK0000BM0000|", receivedMessages.First().ConvertPayloadToString());
  180. }
  181. }
  182. [TestMethod]
  183. public async Task Message_Send_Retry()
  184. {
  185. using (var testEnvironment = new TestEnvironment())
  186. {
  187. testEnvironment.IgnoreClientLogErrors = true;
  188. testEnvironment.IgnoreServerLogErrors = true;
  189. await testEnvironment.StartServerAsync(
  190. new MqttServerOptionsBuilder()
  191. .WithPersistentSessions()
  192. .WithDefaultCommunicationTimeout(TimeSpan.FromMilliseconds(250)));
  193. var client1 = await testEnvironment.ConnectClientAsync(new MqttClientOptionsBuilder().WithCleanSession(false));
  194. await client1.SubscribeAsync("x", MqttQualityOfServiceLevel.AtLeastOnce);
  195. var retries = 0;
  196. async Task Handler1(MqttApplicationMessageReceivedEventArgs eventArgs)
  197. {
  198. retries++;
  199. await Task.Delay(1000);
  200. throw new Exception("Broken!");
  201. }
  202. client1.UseApplicationMessageReceivedHandler(Handler1);
  203. var client2 = await testEnvironment.ConnectClientAsync();
  204. await client2.PublishAsync("x");
  205. await Task.Delay(3000);
  206. // The server should disconnect clients which are not responding.
  207. Assert.IsFalse(client1.IsConnected);
  208. await client1.ReconnectAsync().ConfigureAwait(false);
  209. await Task.Delay(1000);
  210. Assert.AreEqual(2, retries);
  211. }
  212. }
  213. [TestMethod]
  214. public async Task NoConnectedHandler_Connect_DoesNotThrowException()
  215. {
  216. using (var testEnvironment = new TestEnvironment())
  217. {
  218. await testEnvironment.StartServerAsync();
  219. var client = await testEnvironment.ConnectClientAsync();
  220. Assert.IsTrue(client.IsConnected);
  221. }
  222. }
  223. [TestMethod]
  224. public async Task NoDisconnectedHandler_Disconnect_DoesNotThrowException()
  225. {
  226. using (var testEnvironment = new TestEnvironment())
  227. {
  228. await testEnvironment.StartServerAsync();
  229. var client = await testEnvironment.ConnectClientAsync();
  230. Assert.IsTrue(client.IsConnected);
  231. await client.DisconnectAsync();
  232. Assert.IsFalse(client.IsConnected);
  233. }
  234. }
  235. }
  236. }