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.

serialize_tests.cpp 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (c) 2012-2013 The Bitcoin Core developers
  2. // Distributed under the MIT software license, see the accompanying
  3. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  4. #include "serialize.h"
  5. #include "streams.h"
  6. #include "hash.h"
  7. #include "test/test_bitcoin.h"
  8. #include <stdint.h>
  9. #include <boost/test/unit_test.hpp>
  10. using namespace std;
  11. BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup)
  12. BOOST_AUTO_TEST_CASE(sizes)
  13. {
  14. BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(char(0), 0));
  15. BOOST_CHECK_EQUAL(sizeof(int8_t), GetSerializeSize(int8_t(0), 0));
  16. BOOST_CHECK_EQUAL(sizeof(uint8_t), GetSerializeSize(uint8_t(0), 0));
  17. BOOST_CHECK_EQUAL(sizeof(int16_t), GetSerializeSize(int16_t(0), 0));
  18. BOOST_CHECK_EQUAL(sizeof(uint16_t), GetSerializeSize(uint16_t(0), 0));
  19. BOOST_CHECK_EQUAL(sizeof(int32_t), GetSerializeSize(int32_t(0), 0));
  20. BOOST_CHECK_EQUAL(sizeof(uint32_t), GetSerializeSize(uint32_t(0), 0));
  21. BOOST_CHECK_EQUAL(sizeof(int64_t), GetSerializeSize(int64_t(0), 0));
  22. BOOST_CHECK_EQUAL(sizeof(uint64_t), GetSerializeSize(uint64_t(0), 0));
  23. BOOST_CHECK_EQUAL(sizeof(float), GetSerializeSize(float(0), 0));
  24. BOOST_CHECK_EQUAL(sizeof(double), GetSerializeSize(double(0), 0));
  25. // Bool is serialized as char
  26. BOOST_CHECK_EQUAL(sizeof(char), GetSerializeSize(bool(0), 0));
  27. // Sanity-check GetSerializeSize and c++ type matching
  28. BOOST_CHECK_EQUAL(GetSerializeSize(char(0), 0), 1);
  29. BOOST_CHECK_EQUAL(GetSerializeSize(int8_t(0), 0), 1);
  30. BOOST_CHECK_EQUAL(GetSerializeSize(uint8_t(0), 0), 1);
  31. BOOST_CHECK_EQUAL(GetSerializeSize(int16_t(0), 0), 2);
  32. BOOST_CHECK_EQUAL(GetSerializeSize(uint16_t(0), 0), 2);
  33. BOOST_CHECK_EQUAL(GetSerializeSize(int32_t(0), 0), 4);
  34. BOOST_CHECK_EQUAL(GetSerializeSize(uint32_t(0), 0), 4);
  35. BOOST_CHECK_EQUAL(GetSerializeSize(int64_t(0), 0), 8);
  36. BOOST_CHECK_EQUAL(GetSerializeSize(uint64_t(0), 0), 8);
  37. BOOST_CHECK_EQUAL(GetSerializeSize(float(0), 0), 4);
  38. BOOST_CHECK_EQUAL(GetSerializeSize(double(0), 0), 8);
  39. BOOST_CHECK_EQUAL(GetSerializeSize(bool(0), 0), 1);
  40. }
  41. BOOST_AUTO_TEST_CASE(floats_conversion)
  42. {
  43. // Choose values that map unambigiously to binary floating point to avoid
  44. // rounding issues at the compiler side.
  45. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x00000000), 0.0F);
  46. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f000000), 0.5F);
  47. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x3f800000), 1.0F);
  48. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40000000), 2.0F);
  49. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x40800000), 4.0F);
  50. BOOST_CHECK_EQUAL(ser_uint32_to_float(0x44444444), 785.066650390625F);
  51. BOOST_CHECK_EQUAL(ser_float_to_uint32(0.0F), 0x00000000);
  52. BOOST_CHECK_EQUAL(ser_float_to_uint32(0.5F), 0x3f000000);
  53. BOOST_CHECK_EQUAL(ser_float_to_uint32(1.0F), 0x3f800000);
  54. BOOST_CHECK_EQUAL(ser_float_to_uint32(2.0F), 0x40000000);
  55. BOOST_CHECK_EQUAL(ser_float_to_uint32(4.0F), 0x40800000);
  56. BOOST_CHECK_EQUAL(ser_float_to_uint32(785.066650390625F), 0x44444444);
  57. }
  58. BOOST_AUTO_TEST_CASE(doubles_conversion)
  59. {
  60. // Choose values that map unambigiously to binary floating point to avoid
  61. // rounding issues at the compiler side.
  62. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x0000000000000000ULL), 0.0);
  63. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3fe0000000000000ULL), 0.5);
  64. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x3ff0000000000000ULL), 1.0);
  65. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4000000000000000ULL), 2.0);
  66. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4010000000000000ULL), 4.0);
  67. BOOST_CHECK_EQUAL(ser_uint64_to_double(0x4088888880000000ULL), 785.066650390625);
  68. BOOST_CHECK_EQUAL(ser_double_to_uint64(0.0), 0x0000000000000000ULL);
  69. BOOST_CHECK_EQUAL(ser_double_to_uint64(0.5), 0x3fe0000000000000ULL);
  70. BOOST_CHECK_EQUAL(ser_double_to_uint64(1.0), 0x3ff0000000000000ULL);
  71. BOOST_CHECK_EQUAL(ser_double_to_uint64(2.0), 0x4000000000000000ULL);
  72. BOOST_CHECK_EQUAL(ser_double_to_uint64(4.0), 0x4010000000000000ULL);
  73. BOOST_CHECK_EQUAL(ser_double_to_uint64(785.066650390625), 0x4088888880000000ULL);
  74. }
  75. /*
  76. Python code to generate the below hashes:
  77. def reversed_hex(x):
  78. return binascii.hexlify(''.join(reversed(x)))
  79. def dsha256(x):
  80. return hashlib.sha256(hashlib.sha256(x).digest()).digest()
  81. reversed_hex(dsha256(''.join(struct.pack('<f', x) for x in range(0,1000)))) == '8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c'
  82. reversed_hex(dsha256(''.join(struct.pack('<d', x) for x in range(0,1000)))) == '43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96'
  83. */
  84. BOOST_AUTO_TEST_CASE(floats)
  85. {
  86. CDataStream ss(SER_DISK, 0);
  87. // encode
  88. for (int i = 0; i < 1000; i++) {
  89. ss << float(i);
  90. }
  91. BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("8e8b4cf3e4df8b332057e3e23af42ebc663b61e0495d5e7e32d85099d7f3fe0c"));
  92. // decode
  93. for (int i = 0; i < 1000; i++) {
  94. float j;
  95. ss >> j;
  96. BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
  97. }
  98. }
  99. BOOST_AUTO_TEST_CASE(doubles)
  100. {
  101. CDataStream ss(SER_DISK, 0);
  102. // encode
  103. for (int i = 0; i < 1000; i++) {
  104. ss << double(i);
  105. }
  106. BOOST_CHECK(Hash(ss.begin(), ss.end()) == uint256S("43d0c82591953c4eafe114590d392676a01585d25b25d433557f0d7878b23f96"));
  107. // decode
  108. for (int i = 0; i < 1000; i++) {
  109. double j;
  110. ss >> j;
  111. BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
  112. }
  113. }
  114. BOOST_AUTO_TEST_CASE(varints)
  115. {
  116. // encode
  117. CDataStream ss(SER_DISK, 0);
  118. CDataStream::size_type size = 0;
  119. for (int i = 0; i < 100000; i++) {
  120. ss << VARINT(i);
  121. size += ::GetSerializeSize(VARINT(i), 0, 0);
  122. BOOST_CHECK(size == ss.size());
  123. }
  124. for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
  125. ss << VARINT(i);
  126. size += ::GetSerializeSize(VARINT(i), 0, 0);
  127. BOOST_CHECK(size == ss.size());
  128. }
  129. // decode
  130. for (int i = 0; i < 100000; i++) {
  131. int j = -1;
  132. ss >> VARINT(j);
  133. BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
  134. }
  135. for (uint64_t i = 0; i < 100000000000ULL; i += 999999937) {
  136. uint64_t j = -1;
  137. ss >> VARINT(j);
  138. BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
  139. }
  140. }
  141. BOOST_AUTO_TEST_CASE(compactsize)
  142. {
  143. CDataStream ss(SER_DISK, 0);
  144. vector<char>::size_type i, j;
  145. for (i = 1; i <= MAX_SIZE; i *= 2)
  146. {
  147. WriteCompactSize(ss, i-1);
  148. WriteCompactSize(ss, i);
  149. }
  150. for (i = 1; i <= MAX_SIZE; i *= 2)
  151. {
  152. j = ReadCompactSize(ss);
  153. BOOST_CHECK_MESSAGE((i-1) == j, "decoded:" << j << " expected:" << (i-1));
  154. j = ReadCompactSize(ss);
  155. BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
  156. }
  157. }
  158. static bool isCanonicalException(const std::ios_base::failure& ex)
  159. {
  160. std::ios_base::failure expectedException("non-canonical ReadCompactSize()");
  161. // The string returned by what() can be different for different platforms.
  162. // Instead of directly comparing the ex.what() with an expected string,
  163. // create an instance of exception to see if ex.what() matches
  164. // the expected explanatory string returned by the exception instance.
  165. return strcmp(expectedException.what(), ex.what()) == 0;
  166. }
  167. BOOST_AUTO_TEST_CASE(noncanonical)
  168. {
  169. // Write some non-canonical CompactSize encodings, and
  170. // make sure an exception is thrown when read back.
  171. CDataStream ss(SER_DISK, 0);
  172. vector<char>::size_type n;
  173. // zero encoded with three bytes:
  174. ss.write("\xfd\x00\x00", 3);
  175. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  176. // 0xfc encoded with three bytes:
  177. ss.write("\xfd\xfc\x00", 3);
  178. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  179. // 0xfd encoded with three bytes is OK:
  180. ss.write("\xfd\xfd\x00", 3);
  181. n = ReadCompactSize(ss);
  182. BOOST_CHECK(n == 0xfd);
  183. // zero encoded with five bytes:
  184. ss.write("\xfe\x00\x00\x00\x00", 5);
  185. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  186. // 0xffff encoded with five bytes:
  187. ss.write("\xfe\xff\xff\x00\x00", 5);
  188. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  189. // zero encoded with nine bytes:
  190. ss.write("\xff\x00\x00\x00\x00\x00\x00\x00\x00", 9);
  191. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  192. // 0x01ffffff encoded with nine bytes:
  193. ss.write("\xff\xff\xff\xff\x01\x00\x00\x00\x00", 9);
  194. BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
  195. }
  196. BOOST_AUTO_TEST_CASE(insert_delete)
  197. {
  198. // Test inserting/deleting bytes.
  199. CDataStream ss(SER_DISK, 0);
  200. BOOST_CHECK_EQUAL(ss.size(), 0);
  201. ss.write("\x00\x01\x02\xff", 4);
  202. BOOST_CHECK_EQUAL(ss.size(), 4);
  203. char c = (char)11;
  204. // Inserting at beginning/end/middle:
  205. ss.insert(ss.begin(), c);
  206. BOOST_CHECK_EQUAL(ss.size(), 5);
  207. BOOST_CHECK_EQUAL(ss[0], c);
  208. BOOST_CHECK_EQUAL(ss[1], 0);
  209. ss.insert(ss.end(), c);
  210. BOOST_CHECK_EQUAL(ss.size(), 6);
  211. BOOST_CHECK_EQUAL(ss[4], (char)0xff);
  212. BOOST_CHECK_EQUAL(ss[5], c);
  213. ss.insert(ss.begin()+2, c);
  214. BOOST_CHECK_EQUAL(ss.size(), 7);
  215. BOOST_CHECK_EQUAL(ss[2], c);
  216. // Delete at beginning/end/middle
  217. ss.erase(ss.begin());
  218. BOOST_CHECK_EQUAL(ss.size(), 6);
  219. BOOST_CHECK_EQUAL(ss[0], 0);
  220. ss.erase(ss.begin()+ss.size()-1);
  221. BOOST_CHECK_EQUAL(ss.size(), 5);
  222. BOOST_CHECK_EQUAL(ss[4], (char)0xff);
  223. ss.erase(ss.begin()+1);
  224. BOOST_CHECK_EQUAL(ss.size(), 4);
  225. BOOST_CHECK_EQUAL(ss[0], 0);
  226. BOOST_CHECK_EQUAL(ss[1], 1);
  227. BOOST_CHECK_EQUAL(ss[2], 2);
  228. BOOST_CHECK_EQUAL(ss[3], (char)0xff);
  229. // Make sure GetAndClear does the right thing:
  230. CSerializeData d;
  231. ss.GetAndClear(d);
  232. BOOST_CHECK_EQUAL(ss.size(), 0);
  233. }
  234. BOOST_AUTO_TEST_SUITE_END()