diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bf7a01d..6151fad 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -54,6 +54,7 @@ add_executable( all_tests all_tests.cpp thread/thread_tests.cpp bloom_test.cpp real128_test.cpp + serialization_test.cpp time_test.cpp utf8_test.cpp ) diff --git a/tests/serialization_test.cpp b/tests/serialization_test.cpp new file mode 100644 index 0000000..1e35f86 --- /dev/null +++ b/tests/serialization_test.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include +#include + +namespace fc { namespace test { + + struct item; + inline bool operator < ( const item& a, const item& b ); + inline bool operator == ( const item& a, const item& b ); + + struct item_wrapper + { + item_wrapper() {} + item_wrapper(item&& it) { v.reserve(1); v.insert( it ); } + boost::container::flat_set v; + }; + inline bool operator < ( const item_wrapper& a, const item_wrapper& b ); + inline bool operator == ( const item_wrapper& a, const item_wrapper& b ); + + struct item + { + item(int32_t lvl = 0) : level(lvl) {} + item(item_wrapper&& wp, int32_t lvl = 0) : level(lvl), w(wp) {} + int32_t level; + item_wrapper w; + }; + + inline bool operator == ( const item& a, const item& b ) + { return ( std::tie( a.level, a.w ) == std::tie( b.level, b.w ) ); } + + inline bool operator < ( const item& a, const item& b ) + { return ( std::tie( a.level, a.w ) < std::tie( b.level, b.w ) ); } + + inline bool operator == ( const item_wrapper& a, const item_wrapper& b ) + { return ( std::tie( a.v ) == std::tie( b.v ) ); } + + inline bool operator < ( const item_wrapper& a, const item_wrapper& b ) + { return ( std::tie( a.v ) < std::tie( b.v ) ); } + +} } + +FC_REFLECT( fc::test::item_wrapper, (v) ); +FC_REFLECT( fc::test::item, (level)(w) ); + +BOOST_AUTO_TEST_SUITE(fc_serialization) + +BOOST_AUTO_TEST_CASE( nested_objects_test ) +{ try { + + auto create_nested_object = []( uint32_t level ) + { + ilog( "Creating nested object with ${lv} level(s)", ("lv",level) ); + fc::test::item nested; + for( uint32_t i = 1; i <= level; i++ ) + { + if( i % 100 == 0 ) + ilog( "Creating level ${lv}", ("lv",i) ); + fc::test::item_wrapper wp( std::move(nested) ); + nested = fc::test::item( std::move(wp), i ); + } + return nested; + }; + + // 100 levels, should be allowed + { + auto nested = create_nested_object( 100 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + fc::raw::pack( ss, nested ); + + BOOST_TEST_MESSAGE( "About to unpack." ); + fc::test::item unpacked; + fc::raw::unpack( ss, unpacked ); + + BOOST_CHECK( unpacked == nested ); + } + + // 150 levels, by default packing will fail + { + auto nested = create_nested_object( 150 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + BOOST_CHECK_THROW( fc::raw::pack( ss, nested ), fc::assert_exception ); + } + + // 150 levels and allow packing, unpacking will fail + { + auto nested = create_nested_object( 150 ); + + std::stringstream ss; + + BOOST_TEST_MESSAGE( "About to pack." ); + fc::raw::pack( ss, nested, 1500 ); + + BOOST_TEST_MESSAGE( "About to unpack." ); + fc::test::item unpacked; + BOOST_CHECK_THROW( fc::raw::unpack( ss, unpacked ), fc::assert_exception ); + } + +} FC_CAPTURE_LOG_AND_RETHROW ( (0) ) } + +BOOST_AUTO_TEST_SUITE_END()