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.
 
 
 
 

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