codec_multipart.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include <catch.hpp>
  2. #include <zmq_addon.hpp>
  3. #ifdef ZMQ_CPP11
  4. TEST_CASE("multipart codec empty", "[codec_multipart]")
  5. {
  6. using namespace zmq;
  7. multipart_t mmsg;
  8. message_t msg = mmsg.encode();
  9. CHECK(msg.size() == 0);
  10. multipart_t mmsg2;
  11. mmsg2.decode_append(msg);
  12. CHECK(mmsg2.size() == 0);
  13. }
  14. TEST_CASE("multipart codec small", "[codec_multipart]")
  15. {
  16. using namespace zmq;
  17. multipart_t mmsg;
  18. mmsg.addstr("Hello World");
  19. message_t msg = mmsg.encode();
  20. CHECK(msg.size() == 1 + 11); // small size packing
  21. mmsg.addstr("Second frame");
  22. msg = mmsg.encode();
  23. CHECK(msg.size() == 1 + 11 + 1 + 12);
  24. multipart_t mmsg2;
  25. mmsg2.decode_append(msg);
  26. CHECK(mmsg2.size() == 2);
  27. std::string part0 = mmsg2[0].to_string();
  28. CHECK(part0 == "Hello World");
  29. CHECK(mmsg2[1].to_string() == "Second frame");
  30. }
  31. TEST_CASE("multipart codec big", "[codec_multipart]")
  32. {
  33. using namespace zmq;
  34. message_t big(495); // large size packing
  35. big.data<char>()[0] = 'X';
  36. multipart_t mmsg;
  37. mmsg.pushmem(big.data(), big.size());
  38. message_t msg = mmsg.encode();
  39. CHECK(msg.size() == 5 + 495);
  40. CHECK(msg.data<unsigned char>()[0] == std::numeric_limits<uint8_t>::max());
  41. CHECK(msg.data<unsigned char>()[5] == 'X');
  42. CHECK(mmsg.size() == 1);
  43. mmsg.decode_append(msg);
  44. CHECK(mmsg.size() == 2);
  45. CHECK(mmsg[0].data<char>()[0] == 'X');
  46. }
  47. TEST_CASE("multipart codec decode bad data overflow", "[codec_multipart]")
  48. {
  49. using namespace zmq;
  50. char bad_data[3] = {5, 'h', 'i'};
  51. message_t wrong_size(bad_data, 3);
  52. CHECK(wrong_size.size() == 3);
  53. CHECK(wrong_size.data<char>()[0] == 5);
  54. CHECK_THROWS_AS(
  55. multipart_t::decode(wrong_size),
  56. const std::out_of_range&);
  57. }
  58. TEST_CASE("multipart codec decode bad data extra data", "[codec_multipart]")
  59. {
  60. using namespace zmq;
  61. char bad_data[3] = {1, 'h', 'i'};
  62. message_t wrong_size(bad_data, 3);
  63. CHECK(wrong_size.size() == 3);
  64. CHECK(wrong_size.data<char>()[0] == 1);
  65. CHECK_THROWS_AS(
  66. multipart_t::decode(wrong_size),
  67. const std::out_of_range&);
  68. }
  69. // After exercising it, this test is disabled over concern of running
  70. // on hosts which lack enough free memory to allow the absurdly large
  71. // message part to be allocated.
  72. #if 0
  73. TEST_CASE("multipart codec encode too big", "[codec_multipart]")
  74. {
  75. using namespace zmq;
  76. const size_t too_big_size = 1L + std::numeric_limits<uint32_t>::max();
  77. CHECK(too_big_size > std::numeric_limits<uint32_t>::max());
  78. char* too_big_data = new char[too_big_size];
  79. multipart_t mmsg(too_big_data, too_big_size);
  80. delete [] too_big_data;
  81. CHECK(mmsg.size() == 1);
  82. CHECK(mmsg[0].size() > std::numeric_limits<uint32_t>::max());
  83. CHECK_THROWS_AS(
  84. mmsg.encode(),
  85. std::range_error);
  86. }
  87. #endif
  88. TEST_CASE("multipart codec free function with vector of message_t", "[codec_multipart]")
  89. {
  90. using namespace zmq;
  91. std::vector<message_t> parts;
  92. parts.emplace_back("Hello", 5);
  93. parts.emplace_back("World",5);
  94. auto msg = encode(parts);
  95. CHECK(msg.size() == 1 + 5 + 1 + 5 );
  96. CHECK(msg.data<unsigned char>()[0] == 5);
  97. CHECK(msg.data<unsigned char>()[1] == 'H');
  98. CHECK(msg.data<unsigned char>()[6] == 5);
  99. CHECK(msg.data<unsigned char>()[7] == 'W');
  100. std::vector<message_t> parts2;
  101. decode(msg, std::back_inserter(parts2));
  102. CHECK(parts.size() == 2);
  103. CHECK(parts[0].size() == 5);
  104. CHECK(parts[1].size() == 5);
  105. }
  106. TEST_CASE("multipart codec free function with vector of const_buffer", "[codec_multipart]")
  107. {
  108. using namespace zmq;
  109. std::vector<const_buffer> parts;
  110. parts.emplace_back("Hello", 5);
  111. parts.emplace_back("World",5);
  112. auto msg = encode(parts);
  113. CHECK(msg.size() == 1 + 5 + 1 + 5 );
  114. CHECK(msg.data<unsigned char>()[0] == 5);
  115. CHECK(msg.data<unsigned char>()[1] == 'H');
  116. CHECK(msg.data<unsigned char>()[6] == 5);
  117. CHECK(msg.data<unsigned char>()[7] == 'W');
  118. std::vector<message_t> parts2;
  119. decode(msg, std::back_inserter(parts2));
  120. CHECK(parts.size() == 2);
  121. CHECK(parts[0].size() == 5);
  122. CHECK(parts[1].size() == 5);
  123. }
  124. TEST_CASE("multipart codec free function with vector of mutable_buffer", "[codec_multipart]")
  125. {
  126. using namespace zmq;
  127. std::vector<mutable_buffer> parts;
  128. char hello[6] = "Hello";
  129. parts.emplace_back(hello, 5);
  130. char world[6] = "World";
  131. parts.emplace_back(world,5);
  132. auto msg = encode(parts);
  133. CHECK(msg.size() == 1 + 5 + 1 + 5 );
  134. CHECK(msg.data<unsigned char>()[0] == 5);
  135. CHECK(msg.data<unsigned char>()[1] == 'H');
  136. CHECK(msg.data<unsigned char>()[6] == 5);
  137. CHECK(msg.data<unsigned char>()[7] == 'W');
  138. std::vector<message_t> parts2;
  139. decode(msg, std::back_inserter(parts2));
  140. CHECK(parts.size() == 2);
  141. CHECK(parts[0].size() == 5);
  142. CHECK(parts[1].size() == 5);
  143. }
  144. TEST_CASE("multipart codec free function with multipart_t", "[codec_multipart]")
  145. {
  146. using namespace zmq;
  147. multipart_t mmsg;
  148. mmsg.addstr("Hello");
  149. mmsg.addstr("World");
  150. auto msg = encode(mmsg);
  151. CHECK(msg.size() == 1 + 5 + 1 + 5);
  152. CHECK(msg.data<unsigned char>()[0] == 5);
  153. CHECK(msg.data<unsigned char>()[1] == 'H');
  154. CHECK(msg.data<unsigned char>()[6] == 5);
  155. CHECK(msg.data<unsigned char>()[7] == 'W');
  156. multipart_t mmsg2;
  157. decode(msg, std::back_inserter(mmsg2));
  158. CHECK(mmsg2.size() == 2);
  159. CHECK(mmsg2[0].size() == 5);
  160. CHECK(mmsg2[1].size() == 5);
  161. }
  162. TEST_CASE("multipart codec static method decode to multipart_t", "[codec_multipart]")
  163. {
  164. using namespace zmq;
  165. multipart_t mmsg;
  166. mmsg.addstr("Hello");
  167. mmsg.addstr("World");
  168. auto msg = encode(mmsg);
  169. auto mmsg2 = multipart_t::decode(msg);
  170. CHECK(mmsg2.size() == 2);
  171. CHECK(mmsg2[0].size() == 5);
  172. CHECK(mmsg2[1].size() == 5);
  173. }
  174. #endif