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.
 
 
 
 

217 lines
8.6 KiB

  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Microsoft.VisualStudio.TestTools.UnitTesting;
  8. using MQTTnet.Tests.Mockups;
  9. using MQTTnet.Client;
  10. using MQTTnet.Exceptions;
  11. using MQTTnet.Extensions.Rpc;
  12. using MQTTnet.Protocol;
  13. using MQTTnet.Formatter;
  14. using MQTTnet.Implementations;
  15. namespace MQTTnet.Tests
  16. {
  17. [TestClass]
  18. public sealed class RPC_Tests : BaseTestClass
  19. {
  20. [TestMethod]
  21. public Task Execute_Success_With_QoS_0()
  22. {
  23. return Execute_Success(MqttQualityOfServiceLevel.AtMostOnce, MqttProtocolVersion.V311);
  24. }
  25. [TestMethod]
  26. public Task Execute_Success_With_QoS_1()
  27. {
  28. return Execute_Success(MqttQualityOfServiceLevel.AtLeastOnce, MqttProtocolVersion.V311);
  29. }
  30. [TestMethod]
  31. public Task Execute_Success_With_QoS_2()
  32. {
  33. return Execute_Success(MqttQualityOfServiceLevel.ExactlyOnce, MqttProtocolVersion.V311);
  34. }
  35. [TestMethod]
  36. public Task Execute_Success_With_QoS_0_MQTT_V5()
  37. {
  38. return Execute_Success(MqttQualityOfServiceLevel.AtMostOnce, MqttProtocolVersion.V500);
  39. }
  40. [TestMethod]
  41. public Task Execute_Success_With_QoS_1_MQTT_V5()
  42. {
  43. return Execute_Success(MqttQualityOfServiceLevel.AtLeastOnce, MqttProtocolVersion.V500);
  44. }
  45. [TestMethod]
  46. public Task Execute_Success_With_QoS_2_MQTT_V5()
  47. {
  48. return Execute_Success(MqttQualityOfServiceLevel.ExactlyOnce, MqttProtocolVersion.V500);
  49. }
  50. [TestMethod]
  51. public Task Execute_Success_With_QoS_0_MQTT_V5_Use_ResponseTopic()
  52. {
  53. return Execute_Success_MQTT_V5(MqttQualityOfServiceLevel.AtMostOnce);
  54. }
  55. [TestMethod]
  56. public Task Execute_Success_With_QoS_1_MQTT_V5_Use_ResponseTopic()
  57. {
  58. return Execute_Success_MQTT_V5(MqttQualityOfServiceLevel.AtLeastOnce);
  59. }
  60. [TestMethod]
  61. public Task Execute_Success_With_QoS_2_MQTT_V5_Use_ResponseTopic()
  62. {
  63. return Execute_Success_MQTT_V5(MqttQualityOfServiceLevel.ExactlyOnce);
  64. }
  65. [TestMethod]
  66. [ExpectedException(typeof(MqttCommunicationTimedOutException))]
  67. public async Task Execute_Timeout()
  68. {
  69. using (var testEnvironment = CreateTestEnvironment())
  70. {
  71. await testEnvironment.StartServer();
  72. var requestSender = await testEnvironment.ConnectClient();
  73. var rpcClient = new MqttRpcClient(requestSender, new MqttRpcClientOptionsBuilder().Build());
  74. await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(2), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
  75. }
  76. }
  77. [TestMethod]
  78. [ExpectedException(typeof(MqttCommunicationTimedOutException))]
  79. public async Task Execute_With_Custom_Topic_Names()
  80. {
  81. using (var testEnvironment = CreateTestEnvironment())
  82. {
  83. await testEnvironment.StartServer();
  84. var requestSender = await testEnvironment.ConnectClient();
  85. var rpcClient = await testEnvironment.ConnectRpcClient(new MqttRpcClientOptionsBuilder().WithTopicGenerationStrategy(new TestTopicStrategy()).Build());
  86. await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(2), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
  87. }
  88. }
  89. async Task Execute_Success(MqttQualityOfServiceLevel qosLevel, MqttProtocolVersion protocolVersion)
  90. {
  91. using (var testEnvironment = CreateTestEnvironment())
  92. {
  93. await testEnvironment.StartServer();
  94. var responseSender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(protocolVersion));
  95. await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping", qosLevel);
  96. responseSender.ApplicationMessageReceivedAsync += e => responseSender.PublishStringAsync(e.ApplicationMessage.Topic + "/response", "pong");
  97. var requestSender = await testEnvironment.ConnectClient();
  98. using (var rpcClient = new MqttRpcClient(requestSender, new MqttRpcClientOptionsBuilder().Build()))
  99. {
  100. var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), "ping", "", qosLevel);
  101. Assert.AreEqual("pong", Encoding.UTF8.GetString(response));
  102. }
  103. }
  104. }
  105. async Task Execute_Success_MQTT_V5(MqttQualityOfServiceLevel qosLevel)
  106. {
  107. using (var testEnvironment = CreateTestEnvironment())
  108. {
  109. await testEnvironment.StartServer();
  110. var responseSender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
  111. await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping", qosLevel);
  112. responseSender.ApplicationMessageReceivedAsync += async e =>
  113. {
  114. await responseSender.PublishStringAsync(e.ApplicationMessage.ResponseTopic, "pong");
  115. };
  116. var requestSender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
  117. using (var rpcClient = new MqttRpcClient(requestSender, new MqttRpcClientOptionsBuilder().Build()))
  118. {
  119. var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), "ping", "", qosLevel);
  120. Assert.AreEqual("pong", Encoding.UTF8.GetString(response));
  121. }
  122. }
  123. }
  124. [TestMethod]
  125. public async Task Execute_Success_MQTT_V5_Mixed_Clients()
  126. {
  127. using (var testEnvironment = CreateTestEnvironment())
  128. {
  129. await testEnvironment.StartServer();
  130. var responseSender = await testEnvironment.ConnectClient();
  131. await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping", MqttQualityOfServiceLevel.AtMostOnce);
  132. responseSender.ApplicationMessageReceivedAsync += async e =>
  133. {
  134. Assert.IsNull(e.ApplicationMessage.ResponseTopic);
  135. await responseSender.PublishStringAsync(e.ApplicationMessage.Topic + "/response", "pong");
  136. };
  137. var requestSender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
  138. using (var rpcClient = new MqttRpcClient(requestSender, new MqttRpcClientOptionsBuilder().Build()))
  139. {
  140. var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(5), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
  141. Assert.AreEqual("pong", Encoding.UTF8.GetString(response));
  142. }
  143. }
  144. }
  145. [TestMethod]
  146. [ExpectedException(typeof(MqttCommunicationTimedOutException))]
  147. public async Task Execute_Timeout_MQTT_V5_Mixed_Clients()
  148. {
  149. using (var testEnvironment = new TestEnvironment(TestContext))
  150. {
  151. await testEnvironment.StartServer();
  152. var responseSender = await testEnvironment.ConnectClient();
  153. await responseSender.SubscribeAsync("MQTTnet.RPC/+/ping", MqttQualityOfServiceLevel.AtMostOnce);
  154. responseSender.ApplicationMessageReceivedAsync += async e =>
  155. {
  156. Assert.IsNull(e.ApplicationMessage.ResponseTopic);
  157. await PlatformAbstractionLayer.CompletedTask;
  158. };
  159. var requestSender = await testEnvironment.ConnectClient(new MqttClientOptionsBuilder().WithProtocolVersion(MqttProtocolVersion.V500));
  160. using (var rpcClient = new MqttRpcClient(requestSender, new MqttRpcClientOptionsBuilder().Build()))
  161. {
  162. var response = await rpcClient.ExecuteAsync(TimeSpan.FromSeconds(2), "ping", "", MqttQualityOfServiceLevel.AtMostOnce);
  163. }
  164. }
  165. }
  166. class TestTopicStrategy : IMqttRpcClientTopicGenerationStrategy
  167. {
  168. public MqttRpcTopicPair CreateRpcTopics(TopicGenerationContext context)
  169. {
  170. return new MqttRpcTopicPair
  171. {
  172. RequestTopic = "a",
  173. ResponseTopic = "b"
  174. };
  175. }
  176. }
  177. }
  178. }