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.
 
 
 
 

628 lines
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.Formatter;
  9. using MQTTnet.Formatter.V3;
  10. using MQTTnet.Internal;
  11. using MQTTnet.Packets;
  12. using MQTTnet.Protocol;
  13. namespace MQTTnet.Tests
  14. {
  15. [TestClass]
  16. public class MqttPacketSerializer_Tests
  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 MqttConnAckPacket
  101. {
  102. IsSessionPresent = true,
  103. ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  104. };
  105. SerializeAndCompare(p, "IAIBBQ==");
  106. }
  107. [TestMethod]
  108. public void SerializeV310_MqttConnAckPacket()
  109. {
  110. var p = new MqttConnAckPacket
  111. {
  112. ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  113. };
  114. SerializeAndCompare(p, "IAIABQ==", MqttProtocolVersion.V310);
  115. }
  116. [TestMethod]
  117. public void DeserializeV311_MqttConnAckPacket()
  118. {
  119. var p = new MqttConnAckPacket
  120. {
  121. IsSessionPresent = true,
  122. ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  123. };
  124. DeserializeAndCompare(p, "IAIBBQ==");
  125. }
  126. [TestMethod]
  127. public void DeserializeV310_MqttConnAckPacket()
  128. {
  129. var p = new MqttConnAckPacket
  130. {
  131. ReturnCode = MqttConnectReturnCode.ConnectionRefusedNotAuthorized
  132. };
  133. DeserializeAndCompare(p, "IAIABQ==", MqttProtocolVersion.V310);
  134. }
  135. [TestMethod]
  136. public void Serialize_LargePacket()
  137. {
  138. var serializer = new MqttV311PacketFormatter();
  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.Encode(publishPacket);
  156. var testChannel = new TestMqttChannel(new MemoryStream(buffer.Array, buffer.Offset, buffer.Count));
  157. var header = new MqttPacketReader(testChannel).ReadFixedHeaderAsync(
  158. new byte[2],
  159. CancellationToken.None).GetAwaiter().GetResult().FixedHeader;
  160. var eof = buffer.Offset + buffer.Count;
  161. var receivedPacket = new ReceivedMqttPacket(
  162. header.Flags,
  163. new MqttPacketBodyReader(buffer.Array, eof - header.RemainingLength, buffer.Count + buffer.Offset),
  164. 0);
  165. var packet = (MqttPublishPacket)serializer.Decode(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 SerializeV500_MqttPublishPacket()
  200. {
  201. var prop = new MqttPublishPacketProperties();
  202. prop.ResponseTopic = "/Response";
  203. prop.UserProperties.Add(new MqttUserProperty("Foo", "Bar"));
  204. var p = new MqttPublishPacket
  205. {
  206. PacketIdentifier = 123,
  207. Dup = true,
  208. Retain = true,
  209. Payload = Encoding.ASCII.GetBytes("HELLO"),
  210. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  211. Topic = "A/B/C",
  212. Properties = prop
  213. };
  214. var deserialized = Roundtrip(p, MqttProtocolVersion.V500);
  215. Assert.AreEqual(prop.ResponseTopic, deserialized.Properties.ResponseTopic);
  216. Assert.IsTrue(deserialized.Properties.UserProperties.Any(x => x.Name == "Foo"));
  217. }
  218. [TestMethod]
  219. public void DeserializeV311_MqttPublishPacket()
  220. {
  221. var p = new MqttPublishPacket
  222. {
  223. PacketIdentifier = 123,
  224. Dup = true,
  225. Retain = true,
  226. Payload = Encoding.ASCII.GetBytes("HELLO"),
  227. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  228. Topic = "A/B/C"
  229. };
  230. DeserializeAndCompare(p, "Ow4ABUEvQi9DAHtIRUxMTw==");
  231. }
  232. [TestMethod]
  233. public void DeserializeV311_MqttPublishPacket_Qos1()
  234. {
  235. var p = new MqttPublishPacket
  236. {
  237. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
  238. };
  239. var p2 = Roundtrip(p);
  240. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  241. Assert.AreEqual(p.Dup, p2.Dup);
  242. }
  243. [TestMethod]
  244. public void DeserializeV311_MqttPublishPacket_Qos2()
  245. {
  246. var p = new MqttPublishPacket
  247. {
  248. QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce,
  249. PacketIdentifier = 1
  250. };
  251. var p2 = Roundtrip(p);
  252. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  253. Assert.AreEqual(p.Dup, p2.Dup);
  254. }
  255. [TestMethod]
  256. public void DeserializeV311_MqttPublishPacket_Qos3()
  257. {
  258. var p = new MqttPublishPacket
  259. {
  260. QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce,
  261. PacketIdentifier = 1
  262. };
  263. var p2 = Roundtrip(p);
  264. Assert.AreEqual(p.QualityOfServiceLevel, p2.QualityOfServiceLevel);
  265. Assert.AreEqual(p.Dup, p2.Dup);
  266. }
  267. [TestMethod]
  268. public void DeserializeV311_MqttPublishPacket_DupFalse()
  269. {
  270. var p = new MqttPublishPacket
  271. {
  272. Dup = false,
  273. };
  274. var p2 = Roundtrip(p);
  275. Assert.AreEqual(p.Dup, p2.Dup);
  276. }
  277. [TestMethod]
  278. public void SerializeV311_MqttPubAckPacket()
  279. {
  280. var p = new MqttPubAckPacket
  281. {
  282. PacketIdentifier = 123
  283. };
  284. SerializeAndCompare(p, "QAIAew==");
  285. }
  286. [TestMethod]
  287. public void DeserializeV311_MqttPubAckPacket()
  288. {
  289. var p = new MqttPubAckPacket
  290. {
  291. PacketIdentifier = 123
  292. };
  293. DeserializeAndCompare(p, "QAIAew==");
  294. }
  295. [TestMethod]
  296. public void SerializeV311_MqttPubRecPacket()
  297. {
  298. var p = new MqttPubRecPacket
  299. {
  300. PacketIdentifier = 123
  301. };
  302. SerializeAndCompare(p, "UAIAew==");
  303. }
  304. [TestMethod]
  305. public void DeserializeV311_MqttPubRecPacket()
  306. {
  307. var p = new MqttPubRecPacket
  308. {
  309. PacketIdentifier = 123
  310. };
  311. DeserializeAndCompare(p, "UAIAew==");
  312. }
  313. [TestMethod]
  314. public void SerializeV311_MqttPubRelPacket()
  315. {
  316. var p = new MqttPubRelPacket
  317. {
  318. PacketIdentifier = 123
  319. };
  320. SerializeAndCompare(p, "YgIAew==");
  321. }
  322. [TestMethod]
  323. public void DeserializeV311_MqttPubRelPacket()
  324. {
  325. var p = new MqttPubRelPacket
  326. {
  327. PacketIdentifier = 123
  328. };
  329. DeserializeAndCompare(p, "YgIAew==");
  330. }
  331. [TestMethod]
  332. public void SerializeV311_MqttPubCompPacket()
  333. {
  334. var p = new MqttPubCompPacket
  335. {
  336. PacketIdentifier = 123
  337. };
  338. SerializeAndCompare(p, "cAIAew==");
  339. }
  340. [TestMethod]
  341. public void DeserializeV311_MqttPubCompPacket()
  342. {
  343. var p = new MqttPubCompPacket
  344. {
  345. PacketIdentifier = 123
  346. };
  347. DeserializeAndCompare(p, "cAIAew==");
  348. }
  349. [TestMethod]
  350. public void SerializeV311_MqttSubscribePacket()
  351. {
  352. var p = new MqttSubscribePacket
  353. {
  354. PacketIdentifier = 123
  355. };
  356. p.TopicFilters.Add(new TopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce });
  357. p.TopicFilters.Add(new TopicFilter { Topic = "1/2/3", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  358. p.TopicFilters.Add(new TopicFilter { Topic = "x/y/z", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  359. SerializeAndCompare(p, "ghoAewAFQS9CL0MCAAUxLzIvMwEABXgveS96AA==");
  360. }
  361. [TestMethod]
  362. public void DeserializeV311_MqttSubscribePacket()
  363. {
  364. var p = new MqttSubscribePacket
  365. {
  366. PacketIdentifier = 123
  367. };
  368. p.TopicFilters.Add(new TopicFilter { Topic = "A/B/C", QualityOfServiceLevel = MqttQualityOfServiceLevel.ExactlyOnce });
  369. p.TopicFilters.Add(new TopicFilter { Topic = "1/2/3", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtLeastOnce });
  370. p.TopicFilters.Add(new TopicFilter { Topic = "x/y/z", QualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce });
  371. DeserializeAndCompare(p, "ghoAewAFQS9CL0MCAAUxLzIvMwEABXgveS96AA==");
  372. }
  373. [TestMethod]
  374. public void SerializeV311_MqttSubAckPacket()
  375. {
  376. var p = new MqttSubAckPacket
  377. {
  378. PacketIdentifier = 123
  379. };
  380. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS0);
  381. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS1);
  382. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS2);
  383. p.ReturnCodes.Add(MqttSubscribeReturnCode.Failure);
  384. SerializeAndCompare(p, "kAYAewABAoA=");
  385. }
  386. [TestMethod]
  387. public void DeserializeV311_MqttSubAckPacket()
  388. {
  389. var p = new MqttSubAckPacket
  390. {
  391. PacketIdentifier = 123
  392. };
  393. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS0);
  394. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS1);
  395. p.ReturnCodes.Add(MqttSubscribeReturnCode.SuccessMaximumQoS2);
  396. p.ReturnCodes.Add(MqttSubscribeReturnCode.Failure);
  397. DeserializeAndCompare(p, "kAYAewABAoA=");
  398. }
  399. [TestMethod]
  400. public void SerializeV311_MqttUnsubscribePacket()
  401. {
  402. var p = new MqttUnsubscribePacket
  403. {
  404. PacketIdentifier = 123
  405. };
  406. p.TopicFilters.Add("A/B/C");
  407. p.TopicFilters.Add("1/2/3");
  408. p.TopicFilters.Add("x/y/z");
  409. SerializeAndCompare(p, "ohcAewAFQS9CL0MABTEvMi8zAAV4L3kveg==");
  410. }
  411. [TestMethod]
  412. public void DeserializeV311_MqttUnsubscribePacket()
  413. {
  414. var p = new MqttUnsubscribePacket
  415. {
  416. PacketIdentifier = 123
  417. };
  418. p.TopicFilters.Add("A/B/C");
  419. p.TopicFilters.Add("1/2/3");
  420. p.TopicFilters.Add("x/y/z");
  421. DeserializeAndCompare(p, "ohcAewAFQS9CL0MABTEvMi8zAAV4L3kveg==");
  422. }
  423. [TestMethod]
  424. public void SerializeV311_MqttUnsubAckPacket()
  425. {
  426. var p = new MqttUnsubAckPacket
  427. {
  428. PacketIdentifier = 123
  429. };
  430. SerializeAndCompare(p, "sAIAew==");
  431. }
  432. [TestMethod]
  433. public void DeserializeV311_MqttUnsubAckPacket()
  434. {
  435. var p = new MqttUnsubAckPacket
  436. {
  437. PacketIdentifier = 123
  438. };
  439. DeserializeAndCompare(p, "sAIAew==");
  440. }
  441. private static void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  442. {
  443. IMqttPacketFormatter serializer;
  444. if (protocolVersion == MqttProtocolVersion.V311)
  445. {
  446. serializer = new MqttV311PacketFormatter();
  447. }
  448. else if (protocolVersion == MqttProtocolVersion.V310)
  449. {
  450. serializer = new MqttV310PacketFormatter();
  451. }
  452. else
  453. {
  454. throw new NotSupportedException();
  455. }
  456. var data = serializer.Encode(packet);
  457. Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(data)));
  458. }
  459. protected virtual IMqttPacketWriter WriterFactory()
  460. {
  461. return new MqttPacketWriter();
  462. }
  463. protected virtual IMqttPacketBodyReader ReaderFactory(byte[] data)
  464. {
  465. return new MqttPacketBodyReader(data, 0, data.Length);
  466. }
  467. private void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  468. {
  469. var writer = WriterFactory();
  470. var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer);
  471. var buffer1 = serializer.Encode(packet);
  472. using (var headerStream = new MemoryStream(Join(buffer1)))
  473. {
  474. var channel = new TestMqttChannel(headerStream);
  475. var fixedHeader = new byte[2];
  476. var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader;
  477. using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength))
  478. {
  479. var reader = ReaderFactory(bodyStream.ToArray());
  480. var deserializedPacket = serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0));
  481. var buffer2 = serializer.Encode(deserializedPacket);
  482. Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2)));
  483. }
  484. }
  485. }
  486. private T Roundtrip<T>(T packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311)
  487. where T : MqttBasePacket
  488. {
  489. var writer = WriterFactory();
  490. var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer);
  491. var buffer1 = serializer.Encode(packet);
  492. using (var headerStream = new MemoryStream(Join(buffer1)))
  493. {
  494. var channel = new TestMqttChannel(headerStream);
  495. var fixedHeader = new byte[2];
  496. var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader;
  497. using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, (int)header.RemainingLength))
  498. {
  499. var reader = ReaderFactory(bodyStream.ToArray());
  500. return (T)serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0));
  501. }
  502. }
  503. }
  504. private static byte[] Join(params ArraySegment<byte>[] chunks)
  505. {
  506. var buffer = new MemoryStream();
  507. foreach (var chunk in chunks)
  508. {
  509. buffer.Write(chunk.Array, chunk.Offset, chunk.Count);
  510. }
  511. return buffer.ToArray();
  512. }
  513. }
  514. }