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.
 
 
 
 

575 line
18 KiB

  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using Microsoft.VisualStudio.TestTools.UnitTesting;
  7. using MQTTnet.Adapter;
  8. using MQTTnet.Internal;
  9. using MQTTnet.Packets;
  10. using MQTTnet.Protocol;
  11. using MQTTnet.Serializer;
  12. namespace MQTTnet.Core.Tests
  13. {
  14. [TestClass]
  15. public class MqttPacketSerializerTests
  16. {
  17. [TestMethod]
  18. public void SerializeV310_MqttConnectPacket()
  19. {
  20. var p = new MqttConnectPacket
  21. {
  22. ClientId = "XYZ",
  23. Password = "PASS",
  24. Username = "USER",
  25. KeepAlivePeriod = 123,
  26. CleanSession = true
  27. };
  28. SerializeAndCompare(p, "EB0ABk1RSXNkcAPCAHsAA1hZWgAEVVNFUgAEUEFTUw==", MqttProtocolVersion.V310);
  29. }
  30. [TestMethod]
  31. public void SerializeV311_MqttConnectPacket()
  32. {
  33. var p = new MqttConnectPacket
  34. {
  35. ClientId = "XYZ",
  36. Password = "PASS",
  37. Username = "USER",
  38. KeepAlivePeriod = 123,
  39. CleanSession = true
  40. };
  41. SerializeAndCompare(p, "EBsABE1RVFQEwgB7AANYWVoABFVTRVIABFBBU1M=");
  42. }
  43. [TestMethod]
  44. public void SerializeV311_MqttConnectPacketWithWillMessage()
  45. {
  46. var p = new MqttConnectPacket
  47. {
  48. ClientId = "XYZ",
  49. Password = "PASS",
  50. Username = "USER",
  51. KeepAlivePeriod = 123,
  52. CleanSession = true,
  53. WillMessage = new MqttApplicationMessage
  54. {
  55. Topic = "My/last/will",
  56. Payload = Encoding.UTF8.GetBytes("Good byte."),
  57. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  58. Retain = true
  59. }
  60. };
  61. SerializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw==");
  62. }
  63. [TestMethod]
  64. public void DeserializeV311_MqttConnectPacket()
  65. {
  66. var p = new MqttConnectPacket
  67. {
  68. ClientId = "XYZ",
  69. Password = "PASS",
  70. Username = "USER",
  71. KeepAlivePeriod = 123,
  72. CleanSession = true
  73. };
  74. DeserializeAndCompare(p, "EBsABE1RVFQEwgB7AANYWVoABFVTRVIABFBBU1M=");
  75. }
  76. [TestMethod]
  77. public void DeserializeV311_MqttConnectPacketWithWillMessage()
  78. {
  79. var p = new MqttConnectPacket
  80. {
  81. ClientId = "XYZ",
  82. Password = "PASS",
  83. Username = "USER",
  84. KeepAlivePeriod = 123,
  85. CleanSession = true,
  86. WillMessage = new MqttApplicationMessage
  87. {
  88. Topic = "My/last/will",
  89. Payload = Encoding.UTF8.GetBytes("Good byte."),
  90. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  91. Retain = true
  92. }
  93. };
  94. DeserializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw==");
  95. }
  96. [TestMethod]
  97. public void SerializeV311_MqttConnAckPacket()
  98. {
  99. var p = new MqttConnAckPacket
  100. {
  101. IsSessionPresent = true,
  102. ConnectReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  103. };
  104. SerializeAndCompare(p, "IAIBBQ==");
  105. }
  106. [TestMethod]
  107. public void SerializeV310_MqttConnAckPacket()
  108. {
  109. var p = new MqttConnAckPacket
  110. {
  111. ConnectReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  112. };
  113. SerializeAndCompare(p, "IAIABQ==", MqttProtocolVersion.V310);
  114. }
  115. [TestMethod]
  116. public void DeserializeV311_MqttConnAckPacket()
  117. {
  118. var p = new MqttConnAckPacket
  119. {
  120. IsSessionPresent = true,
  121. ConnectReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  122. };
  123. DeserializeAndCompare(p, "IAIBBQ==");
  124. }
  125. [TestMethod]
  126. public void DeserializeV310_MqttConnAckPacket()
  127. {
  128. var p = new MqttConnAckPacket
  129. {
  130. ConnectReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  131. };
  132. DeserializeAndCompare(p, "IAIABQ==", MqttProtocolVersion.V310);
  133. }
  134. [TestMethod]
  135. public void Serialize_LargePacket()
  136. {
  137. var serializer = new MqttPacketSerializer { ProtocolVersion = MqttProtocolVersion.V311 };
  138. const int payloadLength = 80000;
  139. var payload = new byte[payloadLength];
  140. var value = 0;
  141. for (var i = 0; i < payloadLength; i++)
  142. {
  143. if (value > 255)
  144. {
  145. value = 0;
  146. }
  147. payload[i] = (byte)value;
  148. }
  149. var publishPacket = new MqttPublishPacket
  150. {
  151. Topic = "abcdefghijklmnopqrstuvwxyz0123456789",
  152. Payload = payload
  153. };
  154. var buffer = serializer.Serialize(publishPacket);
  155. var testChannel = new TestMqttChannel(new MemoryStream(buffer.Array, buffer.Offset, buffer.Count));
  156. var header = MqttPacketReader.ReadFixedHeaderAsync(
  157. testChannel,
  158. new byte[2],
  159. new byte[1],
  160. CancellationToken.None).GetAwaiter().GetResult();
  161. var eof = buffer.Offset + buffer.Count;
  162. var receivedPacket = new ReceivedMqttPacket(
  163. header.Flags,
  164. new MqttPacketBodyReader(buffer.Array, eof - header.RemainingLength, buffer.Count + buffer.Offset));
  165. var packet = (MqttPublishPacket)serializer.Deserialize(receivedPacket);
  166. Assert.AreEqual(publishPacket.Topic, packet.Topic);
  167. Assert.IsTrue(publishPacket.Payload.SequenceEqual(packet.Payload));
  168. }
  169. [TestMethod]
  170. public void SerializeV311_MqttDisconnectPacket()
  171. {
  172. SerializeAndCompare(new MqttDisconnectPacket(), "4AA=");
  173. }
  174. [TestMethod]
  175. public void SerializeV311_MqttPingReqPacket()
  176. {
  177. SerializeAndCompare(new MqttPingReqPacket(), "wAA=");
  178. }
  179. [TestMethod]
  180. public void SerializeV311_MqttPingRespPacket()
  181. {
  182. SerializeAndCompare(new MqttPingRespPacket(), "0AA=");
  183. }
  184. [TestMethod]
  185. public void SerializeV311_MqttPublishPacket()
  186. {
  187. var p = new MqttPublishPacket
  188. {
  189. PacketIdentifier = 123,
  190. Dup = true,
  191. Retain = true,
  192. Payload = Encoding.ASCII.GetBytes("HELLO"),
  193. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  194. Topic = "A/B/C"
  195. };
  196. SerializeAndCompare(p, "Ow4ABUEvQi9DAHtIRUxMTw==");
  197. }
  198. [TestMethod]
  199. public void DeserializeV311_MqttPublishPacket()
  200. {
  201. var p = new MqttPublishPacket
  202. {
  203. PacketIdentifier = 123,
  204. Dup = true,
  205. Retain = true,
  206. Payload = Encoding.ASCII.GetBytes("HELLO"),
  207. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  208. Topic = "A/B/C"
  209. };
  210. DeserializeAndCompare(p, "Ow4ABUEvQi9DAHtIRUxMTw==");
  211. }
  212. [TestMethod]
  213. public void DeserializeV311_MqttPublishPacket_Qos1()
  214. {
  215. var p = new MqttPublishPacket
  216. {
  217. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
  218. };
  219. var p2 = Roundtrip(p);
  220. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  221. Assert.AreEqual(p.Dup, p2.Dup);
  222. }
  223. [TestMethod]
  224. public void DeserializeV311_MqttPublishPacket_Qos2()
  225. {
  226. var p = new MqttPublishPacket
  227. {
  228. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  229. PacketIdentifier = 1
  230. };
  231. var p2 = Roundtrip(p);
  232. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  233. Assert.AreEqual(p.Dup, p2.Dup);
  234. }
  235. [TestMethod]
  236. public void DeserializeV311_MqttPublishPacket_Qos3()
  237. {
  238. var p = new MqttPublishPacket
  239. {
  240. QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce,
  241. PacketIdentifier = 1
  242. };
  243. var p2 = Roundtrip(p);
  244. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  245. Assert.AreEqual(p.Dup, p2.Dup);
  246. }
  247. [TestMethod]
  248. public void DeserializeV311_MqttPublishPacket_DupFalse()
  249. {
  250. var p = new MqttPublishPacket
  251. {
  252. Dup = false,
  253. };
  254. var p2 = Roundtrip(p);
  255. Assert.AreEqual(p.Dup, p2.Dup);
  256. }
  257. [TestMethod]
  258. public void SerializeV311_MqttPubAckPacket()
  259. {
  260. var p = new MqttPubAckPacket
  261. {
  262. PacketIdentifier = 123
  263. };
  264. SerializeAndCompare(p, "QAIAew==");
  265. }
  266. [TestMethod]
  267. public void DeserializeV311_MqttPubAckPacket()
  268. {
  269. var p = new MqttPubAckPacket
  270. {
  271. PacketIdentifier = 123
  272. };
  273. DeserializeAndCompare(p, "QAIAew==");
  274. }
  275. [TestMethod]
  276. public void SerializeV311_MqttPubRecPacket()
  277. {
  278. var p = new MqttPubRecPacket
  279. {
  280. PacketIdentifier = 123
  281. };
  282. SerializeAndCompare(p, "UAIAew==");
  283. }
  284. [TestMethod]
  285. public void DeserializeV311_MqttPubRecPacket()
  286. {
  287. var p = new MqttPubRecPacket
  288. {
  289. PacketIdentifier = 123
  290. };
  291. DeserializeAndCompare(p, "UAIAew==");
  292. }
  293. [TestMethod]
  294. public void SerializeV311_MqttPubRelPacket()
  295. {
  296. var p = new MqttPubRelPacket
  297. {
  298. PacketIdentifier = 123
  299. };
  300. SerializeAndCompare(p, "YgIAew==");
  301. }
  302. [TestMethod]
  303. public void DeserializeV311_MqttPubRelPacket()
  304. {
  305. var p = new MqttPubRelPacket
  306. {
  307. PacketIdentifier = 123
  308. };
  309. DeserializeAndCompare(p, "YgIAew==");
  310. }
  311. [TestMethod]
  312. public void SerializeV311_MqttPubCompPacket()
  313. {
  314. var p = new MqttPubCompPacket
  315. {
  316. PacketIdentifier = 123
  317. };
  318. SerializeAndCompare(p, "cAIAew==");
  319. }
  320. [TestMethod]
  321. public void DeserializeV311_MqttPubCompPacket()
  322. {
  323. var p = new MqttPubCompPacket
  324. {
  325. PacketIdentifier = 123
  326. };
  327. DeserializeAndCompare(p, "cAIAew==");
  328. }
  329. [TestMethod]
  330. public void SerializeV311_MqttSubscribePacket()
  331. {
  332. var p = new MqttSubscribePacket
  333. {
  334. PacketIdentifier = 123
  335. };
  336. p.TopicFilters.Add(new TopicFilter("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce));
  337. p.TopicFilters.Add(new TopicFilter("1/2/3", MqttQualityOfServiceLevel.AtLeastOnce));
  338. p.TopicFilters.Add(new TopicFilter("x/y/z", MqttQualityOfServiceLevel.AtMostOnce));
  339. SerializeAndCompare(p, "ghoAewAFQS9CL0MCAAUxLzIvMwEABXgveS96AA==");
  340. }
  341. [TestMethod]
  342. public void DeserializeV311_MqttSubscribePacket()
  343. {
  344. var p = new MqttSubscribePacket
  345. {
  346. PacketIdentifier = 123
  347. };
  348. p.TopicFilters.Add(new TopicFilter("A/B/C", MqttQualityOfServiceLevel.ExactlyOnce));
  349. p.TopicFilters.Add(new TopicFilter("1/2/3", MqttQualityOfServiceLevel.AtLeastOnce));
  350. p.TopicFilters.Add(new TopicFilter("x/y/z", MqttQualityOfServiceLevel.AtMostOnce));
  351. DeserializeAndCompare(p, "ghoAewAFQS9CL0MCAAUxLzIvMwEABXgveS96AA==");
  352. }
  353. [TestMethod]
  354. public void SerializeV311_MqttSubAckPacket()
  355. {
  356. var p = new MqttSubAckPacket
  357. {
  358. PacketIdentifier = 123
  359. };
  360. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS0);
  361. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS1);
  362. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS2);
  363. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.Failure);
  364. SerializeAndCompare(p, "kAYAewABAoA=");
  365. }
  366. [TestMethod]
  367. public void DeserializeV311_MqttSubAckPacket()
  368. {
  369. var p = new MqttSubAckPacket
  370. {
  371. PacketIdentifier = 123
  372. };
  373. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS0);
  374. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS1);
  375. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS2);
  376. p.SubscribeReturnCodes.Add(MqttSubscribeReturnCode.Failure);
  377. DeserializeAndCompare(p, "kAYAewABAoA=");
  378. }
  379. [TestMethod]
  380. public void SerializeV311_MqttUnsubscribePacket()
  381. {
  382. var p = new MqttUnsubscribePacket
  383. {
  384. PacketIdentifier = 123
  385. };
  386. p.TopicFilters.Add("A/B/C");
  387. p.TopicFilters.Add("1/2/3");
  388. p.TopicFilters.Add("x/y/z");
  389. SerializeAndCompare(p, "ohcAewAFQS9CL0MABTEvMi8zAAV4L3kveg==");
  390. }
  391. [TestMethod]
  392. public void DeserializeV311_MqttUnsubscribePacket()
  393. {
  394. var p = new MqttUnsubscribePacket
  395. {
  396. PacketIdentifier = 123
  397. };
  398. p.TopicFilters.Add("A/B/C");
  399. p.TopicFilters.Add("1/2/3");
  400. p.TopicFilters.Add("x/y/z");
  401. DeserializeAndCompare(p, "ohcAewAFQS9CL0MABTEvMi8zAAV4L3kveg==");
  402. }
  403. [TestMethod]
  404. public void SerializeV311_MqttUnsubAckPacket()
  405. {
  406. var p = new MqttUnsubAckPacket
  407. {
  408. PacketIdentifier = 123
  409. };
  410. SerializeAndCompare(p, "sAIAew==");
  411. }
  412. [TestMethod]
  413. public void DeserializeV311_MqttUnsubAckPacket()
  414. {
  415. var p = new MqttUnsubAckPacket
  416. {
  417. PacketIdentifier = 123
  418. };
  419. DeserializeAndCompare(p, "sAIAew==");
  420. }
  421. private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  422. {
  423. var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion };
  424. var data = serializer.Serialize(packet);
  425. Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(data)));
  426. }
  427. private static void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  428. {
  429. var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion };
  430. var buffer1 = serializer.Serialize(packet);
  431. using (var headerStream = new MemoryStream(Join(buffer1)))
  432. {
  433. var channel = new TestMqttChannel(headerStream);
  434. var fixedHeader = new byte[2];
  435. var singleByteBuffer = new byte[1];
  436. var header = MqttPacketReader.ReadFixedHeaderAsync(channel, fixedHeader, singleByteBuffer, CancellationToken.None).GetAwaiter().GetResult();
  437. using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength))
  438. {
  439. var deserializedPacket = serializer.Deserialize(new ReceivedMqttPacket(header.Flags, new MqttPacketBodyReader(bodyStream.ToArray(), 0, (int)bodyStream.Length)));
  440. var buffer2 = serializer.Serialize(deserializedPacket);
  441. Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2)));
  442. }
  443. }
  444. }
  445. private static T Roundtrip<T>(T packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  446. where T : MqttBasePacket
  447. {
  448. var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion };
  449. var buffer1 = serializer.Serialize(packet);
  450. using (var headerStream = new MemoryStream(Join(buffer1)))
  451. {
  452. var channel = new TestMqttChannel(headerStream);
  453. var fixedHeader = new byte[2];
  454. var singleByteBuffer = new byte[1];
  455. var header = MqttPacketReader.ReadFixedHeaderAsync(channel, fixedHeader, singleByteBuffer, CancellationToken.None).GetAwaiter().GetResult();
  456. using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength))
  457. {
  458. return (T)serializer.Deserialize(new ReceivedMqttPacket(header.Flags, new MqttPacketBodyReader(bodyStream.ToArray(), 0, (int)bodyStream.Length)));
  459. }
  460. }
  461. }
  462. private static byte[] Join(params ArraySegment<byte>[] chunks)
  463. {
  464. var buffer = new MemoryStream();
  465. foreach (var chunk in chunks)
  466. {
  467. buffer.Write(chunk.Array, chunk.Offset, chunk.Count);
  468. }
  469. return buffer.ToArray();
  470. }
  471. }
  472. }