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.
 
 
 
 

629 lines
19 KiB

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