LCOV - code coverage report
Current view: top level - src/test - serialize_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 140 140 100.0 %
Date: 2015-10-12 22:39:14 Functions: 21 39 53.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11