Changeset View
Changeset View
Standalone View
Standalone View
src/test/serialize_tests.cpp
Show First 20 Lines • Show All 446 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(class_methods) { | ||||
BOOST_CHECK(methodtest3 == methodtest4); | BOOST_CHECK(methodtest3 == methodtest4); | ||||
CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, | CDataStream ss2(SER_DISK, PROTOCOL_VERSION, intval, boolval, stringval, | ||||
charstrval, txval, proofval); | charstrval, txval, proofval); | ||||
ss2 >> methodtest3; | ss2 >> methodtest3; | ||||
BOOST_CHECK(methodtest3 == methodtest4); | BOOST_CHECK(methodtest3 == methodtest4); | ||||
} | } | ||||
namespace { | |||||
struct DifferentialIndexedItem { | |||||
uint32_t index; | |||||
std::string text; | |||||
template <typename Stream> void SerData(Stream &s) { s << text; } | |||||
template <typename Stream> void UnserData(Stream &s) { s >> text; } | |||||
bool operator==(const DifferentialIndexedItem &other) const { | |||||
return index == other.index && text == other.text; | |||||
} | |||||
bool operator!=(const DifferentialIndexedItem &other) const { | |||||
return !(*this == other); | |||||
} | |||||
// Make boost happy | |||||
friend std::ostream &operator<<(std::ostream &os, | |||||
const DifferentialIndexedItem &item) { | |||||
os << "index: " << item.index << ", text: " << item.text; | |||||
return os; | |||||
} | |||||
DifferentialIndexedItem() {} | |||||
DifferentialIndexedItem(uint32_t indexIn) | |||||
: index(indexIn), text(ToString(index)) {} | |||||
}; | |||||
template <typename Formatter, typename T> | |||||
static void checkDifferentialEncodingRoundtrip() { | |||||
Formatter formatter; | |||||
const std::vector<T> indicesIn{0, 1, 2, 5, 10, 20, 50, 100}; | |||||
std::vector<T> indicesOut; | |||||
CDataStream ss(SER_DISK, PROTOCOL_VERSION); | |||||
formatter.Ser(ss, indicesIn); | |||||
formatter.Unser(ss, indicesOut); | |||||
BOOST_CHECK_EQUAL_COLLECTIONS(indicesIn.begin(), indicesIn.end(), | |||||
indicesOut.begin(), indicesOut.end()); | |||||
} | |||||
template <typename Formatter, typename T> | |||||
static void checkDifferentialEncodingOverflow() { | |||||
Formatter formatter; | |||||
{ | |||||
const std::vector<T> indicesIn{1, 0}; | |||||
CDataStream ss(SER_DISK, PROTOCOL_VERSION); | |||||
BOOST_CHECK_EXCEPTION(formatter.Ser(ss, indicesIn), | |||||
std::ios_base::failure, | |||||
HasReason("differential value overflow")); | |||||
} | |||||
} | |||||
} // namespace | |||||
BOOST_AUTO_TEST_CASE(difference_formatter) { | BOOST_AUTO_TEST_CASE(difference_formatter) { | ||||
{ | |||||
// Roundtrip with internals check | |||||
VectorFormatter<DifferenceFormatter> formatter; | VectorFormatter<DifferenceFormatter> formatter; | ||||
{ | |||||
std::vector<uint32_t> indicesIn{0, 1, 2, 5, 10, 20, 50, 100}; | std::vector<uint32_t> indicesIn{0, 1, 2, 5, 10, 20, 50, 100}; | ||||
std::vector<uint32_t> indicesOut; | std::vector<uint32_t> indicesOut; | ||||
CDataStream ss(SER_DISK, PROTOCOL_VERSION); | CDataStream ss(SER_DISK, PROTOCOL_VERSION); | ||||
formatter.Ser(ss, indicesIn); | formatter.Ser(ss, indicesIn); | ||||
// Check the stream is differentially encoded. Don't care about the | // Check the stream is differentially encoded. Don't care about the | ||||
// prefixes and vector length here (assumed to be < 253). | // prefixes and vector length here (assumed to be < 253). | ||||
const std::string streamStr = ss.str(); | const std::string streamStr = ss.str(); | ||||
const std::string differences = | const std::string differences = | ||||
HexStr(streamStr.substr(streamStr.size() - indicesIn.size())); | HexStr(streamStr.substr(streamStr.size() - indicesIn.size())); | ||||
BOOST_CHECK_EQUAL(differences, "0000000204091d31"); | BOOST_CHECK_EQUAL(differences, "0000000204091d31"); | ||||
formatter.Unser(ss, indicesOut); | formatter.Unser(ss, indicesOut); | ||||
BOOST_CHECK_EQUAL_COLLECTIONS(indicesIn.begin(), indicesIn.end(), | BOOST_CHECK_EQUAL_COLLECTIONS(indicesIn.begin(), indicesIn.end(), | ||||
indicesOut.begin(), indicesOut.end()); | indicesOut.begin(), indicesOut.end()); | ||||
} | } | ||||
{ | checkDifferentialEncodingRoundtrip<VectorFormatter<DifferenceFormatter>, | ||||
std::vector<uint32_t> indicesIn{1, 0}; | uint32_t>(); | ||||
checkDifferentialEncodingRoundtrip< | |||||
CDataStream ss(SER_DISK, PROTOCOL_VERSION); | VectorFormatter<DifferentialIndexedItemFormatter>, | ||||
BOOST_CHECK_EXCEPTION(formatter.Ser(ss, indicesIn), | DifferentialIndexedItem>(); | ||||
std::ios_base::failure, | |||||
HasReason("differential value overflow")); | |||||
} | |||||
{ | { | ||||
// Checking 32 bits overflow requires to manually create the serialized | |||||
// stream, so only do it with uint32_t | |||||
std::vector<uint32_t> indicesOut; | std::vector<uint32_t> indicesOut; | ||||
// Compute the number of MAX_SIZE increment we need to cause an overflow | // Compute the number of MAX_SIZE increment we need to cause an overflow | ||||
const uint64_t overflow = | const uint64_t overflow = | ||||
uint64_t(std::numeric_limits<uint32_t>::max()) + 1; | uint64_t(std::numeric_limits<uint32_t>::max()) + 1; | ||||
// Due to differential encoding, a value of MAX_SIZE bumps the index by | // Due to differential encoding, a value of MAX_SIZE bumps the index by | ||||
// MAX_SIZE + 1 | // MAX_SIZE + 1 | ||||
BOOST_CHECK_GE(overflow, MAX_SIZE + 1); | BOOST_CHECK_GE(overflow, MAX_SIZE + 1); | ||||
Show All 12 Lines | checkDifferentialEncodingRoundtrip< | ||||
WriteCompactSize(ss, MAX_SIZE); | WriteCompactSize(ss, MAX_SIZE); | ||||
} | } | ||||
// This will cause an overflow if lastItemDifference >= remainder | // This will cause an overflow if lastItemDifference >= remainder | ||||
WriteCompactSize(ss, lastItemDifference); | WriteCompactSize(ss, lastItemDifference); | ||||
return ss; | return ss; | ||||
}; | }; | ||||
VectorFormatter<DifferenceFormatter> formatter; | |||||
auto noThrowStream = buildStream(remainder - 1); | auto noThrowStream = buildStream(remainder - 1); | ||||
BOOST_CHECK_NO_THROW(formatter.Unser(noThrowStream, indicesOut)); | BOOST_CHECK_NO_THROW(formatter.Unser(noThrowStream, indicesOut)); | ||||
auto overflowStream = buildStream(remainder); | auto overflowStream = buildStream(remainder); | ||||
BOOST_CHECK_EXCEPTION(formatter.Unser(overflowStream, indicesOut), | BOOST_CHECK_EXCEPTION(formatter.Unser(overflowStream, indicesOut), | ||||
std::ios_base::failure, | std::ios_base::failure, | ||||
HasReason("differential value overflow")); | HasReason("differential value overflow")); | ||||
} | } | ||||
checkDifferentialEncodingOverflow<VectorFormatter<DifferenceFormatter>, | |||||
uint32_t>(); | |||||
checkDifferentialEncodingOverflow< | |||||
VectorFormatter<DifferentialIndexedItemFormatter>, | |||||
DifferentialIndexedItem>(); | |||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |