diff --git a/CMakeLists.txt b/CMakeLists.txt index 49cfbfd31..d0d53dbd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.6.2) project (cereal) -option(SKIP_PORTABILITY_TEST "Skip portability tests" OFF) +option(SKIP_PORTABILITY_TEST "Skip portability (32 bit) tests" OFF) if(NOT CMAKE_VERSION VERSION_LESS 3.0) # installing cereal requires INTERFACE lib option(JUST_INSTALL_CEREAL "Don't do anything besides installing the library" OFF) endif() @@ -49,13 +49,15 @@ endif() include_directories(./include) -find_package(Boost COMPONENTS serialization unit_test_framework) +# Boost serialization for performance sandbox +find_package(Boost COMPONENTS serialization) if(Boost_FOUND) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) - enable_testing() - add_subdirectory(unittests) endif(Boost_FOUND) + +enable_testing() +add_subdirectory(unittests) add_subdirectory(sandbox) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index ae221d038..a5a91ae30 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -1,6 +1,6 @@ file(GLOB TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) -# A semi-colon separated list of test sources that should not be automatically built with boost unit test +# A semi-colon separated list of test sources that should not be automatically built with doctest set(SPECIAL_TESTS "portability_test.cpp") # Build the portability test only if we are on a 64-bit machine (void* is 8 bytes) @@ -15,7 +15,7 @@ if((${CMAKE_SIZEOF_VOID_P} EQUAL 8) AND (NOT SKIP_PORTABILITY_TEST)) endif() -# Build all of the non-special tests and link against the boost unit test framework +# Build all of the non-special tests foreach(TEST_SOURCE ${TESTS}) string(REPLACE ".cpp" "" TEST_TARGET "${TEST_SOURCE}") @@ -27,21 +27,16 @@ foreach(TEST_SOURCE ${TESTS}) if(IS_SPECIAL_TEST EQUAL -1) add_executable(${TEST_TARGET} ${TEST_SOURCE}) - set_target_properties(${TEST_TARGET} PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MODULE=${TEST_TARGET}") - target_link_libraries(${TEST_TARGET} ${Boost_LIBRARIES}) target_link_libraries(${TEST_TARGET} ${CEREAL_THREAD_LIBS}) add_test("${TEST_TARGET}" "${TEST_TARGET}") - # TODO: This won't work right now, because we would need a 32-bit boost - ## If we are on a 64-bit machine, create an extra 32-bit version of the test - #if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) - # add_executable(${TEST_TARGET}_32 ${TEST_SOURCE}) - # set_target_properties(${TEST_TARGET}_32 PROPERTIES - # COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MODULE=${TEST_TARGET}" - # COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") - # target_link_libraries(${TEST_TARGET}_32 ${Boost_LIBRARIES}) - # add_test("${TEST_TARGET}_32" "${TEST_TARGET}_32") - #endif() + # If we are on a 64-bit machine, create an extra 32-bit version of the test if portability testing is enabled + if((${CMAKE_SIZEOF_VOID_P} EQUAL 8) AND (NOT SKIP_PORTABILITY_TEST)) + add_executable(${TEST_TARGET}_32 ${TEST_SOURCE}) + set_target_properties(${TEST_TARGET}_32 PROPERTIES + COMPILE_FLAGS "-m32" LINK_FLAGS "-m32") + add_test("${TEST_TARGET}_32" "${TEST_TARGET}_32") + endif() endif() @@ -69,11 +64,9 @@ foreach(TEST_SOURCE ${TESTS}) add_dependencies(coverage ${COVERAGE_TARGET}) add_executable(${COVERAGE_TARGET} EXCLUDE_FROM_ALL ${TEST_SOURCE}) - set_target_properties(${COVERAGE_TARGET} PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK;BOOST_TEST_MODULE=${COVERAGE_TARGET}") set_target_properties(${COVERAGE_TARGET} PROPERTIES COMPILE_FLAGS "-coverage") set_target_properties(${COVERAGE_TARGET} PROPERTIES LINK_FLAGS "-coverage") set_target_properties(${COVERAGE_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/coverage") - target_link_libraries(${COVERAGE_TARGET} ${Boost_LIBRARIES}) target_link_libraries(${COVERAGE_TARGET} ${CEREAL_THREAD_LIBS}) endif() endforeach() diff --git a/unittests/array.cpp b/unittests/array.cpp index 2ae3fcc80..5cd1c392a 100644 --- a/unittests/array.cpp +++ b/unittests/array.cpp @@ -24,90 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "array.hpp" -template -void test_array() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::array o_podarray; - for(auto & elem : o_podarray) - elem = random_value(gen); - - std::array o_iserarray; - for(auto & elem : o_iserarray) - elem = StructInternalSerialize( random_value(gen), random_value(gen) ); - - std::array o_isplarray; - for(auto & elem : o_isplarray) - elem = StructInternalSplit( random_value(gen), random_value(gen) ); - - std::array o_eserarray; - for(auto & elem : o_eserarray) - elem = StructExternalSerialize( random_value(gen), random_value(gen) ); - - std::array o_esplarray; - for(auto & elem : o_esplarray) - elem = StructExternalSplit( random_value(gen), random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podarray); - oar(o_iserarray); - oar(o_isplarray); - oar(o_eserarray); - oar(o_esplarray); - } - - std::array i_podarray; - std::array i_iserarray; - std::array i_isplarray; - std::array i_eserarray; - std::array i_esplarray; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podarray); - iar(i_iserarray); - iar(i_isplarray); - iar(i_eserarray); - iar(i_esplarray); - } - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podarray.begin(), i_podarray.end(), o_podarray.begin(), o_podarray.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserarray.begin(), i_iserarray.end(), o_iserarray.begin(), o_iserarray.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplarray.begin(), i_isplarray.end(), o_isplarray.begin(), o_isplarray.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserarray.begin(), i_eserarray.end(), o_eserarray.begin(), o_eserarray.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplarray.begin(), i_esplarray.end(), o_esplarray.begin(), o_esplarray.end()); - } -} +TEST_SUITE("array"); -BOOST_AUTO_TEST_CASE( binary_array ) +TEST_CASE("binary_array") { test_array(); } -BOOST_AUTO_TEST_CASE( portable_binary_array ) +TEST_CASE("portable_binary_array") { test_array(); } -BOOST_AUTO_TEST_CASE( xml_array ) +TEST_CASE("xml_array") { test_array(); } -BOOST_AUTO_TEST_CASE( json_array ) +TEST_CASE("json_array") { test_array(); } +TEST_SUITE_END(); diff --git a/unittests/array.hpp b/unittests/array.hpp new file mode 100644 index 000000000..766225b21 --- /dev/null +++ b/unittests/array.hpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_ARRAY_H_ +#define CEREAL_TEST_ARRAY_H_ +#include "common.hpp" + +template inline +void test_array() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::array o_podarray; + for(auto & elem : o_podarray) + elem = random_value(gen); + + std::array o_iserarray; + for(auto & elem : o_iserarray) + elem = StructInternalSerialize( random_value(gen), random_value(gen) ); + + std::array o_isplarray; + for(auto & elem : o_isplarray) + elem = StructInternalSplit( random_value(gen), random_value(gen) ); + + std::array o_eserarray; + for(auto & elem : o_eserarray) + elem = StructExternalSerialize( random_value(gen), random_value(gen) ); + + std::array o_esplarray; + for(auto & elem : o_esplarray) + elem = StructExternalSplit( random_value(gen), random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podarray); + oar(o_iserarray); + oar(o_isplarray); + oar(o_eserarray); + oar(o_esplarray); + } + + std::array i_podarray; + std::array i_iserarray; + std::array i_isplarray; + std::array i_eserarray; + std::array i_esplarray; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podarray); + iar(i_iserarray); + iar(i_isplarray); + iar(i_eserarray); + iar(i_esplarray); + } + + check_collection( i_podarray, o_podarray ); + check_collection( i_iserarray, o_iserarray ); + check_collection( i_isplarray, o_isplarray ); + check_collection( i_eserarray, o_eserarray ); + check_collection( i_esplarray, o_esplarray ); + } +} + +#endif // CEREAL_TEST_ARRAY_H_ diff --git a/unittests/basic_string.cpp b/unittests/basic_string.cpp index 65cfffb0f..245530e19 100644 --- a/unittests/basic_string.cpp +++ b/unittests/basic_string.cpp @@ -24,109 +24,27 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "basic_string.hpp" -template -void test_string_basic() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(size_t i=0; i<100; ++i) - { - std::basic_string o_string = random_basic_string(gen); - std::basic_string o_string2 = ""; - std::basic_string o_string3; - - std::ostringstream os; - { - OArchive oar(os); - oar(o_string); - oar(o_string2); - oar(o_string3); - } - - std::basic_string i_string; - std::basic_string i_string2; - std::basic_string i_string3; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_string); - iar(i_string2); - iar(i_string3); - } - - BOOST_CHECK_EQUAL(i_string, o_string); - BOOST_CHECK_EQUAL(i_string2, o_string2); - BOOST_CHECK_EQUAL(i_string3, o_string3); - } -} +TEST_SUITE("basic_string"); -template -void test_string_all() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(size_t i=0; i<100; ++i) - { - std::basic_string o_string = random_basic_string(gen); - std::basic_string o_wstring = random_basic_string(gen); - std::basic_string o_u16string = random_basic_string(gen); - std::basic_string o_u32string = random_basic_string(gen); - - std::ostringstream os; - { - OArchive oar(os); - oar(o_string); - oar(o_wstring); - oar(o_u16string); - oar(o_u32string); - } - - std::basic_string i_string; - std::basic_string i_wstring; - std::basic_string i_u16string; - std::basic_string i_u32string; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_string); - iar(i_wstring); - iar(i_u16string); - iar(i_u32string); - } - - BOOST_CHECK_EQUAL(i_string, o_string); - BOOST_CHECK_EQUAL_COLLECTIONS(i_wstring.begin(), i_wstring.end(), o_wstring.begin(), o_wstring.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_u16string.begin(), i_u16string.end(), o_u16string.begin(), o_u16string.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_u32string.begin(), i_u32string.end(), o_u32string.begin(), o_u32string.end()); - } -} - -BOOST_AUTO_TEST_CASE( binary_string ) +TEST_CASE("binary_string") { test_string_all(); } -BOOST_AUTO_TEST_CASE( portable_binary_string ) +TEST_CASE("portable_binary_string") { test_string_all(); } -BOOST_AUTO_TEST_CASE( xml_string_basic ) +TEST_CASE("xml_string_basic") { test_string_basic(); } -BOOST_AUTO_TEST_CASE( json_string_basic ) +TEST_CASE("json_string_basic") { test_string_basic(); } @@ -148,23 +66,10 @@ void test_ws_in_out(Out const & o_value_with_ws) iar(i_value_with_ws); } - BOOST_CHECK_EQUAL(i_value_with_ws, o_value_with_ws); + CHECK(i_value_with_ws == o_value_with_ws); } -namespace boost -{ - void save( cereal::XMLOutputArchive & ar, boost::string_ref const & str ) - { - ar.saveValue( str ); - } - - bool operator==( std::string const & s1, boost::string_ref const & s2 ) - { - return s1 == std::string(s2.data(), s2.length()); - } -} - -BOOST_AUTO_TEST_CASE( xml_string_issue109 ) +TEST_CASE("xml_string_issue109") { char strings[][20] = { "some text", @@ -185,16 +90,9 @@ BOOST_AUTO_TEST_CASE( xml_string_issue109 ) test_ws_in_out( o_string ); } - - for( size_t i=0; i<( sizeof( strings ) / sizeof( strings[0] ) ); ++i ) - { - boost::string_ref o_string = strings[i]; - - test_ws_in_out( o_string ); - } } -BOOST_AUTO_TEST_CASE( xml_char_issue109 ) +TEST_CASE("xml_char_issue109") { uint8_t chars[] = { ' ', @@ -251,11 +149,11 @@ void test_ws_in_out_array(Out const (&o_a_value_with_ws)[Nb]) for (size_t uiIndex = 0; uiIndex < Nb; ++uiIndex) { - BOOST_CHECK_EQUAL(i_a_value_with_ws[uiIndex], o_a_value_with_ws[uiIndex]); + CHECK(i_a_value_with_ws[uiIndex] == o_a_value_with_ws[uiIndex]); } } -BOOST_AUTO_TEST_CASE(xml_string_issue_consecutive_calls) +TEST_CASE("xml_string_issue_consecutive_calls") { std::string strings[] = { "some text", @@ -269,3 +167,5 @@ BOOST_AUTO_TEST_CASE(xml_string_issue_consecutive_calls) test_ws_in_out_array(strings); } + +TEST_SUITE_END(); diff --git a/unittests/basic_string.hpp b/unittests/basic_string.hpp new file mode 100644 index 000000000..5ee37aac1 --- /dev/null +++ b/unittests/basic_string.hpp @@ -0,0 +1,114 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_BASIC_STRING_H_ +#define CEREAL_TEST_BASIC_STRING_H_ +#include "common.hpp" + +template inline +void test_string_basic() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(size_t i=0; i<100; ++i) + { + std::basic_string o_string = random_basic_string(gen); + std::basic_string o_string2 = ""; + std::basic_string o_string3; + + std::ostringstream os; + { + OArchive oar(os); + oar(o_string); + oar(o_string2); + oar(o_string3); + } + + std::basic_string i_string; + std::basic_string i_string2; + std::basic_string i_string3; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_string); + iar(i_string2); + iar(i_string3); + } + + CHECK_EQ(i_string, o_string); + CHECK_EQ(i_string2, o_string2); + CHECK_EQ(i_string3, o_string3); + } +} + +template inline +void test_string_all() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(size_t i=0; i<100; ++i) + { + std::basic_string o_string = random_basic_string(gen); + std::basic_string o_wstring = random_basic_string(gen); + std::basic_string o_u16string = random_basic_string(gen); + std::basic_string o_u32string = random_basic_string(gen); + + std::ostringstream os; + { + OArchive oar(os); + oar(o_string); + oar(o_wstring); + oar(o_u16string); + oar(o_u32string); + } + + std::basic_string i_string; + std::basic_string i_wstring; + std::basic_string i_u16string; + std::basic_string i_u32string; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_string); + iar(i_wstring); + iar(i_u16string); + iar(i_u32string); + } + + CHECK_EQ(i_string, o_string); + check_collection( i_wstring, o_wstring ); + check_collection( i_u16string, o_u16string ); + check_collection( i_u32string, o_u32string ); + } +} + +#endif // CEREAL_TEST_BASIC_STRING_H_ diff --git a/unittests/bitset.cpp b/unittests/bitset.cpp index c731126aa..912c22c99 100644 --- a/unittests/bitset.cpp +++ b/unittests/bitset.cpp @@ -24,83 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "bitset.hpp" -template -void test_bitset() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rng32 = [&](){ return random_binary_string<32>( gen ); }; - auto rng65 = [&](){ return random_binary_string<65>( gen ); }; - auto rng256 = [&](){ return random_binary_string<256>( gen ); }; - auto rng512 = [&](){ return random_binary_string<512>( gen ); }; - - for(int ii=0; ii<100; ++ii) - { - std::bitset<32> o_bit32( rng32() ); - std::bitset<65> o_bit65( rng65() ); - std::bitset<256> o_bit256( rng256() ); - std::bitset<512> o_bit512( rng512() ); - std::bitset<32> o_bit32_low( 0 ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_bit32); - oar(o_bit65); - oar(o_bit256); - oar(o_bit512); - oar(o_bit32_low); - } - - std::bitset<32> i_bit32; - std::bitset<65> i_bit65; - std::bitset<256> i_bit256; - std::bitset<512> i_bit512; - std::bitset<32> i_bit32_low( 0xffffffff ); +TEST_SUITE("bitset"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_bit32); - iar(i_bit65); - iar(i_bit256); - iar(i_bit512); - iar(i_bit32_low); - } - - BOOST_CHECK_EQUAL( o_bit32, i_bit32 ); - BOOST_CHECK_EQUAL( o_bit65, i_bit65 ); - BOOST_CHECK_EQUAL( o_bit256, i_bit256 ); - BOOST_CHECK_EQUAL( o_bit512, i_bit512 ); - - BOOST_CHECK_EQUAL( o_bit32_low, i_bit32_low ); - } -} - -BOOST_AUTO_TEST_CASE( binary_bitset ) +TEST_CASE("binary_bitset") { test_bitset(); } -BOOST_AUTO_TEST_CASE( portable_binary_bitset ) +TEST_CASE("portable_binary_bitset") { test_bitset(); } -BOOST_AUTO_TEST_CASE( xml_bitset ) +TEST_CASE("xml_bitset") { test_bitset(); } -BOOST_AUTO_TEST_CASE( json_bitset ) +TEST_CASE("json_bitset") { test_bitset(); } - +TEST_SUITE_END(); diff --git a/unittests/bitset.hpp b/unittests/bitset.hpp new file mode 100644 index 000000000..09f597cf3 --- /dev/null +++ b/unittests/bitset.hpp @@ -0,0 +1,87 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_BITSET_H_ +#define CEREAL_TEST_BITSET_H_ +#include "common.hpp" + +template inline +void test_bitset() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rng32 = [&](){ return random_binary_string<32>( gen ); }; + auto rng65 = [&](){ return random_binary_string<65>( gen ); }; + auto rng256 = [&](){ return random_binary_string<256>( gen ); }; + auto rng512 = [&](){ return random_binary_string<512>( gen ); }; + + for(int ii=0; ii<100; ++ii) + { + std::bitset<32> o_bit32( rng32() ); + std::bitset<65> o_bit65( rng65() ); + std::bitset<256> o_bit256( rng256() ); + std::bitset<512> o_bit512( rng512() ); + std::bitset<32> o_bit32_low( 0 ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_bit32); + oar(o_bit65); + oar(o_bit256); + oar(o_bit512); + oar(o_bit32_low); + } + + std::bitset<32> i_bit32; + std::bitset<65> i_bit65; + std::bitset<256> i_bit256; + std::bitset<512> i_bit512; + std::bitset<32> i_bit32_low( 0xffffffff ); + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_bit32); + iar(i_bit65); + iar(i_bit256); + iar(i_bit512); + iar(i_bit32_low); + } + + CHECK_EQ( o_bit32, i_bit32 ); + CHECK_EQ( o_bit65, i_bit65 ); + CHECK_EQ( o_bit256, i_bit256 ); + CHECK_EQ( o_bit512, i_bit512 ); + + CHECK_EQ( o_bit32_low, i_bit32_low ); + } +} + +#endif // CEREAL_TEST_BITSET_H_ diff --git a/unittests/boost_variant.cpp b/unittests/boost_variant.cpp index 3bb9d75f2..7e073b8f4 100644 --- a/unittests/boost_variant.cpp +++ b/unittests/boost_variant.cpp @@ -24,64 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "boost_variant.hpp" -template -void test_boost_variant() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - boost::variant o_bv1 = random_value(gen); - boost::variant o_bv2 = random_value(gen); - boost::variant o_bv3 = random_basic_string(gen); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_bv1); - oar(o_bv2); - oar(o_bv3); - } - - decltype(o_bv1) i_bv1; - decltype(o_bv2) i_bv2; - decltype(o_bv3) i_bv3; +TEST_SUITE("boost_variant"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_bv1); - iar(i_bv2); - iar(i_bv3); - } - - BOOST_CHECK_EQUAL( boost::get(i_bv1), boost::get(o_bv1) ); - BOOST_CHECK_CLOSE( boost::get(i_bv2), boost::get(o_bv2), 1e-5 ); - BOOST_CHECK_EQUAL( boost::get(i_bv3), boost::get(o_bv3) ); -} - -BOOST_AUTO_TEST_CASE( binary_boost_variant ) +TEST_CASE("binary_boost_variant") { test_boost_variant(); } -BOOST_AUTO_TEST_CASE( portable_binary_boost_variant ) +TEST_CASE("portable_binary_boost_variant") { test_boost_variant(); } -BOOST_AUTO_TEST_CASE( xml_boost_variant ) +TEST_CASE("xml_boost_variant") { test_boost_variant(); } -BOOST_AUTO_TEST_CASE( json_boost_variant ) +TEST_CASE("json_boost_variant") { test_boost_variant(); } - +TEST_SUITE_END(); diff --git a/unittests/boost_variant.hpp b/unittests/boost_variant.hpp new file mode 100644 index 000000000..bedb6a89a --- /dev/null +++ b/unittests/boost_variant.hpp @@ -0,0 +1,70 @@ +/* + Copyright (c) 2015, Kyle Fleming + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_BOOST_VARIANT_H_ +#define CEREAL_TEST_BOOST_VARIANT_H_ + +#include "common.hpp" +#include + +template inline +void test_boost_variant() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + boost::variant o_bv1 = random_value(gen); + boost::variant o_bv2 = random_value(gen); + boost::variant o_bv3 = random_basic_string(gen); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_bv1); + oar(o_bv2); + oar(o_bv3); + } + + decltype(o_bv1) i_bv1; + decltype(o_bv2) i_bv2; + decltype(o_bv3) i_bv3; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_bv1); + iar(i_bv2); + iar(i_bv3); + } + + CHECK_EQ( boost::get(i_bv1), boost::get(o_bv1) ); + CHECK_EQ( boost::get(i_bv2), doctest::Approx(boost::get(o_bv2)).epsilon(1e-5) ); + CHECK_EQ( boost::get(i_bv3), boost::get(o_bv3) ); +} + +#endif // CEREAL_TEST_BOOST_VARIANT_H_ diff --git a/unittests/chrono.cpp b/unittests/chrono.cpp index c71238a6c..b175decdd 100644 --- a/unittests/chrono.cpp +++ b/unittests/chrono.cpp @@ -24,100 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "chrono.hpp" -template -void test_chrono() -{ - for(int ii=0; ii<100; ++ii) - { - auto o_timePoint1 = std::chrono::system_clock::now(); - #ifndef CEREAL_OLDER_GCC - auto o_timePoint2 = std::chrono::steady_clock::now(); - #endif // CEREAL_OLDER_GCC - auto o_timePoint3 = std::chrono::high_resolution_clock::now(); - - auto o_duration1 = std::chrono::system_clock::now() - o_timePoint1; - #ifndef CEREAL_OLDER_GCC - auto o_duration2 = std::chrono::steady_clock::now() - o_timePoint2; - #endif // CEREAL_OLDER_GCC - auto o_duration3 = std::chrono::high_resolution_clock::now() - o_timePoint3; - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_timePoint1); - #ifndef CEREAL_OLDER_GCC - oar(o_timePoint2); - #endif // CEREAL_OLDER_GCC - oar(o_timePoint3); - oar(o_duration1); - #ifndef CEREAL_OLDER_GCC - oar(o_duration2); - #endif // CEREAL_OLDER_GCC - oar(o_duration3); - } - - decltype(o_timePoint1) i_timePoint1; - #ifndef CEREAL_OLDER_GCC - decltype(o_timePoint2) i_timePoint2; - #endif // CEREAL_OLDER_GCC - decltype(o_timePoint3) i_timePoint3; - decltype(o_duration1) i_duration1; - #ifndef CEREAL_OLDER_GCC - decltype(o_duration2) i_duration2; - #endif // CEREAL_OLDER_GCC - decltype(o_duration3) i_duration3; +TEST_SUITE("chrono"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_timePoint1); - #ifndef CEREAL_OLDER_GCC - iar(i_timePoint2); - #endif // CEREAL_OLDER_GCC - iar(i_timePoint3); - iar(i_duration1); - #ifndef CEREAL_OLDER_GCC - iar(i_duration2); - #endif // CEREAL_OLDER_GCC - iar(i_duration3); - } - - BOOST_CHECK( o_timePoint1 == i_timePoint1 ); - #ifndef CEREAL_OLDER_GCC - BOOST_CHECK( o_timePoint2 == i_timePoint2 ); - #endif // CEREAL_OLDER_GCC - BOOST_CHECK( o_timePoint3 == i_timePoint3 ); - BOOST_CHECK( o_duration1 == i_duration1 ); - #ifndef CEREAL_OLDER_GCC - BOOST_CHECK( o_duration2 == i_duration2 ); - #endif // CEREAL_OLDER_GCC - BOOST_CHECK( o_duration3 == i_duration3 ); - } -} - -BOOST_AUTO_TEST_CASE( binary_chrono ) +TEST_CASE("binary_chrono") { test_chrono(); } -BOOST_AUTO_TEST_CASE( portable_binary_chrono ) +TEST_CASE("portable_binary_chrono") { test_chrono(); } -BOOST_AUTO_TEST_CASE( xml_chrono ) +TEST_CASE("xml_chrono") { test_chrono(); } -BOOST_AUTO_TEST_CASE( json_chrono ) +TEST_CASE("json_chrono") { test_chrono(); } - +TEST_SUITE_END(); diff --git a/unittests/chrono.hpp b/unittests/chrono.hpp new file mode 100644 index 000000000..3e66623a5 --- /dev/null +++ b/unittests/chrono.hpp @@ -0,0 +1,105 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_CHRONO_H_ +#define CEREAL_TEST_CHRONO_H_ + +#include "common.hpp" + +template inline +void test_chrono() +{ + for(int ii=0; ii<100; ++ii) + { + auto o_timePoint1 = std::chrono::system_clock::now(); + #ifndef CEREAL_OLDER_GCC + auto o_timePoint2 = std::chrono::steady_clock::now(); + #endif // CEREAL_OLDER_GCC + auto o_timePoint3 = std::chrono::high_resolution_clock::now(); + + auto o_duration1 = std::chrono::system_clock::now() - o_timePoint1; + #ifndef CEREAL_OLDER_GCC + auto o_duration2 = std::chrono::steady_clock::now() - o_timePoint2; + #endif // CEREAL_OLDER_GCC + auto o_duration3 = std::chrono::high_resolution_clock::now() - o_timePoint3; + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_timePoint1); + #ifndef CEREAL_OLDER_GCC + oar(o_timePoint2); + #endif // CEREAL_OLDER_GCC + oar(o_timePoint3); + oar(o_duration1); + #ifndef CEREAL_OLDER_GCC + oar(o_duration2); + #endif // CEREAL_OLDER_GCC + oar(o_duration3); + } + + decltype(o_timePoint1) i_timePoint1; + #ifndef CEREAL_OLDER_GCC + decltype(o_timePoint2) i_timePoint2; + #endif // CEREAL_OLDER_GCC + decltype(o_timePoint3) i_timePoint3; + decltype(o_duration1) i_duration1; + #ifndef CEREAL_OLDER_GCC + decltype(o_duration2) i_duration2; + #endif // CEREAL_OLDER_GCC + decltype(o_duration3) i_duration3; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_timePoint1); + #ifndef CEREAL_OLDER_GCC + iar(i_timePoint2); + #endif // CEREAL_OLDER_GCC + iar(i_timePoint3); + iar(i_duration1); + #ifndef CEREAL_OLDER_GCC + iar(i_duration2); + #endif // CEREAL_OLDER_GCC + iar(i_duration3); + } + + CHECK_EQ( o_timePoint1, i_timePoint1 ); + #ifndef CEREAL_OLDER_GCC + CHECK_EQ( o_timePoint2, i_timePoint2 ); + #endif // CEREAL_OLDER_GCC + CHECK_EQ( o_timePoint3, i_timePoint3 ); + CHECK_EQ( o_duration1, i_duration1 ); + #ifndef CEREAL_OLDER_GCC + CHECK_EQ( o_duration2, i_duration2 ); + #endif // CEREAL_OLDER_GCC + CHECK_EQ( o_duration3, i_duration3 ); + } +} + +#endif // CEREAL_TEST_CHRONO_H_ diff --git a/unittests/common.hpp b/unittests/common.hpp index c126e3f06..5376d0a43 100644 --- a/unittests/common.hpp +++ b/unittests/common.hpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -56,32 +55,11 @@ #include #include -#include -#if BOOST_VERSION >= 105900 -#include +#include "doctest.h" -namespace boost -{ - namespace test_tools - { - namespace tt_detail - { - template - struct print_log_value< ::std::pair > - { - void operator()(::std::ostream & os, ::std::pair const & p ) - { - os << "([" << p.first << "], [" << p.second << "])"; - } - }; - } - } -} - -#endif // appropriate boost version - -namespace boost +namespace std { + // Ostream overload for std::pair template inline ::std::ostream & operator<<(::std::ostream & os, ::std::pair const & p) { @@ -90,6 +68,22 @@ namespace boost } } +// Checks that collections have equal size and all elements are the same +template inline +void check_collection( T const & a, T const & b ) +{ + auto aIter = std::begin(a); + auto aEnd = std::end(a); + auto bIter = std::begin(b); + auto bEnd = std::end(b); + + CHECK_EQ( std::distance(aIter, aEnd), std::distance(bIter, bEnd) ); + + for( ; aIter != aEnd; ++aIter, ++bIter ) + CHECK_EQ( *aIter, *bIter ); +} + +// Random Number Generation =============================================== template inline typename std::enable_if::value, T>::type random_value(std::mt19937 & gen) @@ -133,6 +127,7 @@ std::string random_binary_string(std::mt19937 & gen) return s; } +// Generic struct useful for testing many serialization functions struct StructBase { StructBase() {} @@ -190,7 +185,7 @@ struct StructExternalSerialize : StructBase StructExternalSerialize(int x_, int y_) : StructBase{x_,y_} {} }; - template +template void serialize(Archive & ar, StructExternalSerialize & s) { ar(s.x, s.y); @@ -202,19 +197,18 @@ struct StructExternalSplit : StructBase StructExternalSplit(int x_, int y_) : StructBase{x_,y_} {} }; - template inline +template inline void save(Archive & ar, StructExternalSplit const & s) { ar(s.x, s.y); } - template inline +template inline void load(Archive & ar, StructExternalSplit & s) { ar(s.x, s.y); } - template struct StructHash { public: @@ -225,5 +219,5 @@ struct StructHash { return h1 ^ ( h2 << 1 ); } }; - + #endif // CEREAL_TEST_COMMON_H_ diff --git a/unittests/complex.cpp b/unittests/complex.cpp index 786e0da10..168d1038c 100644 --- a/unittests/complex.cpp +++ b/unittests/complex.cpp @@ -24,73 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "complex.hpp" -template -void test_complex() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rngF = [&](){ return random_value(gen); }; - auto rngD = [&](){ return random_value(gen); }; - auto rngLD = [&](){ return random_value(gen); }; - - for(int ii=0; ii<100; ++ii) - { - std::complex o_float( rngF(), rngF() ); - std::complex o_double( rngD(), rngD() ); - std::complex o_ldouble( rngLD(), rngLD() ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_float); - oar(o_double); - oar(o_ldouble); - } - - std::complex i_float; - std::complex i_double; - std::complex i_ldouble; +TEST_SUITE("complex"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_float); - iar(i_double); - iar(i_ldouble); - } - - BOOST_CHECK_EQUAL( o_float, i_float ); - BOOST_CHECK_CLOSE( o_double.real(), i_double.real(), 1e-5); - BOOST_CHECK_CLOSE( o_double.imag(), i_double.imag(), 1e-5); - BOOST_CHECK_CLOSE( o_ldouble.real(), i_ldouble.real(), 1e-5); - BOOST_CHECK_CLOSE( o_ldouble.imag(), i_ldouble.imag(), 1e-5); - } -} - -BOOST_AUTO_TEST_CASE( binary_complex ) +TEST_CASE("binary_complex") { test_complex(); } -BOOST_AUTO_TEST_CASE( portable_binary_complex ) +TEST_CASE("portable_binary_complex") { test_complex(); } -BOOST_AUTO_TEST_CASE( xml_complex ) +TEST_CASE("xml_complex") { test_complex(); } -BOOST_AUTO_TEST_CASE( json_complex ) +TEST_CASE("json_complex") { test_complex(); } - +TEST_SUITE_END(); diff --git a/unittests/complex.hpp b/unittests/complex.hpp new file mode 100644 index 000000000..1f2387900 --- /dev/null +++ b/unittests/complex.hpp @@ -0,0 +1,77 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_COMPLEX_H_ +#define CEREAL_TEST_COMPLEX_H_ +#include "common.hpp" + +template inline +void test_complex() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rngF = [&](){ return random_value(gen); }; + auto rngD = [&](){ return random_value(gen); }; + auto rngLD = [&](){ return random_value(gen); }; + + for(int ii=0; ii<100; ++ii) + { + std::complex o_float( rngF(), rngF() ); + std::complex o_double( rngD(), rngD() ); + std::complex o_ldouble( rngLD(), rngLD() ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_float); + oar(o_double); + oar(o_ldouble); + } + + std::complex i_float; + std::complex i_double; + std::complex i_ldouble; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_float); + iar(i_double); + iar(i_ldouble); + } + + CHECK_EQ( o_float, i_float ); + CHECK_EQ( o_double.real(), doctest::Approx(i_double.real()).epsilon(1e-5) ); + CHECK_EQ( o_double.imag(), doctest::Approx(i_double.imag()).epsilon(1e-5) ); + CHECK_EQ( o_ldouble.real(), doctest::Approx(i_ldouble.real()).epsilon(1e-5) ); + CHECK_EQ( o_ldouble.imag(), doctest::Approx(i_ldouble.imag()).epsilon(1e-5) ); + } +} + +#endif // CEREAL_TEST_COMPLEX_H_ diff --git a/unittests/deque.cpp b/unittests/deque.cpp index 9bf694d9d..cbfaea1b4 100644 --- a/unittests/deque.cpp +++ b/unittests/deque.cpp @@ -24,95 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "deque.hpp" -template -void test_deque() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::deque o_poddeque(100); - for(auto & elem : o_poddeque) - elem = random_value(gen); - - std::deque o_iserdeque(100); - for(auto & elem : o_iserdeque) - elem = StructInternalSerialize( random_value(gen), random_value(gen) ); - - std::deque o_ispldeque(100); - for(auto & elem : o_ispldeque) - elem = StructInternalSplit( random_value(gen), random_value(gen) ); - - std::deque o_eserdeque(100); - for(auto & elem : o_eserdeque) - elem = StructExternalSerialize( random_value(gen), random_value(gen) ); - - std::deque o_espldeque(100); - for(auto & elem : o_espldeque) - elem = StructExternalSplit( random_value(gen), random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_poddeque); - oar(o_iserdeque); - oar(o_ispldeque); - oar(o_eserdeque); - oar(o_espldeque); - } +TEST_SUITE("deque"); - std::deque i_poddeque; - std::deque i_iserdeque; - std::deque i_ispldeque; - std::deque i_eserdeque; - std::deque i_espldeque; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_poddeque); - iar(i_iserdeque); - iar(i_ispldeque); - iar(i_eserdeque); - iar(i_espldeque); - } - - BOOST_CHECK_EQUAL(i_poddeque.size(), o_poddeque.size()); - BOOST_CHECK_EQUAL(i_iserdeque.size(), o_iserdeque.size()); - BOOST_CHECK_EQUAL(i_ispldeque.size(), o_ispldeque.size()); - BOOST_CHECK_EQUAL(i_eserdeque.size(), o_eserdeque.size()); - BOOST_CHECK_EQUAL(i_espldeque.size(), o_espldeque.size()); - - BOOST_CHECK_EQUAL_COLLECTIONS(i_poddeque.begin(), i_poddeque.end(), o_poddeque.begin(), o_poddeque.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserdeque.begin(), i_iserdeque.end(), o_iserdeque.begin(), o_iserdeque.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_ispldeque.begin(), i_ispldeque.end(), o_ispldeque.begin(), o_ispldeque.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserdeque.begin(), i_eserdeque.end(), o_eserdeque.begin(), o_eserdeque.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_espldeque.begin(), i_espldeque.end(), o_espldeque.begin(), o_espldeque.end()); - } -} - -BOOST_AUTO_TEST_CASE( binary_dequeue ) +TEST_CASE("binary_dequeue") { test_deque(); } -BOOST_AUTO_TEST_CASE( portable_binary_dequeue ) +TEST_CASE("portable_binary_dequeue") { test_deque(); } -BOOST_AUTO_TEST_CASE( xml_dequeue ) +TEST_CASE("xml_dequeue") { test_deque(); } -BOOST_AUTO_TEST_CASE( json_dequeue ) +TEST_CASE("json_dequeue") { test_deque(); } + +TEST_SUITE_END(); diff --git a/unittests/deque.hpp b/unittests/deque.hpp new file mode 100644 index 000000000..b129a1e53 --- /dev/null +++ b/unittests/deque.hpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_DEQUE_H_ +#define CEREAL_TEST_DEQUE_H_ +#include "common.hpp" + +template +void test_deque() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::deque o_poddeque(100); + for(auto & elem : o_poddeque) + elem = random_value(gen); + + std::deque o_iserdeque(100); + for(auto & elem : o_iserdeque) + elem = StructInternalSerialize( random_value(gen), random_value(gen) ); + + std::deque o_ispldeque(100); + for(auto & elem : o_ispldeque) + elem = StructInternalSplit( random_value(gen), random_value(gen) ); + + std::deque o_eserdeque(100); + for(auto & elem : o_eserdeque) + elem = StructExternalSerialize( random_value(gen), random_value(gen) ); + + std::deque o_espldeque(100); + for(auto & elem : o_espldeque) + elem = StructExternalSplit( random_value(gen), random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_poddeque); + oar(o_iserdeque); + oar(o_ispldeque); + oar(o_eserdeque); + oar(o_espldeque); + } + + std::deque i_poddeque; + std::deque i_iserdeque; + std::deque i_ispldeque; + std::deque i_eserdeque; + std::deque i_espldeque; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_poddeque); + iar(i_iserdeque); + iar(i_ispldeque); + iar(i_eserdeque); + iar(i_espldeque); + } + + CHECK_EQ(i_poddeque.size(), o_poddeque.size()); + CHECK_EQ(i_iserdeque.size(), o_iserdeque.size()); + CHECK_EQ(i_ispldeque.size(), o_ispldeque.size()); + CHECK_EQ(i_eserdeque.size(), o_eserdeque.size()); + CHECK_EQ(i_espldeque.size(), o_espldeque.size()); + + check_collection(i_poddeque, o_poddeque ); + check_collection(i_iserdeque, o_iserdeque); + check_collection(i_ispldeque, o_ispldeque); + check_collection(i_eserdeque, o_eserdeque); + check_collection(i_espldeque, o_espldeque); + } +} + +#endif // CEREAL_TEST_DEQUE_H_ diff --git a/unittests/doctest.h b/unittests/doctest.h new file mode 100644 index 000000000..2edf60469 --- /dev/null +++ b/unittests/doctest.h @@ -0,0 +1,3374 @@ +// ====================================================================== +// == DO NOT MODIFY THIS FILE BY HAND - IT IS AUTO GENERATED BY CMAKE! == +// ====================================================================== +// +// doctest.h - the lightest feature-rich C++ single-header testing framework for unit tests and TDD +// +// Copyright (c) 2016 Viktor Kirilov +// +// Distributed under the MIT Software License +// See accompanying file LICENSE.txt or copy at +// https://opensource.org/licenses/MIT +// +// The documentation can be found at the library's page: +// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= +// +// The library is heavily influenced by Catch - https://github.com/philsquared/Catch +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/philsquared/Catch/blob/master/LICENSE_1_0.txt +// +// The concept of subcases (sections in Catch) and expression decomposition are from there. +// Some parts of the code are taken directly: +// - stringification - the detection of "ostream& operator<<(ostream&, const T&)" and StringMaker<> +// - the Approx() helper class for floating point comparison +// - colors in the console +// - breaking into a debugger +// +// The expression decomposing templates are taken from lest - https://github.com/martinmoene/lest +// which uses the Boost Software License - Version 1.0 +// see here - https://github.com/martinmoene/lest/blob/master/LICENSE_1_0.txt +// +// ================================================================================================= +// ================================================================================================= +// ================================================================================================= + +// Suppress this globally (without push/pop) - there is no way to silence it in the +// expression decomposition macros _Pragma() in macros doesn't work for the c++ front-end of g++ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578 +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69543 +// Also the warning is completely worthless nowadays - http://stackoverflow.com/questions/14016993 +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC diagnostic ignored "-Waggregate-return" +#endif + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#pragma clang diagnostic ignored "-Wunused-local-typedef" +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic push +#endif // > gcc 4.6 +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wstrict-overflow" +#pragma GCC diagnostic ignored "-Wmissing-declarations" +#pragma GCC diagnostic ignored "-Winline" +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif // > gcc 4.6 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif // > gcc 4.7 +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3) +#pragma GCC diagnostic ignored "-Wuseless-cast" +#endif // > gcc 5.3 +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration +#pragma warning(disable : 4706) // assignment within conditional expression +#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated +#pragma warning(disable : 4127) // conditional expression is constant +#endif // _MSC_VER + +#ifndef DOCTEST_LIBRARY_INCLUDED +#define DOCTEST_LIBRARY_INCLUDED + +#define DOCTEST_VERSION_MAJOR 1 +#define DOCTEST_VERSION_MINOR 1 +#define DOCTEST_VERSION_PATCH 2 +#define DOCTEST_VERSION_STR "1.1.2" + +#define DOCTEST_VERSION \ + (DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH) + +// ================================================================================================= +// == MODERN C++ FEATURE DETECTION ================================================================= +// ================================================================================================= + +#if __cplusplus >= 201103L +#ifndef DOCTEST_CONFIG_WITH_NULLPTR +#define DOCTEST_CONFIG_WITH_NULLPTR +#endif // DOCTEST_CONFIG_WITH_NULLPTR +#ifndef DOCTEST_CONFIG_WITH_LONG_LONG +#define DOCTEST_CONFIG_WITH_LONG_LONG +#endif // DOCTEST_CONFIG_WITH_LONG_LONG +#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT +#define DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // __cplusplus >= 201103L + +// nullptr + +#ifndef DOCTEST_CONFIG_WITH_NULLPTR +#ifdef __clang__ +#if __has_feature(cxx_nullptr) +#define DOCTEST_CONFIG_WITH_NULLPTR +#endif // __has_feature(cxx_nullptr) +#endif // __clang__ + +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define DOCTEST_CONFIG_WITH_NULLPTR +#endif // __GNUC__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010 +#define DOCTEST_CONFIG_WITH_NULLPTR +#endif // _MSC_VER +#endif // DOCTEST_CONFIG_WITH_NULLPTR + +#if defined(DOCTEST_CONFIG_NO_NULLPTR) && defined(DOCTEST_CONFIG_WITH_NULLPTR) +#undef DOCTEST_CONFIG_WITH_NULLPTR +#endif // DOCTEST_CONFIG_NO_NULLPTR + +// long long + +#ifndef DOCTEST_CONFIG_WITH_LONG_LONG +#if !defined(DOCTEST_CONFIG_WITH_LONG_LONG) && defined(_MSC_VER) && (_MSC_VER >= 1400) +#define DOCTEST_CONFIG_WITH_LONG_LONG +#endif // _MSC_VER +#endif // DOCTEST_CONFIG_WITH_LONG_LONG + +#if defined(DOCTEST_CONFIG_NO_LONG_LONG) && defined(DOCTEST_CONFIG_WITH_LONG_LONG) +#undef DOCTEST_CONFIG_WITH_LONG_LONG +#endif // DOCTEST_CONFIG_NO_LONG_LONG + +// static_assert + +#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT +#ifdef __clang__ +#if __has_feature(cxx_static_assert) +#define DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // __has_feature(cxx_static_assert) +#endif // __clang__ + +#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 3 && defined(__GXX_EXPERIMENTAL_CXX0X__) +#define DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // __GNUC__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1600) // MSVC 2010 +#define DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // _MSC_VER +#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT + +#if defined(DOCTEST_CONFIG_NO_STATIC_ASSERT) && defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT) +#undef DOCTEST_CONFIG_WITH_STATIC_ASSERT +#endif // DOCTEST_CONFIG_NO_STATIC_ASSERT + +#if defined(DOCTEST_CONFIG_WITH_NULLPTR) || defined(DOCTEST_CONFIG_WITH_LONG_LONG) || \ + defined(DOCTEST_CONFIG_WITH_STATIC_ASSERT) +#define DOCTEST_NO_CPP11_COMPAT +#endif // c++11 stuff + +#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT) +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT + +// ================================================================================================= +// == MODERN C++ FEATURE DETECTION END ============================================================= +// ================================================================================================= + +// internal macros for string concatenation and anonymous variable name generation +#define DOCTEST_CAT_IMPL(s1, s2) s1##s2 +#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2) +#ifdef __COUNTER__ // not standard and may be missing for some compilers +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __COUNTER__) +#else // __COUNTER__ +#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__) +#endif // __COUNTER__ + +// macro for making a string out of an identifier +#define DOCTEST_TOSTR_IMPL(x) #x +#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x) + +// for concatenating literals and making the result a string +#define DOCTEST_STR_CONCAT_TOSTR(s1, s2) DOCTEST_TOSTR(s1) DOCTEST_TOSTR(s2) + +// counts the number of elements in a C string +#define DOCTEST_COUNTOF(x) (sizeof(x) / sizeof(x[0])) + +#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x& +#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE +#define DOCTEST_REF_WRAP(x) x +#endif // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE + +// not using __APPLE__ because... this is how Catch does it +#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +#define DOCTEST_PLATFORM_MAC +#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +#define DOCTEST_PLATFORM_IPHONE +#elif defined(_WIN32) || defined(_MSC_VER) +#define DOCTEST_PLATFORM_WINDOWS +#else +#define DOCTEST_PLATFORM_LINUX +#endif + +#define DOCTEST_GCS() (*doctest::detail::getTestsContextState()) + +// should probably take a look at https://github.com/scottt/debugbreak +#ifdef DOCTEST_PLATFORM_MAC +// The following code snippet based on: +// http://cocoawithlove.com/2008/03/break-into-debugger.html +#if defined(__ppc64__) || defined(__ppc__) +#define DOCTEST_BREAK_INTO_DEBUGGER() \ + __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" : : : "memory", "r0", "r3", "r4") +#else // __ppc64__ || __ppc__ +#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) +#endif // __ppc64__ || __ppc__ +#elif defined(_MSC_VER) +#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak() +#elif defined(__MINGW32__) +extern "C" __declspec(dllimport) void __stdcall DebugBreak(); +#define DOCTEST_BREAK_INTO_DEBUGGER() ::DebugBreak() +#else // linux +#define DOCTEST_BREAK_INTO_DEBUGGER() ((void)0) +#endif // linux + +#define DOCTEST_BREAK_INTO_DEBUGGER_CHECKED() \ + if(doctest::detail::isDebuggerActive() && !DOCTEST_GCS().no_breaks) \ + DOCTEST_BREAK_INTO_DEBUGGER(); + +#ifdef __clang__ +// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier) +#include +#endif // __clang__ + +#ifdef _LIBCPP_VERSION +// not forward declaring ostream for libc++ because I had some problems (inline namespaces vs c++98) +// so the header is used - also it is very light and doesn't drag a ton of stuff +#include +#else // _LIBCPP_VERSION +#ifndef DOCTEST_CONFIG_USE_IOSFWD +namespace std +{ +template +struct char_traits; +template <> +struct char_traits; +template +class basic_ostream; +typedef basic_ostream > ostream; +} +#else // DOCTEST_CONFIG_USE_IOSFWD +#include +#endif // DOCTEST_CONFIG_USE_IOSFWD +#endif // _LIBCPP_VERSION + +// static assert macro - because of the c++98 support requires that the message is an +// identifier (no spaces and not a C string) - example without quotes: I_am_a_message +// taken from here: http://stackoverflow.com/a/1980156/3162383 +#ifdef DOCTEST_CONFIG_WITH_STATIC_ASSERT +#define DOCTEST_STATIC_ASSERT(expression, message) static_assert(expression, #message) +#else // DOCTEST_CONFIG_WITH_STATIC_ASSERT +#define DOCTEST_STATIC_ASSERT(expression, message) \ + struct DOCTEST_CAT(__static_assertion_at_line_, __LINE__) \ + { \ + doctest::detail::static_assert_impl::StaticAssertion((expression))> \ + DOCTEST_CAT(DOCTEST_CAT(DOCTEST_CAT(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), \ + _), \ + message); \ + }; \ + typedef doctest::detail::static_assert_impl::StaticAssertionTest \ + DOCTEST_CAT(__static_assertion_test_at_line_, __LINE__) +#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT + +#ifdef DOCTEST_CONFIG_WITH_NULLPTR +#ifdef _LIBCPP_VERSION +#include +#else // _LIBCPP_VERSION +namespace std +{ typedef decltype(nullptr) nullptr_t; } +#endif // _LIBCPP_VERSION +#endif // DOCTEST_CONFIG_WITH_NULLPTR + +namespace doctest +{ +class String +{ + char* m_str; + + void copy(const String& other); + +public: + String(const char* in = ""); + String(const String& other); + ~String(); + + String& operator=(const String& other); + + String operator+(const String& other) const; + String& operator+=(const String& other); + + char& operator[](unsigned pos) { return m_str[pos]; } + const char& operator[](unsigned pos) const { return m_str[pos]; } + + char* c_str() { return m_str; } + const char* c_str() const { return m_str; } + + unsigned size() const; + unsigned length() const; + + int compare(const char* other, bool no_case = false) const; + int compare(const String& other, bool no_case = false) const; +}; + +// clang-format off +inline bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; } +inline bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; } +inline bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; } +inline bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; } +inline bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; } +inline bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; } +// clang-format on + +std::ostream& operator<<(std::ostream& stream, const String& in); + +namespace detail +{ +#ifndef DOCTEST_CONFIG_WITH_STATIC_ASSERT + namespace static_assert_impl + { + template + struct StaticAssertion; + + template <> + struct StaticAssertion + {}; + + template + struct StaticAssertionTest + {}; + } // namespace static_assert_impl +#endif // DOCTEST_CONFIG_WITH_STATIC_ASSERT + + template + struct deferred_false + { static const bool value = false; }; + + namespace has_insertion_operator_impl + { + typedef char no; + typedef char yes[2]; + + struct any_t + { + template + any_t(const DOCTEST_REF_WRAP(T)); + }; + + yes& testStreamable(std::ostream&); + no testStreamable(no); + + no operator<<(const std::ostream&, const any_t&); + + template + struct has_insertion_operator + { + static std::ostream& s; + static const DOCTEST_REF_WRAP(T) t; + static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes); + }; + } // namespace has_insertion_operator_impl + + template + struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator + {}; + + std::ostream* createStream(); + String getStreamResult(std::ostream*); + void freeStream(std::ostream*); + + template + struct StringMakerBase + { + template + static String convert(const DOCTEST_REF_WRAP(T)) { + return "{?}"; + } + }; + + template <> + struct StringMakerBase + { + template + static String convert(const DOCTEST_REF_WRAP(T) in) { + std::ostream* stream = createStream(); + *stream << in; + String result = getStreamResult(stream); + freeStream(stream); + return result; + } + }; + + String rawMemoryToString(const void* object, unsigned size); + + template + String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) { + return rawMemoryToString(&object, sizeof(object)); + } +} // namespace detail + +template +struct StringMaker : detail::StringMakerBase::value> +{}; + +template +struct StringMaker +{ + template + static String convert(U* p) { + if(!p) + return "NULL"; + else + return detail::rawMemoryToString(p); + } +}; + +template +struct StringMaker +{ + static String convert(R C::*p) { + if(!p) + return "NULL"; + else + return detail::rawMemoryToString(p); + } +}; + +template +String toString(const DOCTEST_REF_WRAP(T) value) { + return StringMaker::convert(value); +} + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(char* in); +String toString(const char* in); +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(bool in); +String toString(float in); +String toString(double in); +String toString(double long in); + +String toString(char in); +String toString(char unsigned in); +String toString(int short in); +String toString(int short unsigned in); +String toString(int in); +String toString(int unsigned in); +String toString(int long in); +String toString(int long unsigned in); + +#ifdef DOCTEST_CONFIG_WITH_LONG_LONG +String toString(int long long in); +String toString(int long long unsigned in); +#endif // DOCTEST_CONFIG_WITH_LONG_LONG + +#ifdef DOCTEST_CONFIG_WITH_NULLPTR +String toString(std::nullptr_t in); +#endif // DOCTEST_CONFIG_WITH_NULLPTR + +class Approx +{ +public: + explicit Approx(double value); + + Approx(Approx const& other) + : m_epsilon(other.m_epsilon) + , m_scale(other.m_scale) + , m_value(other.m_value) {} + + Approx operator()(double value) { + Approx approx(value); + approx.epsilon(m_epsilon); + approx.scale(m_scale); + return approx; + } + + friend bool operator==(double lhs, Approx const& rhs); + friend bool operator==(Approx const& lhs, double rhs) { return operator==(rhs, lhs); } + friend bool operator!=(double lhs, Approx const& rhs) { return !operator==(lhs, rhs); } + friend bool operator!=(Approx const& lhs, double rhs) { return !operator==(rhs, lhs); } + + Approx& epsilon(double newEpsilon) { + m_epsilon = newEpsilon; + return *this; + } + + Approx& scale(double newScale) { + m_scale = newScale; + return *this; + } + + String toString() const; + +private: + double m_epsilon; + double m_scale; + double m_value; +}; + +template <> +inline String toString(const DOCTEST_REF_WRAP(Approx) value) { + return value.toString(); +} + +#if !defined(DOCTEST_CONFIG_DISABLE) + +namespace detail +{ + // the function type this library works with + typedef void (*funcType)(void); + + namespace assertType + { + enum Enum + { + // macro traits + + is_warn = 1, + is_check = 2, + is_require = 4, + + is_throws = 8, + is_throws_as = 16, + is_nothrow = 32, + + is_fast = 64, // not checked anywhere - used just to distinguish the types + is_false = 128, + is_unary = 256, + + is_eq = 512, + is_ne = 1024, + + is_lt = 2048, + is_gt = 4096, + + is_ge = 8192, + is_le = 16384, + + // macro types + + DT_WARN = is_warn, + DT_CHECK = is_check, + DT_REQUIRE = is_require, + + DT_WARN_FALSE = is_false | is_warn, + DT_CHECK_FALSE = is_false | is_check, + DT_REQUIRE_FALSE = is_false | is_require, + + DT_WARN_THROWS = is_throws | is_warn, + DT_CHECK_THROWS = is_throws | is_check, + DT_REQUIRE_THROWS = is_throws | is_require, + + DT_WARN_THROWS_AS = is_throws_as | is_warn, + DT_CHECK_THROWS_AS = is_throws_as | is_check, + DT_REQUIRE_THROWS_AS = is_throws_as | is_require, + + DT_WARN_NOTHROW = is_nothrow | is_warn, + DT_CHECK_NOTHROW = is_nothrow | is_check, + DT_REQUIRE_NOTHROW = is_nothrow | is_require, + + DT_WARN_EQ = is_eq | is_warn, + DT_CHECK_EQ = is_eq | is_check, + DT_REQUIRE_EQ = is_eq | is_require, + + DT_WARN_NE = is_ne | is_warn, + DT_CHECK_NE = is_ne | is_check, + DT_REQUIRE_NE = is_ne | is_require, + + DT_WARN_GT = is_gt | is_warn, + DT_CHECK_GT = is_gt | is_check, + DT_REQUIRE_GT = is_gt | is_require, + + DT_WARN_LT = is_lt | is_warn, + DT_CHECK_LT = is_lt | is_check, + DT_REQUIRE_LT = is_lt | is_require, + + DT_WARN_GE = is_ge | is_warn, + DT_CHECK_GE = is_ge | is_check, + DT_REQUIRE_GE = is_ge | is_require, + + DT_WARN_LE = is_le | is_warn, + DT_CHECK_LE = is_le | is_check, + DT_REQUIRE_LE = is_le | is_require, + + DT_WARN_UNARY = is_unary | is_warn, + DT_CHECK_UNARY = is_unary | is_check, + DT_REQUIRE_UNARY = is_unary | is_require, + + DT_WARN_UNARY_FALSE = is_false | is_unary | is_warn, + DT_CHECK_UNARY_FALSE = is_false | is_unary | is_check, + DT_REQUIRE_UNARY_FALSE = is_false | is_unary | is_require, + + DT_FAST_WARN_EQ = is_fast | is_eq | is_warn, + DT_FAST_CHECK_EQ = is_fast | is_eq | is_check, + DT_FAST_REQUIRE_EQ = is_fast | is_eq | is_require, + + DT_FAST_WARN_NE = is_fast | is_ne | is_warn, + DT_FAST_CHECK_NE = is_fast | is_ne | is_check, + DT_FAST_REQUIRE_NE = is_fast | is_ne | is_require, + + DT_FAST_WARN_GT = is_fast | is_gt | is_warn, + DT_FAST_CHECK_GT = is_fast | is_gt | is_check, + DT_FAST_REQUIRE_GT = is_fast | is_gt | is_require, + + DT_FAST_WARN_LT = is_fast | is_lt | is_warn, + DT_FAST_CHECK_LT = is_fast | is_lt | is_check, + DT_FAST_REQUIRE_LT = is_fast | is_lt | is_require, + + DT_FAST_WARN_GE = is_fast | is_ge | is_warn, + DT_FAST_CHECK_GE = is_fast | is_ge | is_check, + DT_FAST_REQUIRE_GE = is_fast | is_ge | is_require, + + DT_FAST_WARN_LE = is_fast | is_le | is_warn, + DT_FAST_CHECK_LE = is_fast | is_le | is_check, + DT_FAST_REQUIRE_LE = is_fast | is_le | is_require, + + DT_FAST_WARN_UNARY = is_fast | is_unary | is_warn, + DT_FAST_CHECK_UNARY = is_fast | is_unary | is_check, + DT_FAST_REQUIRE_UNARY = is_fast | is_unary | is_require, + + DT_FAST_WARN_UNARY_FALSE = is_fast | is_false | is_unary | is_warn, + DT_FAST_CHECK_UNARY_FALSE = is_fast | is_false | is_unary | is_check, + DT_FAST_REQUIRE_UNARY_FALSE = is_fast | is_false | is_unary | is_require + }; + } // namespace assertType + + const char* getAssertString(assertType::Enum val); + + // clang-format off + template struct decay_array { typedef T type; }; + template struct decay_array { typedef T* type; }; + template struct decay_array { typedef T* type; }; + + template struct not_char_pointer { enum { value = true }; }; + template<> struct not_char_pointer { enum { value = false }; }; + template<> struct not_char_pointer { enum { value = false }; }; + + template struct can_use_op : not_char_pointer::type> {}; + + template struct enable_if {}; + template struct enable_if { typedef T type; }; + // clang-format on + + struct TestFailureException + {}; + + bool checkIfShouldThrow(assertType::Enum assert_type); + void fastAssertThrowIfFlagSet(int flags); + void throwException(); + bool always_false(); + + // a struct defining a registered test callback + struct TestData + { + // not used for determining uniqueness + const char* m_suite; // the test suite in which the test was added + const char* m_name; // name of the test function + funcType m_f; // a function pointer to the test function + + // fields by which uniqueness of test cases shall be determined + const char* m_file; // the file in which the test was registered + unsigned m_line; // the line where the test was registered + + TestData(const char* suite, const char* name, funcType f, const char* file, unsigned line) + : m_suite(suite) + , m_name(name) + , m_f(f) + , m_file(file) + , m_line(line) {} + + bool operator<(const TestData& other) const; + }; + + struct SubcaseSignature + { + const char* m_name; + const char* m_file; + int m_line; + + SubcaseSignature(const char* name, const char* file, int line) + : m_name(name) + , m_file(file) + , m_line(line) {} + + bool operator<(const SubcaseSignature& other) const; + }; + + struct Subcase + { + SubcaseSignature m_signature; + bool m_entered; + + Subcase(const char* name, const char* file, int line); + Subcase(const Subcase& other); + ~Subcase(); + + operator bool() const { return m_entered; } + }; + + template + String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op, + const DOCTEST_REF_WRAP(R) rhs) { + return toString(lhs) + op + toString(rhs); + } + + struct Result + { + bool m_passed; + String m_decomposition; + +// to fix gcc 4.7 "-Winline" warnings +#if defined(__GNUC__) && !defined(__clang__) + __attribute__((noinline)) +#endif + ~Result() { + } + + Result(bool passed = false, const String& decomposition = String()) + : m_passed(passed) + , m_decomposition(decomposition) {} + + Result(const Result& other) + : m_passed(other.m_passed) + , m_decomposition(other.m_decomposition) {} + +// to fix gcc 4.7 "-Winline" warnings +#if defined(__GNUC__) && !defined(__clang__) + __attribute__((noinline)) +#endif + Result& + operator=(const Result& other) { + m_passed = other.m_passed; + m_decomposition = other.m_decomposition; + + return *this; + } + + operator bool() { return !m_passed; } + + void invert() { m_passed = !m_passed; } + + // clang-format off + // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence + template Result operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator== (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator!= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator<= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator>= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + template Result operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return Result(); } + // clang-format on + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wsign-compare" +#pragma clang diagnostic ignored "-Wdouble-promotion" +//#pragma clang diagnostic ignored "-Wconversion" +//#pragma clang diagnostic ignored "-Wfloat-equal" +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic push +#endif // > gcc 4.6 +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wsign-compare" +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) +#pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif // > gcc 4.5 +//#pragma GCC diagnostic ignored "-Wconversion" +//#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(push) +// http://stackoverflow.com/questions/39479163 what's the difference between C4018 and C4389 +#pragma warning(disable : 4389) // 'operator' : signed/unsigned mismatch +#pragma warning(disable : 4018) // 'expression' : signed/unsigned mismatch +//#pragma warning(disable : 4805) // 'operation' : unsafe mix of type 'type' and type 'type' in operation +#endif // _MSC_VER + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +// clang-format off +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE bool +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +#define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if::value || can_use_op::value, bool>::type + inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); } + inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); } + inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); } + inline bool gt(const char* lhs, const char* rhs) { return String(lhs) > String(rhs); } + inline bool le(const char* lhs, const char* rhs) { return String(lhs) <= String(rhs); } + inline bool ge(const char* lhs, const char* rhs) { return String(lhs) >= String(rhs); } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + + template DOCTEST_COMPARISON_RETURN_TYPE eq(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs == rhs; } + template DOCTEST_COMPARISON_RETURN_TYPE ne(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs != rhs; } + template DOCTEST_COMPARISON_RETURN_TYPE lt(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs < rhs; } + template DOCTEST_COMPARISON_RETURN_TYPE gt(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs > rhs; } + template DOCTEST_COMPARISON_RETURN_TYPE le(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs <= rhs; } + template DOCTEST_COMPARISON_RETURN_TYPE ge(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs >= rhs; } + // clang-format on + + template + struct Expression_lhs + { + L lhs; + + Expression_lhs(L in) + : lhs(in) {} + + Expression_lhs(const Expression_lhs& other) + : lhs(other.lhs) {} + + operator Result() { return Result(!!lhs, toString(lhs)); } + +// clang-format off +#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs == rhs, stringifyBinaryExpr(lhs, " == ", rhs)); } + template Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs != rhs, stringifyBinaryExpr(lhs, " != ", rhs)); } + template Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs < rhs, stringifyBinaryExpr(lhs, " < " , rhs)); } + template Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs <= rhs, stringifyBinaryExpr(lhs, " <= ", rhs)); } + template Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs > rhs, stringifyBinaryExpr(lhs, " > " , rhs)); } + template Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(lhs >= rhs, stringifyBinaryExpr(lhs, " >= ", rhs)); } +#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + template Result operator==(const DOCTEST_REF_WRAP(R) rhs) { return Result(eq(lhs, rhs), stringifyBinaryExpr(lhs, " == ", rhs)); } + template Result operator!=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ne(lhs, rhs), stringifyBinaryExpr(lhs, " != ", rhs)); } + template Result operator< (const DOCTEST_REF_WRAP(R) rhs) { return Result(lt(lhs, rhs), stringifyBinaryExpr(lhs, " < " , rhs)); } + template Result operator<=(const DOCTEST_REF_WRAP(R) rhs) { return Result(le(lhs, rhs), stringifyBinaryExpr(lhs, " <= ", rhs)); } + template Result operator> (const DOCTEST_REF_WRAP(R) rhs) { return Result(gt(lhs, rhs), stringifyBinaryExpr(lhs, " > " , rhs)); } + template Result operator>=(const DOCTEST_REF_WRAP(R) rhs) { return Result(ge(lhs, rhs), stringifyBinaryExpr(lhs, " >= ", rhs)); } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING + // clang-format on + + // clang-format off + // forbidding some expressions based on this table: http://en.cppreference.com/w/cpp/language/operator_precedence + template int operator& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator^ (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator&& (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator|| (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator+= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator-= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator*= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator/= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator%= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator<<=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator>>=(const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator&= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator^= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + template int operator|= (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison); return int(); } + // these 2 are unfortunate because they should be allowed - they have higher precedence over the comparisons, but the + // ExpressionDecomposer class uses the left shift operator to capture the left operand of the binary expression... + template int operator<< (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Please_Surround_The_Left_Shift_Operation_With_Parenthesis); return int(); } + template int operator>> (const R&) { DOCTEST_STATIC_ASSERT(deferred_false::value, Please_Surround_The_Right_Shift_Operation_With_Parenthesis); return int(); } + // clang-format on + }; + +#ifndef DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic pop +#endif // > gcc 4.6 +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION + + struct ExpressionDecomposer + { + template + Expression_lhs operator<<(const DOCTEST_REF_WRAP(L) operand) { + return Expression_lhs(operand); + } + }; + + // forward declarations of functions used by the macros + int regTest(void (*f)(void), unsigned line, const char* file, const char* name); + int setTestSuiteName(const char* name); + + void addFailedAssert(assertType::Enum assert_type); + + void logTestStart(const char* name, const char* file, unsigned line); + void logTestEnd(); + + void logTestCrashed(); + + void logAssert(bool passed, const char* decomposition, bool threw, const char* expr, + assertType::Enum assert_type, const char* file, int line); + + void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type, + const char* file, int line); + + void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr, + assertType::Enum assert_type, const char* file, int line); + + void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type, + const char* file, int line); + + bool isDebuggerActive(); + void writeToDebugConsole(const String&); + + struct TestAccessibleContextState + { + bool success; // include successful assertions in output + bool no_throw; // to skip exceptions-related assertion macros + bool no_breaks; // to not break into the debugger + const TestData* currentTest; + bool hasLoggedCurrentTestStart; + int numAssertionsForCurrentTestcase; + }; + + struct ContextState; + + TestAccessibleContextState* getTestsContextState(); + + namespace binaryAssertComparison + { + enum Enum + { + eq = 0, + ne, + gt, + lt, + ge, + le + }; + } // namespace binaryAssertComparison + + // clang-format off + template struct RelationalComparator { bool operator()(const DOCTEST_REF_WRAP(L), const DOCTEST_REF_WRAP(R) ) const { return false; } }; + template struct RelationalComparator<0, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return eq(lhs, rhs); } }; + template struct RelationalComparator<1, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return ne(lhs, rhs); } }; + template struct RelationalComparator<2, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return gt(lhs, rhs); } }; + template struct RelationalComparator<3, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return lt(lhs, rhs); } }; + template struct RelationalComparator<4, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return ge(lhs, rhs); } }; + template struct RelationalComparator<5, L, R> { bool operator()(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) const { return le(lhs, rhs); } }; + // clang-format on + + struct ResultBuilder + { + assertType::Enum m_assert_type; + const char* m_file; + int m_line; + const char* m_expr; + const char* m_exception_type; + + Result m_result; + bool m_threw; + bool m_threw_as; + bool m_failed; + + ResultBuilder(assertType::Enum assert_type, const char* file, int line, const char* expr, + const char* exception_type = ""); + +// to fix gcc 4.7 "-Winline" warnings +#if defined(__GNUC__) && !defined(__clang__) + __attribute__((noinline)) +#endif + ~ResultBuilder() { + } + + void setResult(const Result& res) { m_result = res; } + + template + void binary_assert(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { + m_result.m_passed = RelationalComparator()(lhs, rhs); + m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs); + } + + template + void unary_assert(const DOCTEST_REF_WRAP(L) val) { + m_result.m_passed = !!val; + m_result.m_decomposition = toString(val); + } + + bool log(); + void react() const; + }; + + namespace assertAction + { + enum Enum + { + nothing = 0, + dbgbreak = 1, + shouldthrow = 2 + }; + } // namespace assertAction + + template + int fast_binary_assert(assertType::Enum assert_type, const char* file, int line, + const char* lhs_str, const char* rhs_str, const DOCTEST_REF_WRAP(L) lhs, + const DOCTEST_REF_WRAP(R) rhs) { + String expr = String(lhs_str) + ", " + rhs_str; + const char* expr_str = expr.c_str(); + ResultBuilder rb(assert_type, file, line, expr_str); + + rb.m_result.m_passed = RelationalComparator()(lhs, rhs); + rb.m_result.m_decomposition = stringifyBinaryExpr(lhs, ", ", rhs); + + int res = 0; + + if(rb.log()) + res |= assertAction::dbgbreak; + + if(rb.m_failed && checkIfShouldThrow(assert_type)) + res |= assertAction::shouldthrow; + +#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + // ######################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ######################################################################################### + if(res & assertAction::dbgbreak) + DOCTEST_BREAK_INTO_DEBUGGER(); + fastAssertThrowIfFlagSet(res); +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + + return res; + } + + template + int fast_unary_assert(assertType::Enum assert_type, const char* file, int line, + const char* val_str, const DOCTEST_REF_WRAP(L) val) { + ResultBuilder rb(assert_type, file, line, val_str); + + rb.m_result.m_passed = !!val; + rb.m_result.m_decomposition = toString(val); + + int res = 0; + + if(rb.log()) + res |= assertAction::dbgbreak; + + if(rb.m_failed && checkIfShouldThrow(assert_type)) + res |= assertAction::shouldthrow; + +#ifdef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + // ######################################################################################### + // IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK TO SEE THE FAILING ASSERTION + // THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED + // ######################################################################################### + if(res & assertAction::dbgbreak) + DOCTEST_BREAK_INTO_DEBUGGER(); + fastAssertThrowIfFlagSet(res); +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + + return res; + } +} // namespace detail + +#endif // DOCTEST_CONFIG_DISABLE + +class Context +{ +#if !defined(DOCTEST_CONFIG_DISABLE) + detail::ContextState* p; + + void parseArgs(int argc, const char* const* argv, bool withDefaults = false); + +#endif // DOCTEST_CONFIG_DISABLE + +public: + Context(int argc = 0, const char* const* argv = 0); + +// to fix gcc 4.7 "-Winline" warnings +#if defined(__GNUC__) && !defined(__clang__) + __attribute__((noinline)) +#endif + ~Context(); + + void applyCommandLine(int argc, const char* const* argv); + + void addFilter(const char* filter, const char* value); + void clearFilters(); + void setOption(const char* option, int value); + void setOption(const char* option, const char* value); + + bool shouldExit(); + + int run(); +}; + +} // namespace doctest + +// if registering is not disabled +#if !defined(DOCTEST_CONFIG_DISABLE) + +// registers the test by initializing a dummy var with a function +#if defined(__GNUC__) && !defined(__clang__) +#define DOCTEST_REGISTER_FUNCTION(f, name) \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \ + doctest::detail::regTest(f, __LINE__, __FILE__, name); +#elif defined(__clang__) +#define DOCTEST_REGISTER_FUNCTION(f, name) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \ + DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \ + doctest::detail::regTest(f, __LINE__, __FILE__, name); \ + _Pragma("clang diagnostic pop") +#else // MSVC +#define DOCTEST_REGISTER_FUNCTION(f, name) \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \ + doctest::detail::regTest(f, __LINE__, __FILE__, name); +#endif // MSVC + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ + namespace \ + { \ + struct der : base \ + { void f(); }; \ + static void func() { \ + der v; \ + v.f(); \ + } \ + DOCTEST_REGISTER_FUNCTION(func, name) \ + } \ + inline void der::f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ + static void f(); \ + DOCTEST_REGISTER_FUNCTION(f, name) \ + inline void f() + +// for registering tests +#define DOCTEST_TEST_CASE(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(c, name) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \ + DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + +// for subcases +#if defined(__GNUC__) +#define DOCTEST_SUBCASE(name) \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) \ + __attribute__((unused)) = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) +#else // __GNUC__ +#define DOCTEST_SUBCASE(name) \ + if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) = \ + doctest::detail::Subcase(name, __FILE__, __LINE__)) +#endif // __GNUC__ + +// for starting a testsuite block +#if defined(__GNUC__) && !defined(__clang__) +#define DOCTEST_TEST_SUITE(name) \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \ + doctest::detail::setTestSuiteName(name); \ + typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#elif defined(__clang__) +#define DOCTEST_TEST_SUITE(name) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \ + DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = \ + doctest::detail::setTestSuiteName(name); \ + _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#else // MSVC +#define DOCTEST_TEST_SUITE(name) \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(name); \ + typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#endif // MSVC + +// for ending a testsuite block +#if defined(__GNUC__) && !defined(__clang__) +#define DOCTEST_TEST_SUITE_END \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) __attribute__((unused)) = \ + doctest::detail::setTestSuiteName(""); \ + typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#elif defined(__clang__) +#define DOCTEST_TEST_SUITE_END \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") static int \ + DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \ + _Pragma("clang diagnostic pop") typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#else // MSVC +#define DOCTEST_TEST_SUITE_END \ + static int DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_) = doctest::detail::setTestSuiteName(""); \ + typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) +#endif // MSVC + +#define DOCTEST_ASSERT_LOG_AND_REACT(rb) \ + if(rb.log()) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + rb.react() + +#define DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, __FILE__, \ + __LINE__, #expr); \ + try { \ + _DOCTEST_RB.setResult(doctest::detail::ExpressionDecomposer() << expr); \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); + +#if defined(__clang__) +#define DOCTEST_ASSERT_PROXY(expr, assert_type) \ + do { \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Woverloaded-shift-op-parentheses\"") \ + DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \ + _Pragma("clang diagnostic pop") \ + } while(doctest::detail::always_false()) +#else // __clang__ +#define DOCTEST_ASSERT_PROXY(expr, assert_type) \ + do { \ + DOCTEST_ASSERT_IMPLEMENT(expr, assert_type) \ + } while(doctest::detail::always_false()) +#endif // __clang__ + +#define DOCTEST_WARN(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN) +#define DOCTEST_CHECK(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK) +#define DOCTEST_REQUIRE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE) + +#define DOCTEST_WARN_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_WARN_FALSE) +#define DOCTEST_CHECK_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_CHECK_FALSE) +#define DOCTEST_REQUIRE_FALSE(expr) DOCTEST_ASSERT_PROXY(expr, DT_REQUIRE_FALSE) + +#define DOCTEST_ASSERT_THROWS(expr, assert_type) \ + do { \ + if(!DOCTEST_GCS().no_throw) { \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \ + __FILE__, __LINE__, #expr); \ + try { \ + expr; \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } \ + } while(doctest::detail::always_false()) + +#define DOCTEST_ASSERT_THROWS_AS(expr, as, assert_type) \ + do { \ + if(!DOCTEST_GCS().no_throw) { \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \ + __FILE__, __LINE__, #expr, #as); \ + try { \ + expr; \ + } catch(as) { \ + _DOCTEST_RB.m_threw = true; \ + _DOCTEST_RB.m_threw_as = true; \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } \ + } while(doctest::detail::always_false()) + +#define DOCTEST_ASSERT_NOTHROW(expr, assert_type) \ + do { \ + if(!DOCTEST_GCS().no_throw) { \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \ + __FILE__, __LINE__, #expr); \ + try { \ + expr; \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } \ + } while(doctest::detail::always_false()) + +#define DOCTEST_WARN_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_WARN_THROWS) +#define DOCTEST_CHECK_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_CHECK_THROWS) +#define DOCTEST_REQUIRE_THROWS(expr) DOCTEST_ASSERT_THROWS(expr, DT_REQUIRE_THROWS) + +#define DOCTEST_WARN_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_WARN_THROWS_AS) +#define DOCTEST_CHECK_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_CHECK_THROWS_AS) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) DOCTEST_ASSERT_THROWS_AS(expr, ex, DT_REQUIRE_THROWS_AS) + +#define DOCTEST_WARN_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_WARN_NOTHROW) +#define DOCTEST_CHECK_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_CHECK_NOTHROW) +#define DOCTEST_REQUIRE_NOTHROW(expr) DOCTEST_ASSERT_NOTHROW(expr, DT_REQUIRE_NOTHROW) + +#define DOCTEST_BINARY_ASSERT(assert_type, lhs, rhs, comp) \ + do { \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \ + __FILE__, __LINE__, #lhs ", " #rhs); \ + try { \ + _DOCTEST_RB.binary_assert(lhs, rhs); \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } while(doctest::detail::always_false()) + +#define DOCTEST_UNARY_ASSERT(assert_type, val) \ + do { \ + doctest::detail::ResultBuilder _DOCTEST_RB(doctest::detail::assertType::assert_type, \ + __FILE__, __LINE__, #val); \ + try { \ + _DOCTEST_RB.unary_assert(val); \ + } catch(...) { _DOCTEST_RB.m_threw = true; } \ + DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \ + } while(doctest::detail::always_false()) + +#define DOCTEST_WARN_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, lhs, rhs, eq) +#define DOCTEST_CHECK_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, lhs, rhs, eq) +#define DOCTEST_REQUIRE_EQ(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, lhs, rhs, eq) +#define DOCTEST_WARN_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_NE, lhs, rhs, ne) +#define DOCTEST_CHECK_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, lhs, rhs, ne) +#define DOCTEST_REQUIRE_NE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, lhs, rhs, ne) +#define DOCTEST_WARN_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GT, lhs, rhs, gt) +#define DOCTEST_CHECK_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, lhs, rhs, gt) +#define DOCTEST_REQUIRE_GT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, lhs, rhs, gt) +#define DOCTEST_WARN_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lhs, rhs, lt) +#define DOCTEST_CHECK_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lhs, rhs, lt) +#define DOCTEST_REQUIRE_LT(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lhs, rhs, lt) +#define DOCTEST_WARN_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_GE, lhs, rhs, ge) +#define DOCTEST_CHECK_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, lhs, rhs, ge) +#define DOCTEST_REQUIRE_GE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, lhs, rhs, ge) +#define DOCTEST_WARN_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_WARN_LE, lhs, rhs, le) +#define DOCTEST_CHECK_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, lhs, rhs, le) +#define DOCTEST_REQUIRE_LE(lhs, rhs) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, lhs, rhs, le) + +#define DOCTEST_WARN_UNARY(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, v) +#define DOCTEST_CHECK_UNARY(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, v) +#define DOCTEST_REQUIRE_UNARY(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, v) +#define DOCTEST_WARN_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, v) +#define DOCTEST_CHECK_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, v) +#define DOCTEST_REQUIRE_UNARY_FALSE(v) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, v) + +#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \ + do { \ + int _DOCTEST_FAST_RES = doctest::detail::fast_binary_assert< \ + doctest::detail::binaryAssertComparison::comparison>( \ + doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, \ + rhs); \ + if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \ + } while(doctest::detail::always_false()) + +#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \ + do { \ + int _DOCTEST_FAST_RES = doctest::detail::fast_unary_assert( \ + doctest::detail::assertType::assert_type, __FILE__, __LINE__, #val, val); \ + if(_DOCTEST_FAST_RES & doctest::detail::assertAction::dbgbreak) \ + DOCTEST_BREAK_INTO_DEBUGGER(); \ + doctest::detail::fastAssertThrowIfFlagSet(_DOCTEST_FAST_RES); \ + } while(doctest::detail::always_false()) + +#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_FAST_BINARY_ASSERT(assert_type, lhs, rhs, comparison) \ + doctest::detail::fast_binary_assert( \ + doctest::detail::assertType::assert_type, __FILE__, __LINE__, #lhs, #rhs, lhs, rhs) + +#define DOCTEST_FAST_UNARY_ASSERT(assert_type, val) \ + doctest::detail::fast_unary_assert(doctest::detail::assertType::assert_type, __FILE__, \ + __LINE__, #val, val) + +#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS + +#define DOCTEST_FAST_WARN_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_EQ, l, r, eq) +#define DOCTEST_FAST_CHECK_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_EQ, l, r, eq) +#define DOCTEST_FAST_REQUIRE_EQ(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_EQ, l, r, eq) +#define DOCTEST_FAST_WARN_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_NE, l, r, ne) +#define DOCTEST_FAST_CHECK_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_NE, l, r, ne) +#define DOCTEST_FAST_REQUIRE_NE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_NE, l, r, ne) +#define DOCTEST_FAST_WARN_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GT, l, r, gt) +#define DOCTEST_FAST_CHECK_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GT, l, r, gt) +#define DOCTEST_FAST_REQUIRE_GT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GT, l, r, gt) +#define DOCTEST_FAST_WARN_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LT, l, r, lt) +#define DOCTEST_FAST_CHECK_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LT, l, r, lt) +#define DOCTEST_FAST_REQUIRE_LT(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LT, l, r, lt) +#define DOCTEST_FAST_WARN_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_GE, l, r, ge) +#define DOCTEST_FAST_CHECK_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_GE, l, r, ge) +#define DOCTEST_FAST_REQUIRE_GE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_GE, l, r, ge) +#define DOCTEST_FAST_WARN_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_WARN_LE, l, r, le) +#define DOCTEST_FAST_CHECK_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_CHECK_LE, l, r, le) +#define DOCTEST_FAST_REQUIRE_LE(l, r) DOCTEST_FAST_BINARY_ASSERT(DT_FAST_REQUIRE_LE, l, r, le) + +#define DOCTEST_FAST_WARN_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY, v) +#define DOCTEST_FAST_CHECK_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY, v) +#define DOCTEST_FAST_REQUIRE_UNARY(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY, v) +#define DOCTEST_FAST_WARN_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_WARN_UNARY_FALSE, v) +#define DOCTEST_FAST_CHECK_UNARY_FALSE(v) DOCTEST_FAST_UNARY_ASSERT(DT_FAST_CHECK_UNARY_FALSE, v) +#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(v) \ + DOCTEST_FAST_UNARY_ASSERT(DT_FAST_REQUIRE_UNARY_FALSE, v) + +// ================================================================================================= +// == WHAT FOLLOWS IS VERSIONS OF THE MACROS THAT DO NOT DO ANY REGISTERING! == +// == THIS CAN BE ENABLED BY DEFINING DOCTEST_CONFIG_DISABLE GLOBALLY! == +// ================================================================================================= +#else // DOCTEST_CONFIG_DISABLE + +#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \ + namespace \ + { \ + template \ + struct der : base \ + { void f(); }; \ + } \ + template \ + inline void der::f() + +#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, name) \ + template \ + static inline void f() + +// for registering tests +#define DOCTEST_TEST_CASE(name) \ + DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + +// for registering tests with a fixture +#define DOCTEST_TEST_CASE_FIXTURE(x, name) \ + DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \ + DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name) + +// for subcases +#define DOCTEST_SUBCASE(name) + +// for starting a testsuite block +#define DOCTEST_TEST_SUITE(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + +// for ending a testsuite block +#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_) + +#define DOCTEST_WARN(expr) ((void)0) +#define DOCTEST_WARN_FALSE(expr) ((void)0) +#define DOCTEST_WARN_THROWS(expr) ((void)0) +#define DOCTEST_WARN_THROWS_AS(expr, ex) ((void)0) +#define DOCTEST_WARN_NOTHROW(expr) ((void)0) +#define DOCTEST_CHECK(expr) ((void)0) +#define DOCTEST_CHECK_FALSE(expr) ((void)0) +#define DOCTEST_CHECK_THROWS(expr) ((void)0) +#define DOCTEST_CHECK_THROWS_AS(expr, ex) ((void)0) +#define DOCTEST_CHECK_NOTHROW(expr) ((void)0) +#define DOCTEST_REQUIRE(expr) ((void)0) +#define DOCTEST_REQUIRE_FALSE(expr) ((void)0) +#define DOCTEST_REQUIRE_THROWS(expr) ((void)0) +#define DOCTEST_REQUIRE_THROWS_AS(expr, ex) ((void)0) +#define DOCTEST_REQUIRE_NOTHROW(expr) ((void)0) + +#define DOCTEST_WARN_EQ(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_EQ(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_EQ(lhs, rhs) ((void)0) +#define DOCTEST_WARN_NE(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_NE(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_NE(lhs, rhs) ((void)0) +#define DOCTEST_WARN_GT(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_GT(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_GT(lhs, rhs) ((void)0) +#define DOCTEST_WARN_LT(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_LT(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_LT(lhs, rhs) ((void)0) +#define DOCTEST_WARN_GE(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_GE(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_GE(lhs, rhs) ((void)0) +#define DOCTEST_WARN_LE(lhs, rhs) ((void)0) +#define DOCTEST_CHECK_LE(lhs, rhs) ((void)0) +#define DOCTEST_REQUIRE_LE(lhs, rhs) ((void)0) + +#define DOCTEST_WARN_UNARY(val) ((void)0) +#define DOCTEST_CHECK_UNARY(val) ((void)0) +#define DOCTEST_REQUIRE_UNARY(val) ((void)0) +#define DOCTEST_WARN_UNARY_FALSE(val) ((void)0) +#define DOCTEST_CHECK_UNARY_FALSE(val) ((void)0) +#define DOCTEST_REQUIRE_UNARY_FALSE(val) ((void)0) + +#define DOCTEST_FAST_WARN_EQ(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_EQ(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_EQ(lhs, rhs) ((void)0) +#define DOCTEST_FAST_WARN_NE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_NE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_NE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_WARN_GT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_GT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_GT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_WARN_LT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_LT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_LT(lhs, rhs) ((void)0) +#define DOCTEST_FAST_WARN_GE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_GE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_GE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_WARN_LE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_CHECK_LE(lhs, rhs) ((void)0) +#define DOCTEST_FAST_REQUIRE_LE(lhs, rhs) ((void)0) + +#define DOCTEST_FAST_WARN_UNARY(val) ((void)0) +#define DOCTEST_FAST_CHECK_UNARY(val) ((void)0) +#define DOCTEST_FAST_REQUIRE_UNARY(val) ((void)0) +#define DOCTEST_FAST_WARN_UNARY_FALSE(val) ((void)0) +#define DOCTEST_FAST_CHECK_UNARY_FALSE(val) ((void)0) +#define DOCTEST_FAST_REQUIRE_UNARY_FALSE(val) ((void)0) + +#endif // DOCTEST_CONFIG_DISABLE + +// BDD style macros +// clang-format off +#define DOCTEST_SCENARIO(name) TEST_CASE(" Scenario: " name) +#define DOCTEST_GIVEN(name) SUBCASE(" Given: " name) +#define DOCTEST_WHEN(name) SUBCASE(" When: " name) +#define DOCTEST_AND_WHEN(name) SUBCASE("And when: " name) +#define DOCTEST_THEN(name) SUBCASE(" Then: " name) +#define DOCTEST_AND_THEN(name) SUBCASE(" And: " name) +// clang-format on + +// == SHORT VERSIONS OF THE MACROS +#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES) + +#define TEST_CASE DOCTEST_TEST_CASE +#define TEST_CASE_FIXTURE DOCTEST_TEST_CASE_FIXTURE +#define SUBCASE DOCTEST_SUBCASE +#define TEST_SUITE DOCTEST_TEST_SUITE +#define TEST_SUITE_END DOCTEST_TEST_SUITE_END +#define WARN DOCTEST_WARN +#define WARN_FALSE DOCTEST_WARN_FALSE +#define WARN_THROWS DOCTEST_WARN_THROWS +#define WARN_THROWS_AS DOCTEST_WARN_THROWS_AS +#define WARN_NOTHROW DOCTEST_WARN_NOTHROW +#define CHECK DOCTEST_CHECK +#define CHECK_FALSE DOCTEST_CHECK_FALSE +#define CHECK_THROWS DOCTEST_CHECK_THROWS +#define CHECK_THROWS_AS DOCTEST_CHECK_THROWS_AS +#define CHECK_NOTHROW DOCTEST_CHECK_NOTHROW +#define REQUIRE DOCTEST_REQUIRE +#define REQUIRE_FALSE DOCTEST_REQUIRE_FALSE +#define REQUIRE_THROWS DOCTEST_REQUIRE_THROWS +#define REQUIRE_THROWS_AS DOCTEST_REQUIRE_THROWS_AS +#define REQUIRE_NOTHROW DOCTEST_REQUIRE_NOTHROW + +#define SCENARIO DOCTEST_SCENARIO +#define GIVEN DOCTEST_GIVEN +#define WHEN DOCTEST_WHEN +#define AND_WHEN DOCTEST_AND_WHEN +#define THEN DOCTEST_THEN +#define AND_THEN DOCTEST_AND_THEN + +#define WARN_EQ DOCTEST_WARN_EQ +#define CHECK_EQ DOCTEST_CHECK_EQ +#define REQUIRE_EQ DOCTEST_REQUIRE_EQ +#define WARN_NE DOCTEST_WARN_NE +#define CHECK_NE DOCTEST_CHECK_NE +#define REQUIRE_NE DOCTEST_REQUIRE_NE +#define WARN_GT DOCTEST_WARN_GT +#define CHECK_GT DOCTEST_CHECK_GT +#define REQUIRE_GT DOCTEST_REQUIRE_GT +#define WARN_LT DOCTEST_WARN_LT +#define CHECK_LT DOCTEST_CHECK_LT +#define REQUIRE_LT DOCTEST_REQUIRE_LT +#define WARN_GE DOCTEST_WARN_GE +#define CHECK_GE DOCTEST_CHECK_GE +#define REQUIRE_GE DOCTEST_REQUIRE_GE +#define WARN_LE DOCTEST_WARN_LE +#define CHECK_LE DOCTEST_CHECK_LE +#define REQUIRE_LE DOCTEST_REQUIRE_LE +#define WARN_UNARY DOCTEST_WARN_UNARY +#define CHECK_UNARY DOCTEST_CHECK_UNARY +#define REQUIRE_UNARY DOCTEST_REQUIRE_UNARY +#define WARN_UNARY_FALSE DOCTEST_WARN_UNARY_FALSE +#define CHECK_UNARY_FALSE DOCTEST_CHECK_UNARY_FALSE +#define REQUIRE_UNARY_FALSE DOCTEST_REQUIRE_UNARY_FALSE + +#define FAST_WARN_EQ DOCTEST_FAST_WARN_EQ +#define FAST_CHECK_EQ DOCTEST_FAST_CHECK_EQ +#define FAST_REQUIRE_EQ DOCTEST_FAST_REQUIRE_EQ +#define FAST_WARN_NE DOCTEST_FAST_WARN_NE +#define FAST_CHECK_NE DOCTEST_FAST_CHECK_NE +#define FAST_REQUIRE_NE DOCTEST_FAST_REQUIRE_NE +#define FAST_WARN_GT DOCTEST_FAST_WARN_GT +#define FAST_CHECK_GT DOCTEST_FAST_CHECK_GT +#define FAST_REQUIRE_GT DOCTEST_FAST_REQUIRE_GT +#define FAST_WARN_LT DOCTEST_FAST_WARN_LT +#define FAST_CHECK_LT DOCTEST_FAST_CHECK_LT +#define FAST_REQUIRE_LT DOCTEST_FAST_REQUIRE_LT +#define FAST_WARN_GE DOCTEST_FAST_WARN_GE +#define FAST_CHECK_GE DOCTEST_FAST_CHECK_GE +#define FAST_REQUIRE_GE DOCTEST_FAST_REQUIRE_GE +#define FAST_WARN_LE DOCTEST_FAST_WARN_LE +#define FAST_CHECK_LE DOCTEST_FAST_CHECK_LE +#define FAST_REQUIRE_LE DOCTEST_FAST_REQUIRE_LE +#define FAST_WARN_UNARY DOCTEST_FAST_WARN_UNARY +#define FAST_CHECK_UNARY DOCTEST_FAST_CHECK_UNARY +#define FAST_REQUIRE_UNARY DOCTEST_FAST_REQUIRE_UNARY +#define FAST_WARN_UNARY_FALSE DOCTEST_FAST_WARN_UNARY_FALSE +#define FAST_CHECK_UNARY_FALSE DOCTEST_FAST_CHECK_UNARY_FALSE +#define FAST_REQUIRE_UNARY_FALSE DOCTEST_FAST_REQUIRE_UNARY_FALSE + +#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES + +// this is here to clear the 'current test suite' for the current translation unit - at the top +DOCTEST_TEST_SUITE_END(); + +#endif // DOCTEST_LIBRARY_INCLUDED + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic pop +#endif // > gcc 4.6 +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#ifndef DOCTEST_SINGLE_HEADER +#define DOCTEST_SINGLE_HEADER +#endif // DOCTEST_SINGLE_HEADER + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wglobal-constructors" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wsign-conversion" +#pragma clang diagnostic ignored "-Wshorten-64-to-32" +#pragma clang diagnostic ignored "-Wmissing-variable-declarations" +#pragma clang diagnostic ignored "-Wswitch" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#pragma clang diagnostic ignored "-Wmissing-noreturn" +#pragma clang diagnostic ignored "-Wunused-local-typedef" +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic push +#endif // > gcc 4.6 +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC diagnostic ignored "-Wconversion" +#pragma GCC diagnostic ignored "-Weffc++" +#pragma GCC diagnostic ignored "-Wsign-conversion" +#pragma GCC diagnostic ignored "-Wstrict-overflow" +#pragma GCC diagnostic ignored "-Wmissing-declarations" +#pragma GCC diagnostic ignored "-Winline" +#pragma GCC diagnostic ignored "-Wswitch" +#pragma GCC diagnostic ignored "-Wswitch-enum" +#pragma GCC diagnostic ignored "-Wswitch-default" +#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif // > gcc 4.6 +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7) +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#endif // > gcc 4.7 +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ > 3) +#pragma GCC diagnostic ignored "-Wuseless-cast" +#endif // > gcc 5.3 +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4996) // The compiler encountered a deprecated declaration +#pragma warning(disable : 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data +#pragma warning(disable : 4706) // assignment within conditional expression +#pragma warning(disable : 4512) // 'class' : assignment operator could not be generated +#pragma warning(disable : 4127) // conditional expression is constant +#endif // _MSC_VER + +#if defined(DOCTEST_CONFIG_IMPLEMENT) || defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) || \ + !defined(DOCTEST_SINGLE_HEADER) +#ifndef DOCTEST_LIBRARY_IMPLEMENTATION +#define DOCTEST_LIBRARY_IMPLEMENTATION + +#ifndef DOCTEST_SINGLE_HEADER +#include "doctest_fwd.h" +#endif // DOCTEST_SINGLE_HEADER + +#if defined(__clang__) && defined(DOCTEST_NO_CPP11_COMPAT) +#pragma clang diagnostic ignored "-Wc++98-compat" +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif // __clang__ && DOCTEST_NO_CPP11_COMPAT + +// snprintf() not in the C++98 standard +#ifdef _MSC_VER +#define DOCTEST_SNPRINTF _snprintf +#else +#define DOCTEST_SNPRINTF snprintf +#endif + +#define DOCTEST_LOG_START() \ + do { \ + if(!DOCTEST_GCS().hasLoggedCurrentTestStart) { \ + doctest::detail::logTestStart(DOCTEST_GCS().currentTest->m_name, \ + DOCTEST_GCS().currentTest->m_file, \ + DOCTEST_GCS().currentTest->m_line); \ + DOCTEST_GCS().hasLoggedCurrentTestStart = true; \ + } \ + } while(doctest::detail::always_false()) + +// required includes - will go only in one translation unit! +#include +#include +// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37 +#ifdef __BORLANDC__ +#include +#endif // __BORLANDC__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace doctest +{ +namespace detail +{ + // not using std::strlen() because of valgrind errors when optimizations are turned on + // 'Invalid read of size 4' when the test suite len (with '\0') is not a multiple of 4 + // for details see http://stackoverflow.com/questions/35671155 + size_t my_strlen(const char* in) { + const char* temp = in; + while(temp && *temp) + ++temp; + return temp - in; + } + + template + T my_max(const T& lhs, const T& rhs) { + return lhs > rhs ? lhs : rhs; + } + + // case insensitive strcmp + int stricmp(char const* a, char const* b) { + for(;; a++, b++) { + int d = tolower(*a) - tolower(*b); + if(d != 0 || !*a) + return d; + } + } + + template + String fpToString(T value, int precision) { + std::ostringstream oss; + oss << std::setprecision(precision) << std::fixed << value; + std::string d = oss.str(); + size_t i = d.find_last_not_of('0'); + if(i != std::string::npos && i != d.size() - 1) { + if(d[i] == '.') + i++; + d = d.substr(0, i + 1); + } + return d.c_str(); + } + + struct Endianness + { + enum Arch + { + Big, + Little + }; + + static Arch which() { + union _ + { + int asInt; + char asChar[sizeof(int)]; + } u; + + u.asInt = 1; + return (u.asChar[sizeof(int) - 1] == 1) ? Big : Little; + } + }; + + String rawMemoryToString(const void* object, unsigned size) { + // Reverse order for little endian architectures + int i = 0, end = static_cast(size), inc = 1; + if(Endianness::which() == Endianness::Little) { + i = end - 1; + end = inc = -1; + } + + unsigned char const* bytes = static_cast(object); + std::ostringstream os; + os << "0x" << std::setfill('0') << std::hex; + for(; i != end; i += inc) + os << std::setw(2) << static_cast(bytes[i]); + return os.str().c_str(); + } + + std::ostream* createStream() { return new std::ostringstream(); } + String getStreamResult(std::ostream* in) { + return static_cast(in)->str().c_str(); + } + void freeStream(std::ostream* in) { delete in; } + +#ifndef DOCTEST_CONFIG_DISABLE + + // this holds both parameters for the command line and runtime data for tests + struct ContextState : TestAccessibleContextState + { + // == parameters from the command line + + std::vector > filters; + + String order_by; // how tests should be ordered + unsigned rand_seed; // the seed for rand ordering + + unsigned first; // the first (matching) test to be executed + unsigned last; // the last (matching) test to be executed + + int abort_after; // stop tests after this many failed assertions + bool case_sensitive; // if filtering should be case sensitive + bool exit; // if the program should be exited after the tests are ran/whatever + bool no_exitcode; // if the framework should return 0 as the exitcode + bool no_run; // to not run the tests at all (can be done with an "*" exclude) + bool no_colors; // if output to the console should be colorized + bool no_path_in_filenames; // if the path to files should be removed from the output + + bool help; // to print the help + bool version; // to print the version + bool count; // if only the count of matching tests is to be retreived + bool list_test_cases; // to list all tests matching the filters + bool list_test_suites; // to list all suites matching the filters + + // == data for the tests being ran + + int numAssertions; + int numFailedAssertions; + int numFailedAssertionsForCurrentTestcase; + + // stuff for subcases + std::set subcasesPassed; + std::set subcasesEnteredLevels; + std::vector subcasesStack; + int subcasesCurrentLevel; + bool subcasesHasSkipped; + + void resetRunData() { + numAssertions = 0; + numFailedAssertions = 0; + } + + ContextState() + : filters(6) // 6 different filters total + { + resetRunData(); + } + }; + + ContextState*& getContextState(); +#endif // DOCTEST_CONFIG_DISABLE +} // namespace detail + +String::String(const char* in) + : m_str(static_cast(malloc(detail::my_strlen(in) + 1))) { + if(in) + strcpy(m_str, in); + else + m_str[0] = '\0'; +} + +String::String(const String& other) + : m_str(0) { + copy(other); +} + +void String::copy(const String& other) { + if(m_str) + free(m_str); + m_str = static_cast(malloc(detail::my_strlen(other.m_str) + 1)); + strcpy(m_str, other.m_str); +} + +String::~String() { free(m_str); } + +String& String::operator=(const String& other) { + if(this != &other) + copy(other); + return *this; +} + +String String::operator+(const String& other) const { return String(m_str) += other; } + +String& String::operator+=(const String& other) { + using namespace detail; + if(other.m_str != 0) { + char* newStr = static_cast(malloc(my_strlen(m_str) + my_strlen(other.m_str) + 1)); + strcpy(newStr, m_str); + strcpy(newStr + my_strlen(m_str), other.m_str); + free(m_str); + m_str = newStr; + } + return *this; +} + +unsigned String::size() const { return m_str ? detail::my_strlen(m_str) : 0; } +unsigned String::length() const { return size(); } + +int String::compare(const char* other, bool no_case) const { + if(no_case) + return detail::stricmp(m_str, other); + return strcmp(m_str, other); +} + +int String::compare(const String& other, bool no_case) const { + if(no_case) + return detail::stricmp(m_str, other.m_str); + return strcmp(m_str, other.m_str); +} + +std::ostream& operator<<(std::ostream& stream, const String& in) { + stream << in.c_str(); + return stream; +} + +Approx::Approx(double value) + : m_epsilon(static_cast(std::numeric_limits::epsilon()) * 100) + , m_scale(1.0) + , m_value(value) {} + +bool operator==(double lhs, Approx const& rhs) { + // Thanks to Richard Harris for his help refining this formula + return fabs(lhs - rhs.m_value) < + rhs.m_epsilon * (rhs.m_scale + detail::my_max(fabs(lhs), fabs(rhs.m_value))); +} + +String Approx::toString() const { return String("Approx( ") + doctest::toString(m_value) + " )"; } + +#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(char* in) { return toString(static_cast(in)); } +String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; } +#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING +String toString(bool in) { return in ? "true" : "false"; } +String toString(float in) { return detail::fpToString(in, 5) + "f"; } +String toString(double in) { return detail::fpToString(in, 10); } +String toString(double long in) { return detail::fpToString(in, 15); } + +String toString(char in) { + char buf[64]; + sprintf(buf, "%d", in); + return buf; +} + +String toString(char unsigned in) { + char buf[64]; + sprintf(buf, "%ud", in); + return buf; +} + +String toString(int short in) { + char buf[64]; + sprintf(buf, "%d", in); + return buf; +} + +String toString(int short unsigned in) { + char buf[64]; + sprintf(buf, "%u", in); + return buf; +} + +String toString(int in) { + char buf[64]; + sprintf(buf, "%d", in); + return buf; +} + +String toString(int unsigned in) { + char buf[64]; + sprintf(buf, "%u", in); + return buf; +} + +String toString(int long in) { + char buf[64]; + sprintf(buf, "%ld", in); + return buf; +} + +String toString(int long unsigned in) { + char buf[64]; + sprintf(buf, "%lu", in); + return buf; +} + +#ifdef DOCTEST_CONFIG_WITH_LONG_LONG +String toString(int long long in) { + char buf[64]; + sprintf(buf, "%lld", in); + return buf; +} +String toString(int long long unsigned in) { + char buf[64]; + sprintf(buf, "%llu", in); + return buf; +} +#endif // DOCTEST_CONFIG_WITH_LONG_LONG + +#ifdef DOCTEST_CONFIG_WITH_NULLPTR +String toString(std::nullptr_t) { return "nullptr"; } +#endif // DOCTEST_CONFIG_WITH_NULLPTR + +} // namespace doctest + +#if defined(DOCTEST_CONFIG_DISABLE) +namespace doctest +{ +Context::Context(int, const char* const*) {} +Context::~Context() {} +void Context::applyCommandLine(int, const char* const*) {} +void Context::addFilter(const char*, const char*) {} +void Context::clearFilters() {} +void Context::setOption(const char*, int) {} +void Context::setOption(const char*, const char*) {} +bool Context::shouldExit() { return false; } +int Context::run() { return 0; } +} // namespace doctest +#else // DOCTEST_CONFIG_DISABLE + +#if !defined(DOCTEST_CONFIG_COLORS_NONE) +#if !defined(DOCTEST_CONFIG_COLORS_WINDOWS) && !defined(DOCTEST_CONFIG_COLORS_ANSI) +#ifdef DOCTEST_PLATFORM_WINDOWS +#define DOCTEST_CONFIG_COLORS_WINDOWS +#else // linux +#define DOCTEST_CONFIG_COLORS_ANSI +#endif // platform +#endif // DOCTEST_CONFIG_COLORS_WINDOWS && DOCTEST_CONFIG_COLORS_ANSI +#endif // DOCTEST_CONFIG_COLORS_NONE + +#define DOCTEST_PRINTF_COLORED(buffer, color) \ + do { \ + if(buffer[0] != 0) { \ + doctest::detail::Color col(color); \ + printf("%s", buffer); \ + } \ + } while(doctest::detail::always_false()) + +// the buffer size used for snprintf() calls +#if !defined(DOCTEST_SNPRINTF_BUFFER_LENGTH) +#define DOCTEST_SNPRINTF_BUFFER_LENGTH 1024 +#endif // DOCTEST_SNPRINTF_BUFFER_LENGTH + +#if defined(_MSC_VER) || defined(__MINGW32__) +#if defined(_MSC_VER) && _MSC_VER >= 1700 +#define DOCTEST_WINDOWS_SAL_IN_OPT _In_opt_ +#else // _MSC_VER +#define DOCTEST_WINDOWS_SAL_IN_OPT +#endif // _MSC_VER +extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( + DOCTEST_WINDOWS_SAL_IN_OPT const char*); +extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); +#endif // _MSC_VER || __MINGW32__ + +#ifdef DOCTEST_CONFIG_COLORS_ANSI +#include +#endif // DOCTEST_CONFIG_COLORS_ANSI + +#ifdef DOCTEST_CONFIG_COLORS_WINDOWS + +// defines for a leaner windows.h +#ifndef WIN32_MEAN_AND_LEAN +#define WIN32_MEAN_AND_LEAN +#endif // WIN32_MEAN_AND_LEAN +#ifndef VC_EXTRA_LEAN +#define VC_EXTRA_LEAN +#endif // VC_EXTRA_LEAN +#ifndef NOMINMAX +#define NOMINMAX +#endif // NOMINMAX + +// not sure what AfxWin.h is for - here I do what Catch does +#ifdef __AFXDLL +#include +#else +#include +#endif + +#endif // DOCTEST_CONFIG_COLORS_WINDOWS + +namespace doctest +{ +namespace detail +{ + bool TestData::operator<(const TestData& other) const { + if(m_line != other.m_line) + return m_line < other.m_line; + return strcmp(m_file, other.m_file) < 0; + } + + const char* getAssertString(assertType::Enum val) { + switch(val) { + // clang-format off + case assertType::DT_WARN : return "WARN"; + case assertType::DT_CHECK : return "CHECK"; + case assertType::DT_REQUIRE : return "REQUIRE"; + + case assertType::DT_WARN_FALSE : return "WARN_FALSE"; + case assertType::DT_CHECK_FALSE : return "CHECK_FALSE"; + case assertType::DT_REQUIRE_FALSE : return "REQUIRE_FALSE"; + + case assertType::DT_WARN_THROWS : return "WARN_THROWS"; + case assertType::DT_CHECK_THROWS : return "CHECK_THROWS"; + case assertType::DT_REQUIRE_THROWS : return "REQUIRE_THROWS"; + + case assertType::DT_WARN_THROWS_AS : return "WARN_THROWS_AS"; + case assertType::DT_CHECK_THROWS_AS : return "CHECK_THROWS_AS"; + case assertType::DT_REQUIRE_THROWS_AS : return "REQUIRE_THROWS_AS"; + + case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW"; + case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW"; + case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW"; + + case assertType::DT_WARN_EQ : return "WARN_EQ"; + case assertType::DT_CHECK_EQ : return "CHECK_EQ"; + case assertType::DT_REQUIRE_EQ : return "REQUIRE_EQ"; + case assertType::DT_WARN_NE : return "WARN_NE"; + case assertType::DT_CHECK_NE : return "CHECK_NE"; + case assertType::DT_REQUIRE_NE : return "REQUIRE_NE"; + case assertType::DT_WARN_GT : return "WARN_GT"; + case assertType::DT_CHECK_GT : return "CHECK_GT"; + case assertType::DT_REQUIRE_GT : return "REQUIRE_GT"; + case assertType::DT_WARN_LT : return "WARN_LT"; + case assertType::DT_CHECK_LT : return "CHECK_LT"; + case assertType::DT_REQUIRE_LT : return "REQUIRE_LT"; + case assertType::DT_WARN_GE : return "WARN_GE"; + case assertType::DT_CHECK_GE : return "CHECK_GE"; + case assertType::DT_REQUIRE_GE : return "REQUIRE_GE"; + case assertType::DT_WARN_LE : return "WARN_LE"; + case assertType::DT_CHECK_LE : return "CHECK_LE"; + case assertType::DT_REQUIRE_LE : return "REQUIRE_LE"; + + case assertType::DT_WARN_UNARY : return "WARN_UNARY"; + case assertType::DT_CHECK_UNARY : return "CHECK_UNARY"; + case assertType::DT_REQUIRE_UNARY : return "REQUIRE_UNARY"; + case assertType::DT_WARN_UNARY_FALSE : return "WARN_UNARY_FALSE"; + case assertType::DT_CHECK_UNARY_FALSE : return "CHECK_UNARY_FALSE"; + case assertType::DT_REQUIRE_UNARY_FALSE : return "REQUIRE_UNARY_FALSE"; + + case assertType::DT_FAST_WARN_EQ : return "FAST_WARN_EQ"; + case assertType::DT_FAST_CHECK_EQ : return "FAST_CHECK_EQ"; + case assertType::DT_FAST_REQUIRE_EQ : return "FAST_REQUIRE_EQ"; + case assertType::DT_FAST_WARN_NE : return "FAST_WARN_NE"; + case assertType::DT_FAST_CHECK_NE : return "FAST_CHECK_NE"; + case assertType::DT_FAST_REQUIRE_NE : return "FAST_REQUIRE_NE"; + case assertType::DT_FAST_WARN_GT : return "FAST_WARN_GT"; + case assertType::DT_FAST_CHECK_GT : return "FAST_CHECK_GT"; + case assertType::DT_FAST_REQUIRE_GT : return "FAST_REQUIRE_GT"; + case assertType::DT_FAST_WARN_LT : return "FAST_WARN_LT"; + case assertType::DT_FAST_CHECK_LT : return "FAST_CHECK_LT"; + case assertType::DT_FAST_REQUIRE_LT : return "FAST_REQUIRE_LT"; + case assertType::DT_FAST_WARN_GE : return "FAST_WARN_GE"; + case assertType::DT_FAST_CHECK_GE : return "FAST_CHECK_GE"; + case assertType::DT_FAST_REQUIRE_GE : return "FAST_REQUIRE_GE"; + case assertType::DT_FAST_WARN_LE : return "FAST_WARN_LE"; + case assertType::DT_FAST_CHECK_LE : return "FAST_CHECK_LE"; + case assertType::DT_FAST_REQUIRE_LE : return "FAST_REQUIRE_LE"; + + case assertType::DT_FAST_WARN_UNARY : return "FAST_WARN_UNARY"; + case assertType::DT_FAST_CHECK_UNARY : return "FAST_CHECK_UNARY"; + case assertType::DT_FAST_REQUIRE_UNARY : return "FAST_REQUIRE_UNARY"; + case assertType::DT_FAST_WARN_UNARY_FALSE : return "FAST_WARN_UNARY_FALSE"; + case assertType::DT_FAST_CHECK_UNARY_FALSE : return "FAST_CHECK_UNARY_FALSE"; + case assertType::DT_FAST_REQUIRE_UNARY_FALSE: return "FAST_REQUIRE_UNARY_FALSE"; + // clang-format on + } + return ""; + } + + bool checkIfShouldThrow(assertType::Enum assert_type) { + if(assert_type & assertType::is_require) + return true; + + if((assert_type & assertType::is_check) && getContextState()->abort_after > 0) { + if(getContextState()->numFailedAssertions >= getContextState()->abort_after) + return true; + } + + return false; + } + void fastAssertThrowIfFlagSet(int flags) { + if(flags & assertAction::shouldthrow) + throwException(); + } + void throwException() { throw TestFailureException(); } + bool always_false() { return false; } + + // lowers ascii letters + char tolower(const char c) { return ((c >= 'A' && c <= 'Z') ? static_cast(c + 32) : c); } + + // matching of a string against a wildcard mask (case sensitivity configurable) taken from + // http://www.emoticode.net/c/simple-wildcard-string-compare-globbing-function.html + int wildcmp(const char* str, const char* wild, bool caseSensitive) { + const char* cp = 0; + const char* mp = 0; + + // rolled my own tolower() to not include more headers + while((*str) && (*wild != '*')) { + if((caseSensitive ? (*wild != *str) : (tolower(*wild) != tolower(*str))) && + (*wild != '?')) { + return 0; + } + wild++; + str++; + } + + while(*str) { + if(*wild == '*') { + if(!*++wild) { + return 1; + } + mp = wild; + cp = str + 1; + } else if((caseSensitive ? (*wild == *str) : (tolower(*wild) == tolower(*str))) || + (*wild == '?')) { + wild++; + str++; + } else { + wild = mp; + str = cp++; + } + } + + while(*wild == '*') { + wild++; + } + return !*wild; + } + + //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html + //unsigned hashStr(unsigned const char* str) { + // unsigned long hash = 5381; + // char c; + // while((c = *str++)) + // hash = ((hash << 5) + hash) + c; // hash * 33 + c + // return hash; + //} + + // checks if the name matches any of the filters (and can be configured what to do when empty) + int matchesAny(const char* name, std::vector filters, int matchEmpty, + bool caseSensitive) { + if(filters.size() == 0 && matchEmpty) + return 1; + for(unsigned i = 0; i < filters.size(); ++i) + if(wildcmp(name, filters[i].c_str(), caseSensitive)) + return 1; + return 0; + } + + // the current ContextState with which tests are being executed + ContextState*& getContextState() { + static ContextState* data = 0; + return data; + } + + TestAccessibleContextState* getTestsContextState() { return getContextState(); } + + bool SubcaseSignature::operator<(const SubcaseSignature& other) const { + if(m_line != other.m_line) + return m_line < other.m_line; + if(strcmp(m_file, other.m_file) != 0) + return strcmp(m_file, other.m_file) < 0; + return strcmp(m_name, other.m_name) < 0; + } + + Subcase::Subcase(const char* name, const char* file, int line) + : m_signature(name, file, line) + , m_entered(false) { + ContextState* s = getContextState(); + + // if we have already completed it + if(s->subcasesPassed.count(m_signature) != 0) + return; + + // if a Subcase on the same level has already been entered + if(s->subcasesEnteredLevels.count(s->subcasesCurrentLevel) != 0) { + s->subcasesHasSkipped = true; + return; + } + + s->subcasesStack.push_back(*this); + if(s->hasLoggedCurrentTestStart) + logTestEnd(); + s->hasLoggedCurrentTestStart = false; + + s->subcasesEnteredLevels.insert(s->subcasesCurrentLevel++); + m_entered = true; + } + + Subcase::Subcase(const Subcase& other) + : m_signature(other.m_signature.m_name, other.m_signature.m_file, + other.m_signature.m_line) + , m_entered(other.m_entered) {} + + Subcase::~Subcase() { + if(m_entered) { + ContextState* s = getContextState(); + + s->subcasesCurrentLevel--; + // only mark the subcase as passed if no subcases have been skipped + if(s->subcasesHasSkipped == false) + s->subcasesPassed.insert(m_signature); + + if(s->subcasesStack.size() > 0) + s->subcasesStack.pop_back(); + if(s->hasLoggedCurrentTestStart) + logTestEnd(); + s->hasLoggedCurrentTestStart = false; + } + } + + // for sorting tests by file/line + int fileOrderComparator(const void* a, const void* b) { + const TestData* lhs = *static_cast(a); + const TestData* rhs = *static_cast(b); +#ifdef _MSC_VER + // this is needed because MSVC gives different case for drive letters + // for __FILE__ when evaluated in a header and a source file + int res = stricmp(lhs->m_file, rhs->m_file); +#else // _MSC_VER + int res = strcmp(lhs->m_file, rhs->m_file); +#endif // _MSC_VER + if(res != 0) + return res; + return static_cast(lhs->m_line - rhs->m_line); + } + + // for sorting tests by suite/file/line + int suiteOrderComparator(const void* a, const void* b) { + const TestData* lhs = *static_cast(a); + const TestData* rhs = *static_cast(b); + + int res = strcmp(lhs->m_suite, rhs->m_suite); + if(res != 0) + return res; + return fileOrderComparator(a, b); + } + + // for sorting tests by name/suite/file/line + int nameOrderComparator(const void* a, const void* b) { + const TestData* lhs = *static_cast(a); + const TestData* rhs = *static_cast(b); + + int res = strcmp(lhs->m_name, rhs->m_name); + if(res != 0) + return res; + return suiteOrderComparator(a, b); + } + + // holds the current test suite + const char*& getCurrentTestSuite() { + static const char* data = 0; + return data; + } + + // sets the current test suite + int setTestSuiteName(const char* name) { + getCurrentTestSuite() = name; + return 0; + } + + // all the registered tests + std::set& getRegisteredTests() { + static std::set data; + return data; + } + + // used by the macros for registering tests + int regTest(funcType f, unsigned line, const char* file, const char* name) { + getRegisteredTests().insert(TestData(getCurrentTestSuite(), name, f, file, line)); + return 0; + } + + struct Color + { + enum Code + { + None = 0, + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White + }; + Color(Code code) { use(code); } + ~Color() { use(None); } + + void use(Code code); + + private: + Color(Color const& other); + }; + + void Color::use(Code +#ifndef DOCTEST_CONFIG_COLORS_NONE + code +#endif // DOCTEST_CONFIG_COLORS_NONE + ) { + ContextState* p = getContextState(); + if(p->no_colors) + return; +#ifdef DOCTEST_CONFIG_COLORS_ANSI + if(isatty(STDOUT_FILENO)) { + const char* col = ""; + // clang-format off + switch(code) { + case Color::Red: col = "[0;31m"; break; + case Color::Green: col = "[0;32m"; break; + case Color::Blue: col = "[0;34m"; break; + case Color::Cyan: col = "[0;36m"; break; + case Color::Yellow: col = "[0;33m"; break; + case Color::Grey: col = "[1;30m"; break; + case Color::LightGrey: col = "[0;37m"; break; + case Color::BrightRed: col = "[1;31m"; break; + case Color::BrightGreen: col = "[1;32m"; break; + case Color::BrightWhite: col = "[1;37m"; break; + case Color::Bright: // invalid + case Color::None: + case Color::White: + default: col = "[0m"; + } + // clang-format on + printf("\033%s", col); + } +#endif // DOCTEST_CONFIG_COLORS_ANSI + +#ifdef DOCTEST_CONFIG_COLORS_WINDOWS + static HANDLE stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE)); + static WORD originalForegroundAttributes; + static WORD originalBackgroundAttributes; + static bool attrsInitted = false; + if(!attrsInitted) { + attrsInitted = true; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo); + originalForegroundAttributes = + csbiInfo.wAttributes & + ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY); + originalBackgroundAttributes = + csbiInfo.wAttributes & + ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY); + } + +#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(stdoutHandle, x | originalBackgroundAttributes) + + // clang-format off + switch (code) { + case Color::White: DOCTEST_SET_ATTR(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::Red: DOCTEST_SET_ATTR(FOREGROUND_RED); break; + case Color::Green: DOCTEST_SET_ATTR(FOREGROUND_GREEN); break; + case Color::Blue: DOCTEST_SET_ATTR(FOREGROUND_BLUE); break; + case Color::Cyan: DOCTEST_SET_ATTR(FOREGROUND_BLUE | FOREGROUND_GREEN); break; + case Color::Yellow: DOCTEST_SET_ATTR(FOREGROUND_RED | FOREGROUND_GREEN); break; + case Color::Grey: DOCTEST_SET_ATTR(0); break; + case Color::LightGrey: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY); break; + case Color::BrightRed: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_RED); break; + case Color::BrightGreen: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN); break; + case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break; + case Color::None: + case Color::Bright: // invalid + default: DOCTEST_SET_ATTR(originalForegroundAttributes); + } +// clang-format on +#undef DOCTEST_SET_ATTR +#endif // DOCTEST_CONFIG_COLORS_WINDOWS + } + + // this is needed because MSVC does not permit mixing 2 exception handling schemes in a function + int callTestFunc(funcType f) { + int res = EXIT_SUCCESS; + try { + f(); + if(getContextState()->numFailedAssertionsForCurrentTestcase) + res = EXIT_FAILURE; + } catch(const TestFailureException&) { res = EXIT_FAILURE; } catch(...) { + DOCTEST_LOG_START(); + logTestCrashed(); + res = EXIT_FAILURE; + } + return res; + } + + // depending on the current options this will remove the path of filenames + const char* fileForOutput(const char* file) { + if(getContextState()->no_path_in_filenames) { + const char* back = strrchr(file, '\\'); + const char* forward = strrchr(file, '/'); + if(back || forward) { + if(back > forward) + forward = back; + return forward + 1; + } + } + return file; + } + +#ifdef DOCTEST_PLATFORM_MAC +#include +#include +#include + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive() { + int mib[4]; + struct kinfo_proc info; + size_t size; + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + // Call sysctl. + size = sizeof(info); + if(sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, 0, 0) != 0) { + fprintf(stderr, "\n** Call to sysctl failed - unable to determine if debugger is " + "active **\n\n"); + return false; + } + // We're being debugged if the P_TRACED flag is set. + return ((info.kp_proc.p_flag & P_TRACED) != 0); + } +#elif defined(_MSC_VER) || defined(__MINGW32__) + bool isDebuggerActive() { return ::IsDebuggerPresent() != 0; } +#else + bool isDebuggerActive() { return false; } +#endif // Platform + +#ifdef DOCTEST_PLATFORM_WINDOWS + void myOutputDebugString(const String& text) { ::OutputDebugStringA(text.c_str()); } +#else + // TODO: integration with XCode and other IDEs + void myOutputDebugString(const String&) {} +#endif // Platform + + const char* getSeparator() { + return "===============================================================================\n"; + } + + void printToDebugConsole(const String& text) { + if(isDebuggerActive()) + myOutputDebugString(text.c_str()); + } + + void addFailedAssert(assertType::Enum assert_type) { + if((assert_type & assertType::is_warn) == 0) { + getContextState()->numFailedAssertionsForCurrentTestcase++; + getContextState()->numFailedAssertions++; + } + } + + void logTestStart(const char* name, const char* file, unsigned line) { + const char* newLine = "\n"; + + char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)\n", fileForOutput(file), line); + + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "%s\n", name); + + DOCTEST_PRINTF_COLORED(getSeparator(), Color::Yellow); + DOCTEST_PRINTF_COLORED(loc, Color::LightGrey); + DOCTEST_PRINTF_COLORED(msg, Color::None); + + String subcaseStuff = ""; + std::vector& subcasesStack = getContextState()->subcasesStack; + for(unsigned i = 0; i < subcasesStack.size(); ++i) { + char subcase[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(subcase, DOCTEST_COUNTOF(loc), " %s\n", + subcasesStack[i].m_signature.m_name); + DOCTEST_PRINTF_COLORED(subcase, Color::None); + subcaseStuff += subcase; + } + + DOCTEST_PRINTF_COLORED(newLine, Color::None); + + printToDebugConsole(String(getSeparator()) + loc + msg + subcaseStuff.c_str() + newLine); + } + + void logTestEnd() {} + + void logTestCrashed() { + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), "TEST CASE FAILED! (threw exception)\n\n"); + + DOCTEST_PRINTF_COLORED(msg, Color::Red); + + printToDebugConsole(String(msg)); + } + + void logAssert(bool passed, const char* decomposition, bool threw, const char* expr, + assertType::Enum assert_type, const char* file, int line) { + char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line); + + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + if(passed) + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n"); + else + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n", + (threw ? "(threw exception)" : "")); + + char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n", + getAssertString(assert_type), expr); + + char info2[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + char info3[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + info2[0] = 0; + info3[0] = 0; + if(!threw) { + DOCTEST_SNPRINTF(info2, DOCTEST_COUNTOF(info2), "with expansion:\n"); + DOCTEST_SNPRINTF(info3, DOCTEST_COUNTOF(info3), " %s( %s )\n", + getAssertString(assert_type), decomposition); + } + + DOCTEST_PRINTF_COLORED(loc, Color::LightGrey); + DOCTEST_PRINTF_COLORED(msg, passed ? Color::BrightGreen : Color::Red); + DOCTEST_PRINTF_COLORED(info1, Color::Cyan); + DOCTEST_PRINTF_COLORED(info2, Color::None); + DOCTEST_PRINTF_COLORED(info3, Color::Cyan); + DOCTEST_PRINTF_COLORED("\n", Color::None); + + printToDebugConsole(String(loc) + msg + info1 + info2 + info3 + "\n"); + } + + void logAssertThrows(bool threw, const char* expr, assertType::Enum assert_type, + const char* file, int line) { + char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line); + + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + if(threw) + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n"); + else + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n"); + + char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n", + getAssertString(assert_type), expr); + + DOCTEST_PRINTF_COLORED(loc, Color::LightGrey); + DOCTEST_PRINTF_COLORED(msg, threw ? Color::BrightGreen : Color::Red); + DOCTEST_PRINTF_COLORED(info1, Color::Cyan); + + printToDebugConsole(String(loc) + msg + info1); + } + + void logAssertThrowsAs(bool threw, bool threw_as, const char* as, const char* expr, + assertType::Enum assert_type, const char* file, int line) { + char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line); + + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + if(threw_as) + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n"); + else + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED! %s\n", + (threw ? "(threw something else)" : "(didn't throw at all)")); + + char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s, %s )\n\n", + getAssertString(assert_type), expr, as); + + DOCTEST_PRINTF_COLORED(loc, Color::LightGrey); + DOCTEST_PRINTF_COLORED(msg, threw_as ? Color::BrightGreen : Color::Red); + DOCTEST_PRINTF_COLORED(info1, Color::Cyan); + + printToDebugConsole(String(loc) + msg + info1); + } + + void logAssertNothrow(bool threw, const char* expr, assertType::Enum assert_type, + const char* file, int line) { + char loc[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(loc, DOCTEST_COUNTOF(loc), "%s(%d)", fileForOutput(file), line); + + char msg[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + if(!threw) + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " PASSED!\n"); + else + DOCTEST_SNPRINTF(msg, DOCTEST_COUNTOF(msg), " FAILED!\n"); + + char info1[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + DOCTEST_SNPRINTF(info1, DOCTEST_COUNTOF(info1), " %s( %s )\n\n", + getAssertString(assert_type), expr); + + DOCTEST_PRINTF_COLORED(loc, Color::LightGrey); + DOCTEST_PRINTF_COLORED(msg, !threw ? Color::BrightGreen : Color::Red); + DOCTEST_PRINTF_COLORED(info1, Color::Cyan); + + printToDebugConsole(String(loc) + msg + info1); + } + + ResultBuilder::ResultBuilder(assertType::Enum assert_type, const char* file, int line, + const char* expr, const char* exception_type) + : m_assert_type(assert_type) + , m_file(file) + , m_line(line) + , m_expr(expr) + , m_exception_type(exception_type) + , m_threw(false) + , m_threw_as(false) + , m_failed(false) {} + + bool ResultBuilder::log() { + if((m_assert_type & assertType::is_warn) == 0) + DOCTEST_GCS().numAssertionsForCurrentTestcase++; + + if(m_assert_type & assertType::is_false) { + m_result.invert(); + m_failed = m_result; + } else if(m_assert_type & assertType::is_throws) { + m_failed = !m_threw; + } else if(m_assert_type & assertType::is_throws_as) { + m_failed = !m_threw_as; + } else if(m_assert_type & assertType::is_nothrow) { + m_failed = m_threw; + } else { + m_failed = m_result; + } + + if(m_failed || DOCTEST_GCS().success) { + DOCTEST_LOG_START(); + + if(m_assert_type & assertType::is_throws) { + logAssertThrows(m_threw, m_expr, m_assert_type, m_file, m_line); + } else if(m_assert_type & assertType::is_throws_as) { + logAssertThrowsAs(m_threw, m_threw_as, m_exception_type, m_expr, m_assert_type, + m_file, m_line); + } else if(m_assert_type & assertType::is_nothrow) { + logAssertNothrow(m_threw, m_expr, m_assert_type, m_file, m_line); + } else { + logAssert(m_result.m_passed, m_result.m_decomposition.c_str(), m_threw, m_expr, + m_assert_type, m_file, m_line); + } + } + + if(m_failed) { + addFailedAssert(m_assert_type); + if(isDebuggerActive() && !DOCTEST_GCS().no_breaks) + return true; // should break into the debugger + } + return false; + } + + void ResultBuilder::react() const { + if(m_failed && checkIfShouldThrow(m_assert_type)) + throwException(); + } + + // the implementation of parseFlag() + bool parseFlagImpl(int argc, const char* const* argv, const char* pattern) { + for(int i = argc - 1; i >= 0; --i) { + const char* temp = strstr(argv[i], pattern); + if(temp && my_strlen(temp) == my_strlen(pattern)) { + // eliminate strings in which the chars before the option are not '-' + bool noBadCharsFound = true; + while(temp != argv[i]) { + if(*--temp != '-') { + noBadCharsFound = false; + break; + } + } + if(noBadCharsFound && argv[i][0] == '-') + return true; + } + } + return false; + } + + // locates a flag on the command line + bool parseFlag(int argc, const char* const* argv, const char* pattern) { +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + if(!parseFlagImpl(argc, argv, pattern)) + return parseFlagImpl(argc, argv, pattern + 3); // 3 for "dt-" + return true; +#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + return parseFlagImpl(argc, argv, pattern); +#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + } + + // the implementation of parseOption() + bool parseOptionImpl(int argc, const char* const* argv, const char* pattern, String& res) { + for(int i = argc - 1; i >= 0; --i) { + const char* temp = strstr(argv[i], pattern); + if(temp) { + // eliminate matches in which the chars before the option are not '-' + bool noBadCharsFound = true; + const char* curr = argv[i]; + while(curr != temp) { + if(*curr++ != '-') { + noBadCharsFound = false; + break; + } + } + if(noBadCharsFound && argv[i][0] == '-') { + temp += my_strlen(pattern); + unsigned len = my_strlen(temp); + if(len) { + res = temp; + return true; + } + } + } + } + return false; + } + + // parses an option and returns the string after the '=' character + bool parseOption(int argc, const char* const* argv, const char* pattern, String& res, + const String& defaultVal = String()) { + res = defaultVal; +#ifndef DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + if(!parseOptionImpl(argc, argv, pattern, res)) + return parseOptionImpl(argc, argv, pattern + 3, res); // 3 for "dt-" + return true; +#else // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + return parseOptionImpl(argc, argv, pattern, res); +#endif // DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS + } + + // parses a comma separated list of words after a pattern in one of the arguments in argv + bool parseCommaSepArgs(int argc, const char* const* argv, const char* pattern, + std::vector& res) { + String filtersString; + if(parseOption(argc, argv, pattern, filtersString)) { + // tokenize with "," as a separator + char* pch = strtok(filtersString.c_str(), ","); // modifies the string + while(pch != 0) { + if(my_strlen(pch)) + res.push_back(pch); + pch = strtok(0, ","); // uses the strtok() internal state to go to the next token + } + return true; + } + return false; + } + + enum optionType + { + option_bool, + option_int + }; + + // parses an int/bool option from the command line + bool parseIntOption(int argc, const char* const* argv, const char* pattern, optionType type, + int& res) { + String parsedValue; + if(parseOption(argc, argv, pattern, parsedValue)) { + if(type == 0) { + // boolean + const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1 + const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1 + + // if the value matches any of the positive/negative possibilities + for(unsigned i = 0; i < 4; i++) { + if(parsedValue.compare(positive[i], true) == 0) { + res = 1; + return true; + } + if(parsedValue.compare(negative[i], true) == 0) { + res = 0; + return true; + } + } + } else { + // integer + int theInt = atoi(parsedValue.c_str()); + if(theInt != 0) { + res = theInt; + return true; + } + } + } + return false; + } + + void printVersion() { + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("doctest version is \"%s\"\n", DOCTEST_VERSION_STR); + } + + void printHelp() { + printVersion(); + DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("boolean values: \"1/on/yes/true\" or \"0/off/no/false\"\n"); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("filter values: \"str1,str2,str3\" (comma separated strings)\n"); + DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("filters use wildcards for matching strings\n"); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("something passes a filter if any of the strings in a filter matches\n"); + DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("ALL FLAGS, OPTIONS AND FILTERS ALSO AVAILABLE WITH A \"dt-\" PREFIX!!!\n"); + DOCTEST_PRINTF_COLORED("[doctest]\n", Color::Cyan); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("Query flags - the program quits after them. Available:\n\n"); + printf(" -?, --help, -h prints this message\n"); + printf(" -v, --version prints the version\n"); + printf(" -c, --count prints the number of matching tests\n"); + printf(" -ltc, --list-test-cases lists all matching tests by name\n"); + printf(" -lts, --list-test-suites lists all matching test suites\n\n"); + // ==================================================================================== << 79 + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("The available / options/filters are:\n\n"); + printf(" -tc, --test-case= filters tests by their name\n"); + printf(" -tce, --test-case-exclude= filters OUT tests by their name\n"); + printf(" -sf, --source-file= filters tests by their file\n"); + printf(" -sfe, --source-file-exclude= filters OUT tests by their file\n"); + printf(" -ts, --test-suite= filters tests by their test suite\n"); + printf(" -tse, --test-suite-exclude= filters OUT tests by their test suite\n"); + printf(" -ob, --order-by= how the tests should be ordered\n"); + printf(" - by [file/suite/name/rand]\n"); + printf(" -rs, --rand-seed= seed for random ordering\n"); + printf(" -f, --first= the first test passing the filters to\n"); + printf(" execute - for range-based execution\n"); + printf(" -l, --last= the last test passing the filters to\n"); + printf(" execute - for range-based execution\n"); + printf(" -aa, --abort-after= stop after failed assertions\n\n"); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("Bool options - can be used like flags and true is assumed. Available:\n\n"); + printf(" -s, --success= include successful assertions in output\n"); + printf(" -cs, --case-sensitive= filters being treated as case sensitive\n"); + printf(" -e, --exit= exits after the tests finish\n"); + printf(" -nt, --no-throw= skips exceptions-related assert checks\n"); + printf(" -ne, --no-exitcode= returns (or exits) always with success\n"); + printf(" -nr, --no-run= skips all runtime doctest operations\n"); + printf(" -nc, --no-colors= disables colors in output\n"); + printf(" -nb, --no-breaks= disables breakpoints in debuggers\n"); + printf(" -npf, --no-path-filenames= only filenames and no paths in output\n\n"); + // ==================================================================================== << 79 + + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("for more information visit the project documentation\n\n"); + } +} // namespace detail + +Context::Context(int argc, const char* const* argv) + : p(new detail::ContextState) { + parseArgs(argc, argv, true); +} + +Context::~Context() { delete p; } + +void Context::applyCommandLine(int argc, const char* const* argv) { parseArgs(argc, argv); } + +// parses args +void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) { + using namespace detail; + + // clang-format off + parseCommaSepArgs(argc, argv, "dt-source-file=", p->filters[0]); + parseCommaSepArgs(argc, argv, "dt-sf=", p->filters[0]); + parseCommaSepArgs(argc, argv, "dt-source-file-exclude=",p->filters[1]); + parseCommaSepArgs(argc, argv, "dt-sfe=", p->filters[1]); + parseCommaSepArgs(argc, argv, "dt-test-suite=", p->filters[2]); + parseCommaSepArgs(argc, argv, "dt-ts=", p->filters[2]); + parseCommaSepArgs(argc, argv, "dt-test-suite-exclude=", p->filters[3]); + parseCommaSepArgs(argc, argv, "dt-tse=", p->filters[3]); + parseCommaSepArgs(argc, argv, "dt-test-case=", p->filters[4]); + parseCommaSepArgs(argc, argv, "dt-tc=", p->filters[4]); + parseCommaSepArgs(argc, argv, "dt-test-case-exclude=", p->filters[5]); + parseCommaSepArgs(argc, argv, "dt-tce=", p->filters[5]); + // clang-format on + + int intRes = 0; + String strRes; + +#define DOCTEST_PARSE_AS_BOOL_OR_FLAG(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_bool, intRes) || \ + parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_bool, intRes)) \ + p->var = !!intRes; \ + else if(parseFlag(argc, argv, #name) || parseFlag(argc, argv, #sname)) \ + p->var = 1; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_INT_OPTION(name, sname, var, default) \ + if(parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), option_int, intRes) || \ + parseIntOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), option_int, intRes)) \ + p->var = intRes; \ + else if(withDefaults) \ + p->var = default + +#define DOCTEST_PARSE_STR_OPTION(name, sname, var, default) \ + if(parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(name, =), strRes, default) || \ + parseOption(argc, argv, DOCTEST_STR_CONCAT_TOSTR(sname, =), strRes, default) || \ + withDefaults) \ + p->var = strRes + + // clang-format off + DOCTEST_PARSE_STR_OPTION(dt-order-by, dt-ob, order_by, "file"); + DOCTEST_PARSE_INT_OPTION(dt-rand-seed, dt-rs, rand_seed, 0); + + DOCTEST_PARSE_INT_OPTION(dt-first, dt-f, first, 1); + DOCTEST_PARSE_INT_OPTION(dt-last, dt-l, last, 0); + + DOCTEST_PARSE_INT_OPTION(dt-abort-after, dt-aa, abort_after, 0); + + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-success, dt-s, success, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-case-sensitive, dt-cs, case_sensitive, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-exit, dt-e, exit, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-throw, dt-nt, no_throw, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-exitcode, dt-ne, no_exitcode, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-run, dt-nr, no_run, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-colors, dt-nc, no_colors, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-breaks, dt-nb, no_breaks, 0); + DOCTEST_PARSE_AS_BOOL_OR_FLAG(dt-no-path-filenames, dt-npf, no_path_in_filenames, 0); +// clang-format on + +#undef DOCTEST_PARSE_STR_OPTION +#undef DOCTEST_PARSE_INT_OPTION +#undef DOCTEST_PARSE_AS_BOOL_OR_FLAG + + if(withDefaults) { + p->help = false; + p->version = false; + p->count = false; + p->list_test_cases = false; + p->list_test_suites = false; + } + if(parseFlag(argc, argv, "dt-help") || parseFlag(argc, argv, "dt-h") || + parseFlag(argc, argv, "dt-?")) { + p->help = true; + p->exit = true; + } + if(parseFlag(argc, argv, "dt-version") || parseFlag(argc, argv, "dt-v")) { + p->version = true; + p->exit = true; + } + if(parseFlag(argc, argv, "dt-count") || parseFlag(argc, argv, "dt-c")) { + p->count = true; + p->exit = true; + } + if(parseFlag(argc, argv, "dt-list-test-cases") || parseFlag(argc, argv, "dt-ltc")) { + p->list_test_cases = true; + p->exit = true; + } + if(parseFlag(argc, argv, "dt-list-test-suites") || parseFlag(argc, argv, "dt-lts")) { + p->list_test_suites = true; + p->exit = true; + } +} + +// allows the user to add procedurally to the filters from the command line +void Context::addFilter(const char* filter, const char* value) { setOption(filter, value); } + +// allows the user to clear all filters from the command line +void Context::clearFilters() { + for(unsigned i = 0; i < p->filters.size(); ++i) + p->filters[i].clear(); +} + +// allows the user to override procedurally the int/bool options from the command line +void Context::setOption(const char* option, int value) { + setOption(option, toString(value).c_str()); +} + +// allows the user to override procedurally the string options from the command line +void Context::setOption(const char* option, const char* value) { + String argv = String("-") + option + "=" + value; + const char* lvalue = argv.c_str(); + parseArgs(1, &lvalue); +} + +// users should query this in their main() and exit the program if true +bool Context::shouldExit() { return p->exit; } + +// the main function that does all the filtering and test running +int Context::run() { + using namespace detail; + + getContextState() = p; + p->resetRunData(); + + // handle version, help and no_run + if(p->no_run || p->version || p->help) { + if(p->version) + printVersion(); + if(p->help) + printHelp(); + + getContextState() = 0; + + return EXIT_SUCCESS; + } + + printVersion(); + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("run with \"--help\" for options\n"); + + unsigned i = 0; // counter used for loops - here for VC6 + + std::set& registeredTests = getRegisteredTests(); + + std::vector testArray; + for(std::set::iterator it = registeredTests.begin(); it != registeredTests.end(); + ++it) + testArray.push_back(&(*it)); + + // sort the collected records + if(testArray.size() > 0) { + if(p->order_by.compare("file", true) == 0) { + qsort(&testArray[0], testArray.size(), sizeof(TestData*), fileOrderComparator); + } else if(p->order_by.compare("suite", true) == 0) { + qsort(&testArray[0], testArray.size(), sizeof(TestData*), suiteOrderComparator); + } else if(p->order_by.compare("name", true) == 0) { + qsort(&testArray[0], testArray.size(), sizeof(TestData*), nameOrderComparator); + } else if(p->order_by.compare("rand", true) == 0) { + srand(p->rand_seed); + + // random_shuffle implementation + const TestData** first = &testArray[0]; + for(i = testArray.size() - 1; i > 0; --i) { + int idxToSwap = rand() % (i + 1); + + const TestData* temp = first[i]; + + first[i] = first[idxToSwap]; + first[idxToSwap] = temp; + } + } + } + + if(p->list_test_cases) { + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("listing all test case names\n"); + } + + std::set testSuitesPassingFilters; + if(p->list_test_suites) { + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("listing all test suites\n"); + } + + unsigned numTestsPassingFilters = 0; + unsigned numFailed = 0; + // invoke the registered functions if they match the filter criteria (or just count them) + for(i = 0; i < testArray.size(); i++) { + const TestData& data = *testArray[i]; + if(!matchesAny(data.m_file, p->filters[0], 1, p->case_sensitive)) + continue; + if(matchesAny(data.m_file, p->filters[1], 0, p->case_sensitive)) + continue; + if(!matchesAny(data.m_suite, p->filters[2], 1, p->case_sensitive)) + continue; + if(matchesAny(data.m_suite, p->filters[3], 0, p->case_sensitive)) + continue; + if(!matchesAny(data.m_name, p->filters[4], 1, p->case_sensitive)) + continue; + if(matchesAny(data.m_name, p->filters[5], 0, p->case_sensitive)) + continue; + + numTestsPassingFilters++; + + // do not execute the test if we are to only count the number of filter passing tests + if(p->count) + continue; + + // print the name of the test and don't execute it + if(p->list_test_cases) { + printf("%s\n", data.m_name); + continue; + } + + // print the name of the test suite if not done already and don't execute it + if(p->list_test_suites) { + if(testSuitesPassingFilters.count(data.m_suite) == 0) { + printf("%s\n", data.m_suite); + testSuitesPassingFilters.insert(data.m_suite); + } + continue; + } + + // skip the test if it is not in the execution range + if((p->last < numTestsPassingFilters && p->first <= p->last) || + (p->first > numTestsPassingFilters)) + continue; + + // execute the test if it passes all the filtering + { +#ifdef _MSC_VER +//__try { +#endif // _MSC_VER + + p->currentTest = &data; + + // if logging successful tests - force the start log + p->hasLoggedCurrentTestStart = false; + if(p->success) + DOCTEST_LOG_START(); + + unsigned didFail = 0; + p->subcasesPassed.clear(); + do { + // reset the assertion state + p->numAssertionsForCurrentTestcase = 0; + p->numFailedAssertionsForCurrentTestcase = 0; + + // reset some of the fields for subcases (except for the set of fully passed ones) + p->subcasesHasSkipped = false; + p->subcasesCurrentLevel = 0; + p->subcasesEnteredLevels.clear(); + + // execute the test + didFail += callTestFunc(data.m_f); + p->numAssertions += p->numAssertionsForCurrentTestcase; + + // exit this loop if enough assertions have failed + if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after) + p->subcasesHasSkipped = false; + + // if the start has been logged + if(p->hasLoggedCurrentTestStart) + logTestEnd(); + p->hasLoggedCurrentTestStart = false; + + } while(p->subcasesHasSkipped == true); + + if(didFail > 0) + numFailed++; + + // stop executing tests if enough assertions have failed + if(p->abort_after > 0 && p->numFailedAssertions >= p->abort_after) + break; + +#ifdef _MSC_VER +//} __except(1) { +// printf("Unknown SEH exception caught!\n"); +// numFailed++; +//} +#endif // _MSC_VER + } + } + + DOCTEST_PRINTF_COLORED(getSeparator(), numFailed > 0 ? Color::Red : Color::Green); + if(p->count || p->list_test_cases || p->list_test_suites) { + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + printf("number of tests passing the current filters: %d\n", numTestsPassingFilters); + } else { + char buff[DOCTEST_SNPRINTF_BUFFER_LENGTH]; + + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "test cases: %4d", numTestsPassingFilters); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | "); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed", + numTestsPassingFilters - numFailed); + DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | "); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", numFailed); + DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::Red : Color::None); + + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | "); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d skipped\n", + static_cast(testArray.size()) - numTestsPassingFilters); + DOCTEST_PRINTF_COLORED(buff, Color::None); + + DOCTEST_PRINTF_COLORED("[doctest] ", Color::Cyan); + + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "assertions: %4d", p->numAssertions); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | "); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d passed", + p->numAssertions - p->numFailedAssertions); + DOCTEST_PRINTF_COLORED(buff, numFailed > 0 ? Color::None : Color::Green); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " | "); + DOCTEST_PRINTF_COLORED(buff, Color::None); + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), "%4d failed", p->numFailedAssertions); + DOCTEST_PRINTF_COLORED(buff, p->numFailedAssertions > 0 ? Color::Red : Color::None); + + DOCTEST_SNPRINTF(buff, DOCTEST_COUNTOF(buff), " |\n"); + DOCTEST_PRINTF_COLORED(buff, Color::None); + } + + // remove any coloring + DOCTEST_PRINTF_COLORED("", Color::None); + + getContextState() = 0; + + if(numFailed && !p->no_exitcode) + return EXIT_FAILURE; + return EXIT_SUCCESS; +} +} // namespace doctest + +#endif // DOCTEST_CONFIG_DISABLE +#endif // DOCTEST_LIBRARY_IMPLEMENTATION +#endif // DOCTEST_CONFIG_IMPLEMENT + +// == THIS SUPPLIES A MAIN FUNCTION AND SHOULD BE DONE ONLY IN ONE TRANSLATION UNIT +#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_MAIN_CONFIGURED) +#define DOCTEST_MAIN_CONFIGURED +int main(int argc, char** argv) { return doctest::Context(argc, argv).run(); } +#endif // DOCTEST_MAIN_CONFIGURED + +#if defined(__clang__) +#pragma clang diagnostic pop +#endif // __clang__ + +#if defined(__GNUC__) && !defined(__clang__) +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6) +#pragma GCC diagnostic pop +#endif // > gcc 4.6 +#endif // __GNUC__ + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER diff --git a/unittests/forward_list.cpp b/unittests/forward_list.cpp index cf87d6215..aefef2e0b 100644 --- a/unittests/forward_list.cpp +++ b/unittests/forward_list.cpp @@ -24,89 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "forward_list.hpp" -template -void test_forward_list() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::forward_list o_podforward_list(100); - for(auto & elem : o_podforward_list) - elem = random_value(gen); - - std::forward_list o_iserforward_list(100); - for(auto & elem : o_iserforward_list) - elem = StructInternalSerialize( random_value(gen), random_value(gen) ); - - std::forward_list o_isplforward_list(100); - for(auto & elem : o_isplforward_list) - elem = StructInternalSplit( random_value(gen), random_value(gen) ); - - std::forward_list o_eserforward_list(100); - for(auto & elem : o_eserforward_list) - elem = StructExternalSerialize( random_value(gen), random_value(gen) ); - - std::forward_list o_esplforward_list(100); - for(auto & elem : o_esplforward_list) - elem = StructExternalSplit( random_value(gen), random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); +TEST_SUITE("forward_list"); - oar(o_podforward_list); - oar(o_iserforward_list); - oar(o_isplforward_list); - oar(o_eserforward_list); - oar(o_esplforward_list); - } - - std::forward_list i_podforward_list; - std::forward_list i_iserforward_list; - std::forward_list i_isplforward_list; - std::forward_list i_eserforward_list; - std::forward_list i_esplforward_list; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podforward_list); - iar(i_iserforward_list); - iar(i_isplforward_list); - iar(i_eserforward_list); - iar(i_esplforward_list); - } - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podforward_list.begin(), i_podforward_list.end(), o_podforward_list.begin(), o_podforward_list.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserforward_list.begin(), i_iserforward_list.end(), o_iserforward_list.begin(), o_iserforward_list.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplforward_list.begin(), i_isplforward_list.end(), o_isplforward_list.begin(), o_isplforward_list.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserforward_list.begin(), i_eserforward_list.end(), o_eserforward_list.begin(), o_eserforward_list.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplforward_list.begin(), i_esplforward_list.end(), o_esplforward_list.begin(), o_esplforward_list.end()); - } -} - -BOOST_AUTO_TEST_CASE( binary_forward_list ) +TEST_CASE("binary_forward_list") { test_forward_list(); } -BOOST_AUTO_TEST_CASE( portable_binary_forward_list ) +TEST_CASE("portable_binary_forward_list") { test_forward_list(); } -BOOST_AUTO_TEST_CASE( xml_forward_list ) +TEST_CASE("xml_forward_list") { test_forward_list(); } -BOOST_AUTO_TEST_CASE( json_forward_list ) +TEST_CASE("json_forward_list") { test_forward_list(); } + +TEST_SUITE_END(); diff --git a/unittests/forward_list.hpp b/unittests/forward_list.hpp new file mode 100644 index 000000000..c0f568b23 --- /dev/null +++ b/unittests/forward_list.hpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_FORWARD_LIST_H_ +#define CEREAL_TEST_FORWARD_LIST_H_ +#include "common.hpp" + +template inline +void test_forward_list() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::forward_list o_podforward_list(100); + for(auto & elem : o_podforward_list) + elem = random_value(gen); + + std::forward_list o_iserforward_list(100); + for(auto & elem : o_iserforward_list) + elem = StructInternalSerialize( random_value(gen), random_value(gen) ); + + std::forward_list o_isplforward_list(100); + for(auto & elem : o_isplforward_list) + elem = StructInternalSplit( random_value(gen), random_value(gen) ); + + std::forward_list o_eserforward_list(100); + for(auto & elem : o_eserforward_list) + elem = StructExternalSerialize( random_value(gen), random_value(gen) ); + + std::forward_list o_esplforward_list(100); + for(auto & elem : o_esplforward_list) + elem = StructExternalSplit( random_value(gen), random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podforward_list); + oar(o_iserforward_list); + oar(o_isplforward_list); + oar(o_eserforward_list); + oar(o_esplforward_list); + } + + std::forward_list i_podforward_list; + std::forward_list i_iserforward_list; + std::forward_list i_isplforward_list; + std::forward_list i_eserforward_list; + std::forward_list i_esplforward_list; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podforward_list); + iar(i_iserforward_list); + iar(i_isplforward_list); + iar(i_eserforward_list); + iar(i_esplforward_list); + } + + check_collection(i_podforward_list, o_podforward_list ); + check_collection(i_iserforward_list, o_iserforward_list); + check_collection(i_isplforward_list, o_isplforward_list); + check_collection(i_eserforward_list, o_eserforward_list); + check_collection(i_esplforward_list, o_esplforward_list); + } +} + +#endif // CEREAL_TEST_FORWARD_LIST_H_ diff --git a/unittests/list.cpp b/unittests/list.cpp index 8f14fe9ee..099f5306d 100644 --- a/unittests/list.cpp +++ b/unittests/list.cpp @@ -24,90 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "list.hpp" -template -void test_list() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::list o_podlist(100); - for(auto & elem : o_podlist) - elem = random_value(gen); - - std::list o_iserlist(100); - for(auto & elem : o_iserlist) - elem = StructInternalSerialize( random_value(gen), random_value(gen) ); - - std::list o_ispllist(100); - for(auto & elem : o_ispllist) - elem = StructInternalSplit( random_value(gen), random_value(gen) ); - - std::list o_eserlist(100); - for(auto & elem : o_eserlist) - elem = StructExternalSerialize( random_value(gen), random_value(gen) ); - - std::list o_espllist(100); - for(auto & elem : o_espllist) - elem = StructExternalSplit( random_value(gen), random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podlist); - oar(o_iserlist); - oar(o_ispllist); - oar(o_eserlist); - oar(o_espllist); - } - - std::list i_podlist; - std::list i_iserlist; - std::list i_ispllist; - std::list i_eserlist; - std::list i_espllist; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podlist); - iar(i_iserlist); - iar(i_ispllist); - iar(i_eserlist); - iar(i_espllist); - } - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podlist.begin(), i_podlist.end(), o_podlist.begin(), o_podlist.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserlist.begin(), i_iserlist.end(), o_iserlist.begin(), o_iserlist.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_ispllist.begin(), i_ispllist.end(), o_ispllist.begin(), o_ispllist.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserlist.begin(), i_eserlist.end(), o_eserlist.begin(), o_eserlist.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_espllist.begin(), i_espllist.end(), o_espllist.begin(), o_espllist.end()); - } -} +TEST_SUITE("list"); -BOOST_AUTO_TEST_CASE( binary_list ) +TEST_CASE("binary_list") { test_list(); } -BOOST_AUTO_TEST_CASE( portable_binary_list ) +TEST_CASE("portable_binary_list") { test_list(); } -BOOST_AUTO_TEST_CASE( xml_list ) +TEST_CASE("xml_list") { test_list(); } -BOOST_AUTO_TEST_CASE( json_list ) +TEST_CASE("json_list") { test_list(); } +TEST_SUITE_END(); diff --git a/unittests/list.hpp b/unittests/list.hpp new file mode 100644 index 000000000..9e8a7dd05 --- /dev/null +++ b/unittests/list.hpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_LIST_H_ +#define CEREAL_TEST_LIST_H_ +#include "common.hpp" + +template inline +void test_list() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::list o_podlist(100); + for(auto & elem : o_podlist) + elem = random_value(gen); + + std::list o_iserlist(100); + for(auto & elem : o_iserlist) + elem = StructInternalSerialize( random_value(gen), random_value(gen) ); + + std::list o_ispllist(100); + for(auto & elem : o_ispllist) + elem = StructInternalSplit( random_value(gen), random_value(gen) ); + + std::list o_eserlist(100); + for(auto & elem : o_eserlist) + elem = StructExternalSerialize( random_value(gen), random_value(gen) ); + + std::list o_espllist(100); + for(auto & elem : o_espllist) + elem = StructExternalSplit( random_value(gen), random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podlist); + oar(o_iserlist); + oar(o_ispllist); + oar(o_eserlist); + oar(o_espllist); + } + + std::list i_podlist; + std::list i_iserlist; + std::list i_ispllist; + std::list i_eserlist; + std::list i_espllist; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podlist); + iar(i_iserlist); + iar(i_ispllist); + iar(i_eserlist); + iar(i_espllist); + } + + check_collection(i_podlist, o_podlist); + check_collection(i_iserlist, o_iserlist); + check_collection(i_ispllist, o_ispllist); + check_collection(i_eserlist, o_eserlist); + check_collection(i_espllist, o_espllist); + } +} + +#endif // CEREAL_TEST_LIST_H_ diff --git a/unittests/load_construct.cpp b/unittests/load_construct.cpp index 509ac8856..923e19aaa 100644 --- a/unittests/load_construct.cpp +++ b/unittests/load_construct.cpp @@ -24,255 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "load_construct.hpp" -struct OneLA -{ - OneLA( int xx ) : x( xx ) {} - - int x; - - template - void serialize( Archive & ar ) - { ar( x ); } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - int xx; - ar( xx ); - construct( xx ); - } - - bool operator==( OneLA const & other ) const - { return x == other.x; } -}; - -std::ostream& operator<<(std::ostream& os, OneLA const & s) -{ - os << "[" << s.x << "]"; - return os; -} - -struct OneLAVersioned -{ - OneLAVersioned( int xx ) : x( xx ), v() {} - OneLAVersioned( int xx, int vv ) : x( xx ), v( vv ) {} - - int x; - std::uint32_t v; - - template - void serialize( Archive & ar, const std::uint32_t version ) - { ar( x ); v = version; } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct, const std::uint32_t version ) - { - int xx; - ar( xx ); - construct( xx, version ); - } - - bool operator==( OneLAVersioned const & other ) const - { return x == other.x; } -}; - -std::ostream& operator<<(std::ostream& os, OneLAVersioned const & s) -{ - os << "[" << s.x << "]"; - return os; -} - -CEREAL_CLASS_VERSION( OneLAVersioned, 13 ) - -struct TwoLA -{ - TwoLA( int xx ) : x( xx ) {} - - int x; - - template - void serialize( Archive & ar ) - { ar( x ); } - - bool operator==( TwoLA const & other ) const - { return x == other.x; } -}; - -std::ostream& operator<<(std::ostream& os, TwoLA const & s) -{ - os << "[" << s.x << "]"; - return os; -} - -namespace cereal -{ - template <> - struct LoadAndConstruct - { - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - int xx; - ar( xx ); - construct( xx ); - } - }; -} - -struct TwoLAVersioned -{ - TwoLAVersioned( int xx ) : x( xx ), v() {} - TwoLAVersioned( int xx, int vv ) : x( xx ), v( vv ) {} - - int x; - std::uint32_t v; - - template - void serialize( Archive & ar, const std::uint32_t version ) - { ar( x ); v = version; } - - bool operator==( TwoLAVersioned const & other ) const - { return x == other.x; } -}; - -std::ostream& operator<<(std::ostream& os, TwoLAVersioned const & s) -{ - os << "[" << s.x << "]"; - return os; -} - -namespace cereal -{ - template <> - struct LoadAndConstruct - { - template - static void load_and_construct( Archive & ar, cereal::construct & construct, const std::uint32_t version ) - { - int xx; - ar( xx ); - construct( xx, version ); - } - }; -} - -CEREAL_CLASS_VERSION( TwoLAVersioned, 1 ) - -struct ThreeLA : std::enable_shared_from_this -{ - ThreeLA( int xx ) : x( xx ) {} - - int x; - - template - void serialize( Archive & ar ) - { ar( x ); } - - bool operator==( ThreeLA const & other ) const - { return x == other.x; } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - int xx; - ar( xx ); - construct( xx ); - } -}; - -std::ostream& operator<<(std::ostream& os, ThreeLA const & s) -{ - os << "[" << s.x << "]"; - return os; -} - -template -void test_memory_load_construct() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - auto o_shared1 = std::make_shared( random_value(gen) ); - auto o_shared2 = std::make_shared( random_value(gen) ); - std::unique_ptr o_unique1( new OneLA( random_value(gen) ) ); - std::unique_ptr o_unique2( new TwoLA( random_value(gen) ) ); - auto o_shared3 = std::make_shared( random_value(gen) ); - auto o_shared1v = std::make_shared( random_value(gen) ); - auto o_shared2v = std::make_shared( random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_shared1 ); - oar( o_shared2 ); - oar( o_unique1 ); - oar( o_unique2 ); - oar( o_shared3 ); - oar( o_shared1v ); - oar( o_shared2v ); - } - - o_shared3->shared_from_this(); // tests github issue #68 - - decltype(o_shared1) i_shared1; - decltype(o_shared2) i_shared2; - decltype(o_unique1) i_unique1; - decltype(o_unique2) i_unique2; - decltype(o_shared3) i_shared3; - decltype(o_shared1v) i_shared1v; - decltype(o_shared2v) i_shared2v; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_shared1 ); - iar( i_shared2 ); - iar( i_unique1 ); - iar( i_unique2 ); - iar( i_shared3 ); - iar( i_shared1v ); - iar( i_shared2v ); - } - - BOOST_CHECK_EQUAL( *o_shared1, *i_shared1 ); - BOOST_CHECK_EQUAL( *o_shared2, *i_shared2 ); - BOOST_CHECK_EQUAL( *o_unique1, *i_unique1 ); - BOOST_CHECK_EQUAL( *o_unique2, *i_unique2 ); - BOOST_CHECK_EQUAL( *o_shared3, *i_shared3 ); - BOOST_CHECK_EQUAL( *o_shared1v, *i_shared1v ); - BOOST_CHECK_EQUAL(i_shared1v->v, 13u); - BOOST_CHECK_EQUAL( *o_shared2v, *i_shared2v ); - BOOST_CHECK_EQUAL(i_shared2v->v, 1u); - - auto i_shared3_2 = i_shared3->shared_from_this(); - BOOST_CHECK_EQUAL( *o_shared3, *i_shared3_2 ); - } -} +TEST_SUITE("load_construct"); -BOOST_AUTO_TEST_CASE( binary_memory_load_construct ) +TEST_CASE("binary_memory_load_construct") { test_memory_load_construct(); } -BOOST_AUTO_TEST_CASE( portable_binary_memory_load_construct ) +TEST_CASE("portable_binary_memory_load_construct") { test_memory_load_construct(); } -BOOST_AUTO_TEST_CASE( xml_memory_load_construct ) +TEST_CASE("xml_memory_load_construct") { test_memory_load_construct(); } -BOOST_AUTO_TEST_CASE( json_memory_load_construct ) +TEST_CASE("json_memory_load_construct") { test_memory_load_construct(); } +TEST_SUITE_END(); diff --git a/unittests/load_construct.hpp b/unittests/load_construct.hpp new file mode 100644 index 000000000..97b37c1d4 --- /dev/null +++ b/unittests/load_construct.hpp @@ -0,0 +1,260 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_LOAD_CONSTRUCT_H_ +#define CEREAL_TEST_LOAD_CONSTRUCT_H_ +#include "common.hpp" + +struct OneLA +{ + OneLA( int xx ) : x( xx ) {} + + int x; + + template + void serialize( Archive & ar ) + { ar( x ); } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int xx; + ar( xx ); + construct( xx ); + } + + bool operator==( OneLA const & other ) const + { return x == other.x; } +}; + +std::ostream& operator<<(std::ostream& os, OneLA const & s) +{ + os << "[" << s.x << "]"; + return os; +} + +struct OneLAVersioned +{ + OneLAVersioned( int xx ) : x( xx ), v() {} + OneLAVersioned( int xx, int vv ) : x( xx ), v( vv ) {} + + int x; + std::uint32_t v; + + template + void serialize( Archive & ar, const std::uint32_t version ) + { ar( x ); v = version; } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct, const std::uint32_t version ) + { + int xx; + ar( xx ); + construct( xx, version ); + } + + bool operator==( OneLAVersioned const & other ) const + { return x == other.x; } +}; + +std::ostream& operator<<(std::ostream& os, OneLAVersioned const & s) +{ + os << "[" << s.x << "]"; + return os; +} + +CEREAL_CLASS_VERSION( OneLAVersioned, 13 ) + +struct TwoLA +{ + TwoLA( int xx ) : x( xx ) {} + + int x; + + template + void serialize( Archive & ar ) + { ar( x ); } + + bool operator==( TwoLA const & other ) const + { return x == other.x; } +}; + +std::ostream& operator<<(std::ostream& os, TwoLA const & s) +{ + os << "[" << s.x << "]"; + return os; +} + +namespace cereal +{ + template <> + struct LoadAndConstruct + { + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int xx; + ar( xx ); + construct( xx ); + } + }; +} + +struct TwoLAVersioned +{ + TwoLAVersioned( int xx ) : x( xx ), v() {} + TwoLAVersioned( int xx, int vv ) : x( xx ), v( vv ) {} + + int x; + std::uint32_t v; + + template + void serialize( Archive & ar, const std::uint32_t version ) + { ar( x ); v = version; } + + bool operator==( TwoLAVersioned const & other ) const + { return x == other.x; } +}; + +std::ostream& operator<<(std::ostream& os, TwoLAVersioned const & s) +{ + os << "[" << s.x << "]"; + return os; +} + +namespace cereal +{ + template <> + struct LoadAndConstruct + { + template + static void load_and_construct( Archive & ar, cereal::construct & construct, const std::uint32_t version ) + { + int xx; + ar( xx ); + construct( xx, version ); + } + }; +} + +CEREAL_CLASS_VERSION( TwoLAVersioned, 1 ) + +struct ThreeLA : std::enable_shared_from_this +{ + ThreeLA( int xx ) : x( xx ) {} + + int x; + + template + void serialize( Archive & ar ) + { ar( x ); } + + bool operator==( ThreeLA const & other ) const + { return x == other.x; } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int xx; + ar( xx ); + construct( xx ); + } +}; + +std::ostream& operator<<(std::ostream& os, ThreeLA const & s) +{ + os << "[" << s.x << "]"; + return os; +} + +template +void test_memory_load_construct() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + auto o_shared1 = std::make_shared( random_value(gen) ); + auto o_shared2 = std::make_shared( random_value(gen) ); + std::unique_ptr o_unique1( new OneLA( random_value(gen) ) ); + std::unique_ptr o_unique2( new TwoLA( random_value(gen) ) ); + auto o_shared3 = std::make_shared( random_value(gen) ); + auto o_shared1v = std::make_shared( random_value(gen) ); + auto o_shared2v = std::make_shared( random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_shared1 ); + oar( o_shared2 ); + oar( o_unique1 ); + oar( o_unique2 ); + oar( o_shared3 ); + oar( o_shared1v ); + oar( o_shared2v ); + } + + o_shared3->shared_from_this(); // tests github issue #68 + + decltype(o_shared1) i_shared1; + decltype(o_shared2) i_shared2; + decltype(o_unique1) i_unique1; + decltype(o_unique2) i_unique2; + decltype(o_shared3) i_shared3; + decltype(o_shared1v) i_shared1v; + decltype(o_shared2v) i_shared2v; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_shared1 ); + iar( i_shared2 ); + iar( i_unique1 ); + iar( i_unique2 ); + iar( i_shared3 ); + iar( i_shared1v ); + iar( i_shared2v ); + } + + CHECK_EQ( *o_shared1, *i_shared1 ); + CHECK_EQ( *o_shared2, *i_shared2 ); + CHECK_EQ( *o_unique1, *i_unique1 ); + CHECK_EQ( *o_unique2, *i_unique2 ); + CHECK_EQ( *o_shared3, *i_shared3 ); + CHECK_EQ( *o_shared1v, *i_shared1v ); + CHECK_EQ(i_shared1v->v, 13u); + CHECK_EQ( *o_shared2v, *i_shared2v ); + CHECK_EQ(i_shared2v->v, 1u); + + auto i_shared3_2 = i_shared3->shared_from_this(); + CHECK_EQ( *o_shared3, *i_shared3_2 ); + } +} + +#endif // CEREAL_TEST_LOAD_CONSTRUCT_H_ diff --git a/unittests/map.cpp b/unittests/map.cpp index 90dc283f8..40e1b841b 100644 --- a/unittests/map.cpp +++ b/unittests/map.cpp @@ -24,183 +24,49 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "map.hpp" -template -void test_map() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::map> o_vectormap; - for(int j=0; j<10; ++j) - { - size_t id = random_value(gen); - for(int k=0; k<100; ++k) - o_vectormap[id].emplace_back(random_value(gen), random_value(gen)); - } - - std::map o_podmap; - for(int j=0; j<100; ++j) - o_podmap.insert({random_value(gen), random_value(gen)}); - - std::map o_isermap; - for(int j=0; j<100; ++j) - o_isermap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::map o_isplmap; - for(int j=0; j<100; ++j) - o_isplmap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::map o_esermap; - for(int j=0; j<100; ++j) - o_esermap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::map o_esplmap; - for(int j=0; j<100; ++j) - o_esplmap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_vectormap); - oar(o_podmap); - oar(o_isermap); - oar(o_isplmap); - oar(o_esermap); - oar(o_esplmap); - } - - std::map> i_vectormap; - std::map i_podmap; - std::map i_isermap; - std::map i_isplmap; - std::map i_esermap; - std::map i_esplmap; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_vectormap); - iar(i_podmap); - iar(i_isermap); - iar(i_isplmap); - iar(i_esermap); - iar(i_esplmap); - } - - BOOST_CHECK_EQUAL(i_vectormap.size(), o_vectormap.size()); - auto o_v_it = o_vectormap.begin(); - auto i_v_it = i_vectormap.begin(); - for(;o_v_it != o_vectormap.end(); ++o_v_it, ++i_v_it) - { - BOOST_CHECK_EQUAL(i_v_it->second.size(), o_v_it->second.size()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_v_it->second.begin(), i_v_it->second.end(), o_v_it->second.begin(), o_v_it->second.end()); - } - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podmap.begin(), i_podmap.end(), o_podmap.begin(), o_podmap.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isermap.begin(), i_isermap.end(), o_isermap.begin(), o_isermap.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplmap.begin(), i_isplmap.end(), o_isplmap.begin(), o_isplmap.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esermap.begin(), i_esermap.end(), o_esermap.begin(), o_esermap.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplmap.begin(), i_esplmap.end(), o_esplmap.begin(), o_esplmap.end()); - } -} - -template -void test_map_memory() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::map> o_uniqueptrMap; - std::map> o_sharedptrMap; - - for(int j=0; j<100; ++j) - { - #ifdef CEREAL_OLDER_GCC - o_uniqueptrMap.insert( std::make_pair(random_value(gen), std::unique_ptr( new int( random_value(gen) ) )) ); - o_sharedptrMap.insert( std::make_pair(random_value(gen), std::make_shared( random_value(gen) )) ); - #else // NOT CEREAL_OLDER_GCC - o_uniqueptrMap.emplace( random_value(gen), std::unique_ptr( new int( random_value(gen) ) ) ); - o_sharedptrMap.emplace( random_value(gen), std::make_shared( random_value(gen) ) ); - #endif // NOT CEREAL_OLDER_GCC - } - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_uniqueptrMap ); - oar( o_sharedptrMap ); - } +TEST_SUITE("map"); - decltype( o_uniqueptrMap ) i_uniqueptrMap; - decltype( o_sharedptrMap ) i_sharedptrMap; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_uniqueptrMap ); - iar( i_sharedptrMap ); - } - - BOOST_CHECK_EQUAL(o_sharedptrMap.size(), i_sharedptrMap.size()); - BOOST_CHECK_EQUAL(o_uniqueptrMap.size(), i_uniqueptrMap.size()); - - auto o_v_it = o_uniqueptrMap.begin(); - auto i_v_it = i_uniqueptrMap.begin(); - for(;o_v_it != o_uniqueptrMap.end(); ++o_v_it, ++i_v_it) - { - BOOST_CHECK_EQUAL(i_v_it->first, o_v_it->first); - BOOST_CHECK_EQUAL(*i_v_it->second, *o_v_it->second); - } - } -} - -BOOST_AUTO_TEST_CASE( binary_map ) +TEST_CASE("binary_map") { test_map(); } -BOOST_AUTO_TEST_CASE( portable_binary_map ) +TEST_CASE("portable_binary_map") { test_map(); } -BOOST_AUTO_TEST_CASE( xml_map ) +TEST_CASE("xml_map") { test_map(); } -BOOST_AUTO_TEST_CASE( json_map ) +TEST_CASE("json_map") { test_map(); } -BOOST_AUTO_TEST_CASE( binary_map_memory ) +TEST_CASE("binary_map_memory") { test_map_memory(); } -BOOST_AUTO_TEST_CASE( portable_binary_map_memory ) +TEST_CASE("portable_binary_map_memory") { test_map_memory(); } -BOOST_AUTO_TEST_CASE( xml_map_memory ) +TEST_CASE("xml_map_memory") { test_map_memory(); } -BOOST_AUTO_TEST_CASE( json_map_memory ) +TEST_CASE("json_map_memory") { test_map_memory(); } + +TEST_SUITE_END(); diff --git a/unittests/map.hpp b/unittests/map.hpp new file mode 100644 index 000000000..20b7c6222 --- /dev/null +++ b/unittests/map.hpp @@ -0,0 +1,169 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_MAP_H_ +#define CEREAL_TEST_MAP_H_ +#include "common.hpp" + +template inline +void test_map() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::map> o_vectormap; + for(int j=0; j<10; ++j) + { + size_t id = random_value(gen); + for(int k=0; k<100; ++k) + o_vectormap[id].emplace_back(random_value(gen), random_value(gen)); + } + + std::map o_podmap; + for(int j=0; j<100; ++j) + o_podmap.insert({random_value(gen), random_value(gen)}); + + std::map o_isermap; + for(int j=0; j<100; ++j) + o_isermap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::map o_isplmap; + for(int j=0; j<100; ++j) + o_isplmap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::map o_esermap; + for(int j=0; j<100; ++j) + o_esermap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::map o_esplmap; + for(int j=0; j<100; ++j) + o_esplmap.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_vectormap); + oar(o_podmap); + oar(o_isermap); + oar(o_isplmap); + oar(o_esermap); + oar(o_esplmap); + } + + std::map> i_vectormap; + std::map i_podmap; + std::map i_isermap; + std::map i_isplmap; + std::map i_esermap; + std::map i_esplmap; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_vectormap); + iar(i_podmap); + iar(i_isermap); + iar(i_isplmap); + iar(i_esermap); + iar(i_esplmap); + } + + CHECK_EQ(i_vectormap.size(), o_vectormap.size()); + auto o_v_it = o_vectormap.begin(); + auto i_v_it = i_vectormap.begin(); + for(;o_v_it != o_vectormap.end(); ++o_v_it, ++i_v_it) + { + CHECK_EQ(i_v_it->second.size(), o_v_it->second.size()); + check_collection(i_v_it->second, o_v_it->second); + } + + check_collection(i_podmap, o_podmap); + check_collection(i_isermap, o_isermap); + check_collection(i_isplmap, o_isplmap); + check_collection(i_esermap, o_esermap); + check_collection(i_esplmap, o_esplmap); + } +} + +template inline +void test_map_memory() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::map> o_uniqueptrMap; + std::map> o_sharedptrMap; + + for(int j=0; j<100; ++j) + { + #ifdef CEREAL_OLDER_GCC + o_uniqueptrMap.insert( std::make_pair(random_value(gen), std::unique_ptr( new int( random_value(gen) ) )) ); + o_sharedptrMap.insert( std::make_pair(random_value(gen), std::make_shared( random_value(gen) )) ); + #else // NOT CEREAL_OLDER_GCC + o_uniqueptrMap.emplace( random_value(gen), std::unique_ptr( new int( random_value(gen) ) ) ); + o_sharedptrMap.emplace( random_value(gen), std::make_shared( random_value(gen) ) ); + #endif // NOT CEREAL_OLDER_GCC + } + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_uniqueptrMap ); + oar( o_sharedptrMap ); + } + + decltype( o_uniqueptrMap ) i_uniqueptrMap; + decltype( o_sharedptrMap ) i_sharedptrMap; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_uniqueptrMap ); + iar( i_sharedptrMap ); + } + + CHECK_EQ(o_sharedptrMap.size(), i_sharedptrMap.size()); + CHECK_EQ(o_uniqueptrMap.size(), i_uniqueptrMap.size()); + + auto o_v_it = o_uniqueptrMap.begin(); + auto i_v_it = i_uniqueptrMap.begin(); + for(;o_v_it != o_uniqueptrMap.end(); ++o_v_it, ++i_v_it) + { + CHECK_EQ(i_v_it->first, o_v_it->first); + CHECK_EQ(*i_v_it->second, *o_v_it->second); + } + } +} + +#endif // CEREAL_TEST_MAP_H_ diff --git a/unittests/memory.cpp b/unittests/memory.cpp index 8a8641019..8c6259273 100644 --- a/unittests/memory.cpp +++ b/unittests/memory.cpp @@ -24,131 +24,49 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "memory.hpp" -template -void test_memory() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::shared_ptr o_xptr1 = std::make_shared(random_value(gen)); - std::shared_ptr o_xptr2 = o_xptr1; - std::shared_ptr o_yptr1 = std::make_shared(random_value(gen)); - std::shared_ptr o_yptr2 = o_yptr1; - std::shared_ptr o_nullptr1; - std::shared_ptr o_nullptr2; - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_xptr1, o_xptr2 ); - oar( o_yptr1, o_yptr2 ); - oar( o_nullptr1, o_nullptr2 ); - } - - std::shared_ptr i_xptr1; - std::shared_ptr i_xptr2; - std::shared_ptr i_yptr1; - std::shared_ptr i_yptr2; - std::shared_ptr i_nullptr1; - std::shared_ptr i_nullptr2; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_xptr1, i_xptr2); - iar( i_yptr1, i_yptr2); - iar( i_nullptr1, i_nullptr2 ); - } - - BOOST_CHECK_EQUAL(o_xptr1.get(), o_xptr2.get()); - BOOST_CHECK_EQUAL(i_xptr1.get(), i_xptr2.get()); - BOOST_CHECK_EQUAL(*i_xptr1, *i_xptr2); - - BOOST_CHECK_EQUAL(o_yptr1.get(), o_yptr2.get()); - BOOST_CHECK_EQUAL(i_yptr1.get(), i_yptr2.get()); - BOOST_CHECK_EQUAL(*i_yptr1, *i_yptr2); - BOOST_CHECK(!i_nullptr1); - BOOST_CHECK(!i_nullptr2); - } -} +TEST_SUITE("memory"); -BOOST_AUTO_TEST_CASE( binary_memory ) +TEST_CASE("binary_memory") { test_memory(); } -BOOST_AUTO_TEST_CASE( portable_binary_memory ) +TEST_CASE("portable_binary_memory") { test_memory(); } -BOOST_AUTO_TEST_CASE( xml_memory ) +TEST_CASE("xml_memory") { test_memory(); } -BOOST_AUTO_TEST_CASE( json_memory ) +TEST_CASE("json_memory") { test_memory(); } -class TestClass -{ - public: - TestClass(int v) : x(v) { } - int x; - - private: - friend class cereal::access; - TestClass() { }; - - template - void serialize(Archive & ar) { ar(x); } -}; - - -template -void test_default_construction() -{ - auto o_ptr = std::make_shared(1); - std::shared_ptr i_ptr; - - std::ostringstream os; - { - OArchive oar(os); - oar(o_ptr); - } - { - std::istringstream is(os.str()); - IArchive iar(is); - iar(i_ptr); - } - BOOST_CHECK_EQUAL(o_ptr->x, i_ptr->x); -} - -BOOST_AUTO_TEST_CASE( binary_default_construction ) +TEST_CASE("binary_default_construction") { test_default_construction(); } -BOOST_AUTO_TEST_CASE( portable_binary_default_construction ) +TEST_CASE("portable_binary_default_construction") { test_default_construction(); } -BOOST_AUTO_TEST_CASE( xml_default_construction ) +TEST_CASE("xml_default_construction") { test_default_construction(); } -BOOST_AUTO_TEST_CASE( json_default_construction ) +TEST_CASE("json_default_construction") { test_default_construction(); } + +TEST_SUITE_END(); diff --git a/unittests/memory.hpp b/unittests/memory.hpp new file mode 100644 index 000000000..19ec2bbd4 --- /dev/null +++ b/unittests/memory.hpp @@ -0,0 +1,116 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_MEMORY_H_ +#define CEREAL_TEST_MEMORY_H_ +#include "common.hpp" + +template inline +void test_memory() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::shared_ptr o_xptr1 = std::make_shared(random_value(gen)); + std::shared_ptr o_xptr2 = o_xptr1; + std::shared_ptr o_yptr1 = std::make_shared(random_value(gen)); + std::shared_ptr o_yptr2 = o_yptr1; + std::shared_ptr o_nullptr1; + std::shared_ptr o_nullptr2; + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_xptr1, o_xptr2 ); + oar( o_yptr1, o_yptr2 ); + oar( o_nullptr1, o_nullptr2 ); + } + + std::shared_ptr i_xptr1; + std::shared_ptr i_xptr2; + std::shared_ptr i_yptr1; + std::shared_ptr i_yptr2; + std::shared_ptr i_nullptr1; + std::shared_ptr i_nullptr2; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_xptr1, i_xptr2); + iar( i_yptr1, i_yptr2); + iar( i_nullptr1, i_nullptr2 ); + } + + CHECK_EQ(o_xptr1.get(), o_xptr2.get()); + CHECK_EQ(i_xptr1.get(), i_xptr2.get()); + CHECK_EQ(*i_xptr1, *i_xptr2); + + CHECK_EQ(o_yptr1.get(), o_yptr2.get()); + CHECK_EQ(i_yptr1.get(), i_yptr2.get()); + CHECK_EQ(*i_yptr1, *i_yptr2); + CHECK_UNARY_FALSE(i_nullptr1); + CHECK_UNARY_FALSE(i_nullptr2); + } +} + +class TestClass +{ + public: + TestClass(int v) : x(v) { } + int x; + + private: + friend class cereal::access; + TestClass() { }; + + template + void serialize(Archive & ar) { ar(x); } +}; + +template inline +void test_default_construction() +{ + auto o_ptr = std::make_shared(1); + std::shared_ptr i_ptr; + + std::ostringstream os; + { + OArchive oar(os); + oar(o_ptr); + } + { + std::istringstream is(os.str()); + IArchive iar(is); + iar(i_ptr); + } + CHECK_EQ(o_ptr->x, i_ptr->x); +} + +#endif // CEREAL_TEST_LOAD_CONSTRUCT_H_ diff --git a/unittests/memory_cycles.cpp b/unittests/memory_cycles.cpp index a98dd86ff..461decc59 100644 --- a/unittests/memory_cycles.cpp +++ b/unittests/memory_cycles.cpp @@ -24,138 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "memory_cycles.hpp" -struct MemoryCycle -{ - MemoryCycle() = default; - - MemoryCycle( int v ) : - value( v ) - { } - - int value; - std::weak_ptr ptr; - - bool operator==( MemoryCycle const & other ) const - { - return value == other.value && ptr.lock() == other.ptr.lock(); - } - - template - void serialize( Archive & ar ) - { - ar( value, ptr ); - } -}; - -std::ostream& operator<<(std::ostream& os, MemoryCycle const & s) -{ - os << "[value: " << s.value << " ptr: " << s.ptr.lock() << "]"; - return os; -} - -class MemoryCycleLoadAndConstruct -{ - public: - MemoryCycleLoadAndConstruct( int v ) : - value( v ) - { } - - MemoryCycleLoadAndConstruct( int v, - std::weak_ptr p ) : - value( v ), - ptr( p ) - { } - - bool operator==( MemoryCycleLoadAndConstruct const & other ) const - { - return value == other.value && ptr.lock() == other.ptr.lock(); - } - - template - void serialize( Archive & ar ) - { - ar( value, ptr ); - } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - int val; - std::weak_ptr p; - - ar( val, p ); - construct( val, p ); - } - - int value; - std::weak_ptr ptr; -}; - -std::ostream& operator<<(std::ostream& os, MemoryCycleLoadAndConstruct const & s) -{ - os << "[value: " << s.value << " ptr: " << s.ptr.lock() << "]"; - return os; -} - -template -void test_memory_cycles() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - auto o_ptr1 = std::make_shared( random_value(gen) ); - o_ptr1->ptr = o_ptr1; - auto o_ptr2 = std::make_shared( random_value(gen) ); - o_ptr2->ptr = o_ptr2; - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_ptr1 ); - oar( o_ptr2 ); - } - - decltype(o_ptr1) i_ptr1; - decltype(o_ptr2) i_ptr2; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_ptr1 ); - iar( i_ptr2 ); - } - - BOOST_CHECK_EQUAL( o_ptr1->value, i_ptr1->value ); - BOOST_CHECK_EQUAL( i_ptr1.get(), i_ptr1->ptr.lock().get() ); - BOOST_CHECK_EQUAL( o_ptr2->value, i_ptr2->value ); - BOOST_CHECK_EQUAL( i_ptr2.get(), i_ptr2->ptr.lock().get() ); - } -} +TEST_SUITE("memory_cycles"); -BOOST_AUTO_TEST_CASE( binary_memory_cycles ) +TEST_CASE("binary_memory_cycles") { test_memory_cycles(); } -BOOST_AUTO_TEST_CASE( portable_binary_memory_cycles ) +TEST_CASE("portable_binary_memory_cycles") { test_memory_cycles(); } -BOOST_AUTO_TEST_CASE( xml_memory_cycles ) +TEST_CASE("xml_memory_cycles") { test_memory_cycles(); } -BOOST_AUTO_TEST_CASE( json_memory_cycles ) +TEST_CASE("json_memory_cycles") { test_memory_cycles(); } +TEST_SUITE_END(); diff --git a/unittests/memory_cycles.hpp b/unittests/memory_cycles.hpp new file mode 100644 index 000000000..9009723ae --- /dev/null +++ b/unittests/memory_cycles.hpp @@ -0,0 +1,142 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_MEMORY_CYCLES_H_ +#define CEREAL_TEST_MEMORY_CYCLES_H_ +#include "common.hpp" + +struct MemoryCycle +{ + MemoryCycle() = default; + + MemoryCycle( int v ) : + value( v ) + { } + + int value; + std::weak_ptr ptr; + + bool operator==( MemoryCycle const & other ) const + { + return value == other.value && ptr.lock() == other.ptr.lock(); + } + + template + void serialize( Archive & ar ) + { + ar( value, ptr ); + } +}; + +std::ostream& operator<<(std::ostream& os, MemoryCycle const & s) +{ + os << "[value: " << s.value << " ptr: " << s.ptr.lock() << "]"; + return os; +} + +class MemoryCycleLoadAndConstruct +{ + public: + MemoryCycleLoadAndConstruct( int v ) : + value( v ) + { } + + MemoryCycleLoadAndConstruct( int v, + std::weak_ptr p ) : + value( v ), + ptr( p ) + { } + + bool operator==( MemoryCycleLoadAndConstruct const & other ) const + { + return value == other.value && ptr.lock() == other.ptr.lock(); + } + + template + void serialize( Archive & ar ) + { + ar( value, ptr ); + } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int val; + std::weak_ptr p; + + ar( val, p ); + construct( val, p ); + } + + int value; + std::weak_ptr ptr; +}; + +std::ostream& operator<<(std::ostream& os, MemoryCycleLoadAndConstruct const & s) +{ + os << "[value: " << s.value << " ptr: " << s.ptr.lock() << "]"; + return os; +} + +template inline +void test_memory_cycles() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + auto o_ptr1 = std::make_shared( random_value(gen) ); + o_ptr1->ptr = o_ptr1; + auto o_ptr2 = std::make_shared( random_value(gen) ); + o_ptr2->ptr = o_ptr2; + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_ptr1 ); + oar( o_ptr2 ); + } + + decltype(o_ptr1) i_ptr1; + decltype(o_ptr2) i_ptr2; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_ptr1 ); + iar( i_ptr2 ); + } + + CHECK_EQ( o_ptr1->value, i_ptr1->value ); + CHECK_EQ( i_ptr1.get(), i_ptr1->ptr.lock().get() ); + CHECK_EQ( o_ptr2->value, i_ptr2->value ); + CHECK_EQ( i_ptr2.get(), i_ptr2->ptr.lock().get() ); + } +} +#endif // CEREAL_TEST_MEMORY_CYCLES_H_ diff --git a/unittests/multimap.cpp b/unittests/multimap.cpp index af8492d17..8df857e16 100644 --- a/unittests/multimap.cpp +++ b/unittests/multimap.cpp @@ -24,124 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "multimap.hpp" -template -void test_multimap() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::multimap o_podmultimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_podmultimap.insert({key, random_value(gen)}); - o_podmultimap.insert({key, random_value(gen)}); - } - - std::multimap o_isermultimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_isermultimap.insert({key, { random_value(gen), random_value(gen) }}); - o_isermultimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::multimap o_isplmultimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_isplmultimap.insert({key, { random_value(gen), random_value(gen) }}); - o_isplmultimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::multimap o_esermultimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_esermultimap.insert({key, { random_value(gen), random_value(gen) }}); - o_esermultimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::multimap o_esplmultimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_esplmultimap.insert({key, { random_value(gen), random_value(gen) }}); - o_esplmultimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podmultimap); - oar(o_isermultimap); - oar(o_isplmultimap); - oar(o_esermultimap); - oar(o_esplmultimap); - } - - std::multimap i_podmultimap; - std::multimap i_isermultimap; - std::multimap i_isplmultimap; - std::multimap i_esermultimap; - std::multimap i_esplmultimap; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podmultimap); - iar(i_isermultimap); - iar(i_isplmultimap); - iar(i_esermultimap); - iar(i_esplmultimap); - } - -#define MULTIMAP_CHECK(InMap, OutMap) \ - for( auto & pair : OutMap ) \ - { \ - auto const count = InMap.count( pair.first ); \ - BOOST_CHECK_EQUAL( count, OutMap.count( pair.first ) ); \ - auto find = InMap.find( pair.first ); \ - bool found = false; \ - for( size_t i = 0; i < count; ++i, ++find ) \ - found |= find->second == pair.second; \ - BOOST_CHECK( found ); \ - } - - MULTIMAP_CHECK( i_podmultimap, o_podmultimap ); - MULTIMAP_CHECK( i_isermultimap, o_isermultimap ); - MULTIMAP_CHECK( i_isplmultimap, o_isplmultimap ); - MULTIMAP_CHECK( i_esermultimap, o_esermultimap ); - MULTIMAP_CHECK( i_esplmultimap, o_esplmultimap ); - -#undef MULTIMAP_CHECK - } -} +TEST_SUITE("multimap"); -BOOST_AUTO_TEST_CASE( binary_multimap ) +TEST_CASE("binary_multimap") { test_multimap(); } -BOOST_AUTO_TEST_CASE( portable_binary_multimap ) +TEST_CASE("portable_binary_multimap") { test_multimap(); } -BOOST_AUTO_TEST_CASE( xml_multimap ) +TEST_CASE("xml_multimap") { test_multimap(); } -BOOST_AUTO_TEST_CASE( json_multimap ) +TEST_CASE("json_multimap") { test_multimap(); } +TEST_SUITE_END(); diff --git a/unittests/multimap.hpp b/unittests/multimap.hpp new file mode 100644 index 000000000..142676942 --- /dev/null +++ b/unittests/multimap.hpp @@ -0,0 +1,129 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_MULTIMAP_H_ +#define CEREAL_TEST_MULTIMAP_H_ +#include "common.hpp" + +template inline +void test_multimap() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::multimap o_podmultimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_podmultimap.insert({key, random_value(gen)}); + o_podmultimap.insert({key, random_value(gen)}); + } + + std::multimap o_isermultimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_isermultimap.insert({key, { random_value(gen), random_value(gen) }}); + o_isermultimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::multimap o_isplmultimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_isplmultimap.insert({key, { random_value(gen), random_value(gen) }}); + o_isplmultimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::multimap o_esermultimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_esermultimap.insert({key, { random_value(gen), random_value(gen) }}); + o_esermultimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::multimap o_esplmultimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_esplmultimap.insert({key, { random_value(gen), random_value(gen) }}); + o_esplmultimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podmultimap); + oar(o_isermultimap); + oar(o_isplmultimap); + oar(o_esermultimap); + oar(o_esplmultimap); + } + + std::multimap i_podmultimap; + std::multimap i_isermultimap; + std::multimap i_isplmultimap; + std::multimap i_esermultimap; + std::multimap i_esplmultimap; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podmultimap); + iar(i_isermultimap); + iar(i_isplmultimap); + iar(i_esermultimap); + iar(i_esplmultimap); + } + +#define MULTIMAP_CHECK(InMap, OutMap) \ + for( auto & pair : OutMap ) \ + { \ + auto const count = InMap.count( pair.first ); \ + CHECK_EQ( count, OutMap.count( pair.first ) ); \ + auto find = InMap.find( pair.first ); \ + bool found = false; \ + for( size_t i = 0; i < count; ++i, ++find ) \ + found |= find->second == pair.second; \ + CHECK_UNARY( found ); \ + } + + MULTIMAP_CHECK( i_podmultimap, o_podmultimap ); + MULTIMAP_CHECK( i_isermultimap, o_isermultimap ); + MULTIMAP_CHECK( i_isplmultimap, o_isplmultimap ); + MULTIMAP_CHECK( i_esermultimap, o_esermultimap ); + MULTIMAP_CHECK( i_esplmultimap, o_esplmultimap ); + +#undef MULTIMAP_CHECK + } +} + +#endif // CEREAL_TEST_MULTIMAP_H_ diff --git a/unittests/multiset.cpp b/unittests/multiset.cpp index 206c69fb2..de53d2a24 100644 --- a/unittests/multiset.cpp +++ b/unittests/multiset.cpp @@ -24,130 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "multiset.hpp" -template -void test_multiset() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::multiset o_podmultiset; - for(int j=0; j<100; ++j) - { - int value = random_value(gen); - o_podmultiset.insert(value); - o_podmultiset.insert(value); - } - - std::multiset o_isermultiset; - for(int j=0; j<100; ++j) - { - StructInternalSerialize value = { random_value(gen), random_value(gen) }; - o_isermultiset.insert(value); - o_isermultiset.insert(value); - } - - std::multiset o_isplmultiset; - for(int j=0; j<100; ++j) - { - StructInternalSplit value = { random_value(gen), random_value(gen) }; - o_isplmultiset.insert(value); - o_isplmultiset.insert(value); - } - - std::multiset o_esermultiset; - for(int j=0; j<100; ++j) - { - StructExternalSerialize value = { random_value(gen), random_value(gen) }; - o_esermultiset.insert(value); - o_esermultiset.insert(value); - } - - std::multiset o_esplmultiset; - for(int j=0; j<100; ++j) - { - StructExternalSplit value = { random_value(gen), random_value(gen) }; - o_esplmultiset.insert(value); - o_esplmultiset.insert(value); - } - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podmultiset); - oar(o_isermultiset); - oar(o_isplmultiset); - oar(o_esermultiset); - oar(o_esplmultiset); - } - - std::multiset i_podmultiset; - std::multiset i_isermultiset; - std::multiset i_isplmultiset; - std::multiset i_esermultiset; - std::multiset i_esplmultiset; +TEST_SUITE("multiset"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podmultiset); - iar(i_isermultiset); - iar(i_isplmultiset); - iar(i_esermultiset); - iar(i_esplmultiset); - } - - for(auto const & p : i_podmultiset) - { - BOOST_CHECK_EQUAL(o_podmultiset.count(p), i_podmultiset.count(p)); - } - - for(auto const & p : i_isermultiset) - { - BOOST_CHECK_EQUAL(o_isermultiset.count(p), i_isermultiset.count(p)); - } - - for(auto const & p : i_isplmultiset) - { - BOOST_CHECK_EQUAL(o_isplmultiset.count(p), i_isplmultiset.count(p)); - } - - for(auto const & p : i_esermultiset) - { - BOOST_CHECK_EQUAL(o_esermultiset.count(p), i_esermultiset.count(p)); - } - - for(auto const & p : i_esplmultiset) - { - BOOST_CHECK_EQUAL(o_esplmultiset.count(p), i_esplmultiset.count(p)); - } - } -} - -BOOST_AUTO_TEST_CASE( binary_multiset ) +TEST_CASE("binary_multiset") { test_multiset(); } -BOOST_AUTO_TEST_CASE( portable_binary_multiset ) +TEST_CASE("portable_binary_multiset") { test_multiset(); } -BOOST_AUTO_TEST_CASE( xml_multiset ) +TEST_CASE("xml_multiset") { test_multiset(); } -BOOST_AUTO_TEST_CASE( json_multiset ) +TEST_CASE("json_multiset") { test_multiset(); } - +TEST_SUITE_END(); diff --git a/unittests/multiset.hpp b/unittests/multiset.hpp new file mode 100644 index 000000000..89ad7a1e0 --- /dev/null +++ b/unittests/multiset.hpp @@ -0,0 +1,134 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_MULTISET_H_ +#define CEREAL_TEST_MULTISET_H_ +#include "common.hpp" + +template inline +void test_multiset() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::multiset o_podmultiset; + for(int j=0; j<100; ++j) + { + int value = random_value(gen); + o_podmultiset.insert(value); + o_podmultiset.insert(value); + } + + std::multiset o_isermultiset; + for(int j=0; j<100; ++j) + { + StructInternalSerialize value = { random_value(gen), random_value(gen) }; + o_isermultiset.insert(value); + o_isermultiset.insert(value); + } + + std::multiset o_isplmultiset; + for(int j=0; j<100; ++j) + { + StructInternalSplit value = { random_value(gen), random_value(gen) }; + o_isplmultiset.insert(value); + o_isplmultiset.insert(value); + } + + std::multiset o_esermultiset; + for(int j=0; j<100; ++j) + { + StructExternalSerialize value = { random_value(gen), random_value(gen) }; + o_esermultiset.insert(value); + o_esermultiset.insert(value); + } + + std::multiset o_esplmultiset; + for(int j=0; j<100; ++j) + { + StructExternalSplit value = { random_value(gen), random_value(gen) }; + o_esplmultiset.insert(value); + o_esplmultiset.insert(value); + } + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podmultiset); + oar(o_isermultiset); + oar(o_isplmultiset); + oar(o_esermultiset); + oar(o_esplmultiset); + } + + std::multiset i_podmultiset; + std::multiset i_isermultiset; + std::multiset i_isplmultiset; + std::multiset i_esermultiset; + std::multiset i_esplmultiset; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podmultiset); + iar(i_isermultiset); + iar(i_isplmultiset); + iar(i_esermultiset); + iar(i_esplmultiset); + } + + for(auto const & p : i_podmultiset) + { + CHECK_EQ(o_podmultiset.count(p), i_podmultiset.count(p)); + } + + for(auto const & p : i_isermultiset) + { + CHECK_EQ(o_isermultiset.count(p), i_isermultiset.count(p)); + } + + for(auto const & p : i_isplmultiset) + { + CHECK_EQ(o_isplmultiset.count(p), i_isplmultiset.count(p)); + } + + for(auto const & p : i_esermultiset) + { + CHECK_EQ(o_esermultiset.count(p), i_esermultiset.count(p)); + } + + for(auto const & p : i_esplmultiset) + { + CHECK_EQ(o_esplmultiset.count(p), i_esplmultiset.count(p)); + } + } +} + +#endif // CEREAL_TEST_MULTISET_H_ diff --git a/unittests/pair.cpp b/unittests/pair.cpp index 4e1e61a3c..063237bff 100644 --- a/unittests/pair.cpp +++ b/unittests/pair.cpp @@ -24,86 +24,28 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "pair.hpp" -template -void test_pair() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rng = [&](){ return random_value(gen); }; - - for(int ii=0; ii<100; ++ii) - { - std::pair o_podpair = {rng(), rng()}; - std::pair o_iserpair = {{rng(), rng()}, {rng(), rng()}}; - std::pair o_isplpair = {{rng(), rng()}, {rng(), rng()}}; - std::pair o_eserpair = {{rng(), rng()}, {rng(), rng()}}; - std::pair o_esplpair = {{rng(), rng()}, {rng(), rng()}}; - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podpair); - oar(o_iserpair); - oar(o_isplpair); - oar(o_eserpair); - oar(o_esplpair); - } - - std::pair i_podpair; - std::pair i_iserpair; - std::pair i_isplpair; - std::pair i_eserpair; - std::pair i_esplpair; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podpair); - iar(i_iserpair); - iar(i_isplpair); - iar(i_eserpair); - iar(i_esplpair); - } - - BOOST_CHECK_EQUAL( i_podpair.first, o_podpair.first ); - BOOST_CHECK_EQUAL( i_podpair.second, o_podpair.second ); - - BOOST_CHECK_EQUAL( i_iserpair.first, o_iserpair.first ); - BOOST_CHECK_EQUAL( i_iserpair.second, o_iserpair.second ); - - BOOST_CHECK_EQUAL( i_isplpair.first, o_isplpair.first ); - BOOST_CHECK_EQUAL( i_isplpair.second, o_isplpair.second ); - - BOOST_CHECK_EQUAL( i_eserpair.first, o_eserpair.first ); - BOOST_CHECK_EQUAL( i_eserpair.second, o_eserpair.second ); - - BOOST_CHECK_EQUAL( i_esplpair.first, o_esplpair.first ); - BOOST_CHECK_EQUAL( i_esplpair.second, o_esplpair.second ); - } -} +TEST_SUITE("pair"); -BOOST_AUTO_TEST_CASE( binary_pair ) +TEST_CASE("binary_pair") { test_pair(); } -BOOST_AUTO_TEST_CASE( portable_binary_pair ) +TEST_CASE("portable_binary_pair") { test_pair(); } -BOOST_AUTO_TEST_CASE( xml_pair ) +TEST_CASE("xml_pair") { test_pair(); } -BOOST_AUTO_TEST_CASE( json_pair ) +TEST_CASE("json_pair") { test_pair(); } +TEST_SUITE_END(); diff --git a/unittests/pair.hpp b/unittests/pair.hpp new file mode 100644 index 000000000..fe6093178 --- /dev/null +++ b/unittests/pair.hpp @@ -0,0 +1,92 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_PAIR_H_ +#define CEREAL_TEST_PAIR_H_ +#include "common.hpp" + +template inline +void test_pair() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rng = [&](){ return random_value(gen); }; + + for(int ii=0; ii<100; ++ii) + { + std::pair o_podpair = {rng(), rng()}; + std::pair o_iserpair = {{rng(), rng()}, {rng(), rng()}}; + std::pair o_isplpair = {{rng(), rng()}, {rng(), rng()}}; + std::pair o_eserpair = {{rng(), rng()}, {rng(), rng()}}; + std::pair o_esplpair = {{rng(), rng()}, {rng(), rng()}}; + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podpair); + oar(o_iserpair); + oar(o_isplpair); + oar(o_eserpair); + oar(o_esplpair); + } + + std::pair i_podpair; + std::pair i_iserpair; + std::pair i_isplpair; + std::pair i_eserpair; + std::pair i_esplpair; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podpair); + iar(i_iserpair); + iar(i_isplpair); + iar(i_eserpair); + iar(i_esplpair); + } + + CHECK_EQ( i_podpair.first, o_podpair.first ); + CHECK_EQ( i_podpair.second, o_podpair.second ); + + CHECK_EQ( i_iserpair.first, o_iserpair.first ); + CHECK_EQ( i_iserpair.second, o_iserpair.second ); + + CHECK_EQ( i_isplpair.first, o_isplpair.first ); + CHECK_EQ( i_isplpair.second, o_isplpair.second ); + + CHECK_EQ( i_eserpair.first, o_eserpair.first ); + CHECK_EQ( i_eserpair.second, o_eserpair.second ); + + CHECK_EQ( i_esplpair.first, o_esplpair.first ); + CHECK_EQ( i_esplpair.second, o_esplpair.second ); + } +} + +#endif // CEREAL_TEST_PAIR_H_ diff --git a/unittests/pod.cpp b/unittests/pod.cpp index 281d1ed71..b2450e7b4 100644 --- a/unittests/pod.cpp +++ b/unittests/pod.cpp @@ -24,141 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "pod.hpp" -template -void test_pod() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(size_t i=0; i<100; ++i) - { - bool const o_bool = random_value(gen) % 2 ? true : false; - char const o_char = random_value(gen); - unsigned char const o_uchar = random_value(gen); - uint8_t const o_uint8 = random_value(gen); - int8_t const o_int8 = random_value(gen); - uint16_t const o_uint16 = random_value(gen); - int16_t const o_int16 = random_value(gen); - uint32_t const o_uint32 = random_value(gen); - int32_t const o_int32 = random_value(gen); - uint64_t const o_uint64 = random_value(gen); - int64_t const o_int64 = random_value(gen); - float const o_float = random_value(gen); - double const o_double = random_value(gen); - - long double const o_long_double = random_value(gen); - long const o_long = random_value(gen); - unsigned long const o_ulong = random_value(gen); - long long const o_long_long = random_value(gen); - unsigned long long const o_ulong_long = random_value(gen); - - std::ostringstream os; - { - OArchive oar(os); - oar(o_bool); - oar(o_char); - oar(o_uchar); - oar(o_uint8); - oar(o_int8); - oar(o_uint16); - oar(o_int16); - oar(o_uint32); - oar(o_int32); - oar(o_uint64); - oar(o_int64); - oar(o_float); - oar(o_double); - oar(o_long_double); - oar(o_long); - oar(o_ulong); - oar(o_long_long); - oar(o_ulong_long); - } - - bool i_bool = false; - char i_char = 0; - unsigned char i_uchar = 0; - uint8_t i_uint8 = 0; - int8_t i_int8 = 0; - uint16_t i_uint16 = 0; - int16_t i_int16 = 0; - uint32_t i_uint32 = 0; - int32_t i_int32 = 0; - uint64_t i_uint64 = 0; - int64_t i_int64 = 0; - float i_float = 0; - double i_double = 0; - - long double i_long_double = 0; - long i_long = 0; - unsigned long i_ulong = 0; - long long i_long_long = 0; - unsigned long long i_ulong_long = 0; +TEST_SUITE("pod"); - std::istringstream is(os.str()); - { - IArchive iar(is); - iar(i_bool); - iar(i_char); - iar(i_uchar); - iar(i_uint8); - iar(i_int8); - iar(i_uint16); - iar(i_int16); - iar(i_uint32); - iar(i_int32); - iar(i_uint64); - iar(i_int64); - iar(i_float); - iar(i_double); - iar(i_long_double); - iar(i_long); - iar(i_ulong); - iar(i_long_long); - iar(i_ulong_long); - } - - BOOST_CHECK_EQUAL(i_bool , o_bool); - BOOST_CHECK_EQUAL(i_char , o_char); - BOOST_CHECK_EQUAL(i_uchar , o_uchar); - BOOST_CHECK_EQUAL(i_uint8 , o_uint8); - BOOST_CHECK_EQUAL(i_int8 , o_int8); - BOOST_CHECK_EQUAL(i_uint16 , o_uint16); - BOOST_CHECK_EQUAL(i_int16 , o_int16); - BOOST_CHECK_EQUAL(i_uint32 , o_uint32); - BOOST_CHECK_EQUAL(i_int32 , o_int32); - BOOST_CHECK_EQUAL(i_uint64 , o_uint64); - BOOST_CHECK_EQUAL(i_int64 , o_int64); - BOOST_CHECK_CLOSE(i_float , o_float, 1e-5F); - BOOST_CHECK_CLOSE(i_double , o_double, 1e-5); - - BOOST_CHECK_CLOSE(i_long_double, o_long_double, 1e-5); - BOOST_CHECK_EQUAL(i_long, o_long); - BOOST_CHECK_EQUAL(i_ulong, o_ulong); - BOOST_CHECK_EQUAL(i_long_long, o_long_long); - BOOST_CHECK_EQUAL(i_ulong_long, o_ulong_long); - } -} - -BOOST_AUTO_TEST_CASE( binary_pod ) +TEST_CASE("binary_pod") { test_pod(); } -BOOST_AUTO_TEST_CASE( portable_binary_pod ) +TEST_CASE("portable_binary_pod") { test_pod(); } -BOOST_AUTO_TEST_CASE( xml_pod ) +TEST_CASE("xml_pod") { test_pod(); } -BOOST_AUTO_TEST_CASE( json_pod ) +TEST_CASE("json_pod") { test_pod(); } + +TEST_SUITE_END(); diff --git a/unittests/pod.hpp b/unittests/pod.hpp new file mode 100644 index 000000000..876d81903 --- /dev/null +++ b/unittests/pod.hpp @@ -0,0 +1,147 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_POD_H_ +#define CEREAL_TEST_POD_H_ +#include "common.hpp" + +template inline +void test_pod() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(size_t i=0; i<100; ++i) + { + bool const o_bool = random_value(gen) % 2 ? true : false; + char const o_char = random_value(gen); + unsigned char const o_uchar = random_value(gen); + uint8_t const o_uint8 = random_value(gen); + int8_t const o_int8 = random_value(gen); + uint16_t const o_uint16 = random_value(gen); + int16_t const o_int16 = random_value(gen); + uint32_t const o_uint32 = random_value(gen); + int32_t const o_int32 = random_value(gen); + uint64_t const o_uint64 = random_value(gen); + int64_t const o_int64 = random_value(gen); + float const o_float = random_value(gen); + double const o_double = random_value(gen); + + long double const o_long_double = random_value(gen); + long const o_long = random_value(gen); + unsigned long const o_ulong = random_value(gen); + long long const o_long_long = random_value(gen); + unsigned long long const o_ulong_long = random_value(gen); + + std::ostringstream os; + { + OArchive oar(os); + oar(o_bool); + oar(o_char); + oar(o_uchar); + oar(o_uint8); + oar(o_int8); + oar(o_uint16); + oar(o_int16); + oar(o_uint32); + oar(o_int32); + oar(o_uint64); + oar(o_int64); + oar(o_float); + oar(o_double); + oar(o_long_double); + oar(o_long); + oar(o_ulong); + oar(o_long_long); + oar(o_ulong_long); + } + + bool i_bool = false; + char i_char = 0; + unsigned char i_uchar = 0; + uint8_t i_uint8 = 0; + int8_t i_int8 = 0; + uint16_t i_uint16 = 0; + int16_t i_int16 = 0; + uint32_t i_uint32 = 0; + int32_t i_int32 = 0; + uint64_t i_uint64 = 0; + int64_t i_int64 = 0; + float i_float = 0; + double i_double = 0; + + long double i_long_double = 0; + long i_long = 0; + unsigned long i_ulong = 0; + long long i_long_long = 0; + unsigned long long i_ulong_long = 0; + + std::istringstream is(os.str()); + { + IArchive iar(is); + iar(i_bool); + iar(i_char); + iar(i_uchar); + iar(i_uint8); + iar(i_int8); + iar(i_uint16); + iar(i_int16); + iar(i_uint32); + iar(i_int32); + iar(i_uint64); + iar(i_int64); + iar(i_float); + iar(i_double); + iar(i_long_double); + iar(i_long); + iar(i_ulong); + iar(i_long_long); + iar(i_ulong_long); + } + + CHECK_EQ(i_bool , o_bool); + CHECK_EQ(i_char , o_char); + CHECK_EQ(i_uchar , o_uchar); + CHECK_EQ(i_uint8 , o_uint8); + CHECK_EQ(i_int8 , o_int8); + CHECK_EQ(i_uint16 , o_uint16); + CHECK_EQ(i_int16 , o_int16); + CHECK_EQ(i_uint32 , o_uint32); + CHECK_EQ(i_int32 , o_int32); + CHECK_EQ(i_uint64 , o_uint64); + CHECK_EQ(i_int64 , o_int64); + CHECK_EQ(i_float , doctest::Approx(o_float).epsilon(1e-5F)); + CHECK_EQ(i_double , doctest::Approx(o_double).epsilon(1e-5)); + + CHECK_EQ(i_long_double, doctest::Approx(o_long_double).epsilon(1e-5L)); + CHECK_EQ(i_long, o_long); + CHECK_EQ(i_ulong, o_ulong); + CHECK_EQ(i_long_long, o_long_long); + CHECK_EQ(i_ulong_long, o_ulong_long); + } +} + +#endif // CEREAL_TEST_POD_H_ diff --git a/unittests/polymorphic.cpp b/unittests/polymorphic.cpp index 2b963e55e..87e6de46f 100644 --- a/unittests/polymorphic.cpp +++ b/unittests/polymorphic.cpp @@ -24,373 +24,51 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "polymorphic.hpp" -#if CEREAL_THREAD_SAFE -#include -static std::mutex boostTestMutex; -#endif - -struct PolyBaseA -{ - virtual void foo() = 0; - virtual ~PolyBaseA() {} -}; - -struct PolyBaseAA : PolyBaseA -{ - PolyBaseAA() {} - PolyBaseAA( long ww ) : w(ww) {} - virtual ~PolyBaseAA() {} - long w; - - void foo() {} - - template - void serialize( Archive & ar ) - { - ar( w ); - } - - static void doesNothing() - { - cereal::detail::RegisterPolymorphicCaster::bind(); - } - - bool operator==( PolyBaseAA const & other ) const - { - return w == other.w; - } -}; - -struct PolyBaseB : virtual PolyBaseAA -{ - PolyBaseB() {} - PolyBaseB( int xx, long ww ) : PolyBaseAA(ww), x(xx) {} - virtual ~PolyBaseB() {} - int x; - - template - void serialize( Archive & ar ) - { - ar( cereal::virtual_base_class( this ) ); - ar( x ); - } - - bool operator==( PolyBaseB const & other ) const - { - return PolyBaseAA::operator==( other ) && - x == other.x; - } -}; - -struct PolyBaseC : virtual PolyBaseAA -{ - PolyBaseC() {} - PolyBaseC( double yy, long ww ) : PolyBaseAA(ww), y(yy) {} - virtual ~PolyBaseC() {} - double y; - - template - void serialize( Archive & ar ) - { - ar( cereal::virtual_base_class( this ) ); - ar( y ); - } - - bool operator==( PolyBaseC const & other ) const - { - return PolyBaseAA::operator==( other ) && - std::abs(y - other.y) < 1e-5; - } -}; - -struct PolyDerivedD : PolyBaseB, PolyBaseC -{ - PolyDerivedD() {} - PolyDerivedD( std::string const & zz, double yy, int xx, long ww ) : - PolyBaseAA( ww ), PolyBaseB( xx, ww ), PolyBaseC( yy, ww ), z(zz) {} - virtual ~PolyDerivedD() {} - std::string z; - - template - void serialize( Archive & ar ) - { - ar( cereal::base_class( this ) ); - ar( cereal::base_class( this ) ); - ar( z ); - } - - bool operator==( PolyDerivedD const & other ) const - { - return PolyBaseB::operator==( other ) && - PolyBaseC::operator==( other ) && - z == other.z; - } -}; +TEST_SUITE("polymorphic"); -CEREAL_REGISTER_TYPE(PolyDerivedD) - -struct PolyBase -{ - PolyBase() {} - PolyBase( int xx, float yy ) : x(xx), y(yy) {} - virtual ~PolyBase() {} - int x; - float y; - - template - void serialize( Archive & ar ) - { - ar( x, y ); - } - - virtual void foo() = 0; - - bool operator==( PolyBase const & other ) const - { - return x == other.x && std::abs(y - other.y) < 1e-5; - } -}; - -struct PolyDerived : PolyBase -{ - PolyDerived() {} - PolyDerived( int xx, float yy, bool aa, double bb ) : - PolyBase( xx, yy ), a(aa), b(bb) {} - virtual ~PolyDerived() {} - - bool a; - double b; - - template - void serialize( Archive & ar ) - { - ar( cereal::base_class( this ), - a, b ); - } - - bool operator==( PolyDerived const & other ) const - { - return PolyBase::operator==( other ) && a == other.a && std::abs(b - other.b) < 1e-5; - } - - void foo() {} -}; - -CEREAL_REGISTER_TYPE(PolyDerived) - -struct PolyLA : std::enable_shared_from_this -{ - PolyLA() {} - virtual ~PolyLA() {} - virtual void foo() = 0; -}; - -struct PolyDerivedLA : public PolyLA -{ - PolyDerivedLA( int xx ) : x( xx ) { } - virtual ~PolyDerivedLA() {} - - int x; - std::vector> vec; - - template - void serialize( Archive & ar ) - { - ar( x ); - ar( vec ); - } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - int xx; - ar( xx ); - construct( xx ); - ar( construct->vec ); - } - - void foo() {} - - bool operator==( PolyDerivedLA const & other ) const - { - if( x != other.x ) - return false; - if( vec.size() != other.vec.size() ) - return false; - for( size_t i = 0; i < vec.size(); ++i ) - if( !(*std::dynamic_pointer_cast(vec[i]) == *std::dynamic_pointer_cast(other.vec[i])) ) - return false; - - return true; - } -}; - -CEREAL_REGISTER_TYPE(PolyDerivedLA) -CEREAL_REGISTER_POLYMORPHIC_RELATION(PolyLA, PolyDerivedLA) - -std::ostream& operator<<(std::ostream& os, PolyDerivedLA const & s) -{ - os << "[x: " << s.x << "] "; - for( auto const & v : s.vec ) - os << " child: " << (*std::dynamic_pointer_cast(v)); - return os; -} - -std::ostream& operator<<(std::ostream& os, PolyDerived const & s) -{ - os << "[x: " << s.x << " y: " << s.y << " a: " << s.a << " b: " << s.b << "]"; - return os; -} - -std::ostream& operator<<(std::ostream& os, PolyDerivedD const & s) -{ - os << "[w: " << s.w << " x: " << s.x << " y: " << s.y << " z: " << s.z << "]"; - return os; -} - -template -void test_polymorphic() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rngB = [&](){ return random_value( gen ) % 2 == 0; }; - auto rngI = [&](){ return random_value( gen ); }; - auto rngL = [&](){ return random_value( gen ); }; - auto rngF = [&](){ return random_value( gen ); }; - auto rngD = [&](){ return random_value( gen ); }; - - for(int ii=0; ii<100; ++ii) - { - std::shared_ptr o_shared = std::make_shared( rngI(), rngF(), rngB(), rngD() ); - std::weak_ptr o_weak = o_shared; - std::unique_ptr o_unique( new PolyDerived( rngI(), rngF(), rngB(), rngD() ) ); - - std::shared_ptr o_sharedA = std::make_shared( random_basic_string(gen), - rngD(), rngI(), rngL() ); - - std::weak_ptr o_weakA = o_sharedA; - std::unique_ptr o_uniqueA( new PolyDerivedD( random_basic_string(gen), - rngD(), rngI(), rngL() ) ); - - auto pda = std::make_shared( rngI() ); - pda->vec.emplace_back( std::make_shared( rngI() ) ); - std::shared_ptr o_sharedLA = pda; - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_shared, o_weak, o_unique ); - oar( o_sharedLA ); - - oar( o_sharedA, o_weakA, o_uniqueA ); - } - - decltype(o_shared) i_shared; - decltype(o_weak) i_weak; - decltype(o_unique) i_unique; - - decltype(o_sharedLA) i_sharedLA; - - decltype(o_sharedA) i_sharedA; - decltype(o_weakA) i_weakA; - decltype(o_uniqueA) i_uniqueA; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_shared, i_weak, i_unique ); - iar( i_sharedLA ); - iar( i_sharedA, i_weakA, i_uniqueA ); - } - - auto i_locked = i_weak.lock(); - auto o_locked = o_weak.lock(); - - auto i_sharedLA2 = i_sharedLA->shared_from_this(); - - auto i_lockedA = i_weakA.lock(); - auto o_lockedA = o_weakA.lock(); - - #if CEREAL_THREAD_SAFE - std::lock_guard lock( boostTestMutex ); - #endif - - BOOST_CHECK_EQUAL(i_shared.get(), i_locked.get()); - BOOST_CHECK_EQUAL(*dynamic_cast(i_shared.get()), *dynamic_cast(o_shared.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_shared.get()), *dynamic_cast(i_locked.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_locked.get()), *dynamic_cast(o_locked.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_unique.get()), *dynamic_cast(o_unique.get())); - - BOOST_CHECK_EQUAL(*dynamic_cast(i_sharedLA.get()), *dynamic_cast(o_sharedLA.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_sharedLA2.get()), *dynamic_cast(o_sharedLA.get())); - - BOOST_CHECK_EQUAL(i_sharedA.get(), i_lockedA.get()); - BOOST_CHECK_EQUAL(*dynamic_cast(i_sharedA.get()), *dynamic_cast(o_sharedA.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_sharedA.get()), *dynamic_cast(i_lockedA.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_lockedA.get()), *dynamic_cast(o_lockedA.get())); - BOOST_CHECK_EQUAL(*dynamic_cast(i_uniqueA.get()), *dynamic_cast(o_uniqueA.get())); - } -} - -BOOST_AUTO_TEST_CASE( binary_polymorphic ) +TEST_CASE("binary_polymorphic") { test_polymorphic(); } -BOOST_AUTO_TEST_CASE( portable_binary_polymorphic ) +TEST_CASE("portable_binary_polymorphic") { test_polymorphic(); } -BOOST_AUTO_TEST_CASE( xml_polymorphic ) +TEST_CASE("xml_polymorphic") { test_polymorphic(); } -BOOST_AUTO_TEST_CASE( json_polymorphic ) +TEST_CASE("json_polymorphic") { test_polymorphic(); } #if CEREAL_THREAD_SAFE -template -void test_polymorphic_threading() -{ - std::vector> pool; - for( size_t i = 0; i < 100; ++i ) - pool.emplace_back( std::async( std::launch::async, - [](){ test_polymorphic(); return true; } ) ); - - for( auto & future : pool ) - future.wait(); - - for( auto & future : pool ) - BOOST_CHECK( future.get() == true ); -} - -BOOST_AUTO_TEST_CASE( binary_polymorphic_threading ) +TEST_CASE("binary_polymorphic_threading") { test_polymorphic_threading(); } -BOOST_AUTO_TEST_CASE( portable_binary_polymorphic_threading ) +TEST_CASE("portable_binary_polymorphic_threading") { test_polymorphic_threading(); } -BOOST_AUTO_TEST_CASE( xml_polymorphic_threading ) +TEST_CASE("xml_polymorphic_threading") { test_polymorphic_threading(); } -BOOST_AUTO_TEST_CASE( json_polymorphic_threading ) +TEST_CASE("json_polymorphic_threading") { test_polymorphic_threading(); } #endif // CEREAL_THREAD_SAFE + +TEST_SUITE_END(); diff --git a/unittests/polymorphic.hpp b/unittests/polymorphic.hpp new file mode 100644 index 000000000..d882cc0af --- /dev/null +++ b/unittests/polymorphic.hpp @@ -0,0 +1,362 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_POLYMORPHIC_H_ +#define CEREAL_TEST_POLYMORPHIC_H_ +#include "common.hpp" + +#if CEREAL_THREAD_SAFE +#include +#endif + +struct PolyBaseA +{ + virtual void foo() = 0; + virtual ~PolyBaseA() {} +}; + +struct PolyBaseAA : PolyBaseA +{ + PolyBaseAA() {} + PolyBaseAA( long ww ) : w(ww) {} + virtual ~PolyBaseAA() {} + long w; + + void foo() {} + + template + void serialize( Archive & ar ) + { + ar( w ); + } + + static void doesNothing() + { + cereal::detail::RegisterPolymorphicCaster::bind(); + } + + bool operator==( PolyBaseAA const & other ) const + { + return w == other.w; + } +}; + +struct PolyBaseB : virtual PolyBaseAA +{ + PolyBaseB() {} + PolyBaseB( int xx, long ww ) : PolyBaseAA(ww), x(xx) {} + virtual ~PolyBaseB() {} + int x; + + template + void serialize( Archive & ar ) + { + ar( cereal::virtual_base_class( this ) ); + ar( x ); + } + + bool operator==( PolyBaseB const & other ) const + { + return PolyBaseAA::operator==( other ) && + x == other.x; + } +}; + +struct PolyBaseC : virtual PolyBaseAA +{ + PolyBaseC() {} + PolyBaseC( double yy, long ww ) : PolyBaseAA(ww), y(yy) {} + virtual ~PolyBaseC() {} + double y; + + template + void serialize( Archive & ar ) + { + ar( cereal::virtual_base_class( this ) ); + ar( y ); + } + + bool operator==( PolyBaseC const & other ) const + { + return PolyBaseAA::operator==( other ) && + std::abs(y - other.y) < 1e-5; + } +}; + +struct PolyDerivedD : PolyBaseB, PolyBaseC +{ + PolyDerivedD() {} + PolyDerivedD( std::string const & zz, double yy, int xx, long ww ) : + PolyBaseAA( ww ), PolyBaseB( xx, ww ), PolyBaseC( yy, ww ), z(zz) {} + virtual ~PolyDerivedD() {} + std::string z; + + template + void serialize( Archive & ar ) + { + ar( cereal::base_class( this ) ); + ar( cereal::base_class( this ) ); + ar( z ); + } + + bool operator==( PolyDerivedD const & other ) const + { + return PolyBaseB::operator==( other ) && + PolyBaseC::operator==( other ) && + z == other.z; + } +}; + +CEREAL_REGISTER_TYPE(PolyDerivedD) + +struct PolyBase +{ + PolyBase() {} + PolyBase( int xx, float yy ) : x(xx), y(yy) {} + virtual ~PolyBase() {} + int x; + float y; + + template + void serialize( Archive & ar ) + { + ar( x, y ); + } + + virtual void foo() = 0; + + bool operator==( PolyBase const & other ) const + { + return x == other.x && std::abs(y - other.y) < 1e-5; + } +}; + +struct PolyDerived : PolyBase +{ + PolyDerived() {} + PolyDerived( int xx, float yy, bool aa, double bb ) : + PolyBase( xx, yy ), a(aa), b(bb) {} + virtual ~PolyDerived() {} + + bool a; + double b; + + template + void serialize( Archive & ar ) + { + ar( cereal::base_class( this ), + a, b ); + } + + bool operator==( PolyDerived const & other ) const + { + return PolyBase::operator==( other ) && a == other.a && std::abs(b - other.b) < 1e-5; + } + + void foo() {} +}; + +CEREAL_REGISTER_TYPE(PolyDerived) + +struct PolyLA : std::enable_shared_from_this +{ + PolyLA() {} + virtual ~PolyLA() {} + virtual void foo() = 0; +}; + +struct PolyDerivedLA : public PolyLA +{ + PolyDerivedLA( int xx ) : x( xx ) { } + virtual ~PolyDerivedLA() {} + + int x; + std::vector> vec; + + template + void serialize( Archive & ar ) + { + ar( x ); + ar( vec ); + } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + int xx; + ar( xx ); + construct( xx ); + ar( construct->vec ); + } + + void foo() {} + + bool operator==( PolyDerivedLA const & other ) const + { + if( x != other.x ) + return false; + if( vec.size() != other.vec.size() ) + return false; + for( size_t i = 0; i < vec.size(); ++i ) + if( !(*std::dynamic_pointer_cast(vec[i]) == *std::dynamic_pointer_cast(other.vec[i])) ) + return false; + + return true; + } +}; + +CEREAL_REGISTER_TYPE(PolyDerivedLA) +CEREAL_REGISTER_POLYMORPHIC_RELATION(PolyLA, PolyDerivedLA) + +std::ostream& operator<<(std::ostream& os, PolyDerivedLA const & s) +{ + os << "[x: " << s.x << "] "; + for( auto const & v : s.vec ) + os << " child: " << (*std::dynamic_pointer_cast(v)); + return os; +} + +std::ostream& operator<<(std::ostream& os, PolyDerived const & s) +{ + os << "[x: " << s.x << " y: " << s.y << " a: " << s.a << " b: " << s.b << "]"; + return os; +} + +std::ostream& operator<<(std::ostream& os, PolyDerivedD const & s) +{ + os << "[w: " << s.w << " x: " << s.x << " y: " << s.y << " z: " << s.z << "]"; + return os; +} + +template inline +void test_polymorphic() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + #if CEREAL_THREAD_SAFE + static std::mutex testMutex; + #endif + + auto rngB = [&](){ return random_value( gen ) % 2 == 0; }; + auto rngI = [&](){ return random_value( gen ); }; + auto rngL = [&](){ return random_value( gen ); }; + auto rngF = [&](){ return random_value( gen ); }; + auto rngD = [&](){ return random_value( gen ); }; + + for(int ii=0; ii<100; ++ii) + { + std::shared_ptr o_shared = std::make_shared( rngI(), rngF(), rngB(), rngD() ); + std::weak_ptr o_weak = o_shared; + std::unique_ptr o_unique( new PolyDerived( rngI(), rngF(), rngB(), rngD() ) ); + + std::shared_ptr o_sharedA = std::make_shared( random_basic_string(gen), + rngD(), rngI(), rngL() ); + + std::weak_ptr o_weakA = o_sharedA; + std::unique_ptr o_uniqueA( new PolyDerivedD( random_basic_string(gen), + rngD(), rngI(), rngL() ) ); + + auto pda = std::make_shared( rngI() ); + pda->vec.emplace_back( std::make_shared( rngI() ) ); + std::shared_ptr o_sharedLA = pda; + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_shared, o_weak, o_unique ); + oar( o_sharedLA ); + + oar( o_sharedA, o_weakA, o_uniqueA ); + } + + decltype(o_shared) i_shared; + decltype(o_weak) i_weak; + decltype(o_unique) i_unique; + + decltype(o_sharedLA) i_sharedLA; + + decltype(o_sharedA) i_sharedA; + decltype(o_weakA) i_weakA; + decltype(o_uniqueA) i_uniqueA; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_shared, i_weak, i_unique ); + iar( i_sharedLA ); + iar( i_sharedA, i_weakA, i_uniqueA ); + } + + auto i_locked = i_weak.lock(); + auto o_locked = o_weak.lock(); + + auto i_sharedLA2 = i_sharedLA->shared_from_this(); + + auto i_lockedA = i_weakA.lock(); + auto o_lockedA = o_weakA.lock(); + + #if CEREAL_THREAD_SAFE + std::lock_guard lock( testMutex ); + #endif + + CHECK_EQ(i_shared.get(), i_locked.get()); + CHECK_EQ(*dynamic_cast(i_shared.get()), *dynamic_cast(o_shared.get())); + CHECK_EQ(*dynamic_cast(i_shared.get()), *dynamic_cast(i_locked.get())); + CHECK_EQ(*dynamic_cast(i_locked.get()), *dynamic_cast(o_locked.get())); + CHECK_EQ(*dynamic_cast(i_unique.get()), *dynamic_cast(o_unique.get())); + + CHECK_EQ(*dynamic_cast(i_sharedLA.get()), *dynamic_cast(o_sharedLA.get())); + CHECK_EQ(*dynamic_cast(i_sharedLA2.get()), *dynamic_cast(o_sharedLA.get())); + + CHECK_EQ(i_sharedA.get(), i_lockedA.get()); + CHECK_EQ(*dynamic_cast(i_sharedA.get()), *dynamic_cast(o_sharedA.get())); + CHECK_EQ(*dynamic_cast(i_sharedA.get()), *dynamic_cast(i_lockedA.get())); + CHECK_EQ(*dynamic_cast(i_lockedA.get()), *dynamic_cast(o_lockedA.get())); + CHECK_EQ(*dynamic_cast(i_uniqueA.get()), *dynamic_cast(o_uniqueA.get())); + } +} + +#if CEREAL_THREAD_SAFE +template inline +void test_polymorphic_threading() +{ + std::vector> pool; + for( size_t i = 0; i < 100; ++i ) + pool.emplace_back( std::async( std::launch::async, + [](){ test_polymorphic(); return true; } ) ); + + for( auto & future : pool ) + future.wait(); + + for( auto & future : pool ) + CHECK_UNARY( future.get() ); +} +#endif // CEREAL_THREAD_SAFE + +#endif // CEREAL_TEST_POLYMORPHIC_H_ diff --git a/unittests/portable_binary_archive.cpp b/unittests/portable_binary_archive.cpp index af1018b5d..3b64b0bba 100644 --- a/unittests/portable_binary_archive.cpp +++ b/unittests/portable_binary_archive.cpp @@ -24,146 +24,24 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "portable_binary_archive.hpp" -namespace mynamespace { struct MyCustomClass {}; } +TEST_SUITE("portable_binary_archive"); #ifdef _MSC_VER -BOOST_AUTO_TEST_CASE( util ) +TEST_CASE("util") { - BOOST_CHECK_EQUAL( cereal::util::demangledName(), "struct mynamespace::MyCustomClass" ); + CHECK_EQ( cereal::util::demangledName(), "struct mynamespace::MyCustomClass" ); } #else -BOOST_AUTO_TEST_CASE( util ) +TEST_CASE("util") { - BOOST_CHECK_EQUAL( cereal::util::demangledName(), "mynamespace::MyCustomClass" ); + CHECK_EQ( cereal::util::demangledName(), "mynamespace::MyCustomClass" ); } #endif -template -inline void swapBytes( T & t ) -{ - cereal::portable_binary_detail::swap_bytes( reinterpret_cast(&t) ); -} - -// swaps all output data -#define CEREAL_TEST_SWAP_OUTPUT \ - swapBytes(o_bool); \ - swapBytes(o_uint8); \ - swapBytes(o_int8); \ - swapBytes(o_uint16); \ - swapBytes(o_int16); \ - swapBytes(o_uint32); \ - swapBytes(o_int32); \ - swapBytes(o_uint64); \ - swapBytes(o_int64); \ - swapBytes(o_float); \ - swapBytes(o_double); - -#define CEREAL_TEST_CHECK_EQUAL \ - BOOST_CHECK_EQUAL(i_bool , o_bool); \ - BOOST_CHECK_EQUAL(i_uint8 , o_uint8); \ - BOOST_CHECK_EQUAL(i_int8 , o_int8); \ - BOOST_CHECK_EQUAL(i_uint16 , o_uint16); \ - BOOST_CHECK_EQUAL(i_int16 , o_int16); \ - BOOST_CHECK_EQUAL(i_uint32 , o_uint32); \ - BOOST_CHECK_EQUAL(i_int32 , o_int32); \ - BOOST_CHECK_EQUAL(i_uint64 , o_uint64); \ - BOOST_CHECK_EQUAL(i_int64 , o_int64); \ - if( !std::isnan(i_float) && !std::isnan(o_float) ) BOOST_CHECK_CLOSE(i_float , o_float, 1e-5F); \ - if( !std::isnan(i_float) && !std::isnan(o_float) ) BOOST_CHECK_CLOSE(i_double , o_double, 1e-5); - -// Last parameter exists to keep everything hidden in options -template -void test_endian_serialization( typename IArchive::Options const & iOptions, typename OArchive::Options const & oOptions, const std::uint8_t inputLittleEndian ) -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(size_t i=0; i<100; ++i) - { - bool o_bool = random_value(gen) % 2 ? true : false; - uint8_t o_uint8 = random_value(gen); - int8_t o_int8 = random_value(gen); - uint16_t o_uint16 = random_value(gen); - int16_t o_int16 = random_value(gen); - uint32_t o_uint32 = random_value(gen); - int32_t o_int32 = random_value(gen); - uint64_t o_uint64 = random_value(gen); - int64_t o_int64 = random_value(gen); - float o_float = random_value(gen); - double o_double = random_value(gen); - - std::vector o_vector(100); - for(auto & elem : o_vector) - elem = random_value(gen); - - std::ostringstream os; - { - OArchive oar(os, oOptions); - oar(o_bool); - oar(o_uint8); - oar(o_int8); - oar(o_uint16); - oar(o_int16); - oar(o_uint32); - oar(o_int32); - oar(o_uint64); - oar(o_int64); - oar(o_float); - oar(o_double); - // We can't test vector directly here since we are artificially interfering with the endianness, - // which can result in the size being incorrect - oar(cereal::binary_data( o_vector.data(), static_cast( o_vector.size() * sizeof(int32_t) ) )); - } - - bool i_bool = false; - uint8_t i_uint8 = 0; - int8_t i_int8 = 0; - uint16_t i_uint16 = 0; - int16_t i_int16 = 0; - uint32_t i_uint32 = 0; - int32_t i_int32 = 0; - uint64_t i_uint64 = 0; - int64_t i_int64 = 0; - float i_float = 0; - double i_double = 0; - std::vector i_vector(100); - - std::istringstream is(os.str()); - { - IArchive iar(is, iOptions); - iar(i_bool); - iar(i_uint8); - iar(i_int8); - iar(i_uint16); - iar(i_int16); - iar(i_uint32); - iar(i_int32); - iar(i_uint64); - iar(i_int64); - iar(i_float); - iar(i_double); - iar(cereal::binary_data( i_vector.data(), static_cast( i_vector.size() * sizeof(int32_t) ) )); - } - - // Convert to big endian if we expect to read big and didn't start big - if( cereal::portable_binary_detail::is_little_endian() ^ inputLittleEndian ) // Convert to little endian if - { - CEREAL_TEST_SWAP_OUTPUT - for( auto & val : o_vector ) - swapBytes(val); - } - - CEREAL_TEST_CHECK_EQUAL - - BOOST_CHECK_EQUAL_COLLECTIONS(i_vector.begin(), i_vector.end(), o_vector.begin(), o_vector.end()); - } -} - -BOOST_AUTO_TEST_CASE( portable_binary_archive_endian_conversions ) +TEST_CASE("portable_binary_archive_endian_conversions") { // (last parameter is whether we load as little endian) test_endian_serialization( @@ -177,7 +55,7 @@ BOOST_AUTO_TEST_CASE( portable_binary_archive_endian_conversions ) } // Tests the default behavior to swap bytes to current machine's endianness -BOOST_AUTO_TEST_CASE( portable_binary_archive_default_behavior ) +TEST_CASE("portable_binary_archive_default_behavior") { std::random_device rd; std::mt19937 gen(rd()); @@ -253,5 +131,4 @@ BOOST_AUTO_TEST_CASE( portable_binary_archive_default_behavior ) } } -#undef CEREAl_TEST_SWAP_DATA -#undef CEREAL_TEST_CHECK_EQUAL +TEST_SUITE_END(); diff --git a/unittests/portable_binary_archive.hpp b/unittests/portable_binary_archive.hpp new file mode 100644 index 000000000..b74c4f96f --- /dev/null +++ b/unittests/portable_binary_archive.hpp @@ -0,0 +1,156 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_PORTABLE_BINARY_ARCHIVE_H_ +#define CEREAL_TEST_PORTABLE_BINARY_ARCHIVE_H_ +#include "common.hpp" + +#include + +namespace mynamespace { struct MyCustomClass {}; } + +template +inline void swapBytes( T & t ) +{ + cereal::portable_binary_detail::swap_bytes( reinterpret_cast(&t) ); +} + +// swaps all output data +#define CEREAL_TEST_SWAP_OUTPUT \ + swapBytes(o_bool); \ + swapBytes(o_uint8); \ + swapBytes(o_int8); \ + swapBytes(o_uint16); \ + swapBytes(o_int16); \ + swapBytes(o_uint32); \ + swapBytes(o_int32); \ + swapBytes(o_uint64); \ + swapBytes(o_int64); \ + swapBytes(o_float); \ + swapBytes(o_double); + +#define CEREAL_TEST_CHECK_EQUAL \ + CHECK_EQ(i_bool , o_bool); \ + CHECK_EQ(i_uint8 , o_uint8); \ + CHECK_EQ(i_int8 , o_int8); \ + CHECK_EQ(i_uint16 , o_uint16); \ + CHECK_EQ(i_int16 , o_int16); \ + CHECK_EQ(i_uint32 , o_uint32); \ + CHECK_EQ(i_int32 , o_int32); \ + CHECK_EQ(i_uint64 , o_uint64); \ + CHECK_EQ(i_int64 , o_int64); \ + if( !std::isnan(i_float) && !std::isnan(o_float) ) CHECK_EQ(i_float , doctest::Approx(o_float).epsilon(1e-5F)); \ + if( !std::isnan(i_float) && !std::isnan(o_float) ) CHECK_EQ(i_double, doctest::Approx(o_double).epsilon(1e-5)); + +// Last parameter exists to keep everything hidden in options +template inline +void test_endian_serialization( typename IArchive::Options const & iOptions, typename OArchive::Options const & oOptions, const std::uint8_t inputLittleEndian ) +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(size_t i=0; i<100; ++i) + { + bool o_bool = random_value(gen) % 2 ? true : false; + uint8_t o_uint8 = random_value(gen); + int8_t o_int8 = random_value(gen); + uint16_t o_uint16 = random_value(gen); + int16_t o_int16 = random_value(gen); + uint32_t o_uint32 = random_value(gen); + int32_t o_int32 = random_value(gen); + uint64_t o_uint64 = random_value(gen); + int64_t o_int64 = random_value(gen); + float o_float = random_value(gen); + double o_double = random_value(gen); + + std::vector o_vector(100); + for(auto & elem : o_vector) + elem = random_value(gen); + + std::ostringstream os; + { + OArchive oar(os, oOptions); + oar(o_bool); + oar(o_uint8); + oar(o_int8); + oar(o_uint16); + oar(o_int16); + oar(o_uint32); + oar(o_int32); + oar(o_uint64); + oar(o_int64); + oar(o_float); + oar(o_double); + // We can't test vector directly here since we are artificially interfering with the endianness, + // which can result in the size being incorrect + oar(cereal::binary_data( o_vector.data(), static_cast( o_vector.size() * sizeof(int32_t) ) )); + } + + bool i_bool = false; + uint8_t i_uint8 = 0; + int8_t i_int8 = 0; + uint16_t i_uint16 = 0; + int16_t i_int16 = 0; + uint32_t i_uint32 = 0; + int32_t i_int32 = 0; + uint64_t i_uint64 = 0; + int64_t i_int64 = 0; + float i_float = 0; + double i_double = 0; + std::vector i_vector(100); + + std::istringstream is(os.str()); + { + IArchive iar(is, iOptions); + iar(i_bool); + iar(i_uint8); + iar(i_int8); + iar(i_uint16); + iar(i_int16); + iar(i_uint32); + iar(i_int32); + iar(i_uint64); + iar(i_int64); + iar(i_float); + iar(i_double); + iar(cereal::binary_data( i_vector.data(), static_cast( i_vector.size() * sizeof(int32_t) ) )); + } + + // Convert to big endian if we expect to read big and didn't start big + if( cereal::portable_binary_detail::is_little_endian() ^ inputLittleEndian ) // Convert to little endian if + { + CEREAL_TEST_SWAP_OUTPUT + for( auto & val : o_vector ) + swapBytes(val); + } + + CEREAL_TEST_CHECK_EQUAL + + check_collection(i_vector, o_vector); + } +} + +#endif // CEREAL_TEST_PORTABLE_BINARY_ARCHIVE_H_ diff --git a/unittests/priority_queue.cpp b/unittests/priority_queue.cpp index 8e0b32fe9..e8b997fc6 100644 --- a/unittests/priority_queue.cpp +++ b/unittests/priority_queue.cpp @@ -24,102 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "priority_queue.hpp" -template -void test_priority_queue() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::priority_queue o_podpriority_queue; - for(int j=0; j<100; ++j) - o_podpriority_queue.push(random_value(gen)); - - std::priority_queue o_iserpriority_queue; - for(int j=0; j<100; ++j) - o_iserpriority_queue.push({ random_value(gen), random_value(gen) }); - - std::priority_queue o_isplpriority_queue; - for(int j=0; j<100; ++j) - o_isplpriority_queue.push({ random_value(gen), random_value(gen) }); - - std::priority_queue o_eserpriority_queue; - for(int j=0; j<100; ++j) - o_eserpriority_queue.push({ random_value(gen), random_value(gen) }); - - std::priority_queue o_esplpriority_queue; - for(int j=0; j<100; ++j) - o_esplpriority_queue.push({ random_value(gen), random_value(gen) }); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podpriority_queue); - oar(o_iserpriority_queue); - oar(o_isplpriority_queue); - oar(o_eserpriority_queue); - oar(o_esplpriority_queue); - } - - std::priority_queue i_podpriority_queue; - std::priority_queue i_iserpriority_queue; - std::priority_queue i_isplpriority_queue; - std::priority_queue i_eserpriority_queue; - std::priority_queue i_esplpriority_queue; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podpriority_queue); - iar(i_iserpriority_queue); - iar(i_isplpriority_queue); - iar(i_eserpriority_queue); - iar(i_esplpriority_queue); - } - - auto & i_podpriority_queue_c = cereal::queue_detail::container(i_podpriority_queue); - auto & i_iserpriority_queue_c = cereal::queue_detail::container(i_iserpriority_queue); - auto & i_isplpriority_queue_c = cereal::queue_detail::container(i_isplpriority_queue); - auto & i_eserpriority_queue_c = cereal::queue_detail::container(i_eserpriority_queue); - auto & i_esplpriority_queue_c = cereal::queue_detail::container(i_esplpriority_queue); - - auto & o_podpriority_queue_c = cereal::queue_detail::container(o_podpriority_queue); - auto & o_iserpriority_queue_c = cereal::queue_detail::container(o_iserpriority_queue); - auto & o_isplpriority_queue_c = cereal::queue_detail::container(o_isplpriority_queue); - auto & o_eserpriority_queue_c = cereal::queue_detail::container(o_eserpriority_queue); - auto & o_esplpriority_queue_c = cereal::queue_detail::container(o_esplpriority_queue); - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podpriority_queue_c.begin(), i_podpriority_queue_c.end(), o_podpriority_queue_c.begin(), o_podpriority_queue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserpriority_queue_c.begin(), i_iserpriority_queue_c.end(), o_iserpriority_queue_c.begin(), o_iserpriority_queue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplpriority_queue_c.begin(), i_isplpriority_queue_c.end(), o_isplpriority_queue_c.begin(), o_isplpriority_queue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserpriority_queue_c.begin(), i_eserpriority_queue_c.end(), o_eserpriority_queue_c.begin(), o_eserpriority_queue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplpriority_queue_c.begin(), i_esplpriority_queue_c.end(), o_esplpriority_queue_c.begin(), o_esplpriority_queue_c.end()); - } -} +TEST_SUITE("priority_queue"); -BOOST_AUTO_TEST_CASE( binary_priority_queue ) +TEST_CASE("binary_priority_queue") { test_priority_queue(); } -BOOST_AUTO_TEST_CASE( portable_binary_priority_queue ) +TEST_CASE("portable_binary_priority_queue") { test_priority_queue(); } -BOOST_AUTO_TEST_CASE( xml_priority_queue ) +TEST_CASE("xml_priority_queue") { test_priority_queue(); } -BOOST_AUTO_TEST_CASE( json_priority_queue ) +TEST_CASE("json_priority_queue") { test_priority_queue(); } +TEST_SUITE_END(); diff --git a/unittests/priority_queue.hpp b/unittests/priority_queue.hpp new file mode 100644 index 000000000..27d31a51d --- /dev/null +++ b/unittests/priority_queue.hpp @@ -0,0 +1,107 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_PRIORITY_QUEUE_H_ +#define CEREAL_TEST_PRIORITY_QUEUE_H_ +#include "common.hpp" + +template inline +void test_priority_queue() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::priority_queue o_podpriority_queue; + for(int j=0; j<100; ++j) + o_podpriority_queue.push(random_value(gen)); + + std::priority_queue o_iserpriority_queue; + for(int j=0; j<100; ++j) + o_iserpriority_queue.push({ random_value(gen), random_value(gen) }); + + std::priority_queue o_isplpriority_queue; + for(int j=0; j<100; ++j) + o_isplpriority_queue.push({ random_value(gen), random_value(gen) }); + + std::priority_queue o_eserpriority_queue; + for(int j=0; j<100; ++j) + o_eserpriority_queue.push({ random_value(gen), random_value(gen) }); + + std::priority_queue o_esplpriority_queue; + for(int j=0; j<100; ++j) + o_esplpriority_queue.push({ random_value(gen), random_value(gen) }); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podpriority_queue); + oar(o_iserpriority_queue); + oar(o_isplpriority_queue); + oar(o_eserpriority_queue); + oar(o_esplpriority_queue); + } + + std::priority_queue i_podpriority_queue; + std::priority_queue i_iserpriority_queue; + std::priority_queue i_isplpriority_queue; + std::priority_queue i_eserpriority_queue; + std::priority_queue i_esplpriority_queue; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podpriority_queue); + iar(i_iserpriority_queue); + iar(i_isplpriority_queue); + iar(i_eserpriority_queue); + iar(i_esplpriority_queue); + } + + auto & i_podpriority_queue_c = cereal::queue_detail::container(i_podpriority_queue); + auto & i_iserpriority_queue_c = cereal::queue_detail::container(i_iserpriority_queue); + auto & i_isplpriority_queue_c = cereal::queue_detail::container(i_isplpriority_queue); + auto & i_eserpriority_queue_c = cereal::queue_detail::container(i_eserpriority_queue); + auto & i_esplpriority_queue_c = cereal::queue_detail::container(i_esplpriority_queue); + + auto & o_podpriority_queue_c = cereal::queue_detail::container(o_podpriority_queue); + auto & o_iserpriority_queue_c = cereal::queue_detail::container(o_iserpriority_queue); + auto & o_isplpriority_queue_c = cereal::queue_detail::container(o_isplpriority_queue); + auto & o_eserpriority_queue_c = cereal::queue_detail::container(o_eserpriority_queue); + auto & o_esplpriority_queue_c = cereal::queue_detail::container(o_esplpriority_queue); + + check_collection(i_podpriority_queue_c, o_podpriority_queue_c); + check_collection(i_iserpriority_queue_c, o_iserpriority_queue_c); + check_collection(i_isplpriority_queue_c, o_isplpriority_queue_c); + check_collection(i_eserpriority_queue_c, o_eserpriority_queue_c); + check_collection(i_esplpriority_queue_c, o_esplpriority_queue_c); + } +} + +#endif // CEREAL_TEST_PRIORITY_QUEUE_H_ diff --git a/unittests/queue.cpp b/unittests/queue.cpp index 175456e77..5f87705b4 100644 --- a/unittests/queue.cpp +++ b/unittests/queue.cpp @@ -24,102 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "queue.hpp" -template -void test_queue() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::queue o_podqueue; - for(int j=0; j<100; ++j) - o_podqueue.push(random_value(gen)); - - std::queue o_iserqueue; - for(int j=0; j<100; ++j) - o_iserqueue.push({ random_value(gen), random_value(gen) }); - - std::queue o_isplqueue; - for(int j=0; j<100; ++j) - o_isplqueue.push({ random_value(gen), random_value(gen) }); - - std::queue o_eserqueue; - for(int j=0; j<100; ++j) - o_eserqueue.push({ random_value(gen), random_value(gen) }); - - std::queue o_esplqueue; - for(int j=0; j<100; ++j) - o_esplqueue.push({ random_value(gen), random_value(gen) }); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podqueue); - oar(o_iserqueue); - oar(o_isplqueue); - oar(o_eserqueue); - oar(o_esplqueue); - } - - std::queue i_podqueue; - std::queue i_iserqueue; - std::queue i_isplqueue; - std::queue i_eserqueue; - std::queue i_esplqueue; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podqueue); - iar(i_iserqueue); - iar(i_isplqueue); - iar(i_eserqueue); - iar(i_esplqueue); - } - - auto & i_podqueue_c = cereal::queue_detail::container(i_podqueue); - auto & i_iserqueue_c = cereal::queue_detail::container(i_iserqueue); - auto & i_isplqueue_c = cereal::queue_detail::container(i_isplqueue); - auto & i_eserqueue_c = cereal::queue_detail::container(i_eserqueue); - auto & i_esplqueue_c = cereal::queue_detail::container(i_esplqueue); - - auto & o_podqueue_c = cereal::queue_detail::container(o_podqueue); - auto & o_iserqueue_c = cereal::queue_detail::container(o_iserqueue); - auto & o_isplqueue_c = cereal::queue_detail::container(o_isplqueue); - auto & o_eserqueue_c = cereal::queue_detail::container(o_eserqueue); - auto & o_esplqueue_c = cereal::queue_detail::container(o_esplqueue); - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podqueue_c.begin(), i_podqueue_c.end(), o_podqueue_c.begin(), o_podqueue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserqueue_c.begin(), i_iserqueue_c.end(), o_iserqueue_c.begin(), o_iserqueue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplqueue_c.begin(), i_isplqueue_c.end(), o_isplqueue_c.begin(), o_isplqueue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserqueue_c.begin(), i_eserqueue_c.end(), o_eserqueue_c.begin(), o_eserqueue_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplqueue_c.begin(), i_esplqueue_c.end(), o_esplqueue_c.begin(), o_esplqueue_c.end()); - } -} +TEST_SUITE("queue"); -BOOST_AUTO_TEST_CASE( binary_queue ) +TEST_CASE("binary_queue") { test_queue(); } -BOOST_AUTO_TEST_CASE( portable_binary_queue ) +TEST_CASE("portable_binary_queue") { test_queue(); } -BOOST_AUTO_TEST_CASE( xml_queue ) +TEST_CASE("xml_queue") { test_queue(); } -BOOST_AUTO_TEST_CASE( json_queue ) +TEST_CASE("json_queue") { test_queue(); } +TEST_SUITE_END(); diff --git a/unittests/queue.hpp b/unittests/queue.hpp new file mode 100644 index 000000000..3b0484de6 --- /dev/null +++ b/unittests/queue.hpp @@ -0,0 +1,107 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_QUEUE_H_ +#define CEREAL_TEST_QUEUE_H_ +#include "common.hpp" + +template inline +void test_queue() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::queue o_podqueue; + for(int j=0; j<100; ++j) + o_podqueue.push(random_value(gen)); + + std::queue o_iserqueue; + for(int j=0; j<100; ++j) + o_iserqueue.push({ random_value(gen), random_value(gen) }); + + std::queue o_isplqueue; + for(int j=0; j<100; ++j) + o_isplqueue.push({ random_value(gen), random_value(gen) }); + + std::queue o_eserqueue; + for(int j=0; j<100; ++j) + o_eserqueue.push({ random_value(gen), random_value(gen) }); + + std::queue o_esplqueue; + for(int j=0; j<100; ++j) + o_esplqueue.push({ random_value(gen), random_value(gen) }); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podqueue); + oar(o_iserqueue); + oar(o_isplqueue); + oar(o_eserqueue); + oar(o_esplqueue); + } + + std::queue i_podqueue; + std::queue i_iserqueue; + std::queue i_isplqueue; + std::queue i_eserqueue; + std::queue i_esplqueue; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podqueue); + iar(i_iserqueue); + iar(i_isplqueue); + iar(i_eserqueue); + iar(i_esplqueue); + } + + auto & i_podqueue_c = cereal::queue_detail::container(i_podqueue); + auto & i_iserqueue_c = cereal::queue_detail::container(i_iserqueue); + auto & i_isplqueue_c = cereal::queue_detail::container(i_isplqueue); + auto & i_eserqueue_c = cereal::queue_detail::container(i_eserqueue); + auto & i_esplqueue_c = cereal::queue_detail::container(i_esplqueue); + + auto & o_podqueue_c = cereal::queue_detail::container(o_podqueue); + auto & o_iserqueue_c = cereal::queue_detail::container(o_iserqueue); + auto & o_isplqueue_c = cereal::queue_detail::container(o_isplqueue); + auto & o_eserqueue_c = cereal::queue_detail::container(o_eserqueue); + auto & o_esplqueue_c = cereal::queue_detail::container(o_esplqueue); + + check_collection(i_podqueue_c, o_podqueue_c); + check_collection(i_iserqueue_c, o_iserqueue_c); + check_collection(i_isplqueue_c, o_isplqueue_c); + check_collection(i_eserqueue_c, o_eserqueue_c); + check_collection(i_esplqueue_c, o_esplqueue_c); + } +} + +#endif // CEREAL_TEST_QUEUE_H_ diff --git a/unittests/set.cpp b/unittests/set.cpp index e9bb3bb70..cc2e00c0c 100644 --- a/unittests/set.cpp +++ b/unittests/set.cpp @@ -24,90 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "set.hpp" -template -void test_set() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::set o_podset; - for(int j=0; j<100; ++j) - o_podset.insert(random_value(gen)); - - std::set o_iserset; - for(int j=0; j<100; ++j) - o_iserset.insert({ random_value(gen), random_value(gen) }); - - std::set o_isplset; - for(int j=0; j<100; ++j) - o_isplset.insert({ random_value(gen), random_value(gen) }); - - std::set o_eserset; - for(int j=0; j<100; ++j) - o_eserset.insert({ random_value(gen), random_value(gen) }); - - std::set o_esplset; - for(int j=0; j<100; ++j) - o_esplset.insert({ random_value(gen), random_value(gen) }); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podset); - oar(o_iserset); - oar(o_isplset); - oar(o_eserset); - oar(o_esplset); - } - - std::set i_podset; - std::set i_iserset; - std::set i_isplset; - std::set i_eserset; - std::set i_esplset; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podset); - iar(i_iserset); - iar(i_isplset); - iar(i_eserset); - iar(i_esplset); - } - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podset.begin(), i_podset.end(), o_podset.begin(), o_podset.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserset.begin(), i_iserset.end(), o_iserset.begin(), o_iserset.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplset.begin(), i_isplset.end(), o_isplset.begin(), o_isplset.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserset.begin(), i_eserset.end(), o_eserset.begin(), o_eserset.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplset.begin(), i_esplset.end(), o_esplset.begin(), o_esplset.end()); - } -} +TEST_SUITE("set"); -BOOST_AUTO_TEST_CASE( binary_set ) +TEST_CASE("binary_set") { test_set(); } -BOOST_AUTO_TEST_CASE( portable_binary_set ) +TEST_CASE("portable_binary_set") { test_set(); } -BOOST_AUTO_TEST_CASE( xml_set ) +TEST_CASE("xml_set") { test_set(); } -BOOST_AUTO_TEST_CASE( json_set ) +TEST_CASE("json_set") { test_set(); } +TEST_SUITE_END(); diff --git a/unittests/set.hpp b/unittests/set.hpp new file mode 100644 index 000000000..6e3994212 --- /dev/null +++ b/unittests/set.hpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_SET_H_ +#define CEREAL_TEST_SET_H_ +#include "common.hpp" + +template inline +void test_set() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::set o_podset; + for(int j=0; j<100; ++j) + o_podset.insert(random_value(gen)); + + std::set o_iserset; + for(int j=0; j<100; ++j) + o_iserset.insert({ random_value(gen), random_value(gen) }); + + std::set o_isplset; + for(int j=0; j<100; ++j) + o_isplset.insert({ random_value(gen), random_value(gen) }); + + std::set o_eserset; + for(int j=0; j<100; ++j) + o_eserset.insert({ random_value(gen), random_value(gen) }); + + std::set o_esplset; + for(int j=0; j<100; ++j) + o_esplset.insert({ random_value(gen), random_value(gen) }); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podset); + oar(o_iserset); + oar(o_isplset); + oar(o_eserset); + oar(o_esplset); + } + + std::set i_podset; + std::set i_iserset; + std::set i_isplset; + std::set i_eserset; + std::set i_esplset; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podset); + iar(i_iserset); + iar(i_isplset); + iar(i_eserset); + iar(i_esplset); + } + + check_collection(i_podset, o_podset); + check_collection(i_iserset, o_iserset); + check_collection(i_isplset, o_isplset); + check_collection(i_eserset, o_eserset); + check_collection(i_esplset, o_esplset); + } +} + +#endif // CEREAL_TEST_SET_H_ diff --git a/unittests/stack.cpp b/unittests/stack.cpp index edc0920d7..3e4212c10 100644 --- a/unittests/stack.cpp +++ b/unittests/stack.cpp @@ -24,102 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "stack.hpp" -template -void test_stack() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::stack o_podstack; - for(int j=0; j<100; ++j) - o_podstack.push(random_value(gen)); - - std::stack o_iserstack; - for(int j=0; j<100; ++j) - o_iserstack.push({ random_value(gen), random_value(gen) }); - - std::stack o_isplstack; - for(int j=0; j<100; ++j) - o_isplstack.push({ random_value(gen), random_value(gen) }); - - std::stack o_eserstack; - for(int j=0; j<100; ++j) - o_eserstack.push({ random_value(gen), random_value(gen) }); - - std::stack o_esplstack; - for(int j=0; j<100; ++j) - o_esplstack.push({ random_value(gen), random_value(gen) }); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podstack); - oar(o_iserstack); - oar(o_isplstack); - oar(o_eserstack); - oar(o_esplstack); - } - - std::stack i_podstack; - std::stack i_iserstack; - std::stack i_isplstack; - std::stack i_eserstack; - std::stack i_esplstack; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podstack); - iar(i_iserstack); - iar(i_isplstack); - iar(i_eserstack); - iar(i_esplstack); - } - - auto & i_podstack_c = cereal::stack_detail::container(i_podstack); - auto & i_iserstack_c = cereal::stack_detail::container(i_iserstack); - auto & i_isplstack_c = cereal::stack_detail::container(i_isplstack); - auto & i_eserstack_c = cereal::stack_detail::container(i_eserstack); - auto & i_esplstack_c = cereal::stack_detail::container(i_esplstack); - - auto & o_podstack_c = cereal::stack_detail::container(o_podstack); - auto & o_iserstack_c = cereal::stack_detail::container(o_iserstack); - auto & o_isplstack_c = cereal::stack_detail::container(o_isplstack); - auto & o_eserstack_c = cereal::stack_detail::container(o_eserstack); - auto & o_esplstack_c = cereal::stack_detail::container(o_esplstack); - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podstack_c.begin(), i_podstack_c.end(), o_podstack_c.begin(), o_podstack_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iserstack_c.begin(), i_iserstack_c.end(), o_iserstack_c.begin(), o_iserstack_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplstack_c.begin(), i_isplstack_c.end(), o_isplstack_c.begin(), o_isplstack_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eserstack_c.begin(), i_eserstack_c.end(), o_eserstack_c.begin(), o_eserstack_c.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplstack_c.begin(), i_esplstack_c.end(), o_esplstack_c.begin(), o_esplstack_c.end()); - } -} +TEST_SUITE("stack"); -BOOST_AUTO_TEST_CASE( binary_stack ) +TEST_CASE("binary_stack") { test_stack(); } -BOOST_AUTO_TEST_CASE( portable_binary_stack ) +TEST_CASE("portable_binary_stack") { test_stack(); } -BOOST_AUTO_TEST_CASE( xml_stack ) +TEST_CASE("xml_stack") { test_stack(); } -BOOST_AUTO_TEST_CASE( json_stack ) +TEST_CASE("json_stack") { test_stack(); } +TEST_SUITE_END(); diff --git a/unittests/stack.hpp b/unittests/stack.hpp new file mode 100644 index 000000000..4ea1ae38b --- /dev/null +++ b/unittests/stack.hpp @@ -0,0 +1,107 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_STACK_H_ +#define CEREAL_TEST_STACK_H_ +#include "common.hpp" + +template inline +void test_stack() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::stack o_podstack; + for(int j=0; j<100; ++j) + o_podstack.push(random_value(gen)); + + std::stack o_iserstack; + for(int j=0; j<100; ++j) + o_iserstack.push({ random_value(gen), random_value(gen) }); + + std::stack o_isplstack; + for(int j=0; j<100; ++j) + o_isplstack.push({ random_value(gen), random_value(gen) }); + + std::stack o_eserstack; + for(int j=0; j<100; ++j) + o_eserstack.push({ random_value(gen), random_value(gen) }); + + std::stack o_esplstack; + for(int j=0; j<100; ++j) + o_esplstack.push({ random_value(gen), random_value(gen) }); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podstack); + oar(o_iserstack); + oar(o_isplstack); + oar(o_eserstack); + oar(o_esplstack); + } + + std::stack i_podstack; + std::stack i_iserstack; + std::stack i_isplstack; + std::stack i_eserstack; + std::stack i_esplstack; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podstack); + iar(i_iserstack); + iar(i_isplstack); + iar(i_eserstack); + iar(i_esplstack); + } + + auto & i_podstack_c = cereal::stack_detail::container(i_podstack); + auto & i_iserstack_c = cereal::stack_detail::container(i_iserstack); + auto & i_isplstack_c = cereal::stack_detail::container(i_isplstack); + auto & i_eserstack_c = cereal::stack_detail::container(i_eserstack); + auto & i_esplstack_c = cereal::stack_detail::container(i_esplstack); + + auto & o_podstack_c = cereal::stack_detail::container(o_podstack); + auto & o_iserstack_c = cereal::stack_detail::container(o_iserstack); + auto & o_isplstack_c = cereal::stack_detail::container(o_isplstack); + auto & o_eserstack_c = cereal::stack_detail::container(o_eserstack); + auto & o_esplstack_c = cereal::stack_detail::container(o_esplstack); + + check_collection(i_podstack_c, o_podstack_c ); + check_collection(i_iserstack_c, o_iserstack_c); + check_collection(i_isplstack_c, o_isplstack_c); + check_collection(i_eserstack_c, o_eserstack_c); + check_collection(i_esplstack_c, o_esplstack_c); + } +} + +#endif // CEREAL_TEST_STACK_H_ diff --git a/unittests/structs.cpp b/unittests/structs.cpp index 245e15df2..117e7cca5 100644 --- a/unittests/structs.cpp +++ b/unittests/structs.cpp @@ -24,62 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "structs.hpp" -template -void test_structs() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - StructInternalSerialize o_iser = { random_value(gen), random_value(gen) }; - StructInternalSplit o_ispl = { random_value(gen), random_value(gen) }; - StructExternalSerialize o_eser = { random_value(gen), random_value(gen) }; - StructExternalSplit o_espl = { random_value(gen), random_value(gen) }; - - std::ostringstream os; - { - OArchive oar(os); - oar( o_iser, o_ispl, o_eser, o_espl); - } - - StructInternalSerialize i_iser; - StructInternalSplit i_ispl; - StructExternalSerialize i_eser; - StructExternalSplit i_espl; +TEST_SUITE("structs"); - std::istringstream is(os.str()); - { - IArchive iar(is); - iar( i_iser, i_ispl, i_eser, i_espl); - } - - BOOST_CHECK(i_iser == o_iser); - BOOST_CHECK(i_ispl == o_ispl); - BOOST_CHECK(i_eser == o_eser); - BOOST_CHECK(i_espl == o_espl); - } -} - -BOOST_AUTO_TEST_CASE( binary_structs ) +TEST_CASE("binary_structs") { test_structs(); } -BOOST_AUTO_TEST_CASE( portable_binary_structs ) +TEST_CASE("portable_binary_structs") { test_structs(); } -BOOST_AUTO_TEST_CASE( xml_structs ) +TEST_CASE("xml_structs") { test_structs(); } -BOOST_AUTO_TEST_CASE( json_structs ) +TEST_CASE("json_structs") { test_structs(); } + +TEST_SUITE_END(); diff --git a/unittests/structs.hpp b/unittests/structs.hpp new file mode 100644 index 000000000..db7ce1337 --- /dev/null +++ b/unittests/structs.hpp @@ -0,0 +1,68 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_STRUCTS_H_ +#define CEREAL_TEST_STRUCTS_H_ +#include "common.hpp" + +template inline +void test_structs() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + StructInternalSerialize o_iser = { random_value(gen), random_value(gen) }; + StructInternalSplit o_ispl = { random_value(gen), random_value(gen) }; + StructExternalSerialize o_eser = { random_value(gen), random_value(gen) }; + StructExternalSplit o_espl = { random_value(gen), random_value(gen) }; + + std::ostringstream os; + { + OArchive oar(os); + oar( o_iser, o_ispl, o_eser, o_espl); + } + + StructInternalSerialize i_iser; + StructInternalSplit i_ispl; + StructExternalSerialize i_eser; + StructExternalSplit i_espl; + + std::istringstream is(os.str()); + { + IArchive iar(is); + iar( i_iser, i_ispl, i_eser, i_espl); + } + + CHECK_EQ(i_iser, o_iser); + CHECK_EQ(i_ispl, o_ispl); + CHECK_EQ(i_eser, o_eser); + CHECK_EQ(i_espl, o_espl); + } +} + +#endif // CEREAL_TEST_STRUCTS_H_ diff --git a/unittests/structs_minimal.cpp b/unittests/structs_minimal.cpp index 877c65f69..d78f8191e 100644 --- a/unittests/structs_minimal.cpp +++ b/unittests/structs_minimal.cpp @@ -24,248 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "structs_minimal.hpp" -class MemberMinimal -{ - public: - MemberMinimal() = default; - MemberMinimal( std::string const & str ) : x( str ) {} - - protected: - friend class cereal::access; - - template - std::string save_minimal( Archive const & ) const - { - return x; - } - - template - void load_minimal( Archive const &, std::string const & str ) - { - x = str; - } - - public: - std::string x; -}; - -class MemberMinimalVersioned -{ - public: - MemberMinimalVersioned() = default; - MemberMinimalVersioned( double d ) : x( d ) {} - - protected: - friend class cereal::access; - - template - double save_minimal( Archive const &, const std::uint32_t ) const - { - return x; - } - - template - void load_minimal( Archive const &, double const & d, const std::uint32_t ) - { - x = d; - } - - public: - double x; -}; - -struct NonMemberMinimal -{ - NonMemberMinimal() = default; - NonMemberMinimal( std::uint32_t xx ) : x(xx) {} - std::uint32_t x; -}; - -template -std::uint32_t save_minimal( Archive const &, NonMemberMinimal const & nmm ) -{ - return nmm.x; -} - -template -void load_minimal( Archive const &, NonMemberMinimal & nmm, std::uint32_t const & data ) -{ - nmm.x = data; -} - -struct NonMemberMinimalVersioned -{ - NonMemberMinimalVersioned() = default; - NonMemberMinimalVersioned( bool xx ) : x(xx) {} - bool x; -}; - -template -bool save_minimal( Archive const &, NonMemberMinimalVersioned const & nmm, std::uint32_t const ) -{ - return nmm.x; -} - -template -void load_minimal( Archive const &, NonMemberMinimalVersioned & nmm, bool const & data, std::uint32_t const ) -{ - nmm.x = data; -} - -struct TestStruct -{ - TestStruct() = default; - TestStruct( std::string const & s, double d, std::uint32_t u, bool b ) : - mm(s), mmv(d), nmm(u), nmmv(b) {} - - template - void serialize( Archive & ar ) - { - ar( mm, mmv ); - ar( nmm, nmmv ); - } - - MemberMinimal mm; - MemberMinimalVersioned mmv; - NonMemberMinimal nmm; - NonMemberMinimalVersioned nmmv; -}; - -struct Issue79Struct -{ - Issue79Struct() = default; - Issue79Struct( std::int32_t xx ) : x(xx) {} - std::int32_t x; -}; - -template ::value || - std::is_same::value> = cereal::traits::sfinae> -std::string save_minimal( Archive const &, Issue79Struct const & val ) -{ - return std::to_string( val.x ); -} - -template ::value || - std::is_same::value> = cereal::traits::sfinae> -void load_minimal( Archive const &, Issue79Struct & val, std::string const & str ) -{ - val.x = std::stoi( str ); -} - -template ::value || - std::is_same::value> = cereal::traits::sfinae> -std::int32_t save_minimal( Archive const &, Issue79Struct const & val ) -{ - return val.x; -} - -template ::value || - std::is_same::value> = cereal::traits::sfinae> -void load_minimal( Archive const &, Issue79Struct & val, std::int32_t const & xx ) -{ - val.x = xx; -} - -struct Issue79StructInternal -{ - Issue79StructInternal() = default; - Issue79StructInternal( std::int32_t xx ) : x(xx) {} - std::int32_t x; - - template ::value || - std::is_same::value> = cereal::traits::sfinae> - std::string save_minimal( Archive const & ) const - { - return std::to_string( x ); - } +TEST_SUITE("structs_minimal"); - template ::value || - std::is_same::value> = cereal::traits::sfinae> - void load_minimal( Archive const &, std::string const & str ) - { - x = std::stoi( str ); - } - - template ::value || - std::is_same::value> = cereal::traits::sfinae> - std::int32_t save_minimal( Archive const & ) const - { - return x; - } - - template ::value || - std::is_same::value> = cereal::traits::sfinae> - void load_minimal( Archive const &, std::int32_t const & xx ) - { - x = xx; - } -}; - -template -void test_structs_minimal() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - TestStruct o_struct = { random_basic_string(gen), random_value(gen), - random_value(gen), random_value(gen) % 2 ? true : false }; - - Issue79Struct o_struct2 = { random_value(gen) }; - Issue79StructInternal o_struct3 = { random_value(gen) }; - - std::ostringstream os; - { - OArchive oar(os); - oar( o_struct ); - oar( o_struct2 ); - oar( o_struct3 ); - } - - decltype(o_struct) i_struct; - decltype(o_struct2) i_struct2; - decltype(o_struct3) i_struct3; - - std::istringstream is(os.str()); - { - IArchive iar(is); - iar( i_struct ); - iar( i_struct2 ); - iar( i_struct3 ); - } - - BOOST_CHECK(o_struct.mm.x == i_struct.mm.x); - BOOST_CHECK_CLOSE(o_struct.mmv.x, i_struct.mmv.x, 1e-5); - - BOOST_CHECK(o_struct.nmm.x == i_struct.nmm.x); - BOOST_CHECK(o_struct.nmmv.x == i_struct.nmmv.x); - - BOOST_CHECK(o_struct2.x == i_struct2.x); - - BOOST_CHECK(o_struct3.x == i_struct3.x); - } -} - -BOOST_AUTO_TEST_CASE( binary_structs_minimal ) +TEST_CASE("binary_structs_minimal") { test_structs_minimal(); } -BOOST_AUTO_TEST_CASE( portable_binary_structs_minimal ) +TEST_CASE("portable_binary_structs_minimal") { test_structs_minimal(); } -BOOST_AUTO_TEST_CASE( xml_structs_minimal ) +TEST_CASE("xml_structs_minimal") { test_structs_minimal(); } -BOOST_AUTO_TEST_CASE( json_structs_minimal ) +TEST_CASE("json_structs_minimal") { test_structs_minimal(); } + +TEST_SUITE_END(); diff --git a/unittests/structs_minimal.hpp b/unittests/structs_minimal.hpp new file mode 100644 index 000000000..57ccd4999 --- /dev/null +++ b/unittests/structs_minimal.hpp @@ -0,0 +1,254 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_STRUCTS_MINIMAL_H_ +#define CEREAL_TEST_STRUCTS_MINIMAL_H_ +#include "common.hpp" + +class MemberMinimal +{ + public: + MemberMinimal() = default; + MemberMinimal( std::string const & str ) : x( str ) {} + + protected: + friend class cereal::access; + + template + std::string save_minimal( Archive const & ) const + { + return x; + } + + template + void load_minimal( Archive const &, std::string const & str ) + { + x = str; + } + + public: + std::string x; +}; + +class MemberMinimalVersioned +{ + public: + MemberMinimalVersioned() = default; + MemberMinimalVersioned( double d ) : x( d ) {} + + protected: + friend class cereal::access; + + template + double save_minimal( Archive const &, const std::uint32_t ) const + { + return x; + } + + template + void load_minimal( Archive const &, double const & d, const std::uint32_t ) + { + x = d; + } + + public: + double x; +}; + +struct NonMemberMinimal +{ + NonMemberMinimal() = default; + NonMemberMinimal( std::uint32_t xx ) : x(xx) {} + std::uint32_t x; +}; + +template inline +std::uint32_t save_minimal( Archive const &, NonMemberMinimal const & nmm ) +{ + return nmm.x; +} + +template inline +void load_minimal( Archive const &, NonMemberMinimal & nmm, std::uint32_t const & data ) +{ + nmm.x = data; +} + +struct NonMemberMinimalVersioned +{ + NonMemberMinimalVersioned() = default; + NonMemberMinimalVersioned( bool xx ) : x(xx) {} + bool x; +}; + +template inline +bool save_minimal( Archive const &, NonMemberMinimalVersioned const & nmm, std::uint32_t const ) +{ + return nmm.x; +} + +template inline +void load_minimal( Archive const &, NonMemberMinimalVersioned & nmm, bool const & data, std::uint32_t const ) +{ + nmm.x = data; +} + +struct TestStruct +{ + TestStruct() = default; + TestStruct( std::string const & s, double d, std::uint32_t u, bool b ) : + mm(s), mmv(d), nmm(u), nmmv(b) {} + + template + void serialize( Archive & ar ) + { + ar( mm, mmv ); + ar( nmm, nmmv ); + } + + MemberMinimal mm; + MemberMinimalVersioned mmv; + NonMemberMinimal nmm; + NonMemberMinimalVersioned nmmv; +}; + +struct Issue79Struct +{ + Issue79Struct() = default; + Issue79Struct( std::int32_t xx ) : x(xx) {} + std::int32_t x; +}; + +template ::value || + std::is_same::value> = cereal::traits::sfinae> +inline std::string save_minimal( Archive const &, Issue79Struct const & val ) +{ + return std::to_string( val.x ); +} + +template ::value || + std::is_same::value> = cereal::traits::sfinae> +inline void load_minimal( Archive const &, Issue79Struct & val, std::string const & str ) +{ + val.x = std::stoi( str ); +} + +template ::value || + std::is_same::value> = cereal::traits::sfinae> +inline std::int32_t save_minimal( Archive const &, Issue79Struct const & val ) +{ + return val.x; +} + +template ::value || + std::is_same::value> = cereal::traits::sfinae> +inline void load_minimal( Archive const &, Issue79Struct & val, std::int32_t const & xx ) +{ + val.x = xx; +} + +struct Issue79StructInternal +{ + Issue79StructInternal() = default; + Issue79StructInternal( std::int32_t xx ) : x(xx) {} + std::int32_t x; + + template ::value || + std::is_same::value> = cereal::traits::sfinae> + inline std::string save_minimal( Archive const & ) const + { + return std::to_string( x ); + } + + template ::value || + std::is_same::value> = cereal::traits::sfinae> + inline void load_minimal( Archive const &, std::string const & str ) + { + x = std::stoi( str ); + } + + template ::value || + std::is_same::value> = cereal::traits::sfinae> + inline std::int32_t save_minimal( Archive const & ) const + { + return x; + } + + template ::value || + std::is_same::value> = cereal::traits::sfinae> + inline void load_minimal( Archive const &, std::int32_t const & xx ) + { + x = xx; + } +}; + +template inline +void test_structs_minimal() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + TestStruct o_struct = { random_basic_string(gen), random_value(gen), + random_value(gen), random_value(gen) % 2 ? true : false }; + + Issue79Struct o_struct2 = { random_value(gen) }; + Issue79StructInternal o_struct3 = { random_value(gen) }; + + std::ostringstream os; + { + OArchive oar(os); + oar( o_struct ); + oar( o_struct2 ); + oar( o_struct3 ); + } + + decltype(o_struct) i_struct; + decltype(o_struct2) i_struct2; + decltype(o_struct3) i_struct3; + + std::istringstream is(os.str()); + { + IArchive iar(is); + iar( i_struct ); + iar( i_struct2 ); + iar( i_struct3 ); + } + + CHECK_EQ(o_struct.mm.x, i_struct.mm.x); + CHECK_EQ(o_struct.mmv.x, doctest::Approx(i_struct.mmv.x).epsilon(1e-5)); + + CHECK_EQ(o_struct.nmm.x, i_struct.nmm.x); + CHECK_EQ(o_struct.nmmv.x, i_struct.nmmv.x); + + CHECK_EQ(o_struct2.x, i_struct2.x); + + CHECK_EQ(o_struct3.x, i_struct3.x); + } +} + +#endif // CEREAL_TEST_STRUCTS_MINIMAL_H_ diff --git a/unittests/structs_specialized.cpp b/unittests/structs_specialized.cpp index 2ee3fa83d..1aa3e672b 100644 --- a/unittests/structs_specialized.cpp +++ b/unittests/structs_specialized.cpp @@ -24,456 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "structs_specialized.hpp" -struct BogusBase -{ - template - void serialize( Archive & ) {} - - template - void save( Archive & ) const {} - - template - void load( Archive & ) {} - - template - int save_minimal( Archive const & ) const { return 0; } - - template - void load_minimal( Archive const &, int const & ) {} -}; - -struct BogusBaseVersioned -{ - template - void serialize( Archive &, const std::uint32_t ) {} - - template - void save( Archive &, const std::uint32_t ) const {} - - template - void load( Archive &, const std::uint32_t ) {} - - template - int save_minimal( Archive const &, const std::uint32_t ) const { return 0; } - - template - void load_minimal( Archive const &, int const &, const std::uint32_t ) {} -}; - -struct BogusBasePolymorphic -{ - template - void serialize( Archive & ) {} - - virtual void doesNothing() {} -}; - -class SpecializedMSerialize : public BogusBase -{ - public: - SpecializedMSerialize() = default; - SpecializedMSerialize( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - void serialize( Archive & ar ) - { - ar( x ); - } -}; - -class SpecializedMSerializeVersioned : public BogusBaseVersioned -{ - public: - SpecializedMSerializeVersioned() = default; - SpecializedMSerializeVersioned( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - void serialize( Archive & ar, const std::uint32_t ) - { - ar( x ); - } -}; - -class SpecializedMSplit : public BogusBase -{ - public: - SpecializedMSplit() = default; - SpecializedMSplit( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - void save( Archive & ar ) const - { - ar( x ); - } - - template - void load( Archive & ar ) - { - ar( x ); - } -}; - -class SpecializedMSplitVersioned : public BogusBaseVersioned -{ - public: - SpecializedMSplitVersioned() = default; - SpecializedMSplitVersioned( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - void save( Archive & ar, const std::uint32_t ) const - { - ar( x ); - } - - template - void load( Archive & ar, const std::uint32_t ) - { - ar( x ); - } -}; - -class SpecializedMSplitPolymorphic : public BogusBasePolymorphic -{ - public: - SpecializedMSplitPolymorphic() = default; - SpecializedMSplitPolymorphic( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - void save( Archive & ar ) const - { - ar( x ); - } - - template - void load( Archive & ar ) - { - ar( x ); - } -}; - -class SpecializedMSplitMinimal : public BogusBase -{ - public: - SpecializedMSplitMinimal() = default; - SpecializedMSplitMinimal( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - int save_minimal( Archive const & ) const - { - return x; - } - - template - void load_minimal( Archive const &, int const & value ) - { - x = value; - } -}; - -class SpecializedMSplitVersionedMinimal : public BogusBaseVersioned -{ - public: - SpecializedMSplitVersionedMinimal() = default; - SpecializedMSplitVersionedMinimal( int xx ) : x(xx) {} - - int x; - - private: - friend class cereal::access; - template - int save_minimal( Archive const &, const std::uint32_t ) const - { - return x; - } - - template - void load_minimal( Archive const &, int const & value, const std::uint32_t ) - { - x = value; - } -}; - -class SpecializedNMSerialize : public BogusBase -{ - public: - SpecializedNMSerialize() = default; - SpecializedNMSerialize( int xx ) : x(xx) {} - - int x; -}; - -template -void serialize( Archive & ar, SpecializedNMSerialize & s ) -{ - ar( s.x ); -} - -class SpecializedNMSerializeVersioned : public BogusBaseVersioned -{ - public: - SpecializedNMSerializeVersioned() = default; - SpecializedNMSerializeVersioned( int xx ) : x(xx) {} - - int x; -}; - -template -void serialize( Archive & ar, SpecializedNMSerializeVersioned & s ) -{ - ar( s.x ); -} - -class SpecializedNMSplit : public BogusBase -{ - public: - SpecializedNMSplit() = default; - SpecializedNMSplit( int xx ) : x(xx) {} - - int x; -}; - -template -void load( Archive & ar, SpecializedNMSplit & s ) -{ - ar( s.x ); -} - -template -void save( Archive & ar, SpecializedNMSplit const & s ) -{ - ar( s.x ); -} - -class SpecializedNMSplitVersioned : public BogusBaseVersioned -{ - public: - SpecializedNMSplitVersioned() = default; - SpecializedNMSplitVersioned( int xx ) : x(xx) {} - - int x; -}; - -template -void load( Archive & ar, SpecializedNMSplitVersioned & s, const std::uint32_t ) -{ - ar( s.x ); -} - -template -void save( Archive & ar, SpecializedNMSplitVersioned const & s, const std::uint32_t ) -{ - ar( s.x ); -} - -class SpecializedNMSplitMinimal : public BogusBase -{ - public: - SpecializedNMSplitMinimal() = default; - SpecializedNMSplitMinimal( int xx ) : x(xx) {} - - int x; -}; - -template -void load_minimal( Archive const &, SpecializedNMSplitMinimal & s, int const & value ) -{ - s.x = value; -} - -template -int save_minimal( Archive const &, SpecializedNMSplitMinimal const & s ) -{ - return s.x; -} - -class SpecializedNMSplitVersionedMinimal : public BogusBaseVersioned -{ - public: - SpecializedNMSplitVersionedMinimal() = default; - SpecializedNMSplitVersionedMinimal( int xx ) : x(xx) {} - - int x; -}; - -template -void load_minimal( Archive const &, SpecializedNMSplitVersionedMinimal & s, int const & value, const std::uint32_t ) -{ - s.x = value; -} - -template -int save_minimal( Archive const &, SpecializedNMSplitVersionedMinimal const & s, const std::uint32_t ) -{ - return s.x; -} - -namespace cereal -{ - template struct specialize {}; - template struct specialize {}; - - template struct specialize {}; - template struct specialize {}; - template struct specialize {}; - - template struct specialize {}; - template struct specialize {}; - - template struct specialize {}; - template struct specialize {}; - - template struct specialize {}; - template struct specialize {}; - - template struct specialize {}; - template struct specialize {}; -} - -CEREAL_REGISTER_TYPE(SpecializedMSplitPolymorphic) -CEREAL_REGISTER_POLYMORPHIC_RELATION(BogusBasePolymorphic, SpecializedMSplitPolymorphic) - -template -void test_structs_specialized() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - SpecializedMSerialize o_iser = { random_value(gen) }; - SpecializedMSerializeVersioned o_iserv = { random_value(gen) }; - - SpecializedMSplit o_ispl = { random_value(gen) }; - SpecializedMSplitVersioned o_isplv = { random_value(gen) }; - - // added re: issue #180 - std::shared_ptr o_shared_ispl = std::make_shared( random_value(gen) ); - - SpecializedMSplitMinimal o_isplm = { random_value(gen) }; - SpecializedMSplitVersionedMinimal o_isplvm = { random_value(gen) }; - - SpecializedNMSerialize o_eser = { random_value(gen) }; - SpecializedNMSerializeVersioned o_eserv = { random_value(gen) }; - - SpecializedNMSplit o_espl = { random_value(gen) }; - SpecializedNMSplitVersioned o_esplv = { random_value(gen) }; - - SpecializedNMSplitMinimal o_esplm = { random_value(gen) }; - SpecializedNMSplitVersionedMinimal o_esplvm = { random_value(gen) }; - - - std::ostringstream os; - { - OArchive oar(os); - - oar( o_iser, o_iserv, - o_ispl, o_isplv, o_shared_ispl, - o_isplm, o_isplvm, - o_eser, o_eserv, - o_espl, o_esplv, - o_esplm, o_esplvm ); - } - - decltype(o_iser) i_iser; - decltype(o_iserv) i_iserv; - - decltype(o_ispl) i_ispl; - decltype(o_isplv) i_isplv; - - decltype(o_shared_ispl) i_shared_ispl; - - decltype(o_isplm) i_isplm; - decltype(o_isplvm) i_isplvm; - - decltype(o_eser) i_eser; - decltype(o_eserv) i_eserv; - - decltype(o_espl) i_espl; - decltype(o_esplv) i_esplv; - - decltype(o_esplm) i_esplm; - decltype(o_esplvm) i_esplvm; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( i_iser, i_iserv, - i_ispl, i_isplv, i_shared_ispl, - i_isplm, i_isplvm, - i_eser, i_eserv, - i_espl, i_esplv, - i_esplm, i_esplvm ); - } - - BOOST_CHECK(i_iser.x == o_iser.x); - BOOST_CHECK(i_iserv.x == o_iserv.x); - - BOOST_CHECK(i_ispl.x == o_ispl.x); - BOOST_CHECK(i_isplv.x == o_isplv.x); - - BOOST_CHECK_EQUAL(dynamic_cast(i_shared_ispl.get())->x, dynamic_cast(o_shared_ispl.get())->x); - - BOOST_CHECK(i_isplm.x == o_isplm.x); - BOOST_CHECK(i_isplvm.x == o_isplvm.x); - - BOOST_CHECK(i_eser.x == o_eser.x); - BOOST_CHECK(i_eserv.x == o_eserv.x); - - BOOST_CHECK(i_espl.x == o_espl.x); - BOOST_CHECK(i_esplv.x == o_esplv.x); - - BOOST_CHECK(i_esplm.x == o_esplm.x); - BOOST_CHECK(i_esplvm.x == o_esplvm.x); - } -} +TEST_SUITE("structs_specialized"); -BOOST_AUTO_TEST_CASE( binary_structs_specialized ) +TEST_CASE("binary_structs_specialized") { test_structs_specialized(); } -BOOST_AUTO_TEST_CASE( portable_binary_structs_specialized ) +TEST_CASE("portable_binary_structs_specialized") { test_structs_specialized(); } -BOOST_AUTO_TEST_CASE( xml_structs_specialized ) +TEST_CASE("xml_structs_specialized") { test_structs_specialized(); } -BOOST_AUTO_TEST_CASE( json_structs_specialized ) +TEST_CASE("json_structs_specialized") { test_structs_specialized(); } +TEST_SUITE_END(); diff --git a/unittests/structs_specialized.hpp b/unittests/structs_specialized.hpp new file mode 100644 index 000000000..8daec99d3 --- /dev/null +++ b/unittests/structs_specialized.hpp @@ -0,0 +1,461 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_STRUCTS_MINIMAL_H_ +#define CEREAL_TEST_STRUCTS_MINIMAL_H_ +#include "common.hpp" + +struct BogusBase +{ + template + void serialize( Archive & ) {} + + template + void save( Archive & ) const {} + + template + void load( Archive & ) {} + + template + int save_minimal( Archive const & ) const { return 0; } + + template + void load_minimal( Archive const &, int const & ) {} +}; + +struct BogusBaseVersioned +{ + template + void serialize( Archive &, const std::uint32_t ) {} + + template + void save( Archive &, const std::uint32_t ) const {} + + template + void load( Archive &, const std::uint32_t ) {} + + template + int save_minimal( Archive const &, const std::uint32_t ) const { return 0; } + + template + void load_minimal( Archive const &, int const &, const std::uint32_t ) {} +}; + +struct BogusBasePolymorphic +{ + template + void serialize( Archive & ) {} + + virtual void doesNothing() {} +}; + +class SpecializedMSerialize : public BogusBase +{ + public: + SpecializedMSerialize() = default; + SpecializedMSerialize( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + void serialize( Archive & ar ) + { + ar( x ); + } +}; + +class SpecializedMSerializeVersioned : public BogusBaseVersioned +{ + public: + SpecializedMSerializeVersioned() = default; + SpecializedMSerializeVersioned( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + void serialize( Archive & ar, const std::uint32_t ) + { + ar( x ); + } +}; + +class SpecializedMSplit : public BogusBase +{ + public: + SpecializedMSplit() = default; + SpecializedMSplit( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + void save( Archive & ar ) const + { + ar( x ); + } + + template + void load( Archive & ar ) + { + ar( x ); + } +}; + +class SpecializedMSplitVersioned : public BogusBaseVersioned +{ + public: + SpecializedMSplitVersioned() = default; + SpecializedMSplitVersioned( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + void save( Archive & ar, const std::uint32_t ) const + { + ar( x ); + } + + template + void load( Archive & ar, const std::uint32_t ) + { + ar( x ); + } +}; + +class SpecializedMSplitPolymorphic : public BogusBasePolymorphic +{ + public: + SpecializedMSplitPolymorphic() = default; + SpecializedMSplitPolymorphic( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + void save( Archive & ar ) const + { + ar( x ); + } + + template + void load( Archive & ar ) + { + ar( x ); + } +}; + +class SpecializedMSplitMinimal : public BogusBase +{ + public: + SpecializedMSplitMinimal() = default; + SpecializedMSplitMinimal( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + int save_minimal( Archive const & ) const + { + return x; + } + + template + void load_minimal( Archive const &, int const & value ) + { + x = value; + } +}; + +class SpecializedMSplitVersionedMinimal : public BogusBaseVersioned +{ + public: + SpecializedMSplitVersionedMinimal() = default; + SpecializedMSplitVersionedMinimal( int xx ) : x(xx) {} + + int x; + + private: + friend class cereal::access; + template + int save_minimal( Archive const &, const std::uint32_t ) const + { + return x; + } + + template + void load_minimal( Archive const &, int const & value, const std::uint32_t ) + { + x = value; + } +}; + +class SpecializedNMSerialize : public BogusBase +{ + public: + SpecializedNMSerialize() = default; + SpecializedNMSerialize( int xx ) : x(xx) {} + + int x; +}; + +template +void serialize( Archive & ar, SpecializedNMSerialize & s ) +{ + ar( s.x ); +} + +class SpecializedNMSerializeVersioned : public BogusBaseVersioned +{ + public: + SpecializedNMSerializeVersioned() = default; + SpecializedNMSerializeVersioned( int xx ) : x(xx) {} + + int x; +}; + +template +void serialize( Archive & ar, SpecializedNMSerializeVersioned & s ) +{ + ar( s.x ); +} + +class SpecializedNMSplit : public BogusBase +{ + public: + SpecializedNMSplit() = default; + SpecializedNMSplit( int xx ) : x(xx) {} + + int x; +}; + +template +void load( Archive & ar, SpecializedNMSplit & s ) +{ + ar( s.x ); +} + +template +void save( Archive & ar, SpecializedNMSplit const & s ) +{ + ar( s.x ); +} + +class SpecializedNMSplitVersioned : public BogusBaseVersioned +{ + public: + SpecializedNMSplitVersioned() = default; + SpecializedNMSplitVersioned( int xx ) : x(xx) {} + + int x; +}; + +template +void load( Archive & ar, SpecializedNMSplitVersioned & s, const std::uint32_t ) +{ + ar( s.x ); +} + +template +void save( Archive & ar, SpecializedNMSplitVersioned const & s, const std::uint32_t ) +{ + ar( s.x ); +} + +class SpecializedNMSplitMinimal : public BogusBase +{ + public: + SpecializedNMSplitMinimal() = default; + SpecializedNMSplitMinimal( int xx ) : x(xx) {} + + int x; +}; + +template +void load_minimal( Archive const &, SpecializedNMSplitMinimal & s, int const & value ) +{ + s.x = value; +} + +template +int save_minimal( Archive const &, SpecializedNMSplitMinimal const & s ) +{ + return s.x; +} + +class SpecializedNMSplitVersionedMinimal : public BogusBaseVersioned +{ + public: + SpecializedNMSplitVersionedMinimal() = default; + SpecializedNMSplitVersionedMinimal( int xx ) : x(xx) {} + + int x; +}; + +template +void load_minimal( Archive const &, SpecializedNMSplitVersionedMinimal & s, int const & value, const std::uint32_t ) +{ + s.x = value; +} + +template +int save_minimal( Archive const &, SpecializedNMSplitVersionedMinimal const & s, const std::uint32_t ) +{ + return s.x; +} + +namespace cereal +{ + template struct specialize {}; + template struct specialize {}; + + template struct specialize {}; + template struct specialize {}; + template struct specialize {}; + + template struct specialize {}; + template struct specialize {}; + + template struct specialize {}; + template struct specialize {}; + + template struct specialize {}; + template struct specialize {}; + + template struct specialize {}; + template struct specialize {}; +} + +CEREAL_REGISTER_TYPE(SpecializedMSplitPolymorphic) +CEREAL_REGISTER_POLYMORPHIC_RELATION(BogusBasePolymorphic, SpecializedMSplitPolymorphic) + +template inline +void test_structs_specialized() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + SpecializedMSerialize o_iser = { random_value(gen) }; + SpecializedMSerializeVersioned o_iserv = { random_value(gen) }; + + SpecializedMSplit o_ispl = { random_value(gen) }; + SpecializedMSplitVersioned o_isplv = { random_value(gen) }; + + // added re: issue #180 + std::shared_ptr o_shared_ispl = std::make_shared( random_value(gen) ); + + SpecializedMSplitMinimal o_isplm = { random_value(gen) }; + SpecializedMSplitVersionedMinimal o_isplvm = { random_value(gen) }; + + SpecializedNMSerialize o_eser = { random_value(gen) }; + SpecializedNMSerializeVersioned o_eserv = { random_value(gen) }; + + SpecializedNMSplit o_espl = { random_value(gen) }; + SpecializedNMSplitVersioned o_esplv = { random_value(gen) }; + + SpecializedNMSplitMinimal o_esplm = { random_value(gen) }; + SpecializedNMSplitVersionedMinimal o_esplvm = { random_value(gen) }; + + + std::ostringstream os; + { + OArchive oar(os); + + oar( o_iser, o_iserv, + o_ispl, o_isplv, o_shared_ispl, + o_isplm, o_isplvm, + o_eser, o_eserv, + o_espl, o_esplv, + o_esplm, o_esplvm ); + } + + decltype(o_iser) i_iser; + decltype(o_iserv) i_iserv; + + decltype(o_ispl) i_ispl; + decltype(o_isplv) i_isplv; + + decltype(o_shared_ispl) i_shared_ispl; + + decltype(o_isplm) i_isplm; + decltype(o_isplvm) i_isplvm; + + decltype(o_eser) i_eser; + decltype(o_eserv) i_eserv; + + decltype(o_espl) i_espl; + decltype(o_esplv) i_esplv; + + decltype(o_esplm) i_esplm; + decltype(o_esplvm) i_esplvm; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( i_iser, i_iserv, + i_ispl, i_isplv, i_shared_ispl, + i_isplm, i_isplvm, + i_eser, i_eserv, + i_espl, i_esplv, + i_esplm, i_esplvm ); + } + + CHECK_EQ(i_iser.x, o_iser.x); + CHECK_EQ(i_iserv.x, o_iserv.x); + + CHECK_EQ(i_ispl.x, o_ispl.x); + CHECK_EQ(i_isplv.x, o_isplv.x); + + CHECK_EQ(dynamic_cast(i_shared_ispl.get())->x, dynamic_cast(o_shared_ispl.get())->x); + + CHECK_EQ(i_isplm.x, o_isplm.x); + CHECK_EQ(i_isplvm.x, o_isplvm.x); + + CHECK_EQ(i_eser.x, o_eser.x); + CHECK_EQ(i_eserv.x, o_eserv.x); + + CHECK_EQ(i_espl.x, o_espl.x); + CHECK_EQ(i_esplv.x, o_esplv.x); + + CHECK_EQ(i_esplm.x, o_esplm.x); + CHECK_EQ(i_esplvm.x, o_esplvm.x); + } +} + +#endif // CEREAL_TEST_STRUCTS_SPECIALIZED_H_ diff --git a/unittests/tuple.cpp b/unittests/tuple.cpp index 973b1a15b..d3ea635da 100644 --- a/unittests/tuple.cpp +++ b/unittests/tuple.cpp @@ -24,96 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "tuple.hpp" -template -void test_tuple() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rng = [&](){ return random_value(gen); }; - - for(int ii=0; ii<100; ++ii) - { - auto o_podtuple = std::make_tuple( rng(), rng(), rng(), rng() ); - auto o_podtuple11 = std::make_tuple( rng(), rng(), rng(), rng(), rng(), rng(), - rng(), rng(), rng(), rng(), rng() ); - auto o_isertuple = std::make_tuple( StructInternalSerialize( rng(), rng() ), - StructInternalSerialize( rng(), rng() ), - StructInternalSerialize( rng(), rng() ), - StructInternalSerialize( rng(), rng() ) ); - auto o_ispltuple = std::make_tuple( StructInternalSplit( rng(), rng() ), - StructInternalSplit( rng(), rng() ), - StructInternalSplit( rng(), rng() ), - StructInternalSplit( rng(), rng() ) ); - auto o_esertuple = std::make_tuple( StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ) ); - auto o_espltuple = std::make_tuple( StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ), - StructExternalSerialize( rng(), rng() ) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podtuple); - oar(o_podtuple11); - oar(o_isertuple); - oar(o_ispltuple); - oar(o_esertuple); - oar(o_espltuple); - } - - decltype( o_podtuple ) i_podtuple; - decltype( o_podtuple11 ) i_podtuple11; - decltype( o_isertuple ) i_isertuple; - decltype( o_ispltuple ) i_ispltuple; - decltype( o_esertuple ) i_esertuple; - decltype( o_espltuple ) i_espltuple; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podtuple); - iar(i_podtuple11); - iar(i_isertuple); - iar(i_ispltuple); - iar(i_esertuple); - iar(i_espltuple); - } - - BOOST_CHECK_EQUAL( i_podtuple == o_podtuple, true ); - BOOST_CHECK_EQUAL( i_podtuple11 == o_podtuple11, true ); - BOOST_CHECK_EQUAL( i_isertuple == o_isertuple, true ); - BOOST_CHECK_EQUAL( i_ispltuple == o_ispltuple, true ); - BOOST_CHECK_EQUAL( i_esertuple == o_esertuple, true ); - BOOST_CHECK_EQUAL( i_espltuple == o_espltuple, true ); - } -} +TEST_SUITE("tuple"); -BOOST_AUTO_TEST_CASE( binary_tuple ) +TEST_CASE("binary_tuple") { test_tuple(); } -BOOST_AUTO_TEST_CASE( portable_binary_tuple ) +TEST_CASE("portable_binary_tuple") { test_tuple(); } -BOOST_AUTO_TEST_CASE( xml_tuple ) +TEST_CASE("xml_tuple") { test_tuple(); } -BOOST_AUTO_TEST_CASE( json_tuple ) +TEST_CASE("json_tuple") { test_tuple(); } +TEST_SUITE_END(); diff --git a/unittests/tuple.hpp b/unittests/tuple.hpp new file mode 100644 index 000000000..edb25b23b --- /dev/null +++ b/unittests/tuple.hpp @@ -0,0 +1,101 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_TUPLE_H_ +#define CEREAL_TEST_TUPLE_H_ +#include "common.hpp" + +template inline +void test_tuple() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rng = [&](){ return random_value(gen); }; + + for(int ii=0; ii<100; ++ii) + { + auto o_podtuple = std::make_tuple( rng(), rng(), rng(), rng() ); + auto o_podtuple11 = std::make_tuple( rng(), rng(), rng(), rng(), rng(), rng(), + rng(), rng(), rng(), rng(), rng() ); + auto o_isertuple = std::make_tuple( StructInternalSerialize( rng(), rng() ), + StructInternalSerialize( rng(), rng() ), + StructInternalSerialize( rng(), rng() ), + StructInternalSerialize( rng(), rng() ) ); + auto o_ispltuple = std::make_tuple( StructInternalSplit( rng(), rng() ), + StructInternalSplit( rng(), rng() ), + StructInternalSplit( rng(), rng() ), + StructInternalSplit( rng(), rng() ) ); + auto o_esertuple = std::make_tuple( StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ) ); + auto o_espltuple = std::make_tuple( StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ), + StructExternalSerialize( rng(), rng() ) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podtuple); + oar(o_podtuple11); + oar(o_isertuple); + oar(o_ispltuple); + oar(o_esertuple); + oar(o_espltuple); + } + + decltype( o_podtuple ) i_podtuple; + decltype( o_podtuple11 ) i_podtuple11; + decltype( o_isertuple ) i_isertuple; + decltype( o_ispltuple ) i_ispltuple; + decltype( o_esertuple ) i_esertuple; + decltype( o_espltuple ) i_espltuple; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podtuple); + iar(i_podtuple11); + iar(i_isertuple); + iar(i_ispltuple); + iar(i_esertuple); + iar(i_espltuple); + } + + CHECK_EQ( i_podtuple, o_podtuple); + CHECK_EQ( i_podtuple11, o_podtuple11); + CHECK_EQ( i_isertuple, o_isertuple); + CHECK_EQ( i_ispltuple, o_ispltuple); + CHECK_EQ( i_esertuple, o_esertuple); + CHECK_EQ( i_espltuple, o_espltuple); + } +} + +#endif // CEREAL_TEST_TUPLE_H_ diff --git a/unittests/unordered_loads.cpp b/unittests/unordered_loads.cpp index 4357b67c3..93772768a 100644 --- a/unittests/unordered_loads.cpp +++ b/unittests/unordered_loads.cpp @@ -24,134 +24,19 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "unordered_loads.hpp" -struct unordered_naming -{ - int x; - int xx; - int y; - int z; - - template - void save( Archive & ar ) const - { - ar( CEREAL_NVP(x), - CEREAL_NVP(z), - CEREAL_NVP(y), - CEREAL_NVP(xx) ); - } - - template - void load( Archive & ar ) - { - ar( x, - CEREAL_NVP(y), - CEREAL_NVP(z), - CEREAL_NVP(xx) ); - } - - bool operator==( unordered_naming const & other ) const - { - return x == other.x && xx == other.xx && y == other.y && z == other.z; - } -}; - -std::ostream& operator<<(std::ostream& os, unordered_naming const & s) -{ - os << "[x: " << s.x << " xx: " << s.xx << " y: " << s.y << " z: " << s.z << "]"; - return os; -} - -template -void test_unordered_loads() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rngB = [&](){ return random_value( gen ) % 2 == 0; }; - auto rngI = [&](){ return random_value( gen ); }; - auto rngF = [&](){ return random_value( gen ); }; - auto rngD = [&](){ return random_value( gen ); }; - auto rngS = [&](){ return random_basic_string( gen ); }; - - for(int ii=0; ii<100; ++ii) - { - auto const name1 = rngS(); - auto const name2 = rngS(); - auto const name3 = rngS(); - auto const name4 = rngS(); - auto const name5 = rngS(); - auto const name6 = rngS(); - auto const name7 = rngS(); - - int o_int1 = rngI(); - double o_double2 = rngD(); - std::vector o_vecbool3 = { rngB(), rngB(), rngB(), rngB(), rngB() }; - int o_int4 = rngI(); - int o_int5 = rngI(); - int o_int6 = rngI(); - std::pair o_un7; - o_un7.first = rngF(); - o_un7.second.x = rngI(); - o_un7.second.xx = rngI(); - o_un7.second.y = rngI(); - o_un7.second.z = rngI(); - - std::ostringstream os; - { - OArchive oar(os); - - oar( cereal::make_nvp( name1, o_int1 ), - cereal::make_nvp( name2, o_double2 ), - cereal::make_nvp( name3, o_vecbool3 ), - cereal::make_nvp( name4, o_int4 ), - cereal::make_nvp( name5, o_int5 ), - cereal::make_nvp( name6, o_int6 ), - cereal::make_nvp( name7, o_un7 ) ); - } - - decltype(o_int1) i_int1; - decltype(o_double2) i_double2; - decltype(o_vecbool3) i_vecbool3; - decltype(o_int4) i_int4; - decltype(o_int5) i_int5; - decltype(o_int6) i_int6; - decltype(o_un7) i_un7; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar( cereal::make_nvp( name7, i_un7 ), - cereal::make_nvp( name2, i_double2 ), - cereal::make_nvp( name4, i_int4 ), - cereal::make_nvp( name3, i_vecbool3 ), - cereal::make_nvp( name1, i_int1 ), - cereal::make_nvp( name5, i_int5 ), - i_int6 ); - } - - BOOST_CHECK_EQUAL(o_int1, i_int1); - BOOST_CHECK_CLOSE(o_double2 , o_double2, 1e-5); - BOOST_CHECK_EQUAL(o_vecbool3.size(), i_vecbool3.size()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_vecbool3.begin(), i_vecbool3.end(), o_vecbool3.begin(), o_vecbool3.end()); - BOOST_CHECK_EQUAL(o_int4, i_int4); - BOOST_CHECK_EQUAL(o_int5, i_int5); - BOOST_CHECK_EQUAL(o_int6, i_int6); - BOOST_CHECK_EQUAL(o_un7.first, i_un7.first); - BOOST_CHECK_EQUAL(o_un7.second, i_un7.second); - } -} +TEST_SUITE("unordered_loads"); -BOOST_AUTO_TEST_CASE( xml_unordered_loads ) +TEST_CASE("xml_unordered_loads") { test_unordered_loads(); } -BOOST_AUTO_TEST_CASE( json_unordered_loads ) +TEST_CASE("json_unordered_loads") { test_unordered_loads(); } +TEST_SUITE_END(); diff --git a/unittests/unordered_loads.hpp b/unittests/unordered_loads.hpp new file mode 100644 index 000000000..278fb651b --- /dev/null +++ b/unittests/unordered_loads.hpp @@ -0,0 +1,149 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_UNORDERED_LOADS_H_ +#define CEREAL_TEST_UNORDERED_LOADS_H_ +#include "common.hpp" + +struct unordered_naming +{ + int x; + int xx; + int y; + int z; + + template + void save( Archive & ar ) const + { + ar( CEREAL_NVP(x), + CEREAL_NVP(z), + CEREAL_NVP(y), + CEREAL_NVP(xx) ); + } + + template + void load( Archive & ar ) + { + ar( x, + CEREAL_NVP(y), + CEREAL_NVP(z), + CEREAL_NVP(xx) ); + } + + bool operator==( unordered_naming const & other ) const + { + return x == other.x && xx == other.xx && y == other.y && z == other.z; + } +}; + +std::ostream& operator<<(std::ostream& os, unordered_naming const & s) +{ + os << "[x: " << s.x << " xx: " << s.xx << " y: " << s.y << " z: " << s.z << "]"; + return os; +} + +template inline +void test_unordered_loads() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rngB = [&](){ return random_value( gen ) % 2 == 0; }; + auto rngI = [&](){ return random_value( gen ); }; + auto rngF = [&](){ return random_value( gen ); }; + auto rngD = [&](){ return random_value( gen ); }; + auto rngS = [&](){ return random_basic_string( gen ); }; + + for(int ii=0; ii<100; ++ii) + { + auto const name1 = rngS(); + auto const name2 = rngS(); + auto const name3 = rngS(); + auto const name4 = rngS(); + auto const name5 = rngS(); + auto const name6 = rngS(); + auto const name7 = rngS(); + + int o_int1 = rngI(); + double o_double2 = rngD(); + std::vector o_vecbool3 = { rngB(), rngB(), rngB(), rngB(), rngB() }; + int o_int4 = rngI(); + int o_int5 = rngI(); + int o_int6 = rngI(); + std::pair o_un7; + o_un7.first = rngF(); + o_un7.second.x = rngI(); + o_un7.second.xx = rngI(); + o_un7.second.y = rngI(); + o_un7.second.z = rngI(); + + std::ostringstream os; + { + OArchive oar(os); + + oar( cereal::make_nvp( name1, o_int1 ), + cereal::make_nvp( name2, o_double2 ), + cereal::make_nvp( name3, o_vecbool3 ), + cereal::make_nvp( name4, o_int4 ), + cereal::make_nvp( name5, o_int5 ), + cereal::make_nvp( name6, o_int6 ), + cereal::make_nvp( name7, o_un7 ) ); + } + + decltype(o_int1) i_int1; + decltype(o_double2) i_double2; + decltype(o_vecbool3) i_vecbool3; + decltype(o_int4) i_int4; + decltype(o_int5) i_int5; + decltype(o_int6) i_int6; + decltype(o_un7) i_un7; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar( cereal::make_nvp( name7, i_un7 ), + cereal::make_nvp( name2, i_double2 ), + cereal::make_nvp( name4, i_int4 ), + cereal::make_nvp( name3, i_vecbool3 ), + cereal::make_nvp( name1, i_int1 ), + cereal::make_nvp( name5, i_int5 ), + i_int6 ); + } + + CHECK_EQ(o_int1, i_int1); + CHECK_EQ(o_double2, doctest::Approx(o_double2).epsilon(1e-5)); + CHECK_EQ(o_vecbool3.size(), i_vecbool3.size()); + check_collection(i_vecbool3, o_vecbool3); + CHECK_EQ(o_int4, i_int4); + CHECK_EQ(o_int5, i_int5); + CHECK_EQ(o_int6, i_int6); + CHECK_EQ(o_un7.first, i_un7.first); + CHECK_EQ(o_un7.second, i_un7.second); + } +} + +#endif // CEREAL_TEST_UNORDERED_LOADS_H_ diff --git a/unittests/unordered_map.cpp b/unittests/unordered_map.cpp index df81833c9..a0c0cbbae 100644 --- a/unittests/unordered_map.cpp +++ b/unittests/unordered_map.cpp @@ -24,119 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "unordered_map.hpp" -template -void test_unordered_map() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::unordered_map o_podunordered_map; - for(int j=0; j<100; ++j) - o_podunordered_map.insert({random_value(gen), random_value(gen)}); - - std::unordered_map o_iserunordered_map; - for(int j=0; j<100; ++j) - o_iserunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::unordered_map o_isplunordered_map; - for(int j=0; j<100; ++j) - o_isplunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::unordered_map o_eserunordered_map; - for(int j=0; j<100; ++j) - o_eserunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::unordered_map o_esplunordered_map; - for(int j=0; j<100; ++j) - o_esplunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podunordered_map); - oar(o_iserunordered_map); - oar(o_isplunordered_map); - oar(o_eserunordered_map); - oar(o_esplunordered_map); - } - - std::unordered_map i_podunordered_map; - std::unordered_map i_iserunordered_map; - std::unordered_map i_isplunordered_map; - std::unordered_map i_eserunordered_map; - std::unordered_map i_esplunordered_map; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podunordered_map); - iar(i_iserunordered_map); - iar(i_isplunordered_map); - iar(i_eserunordered_map); - iar(i_esplunordered_map); - } - - for(auto const & p : i_podunordered_map) - { - auto v = o_podunordered_map.find(p.first); - BOOST_CHECK(v != o_podunordered_map.end()); - BOOST_CHECK_EQUAL(p.second, v->second); - } - - for(auto const & p : i_iserunordered_map) - { - auto v = o_iserunordered_map.find(p.first); - BOOST_CHECK(v != o_iserunordered_map.end()); - BOOST_CHECK_EQUAL(p.second, v->second); - } - - for(auto const & p : i_isplunordered_map) - { - auto v = o_isplunordered_map.find(p.first); - BOOST_CHECK(v != o_isplunordered_map.end()); - BOOST_CHECK_EQUAL(p.second, v->second); - } - - for(auto const & p : i_eserunordered_map) - { - auto v = o_eserunordered_map.find(p.first); - BOOST_CHECK(v != o_eserunordered_map.end()); - BOOST_CHECK_EQUAL(p.second, v->second); - } - - for(auto const & p : i_esplunordered_map) - { - auto v = o_esplunordered_map.find(p.first); - BOOST_CHECK(v != o_esplunordered_map.end()); - BOOST_CHECK_EQUAL(p.second, v->second); - } - } -} +TEST_SUITE("unordered_map"); -BOOST_AUTO_TEST_CASE( binary_unordered_map ) +TEST_CASE("binary_unordered_map") { test_unordered_map(); } -BOOST_AUTO_TEST_CASE( portable_binary_unordered_map ) +TEST_CASE("portable_binary_unordered_map") { test_unordered_map(); } -BOOST_AUTO_TEST_CASE( xml_unordered_map ) +TEST_CASE("xml_unordered_map") { test_unordered_map(); } -BOOST_AUTO_TEST_CASE( json_unordered_map ) +TEST_CASE("json_unordered_map") { test_unordered_map(); } +TEST_SUITE_END(); diff --git a/unittests/unordered_map.hpp b/unittests/unordered_map.hpp new file mode 100644 index 000000000..78961978d --- /dev/null +++ b/unittests/unordered_map.hpp @@ -0,0 +1,124 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_UNORDERED_MAP_H_ +#define CEREAL_TEST_UNORDERED_MAP_H_ +#include "common.hpp" + +template inline +void test_unordered_map() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::unordered_map o_podunordered_map; + for(int j=0; j<100; ++j) + o_podunordered_map.insert({random_value(gen), random_value(gen)}); + + std::unordered_map o_iserunordered_map; + for(int j=0; j<100; ++j) + o_iserunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::unordered_map o_isplunordered_map; + for(int j=0; j<100; ++j) + o_isplunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::unordered_map o_eserunordered_map; + for(int j=0; j<100; ++j) + o_eserunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::unordered_map o_esplunordered_map; + for(int j=0; j<100; ++j) + o_esplunordered_map.insert({random_value(gen), { random_value(gen), random_value(gen) }}); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podunordered_map); + oar(o_iserunordered_map); + oar(o_isplunordered_map); + oar(o_eserunordered_map); + oar(o_esplunordered_map); + } + + std::unordered_map i_podunordered_map; + std::unordered_map i_iserunordered_map; + std::unordered_map i_isplunordered_map; + std::unordered_map i_eserunordered_map; + std::unordered_map i_esplunordered_map; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podunordered_map); + iar(i_iserunordered_map); + iar(i_isplunordered_map); + iar(i_eserunordered_map); + iar(i_esplunordered_map); + } + + for(auto const & p : i_podunordered_map) + { + auto v = o_podunordered_map.find(p.first); + CHECK_NE(v, o_podunordered_map.end()); + CHECK_EQ(p.second, v->second); + } + + for(auto const & p : i_iserunordered_map) + { + auto v = o_iserunordered_map.find(p.first); + CHECK_NE(v, o_iserunordered_map.end()); + CHECK_EQ(p.second, v->second); + } + + for(auto const & p : i_isplunordered_map) + { + auto v = o_isplunordered_map.find(p.first); + CHECK_NE(v, o_isplunordered_map.end()); + CHECK_EQ(p.second, v->second); + } + + for(auto const & p : i_eserunordered_map) + { + auto v = o_eserunordered_map.find(p.first); + CHECK_NE(v, o_eserunordered_map.end()); + CHECK_EQ(p.second, v->second); + } + + for(auto const & p : i_esplunordered_map) + { + auto v = o_esplunordered_map.find(p.first); + CHECK_NE(v, o_esplunordered_map.end()); + CHECK_EQ(p.second, v->second); + } + } +} + +#endif // CEREAL_TEST_UNORDERED_MAP_H_ diff --git a/unittests/unordered_multimap.cpp b/unittests/unordered_multimap.cpp index ad0913d5f..4d9a7c33f 100644 --- a/unittests/unordered_multimap.cpp +++ b/unittests/unordered_multimap.cpp @@ -24,149 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "unordered_multimap.hpp" -template -void test_unordered_multimap() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::unordered_multimap o_podunordered_multimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_podunordered_multimap.insert({key, random_value(gen)}); - o_podunordered_multimap.insert({key, random_value(gen)}); - } - - std::unordered_multimap o_iserunordered_multimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_iserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - o_iserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::unordered_multimap o_isplunordered_multimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_isplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - o_isplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::unordered_multimap o_eserunordered_multimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_eserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - o_eserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::unordered_multimap o_esplunordered_multimap; - for(int j=0; j<100; ++j) - { - auto key = random_value(gen); - o_esplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - o_esplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); - } - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podunordered_multimap); - oar(o_iserunordered_multimap); - oar(o_isplunordered_multimap); - oar(o_eserunordered_multimap); - oar(o_esplunordered_multimap); - } - - std::unordered_multimap i_podunordered_multimap; - std::unordered_multimap i_iserunordered_multimap; - std::unordered_multimap i_isplunordered_multimap; - std::unordered_multimap i_eserunordered_multimap; - std::unordered_multimap i_esplunordered_multimap; - - std::istringstream is(os.str()); - { - IArchive iar(is); +TEST_SUITE("unordered_multimap"); - iar(i_podunordered_multimap); - iar(i_iserunordered_multimap); - iar(i_isplunordered_multimap); - iar(i_eserunordered_multimap); - iar(i_esplunordered_multimap); - } - - BOOST_CHECK_EQUAL(i_podunordered_multimap.size(), o_podunordered_multimap.size()); - BOOST_CHECK_EQUAL(i_iserunordered_multimap.size(), o_iserunordered_multimap.size()); - BOOST_CHECK_EQUAL(i_isplunordered_multimap.size(), o_isplunordered_multimap.size()); - BOOST_CHECK_EQUAL(i_eserunordered_multimap.size(), o_eserunordered_multimap.size()); - BOOST_CHECK_EQUAL(i_esplunordered_multimap.size(), o_esplunordered_multimap.size()); - - for(auto const & p : i_podunordered_multimap) - { - size_t const bucket = o_podunordered_multimap.bucket(p.first); - auto bucket_begin = o_podunordered_multimap.begin(bucket); - auto bucket_end = o_podunordered_multimap.end(bucket); - BOOST_CHECK(std::find(bucket_begin, bucket_end, p) != bucket_end); - } - - for(auto const & p : i_iserunordered_multimap) - { - size_t const bucket = o_iserunordered_multimap.bucket(p.first); - auto bucket_begin = o_iserunordered_multimap.begin(bucket); - auto bucket_end = o_iserunordered_multimap.end(bucket); - BOOST_CHECK(std::find(bucket_begin, bucket_end, p) != bucket_end); - } - - for(auto const & p : i_isplunordered_multimap) - { - size_t const bucket = o_isplunordered_multimap.bucket(p.first); - auto bucket_begin = o_isplunordered_multimap.begin(bucket); - auto bucket_end = o_isplunordered_multimap.end(bucket); - BOOST_CHECK(std::find(bucket_begin, bucket_end, p) != bucket_end); - } - - for(auto const & p : i_eserunordered_multimap) - { - size_t const bucket = o_eserunordered_multimap.bucket(p.first); - auto bucket_begin = o_eserunordered_multimap.begin(bucket); - auto bucket_end = o_eserunordered_multimap.end(bucket); - BOOST_CHECK(std::find(bucket_begin, bucket_end, p) != bucket_end); - } - - for(auto const & p : i_esplunordered_multimap) - { - size_t const bucket = o_esplunordered_multimap.bucket(p.first); - auto bucket_begin = o_esplunordered_multimap.begin(bucket); - auto bucket_end = o_esplunordered_multimap.end(bucket); - BOOST_CHECK(std::find(bucket_begin, bucket_end, p) != bucket_end); - } - } -} - -BOOST_AUTO_TEST_CASE( binary_unordered_multimap ) +TEST_CASE("binary_unordered_multimap") { test_unordered_multimap(); } -BOOST_AUTO_TEST_CASE( portable_binary_unordered_multimap ) +TEST_CASE("portable_binary_unordered_multimap") { test_unordered_multimap(); } -BOOST_AUTO_TEST_CASE( xml_unordered_multimap ) +TEST_CASE("xml_unordered_multimap") { test_unordered_multimap(); } -BOOST_AUTO_TEST_CASE( json_unordered_multimap ) +TEST_CASE("json_unordered_multimap") { test_unordered_multimap(); } + +TEST_SUITE_END(); diff --git a/unittests/unordered_multimap.hpp b/unittests/unordered_multimap.hpp new file mode 100644 index 000000000..6f000e6db --- /dev/null +++ b/unittests/unordered_multimap.hpp @@ -0,0 +1,155 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_UNORDERED_MULTIMAP_H_ +#define CEREAL_TEST_UNORDERED_MULTIMAP_H_ +#include "common.hpp" + +template inline +void test_unordered_multimap() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::unordered_multimap o_podunordered_multimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_podunordered_multimap.insert({key, random_value(gen)}); + o_podunordered_multimap.insert({key, random_value(gen)}); + } + + std::unordered_multimap o_iserunordered_multimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_iserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + o_iserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::unordered_multimap o_isplunordered_multimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_isplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + o_isplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::unordered_multimap o_eserunordered_multimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_eserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + o_eserunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::unordered_multimap o_esplunordered_multimap; + for(int j=0; j<100; ++j) + { + auto key = random_value(gen); + o_esplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + o_esplunordered_multimap.insert({key, { random_value(gen), random_value(gen) }}); + } + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podunordered_multimap); + oar(o_iserunordered_multimap); + oar(o_isplunordered_multimap); + oar(o_eserunordered_multimap); + oar(o_esplunordered_multimap); + } + + std::unordered_multimap i_podunordered_multimap; + std::unordered_multimap i_iserunordered_multimap; + std::unordered_multimap i_isplunordered_multimap; + std::unordered_multimap i_eserunordered_multimap; + std::unordered_multimap i_esplunordered_multimap; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podunordered_multimap); + iar(i_iserunordered_multimap); + iar(i_isplunordered_multimap); + iar(i_eserunordered_multimap); + iar(i_esplunordered_multimap); + } + + CHECK_EQ(i_podunordered_multimap.size(), o_podunordered_multimap.size()); + CHECK_EQ(i_iserunordered_multimap.size(), o_iserunordered_multimap.size()); + CHECK_EQ(i_isplunordered_multimap.size(), o_isplunordered_multimap.size()); + CHECK_EQ(i_eserunordered_multimap.size(), o_eserunordered_multimap.size()); + CHECK_EQ(i_esplunordered_multimap.size(), o_esplunordered_multimap.size()); + + for(auto const & p : i_podunordered_multimap) + { + size_t const bucket = o_podunordered_multimap.bucket(p.first); + auto bucket_begin = o_podunordered_multimap.begin(bucket); + auto bucket_end = o_podunordered_multimap.end(bucket); + CHECK_NE(std::find(bucket_begin, bucket_end, p), bucket_end); + } + + for(auto const & p : i_iserunordered_multimap) + { + size_t const bucket = o_iserunordered_multimap.bucket(p.first); + auto bucket_begin = o_iserunordered_multimap.begin(bucket); + auto bucket_end = o_iserunordered_multimap.end(bucket); + CHECK_NE(std::find(bucket_begin, bucket_end, p), bucket_end); + } + + for(auto const & p : i_isplunordered_multimap) + { + size_t const bucket = o_isplunordered_multimap.bucket(p.first); + auto bucket_begin = o_isplunordered_multimap.begin(bucket); + auto bucket_end = o_isplunordered_multimap.end(bucket); + CHECK_NE(std::find(bucket_begin, bucket_end, p), bucket_end); + } + + for(auto const & p : i_eserunordered_multimap) + { + size_t const bucket = o_eserunordered_multimap.bucket(p.first); + auto bucket_begin = o_eserunordered_multimap.begin(bucket); + auto bucket_end = o_eserunordered_multimap.end(bucket); + CHECK_NE(std::find(bucket_begin, bucket_end, p), bucket_end); + } + + for(auto const & p : i_esplunordered_multimap) + { + size_t const bucket = o_esplunordered_multimap.bucket(p.first); + auto bucket_begin = o_esplunordered_multimap.begin(bucket); + auto bucket_end = o_esplunordered_multimap.end(bucket); + CHECK_NE(std::find(bucket_begin, bucket_end, p), bucket_end); + } + } +} + +#endif // CEREAL_TEST_UNORDERED_MULTIMAP_H_ diff --git a/unittests/unordered_multiset.cpp b/unittests/unordered_multiset.cpp index 9e7a56d40..a98ffa17c 100644 --- a/unittests/unordered_multiset.cpp +++ b/unittests/unordered_multiset.cpp @@ -24,129 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "unordered_multiset.hpp" -template -void test_unordered_multiset() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::unordered_multiset o_podunordered_multiset; - for(int j=0; j<100; ++j) - { - int value = random_value(gen); - o_podunordered_multiset.insert(value); - o_podunordered_multiset.insert(value); - } - - std::unordered_multiset> o_iserunordered_multiset; - for(int j=0; j<100; ++j) - { - StructInternalSerialize value = { random_value(gen), random_value(gen) }; - o_iserunordered_multiset.insert(value); - o_iserunordered_multiset.insert(value); - } - - std::unordered_multiset> o_isplunordered_multiset; - for(int j=0; j<100; ++j) - { - StructInternalSplit value = { random_value(gen), random_value(gen) }; - o_isplunordered_multiset.insert(value); - o_isplunordered_multiset.insert(value); - } - - std::unordered_multiset> o_eserunordered_multiset; - for(int j=0; j<100; ++j) - { - StructExternalSerialize value = { random_value(gen), random_value(gen) }; - o_eserunordered_multiset.insert(value); - o_eserunordered_multiset.insert(value); - } - - std::unordered_multiset> o_esplunordered_multiset; - for(int j=0; j<100; ++j) - { - StructExternalSplit value = { random_value(gen), random_value(gen) }; - o_esplunordered_multiset.insert(value); - o_esplunordered_multiset.insert(value); - } - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podunordered_multiset); - oar(o_iserunordered_multiset); - oar(o_isplunordered_multiset); - oar(o_eserunordered_multiset); - oar(o_esplunordered_multiset); - } - - std::unordered_multiset i_podunordered_multiset; - std::unordered_multiset> i_iserunordered_multiset; - std::unordered_multiset> i_isplunordered_multiset; - std::unordered_multiset> i_eserunordered_multiset; - std::unordered_multiset> i_esplunordered_multiset; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podunordered_multiset); - iar(i_iserunordered_multiset); - iar(i_isplunordered_multiset); - iar(i_eserunordered_multiset); - iar(i_esplunordered_multiset); - } - - for(auto const & p : i_podunordered_multiset) - { - BOOST_CHECK_EQUAL(o_podunordered_multiset.count(p), i_podunordered_multiset.count(p)); - } - - for(auto const & p : i_iserunordered_multiset) - { - BOOST_CHECK_EQUAL(o_iserunordered_multiset.count(p), i_iserunordered_multiset.count(p)); - } - - for(auto const & p : i_isplunordered_multiset) - { - BOOST_CHECK_EQUAL(o_isplunordered_multiset.count(p), i_isplunordered_multiset.count(p)); - } - - for(auto const & p : i_eserunordered_multiset) - { - BOOST_CHECK_EQUAL(o_eserunordered_multiset.count(p), i_eserunordered_multiset.count(p)); - } - - for(auto const & p : i_esplunordered_multiset) - { - BOOST_CHECK_EQUAL(o_esplunordered_multiset.count(p), i_esplunordered_multiset.count(p)); - } - } -} +TEST_SUITE("unordered_multiset"); -BOOST_AUTO_TEST_CASE( binary_unordered_multiset ) +TEST_CASE("binary_unordered_multiset") { test_unordered_multiset(); } -BOOST_AUTO_TEST_CASE( portable_binary_unordered_multiset ) +TEST_CASE("portable_binary_unordered_multiset") { test_unordered_multiset(); } -BOOST_AUTO_TEST_CASE( xml_unordered_multiset ) +TEST_CASE("xml_unordered_multiset") { test_unordered_multiset(); } -BOOST_AUTO_TEST_CASE( json_unordered_multiset ) +TEST_CASE("json_unordered_multiset") { test_unordered_multiset(); } +TEST_SUITE_END(); diff --git a/unittests/unordered_multiset.hpp b/unittests/unordered_multiset.hpp new file mode 100644 index 000000000..ae9d07236 --- /dev/null +++ b/unittests/unordered_multiset.hpp @@ -0,0 +1,134 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_UNORDERED_MULTISET_H_ +#define CEREAL_TEST_UNORDERED_MULTISET_H_ +#include "common.hpp" + +template inline +void test_unordered_multiset() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::unordered_multiset o_podunordered_multiset; + for(int j=0; j<100; ++j) + { + int value = random_value(gen); + o_podunordered_multiset.insert(value); + o_podunordered_multiset.insert(value); + } + + std::unordered_multiset> o_iserunordered_multiset; + for(int j=0; j<100; ++j) + { + StructInternalSerialize value = { random_value(gen), random_value(gen) }; + o_iserunordered_multiset.insert(value); + o_iserunordered_multiset.insert(value); + } + + std::unordered_multiset> o_isplunordered_multiset; + for(int j=0; j<100; ++j) + { + StructInternalSplit value = { random_value(gen), random_value(gen) }; + o_isplunordered_multiset.insert(value); + o_isplunordered_multiset.insert(value); + } + + std::unordered_multiset> o_eserunordered_multiset; + for(int j=0; j<100; ++j) + { + StructExternalSerialize value = { random_value(gen), random_value(gen) }; + o_eserunordered_multiset.insert(value); + o_eserunordered_multiset.insert(value); + } + + std::unordered_multiset> o_esplunordered_multiset; + for(int j=0; j<100; ++j) + { + StructExternalSplit value = { random_value(gen), random_value(gen) }; + o_esplunordered_multiset.insert(value); + o_esplunordered_multiset.insert(value); + } + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podunordered_multiset); + oar(o_iserunordered_multiset); + oar(o_isplunordered_multiset); + oar(o_eserunordered_multiset); + oar(o_esplunordered_multiset); + } + + std::unordered_multiset i_podunordered_multiset; + std::unordered_multiset> i_iserunordered_multiset; + std::unordered_multiset> i_isplunordered_multiset; + std::unordered_multiset> i_eserunordered_multiset; + std::unordered_multiset> i_esplunordered_multiset; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podunordered_multiset); + iar(i_iserunordered_multiset); + iar(i_isplunordered_multiset); + iar(i_eserunordered_multiset); + iar(i_esplunordered_multiset); + } + + for(auto const & p : i_podunordered_multiset) + { + CHECK_EQ(o_podunordered_multiset.count(p), i_podunordered_multiset.count(p)); + } + + for(auto const & p : i_iserunordered_multiset) + { + CHECK_EQ(o_iserunordered_multiset.count(p), i_iserunordered_multiset.count(p)); + } + + for(auto const & p : i_isplunordered_multiset) + { + CHECK_EQ(o_isplunordered_multiset.count(p), i_isplunordered_multiset.count(p)); + } + + for(auto const & p : i_eserunordered_multiset) + { + CHECK_EQ(o_eserunordered_multiset.count(p), i_eserunordered_multiset.count(p)); + } + + for(auto const & p : i_esplunordered_multiset) + { + CHECK_EQ(o_esplunordered_multiset.count(p), i_esplunordered_multiset.count(p)); + } + } +} + +#endif // CEREAL_TEST_UNORDERED_MULTISET_H_ diff --git a/unittests/unordered_set.cpp b/unittests/unordered_set.cpp index a4b16b971..0c8be1436 100644 --- a/unittests/unordered_set.cpp +++ b/unittests/unordered_set.cpp @@ -24,110 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "unordered_set.hpp" -template -void test_unordered_set() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::unordered_set o_podunordered_set; - for(int j=0; j<100; ++j) - o_podunordered_set.insert(random_value(gen)); - - std::unordered_set> o_iserunordered_set; - for(int j=0; j<100; ++j) - o_iserunordered_set.insert({ random_value(gen), random_value(gen) }); - - std::unordered_set> o_isplunordered_set; - for(int j=0; j<100; ++j) - o_isplunordered_set.insert({ random_value(gen), random_value(gen) }); - - std::unordered_set> o_eserunordered_set; - for(int j=0; j<100; ++j) - o_eserunordered_set.insert({ random_value(gen), random_value(gen) }); - - std::unordered_set> o_esplunordered_set; - for(int j=0; j<100; ++j) - o_esplunordered_set.insert({ random_value(gen), random_value(gen) }); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podunordered_set); - oar(o_iserunordered_set); - oar(o_isplunordered_set); - oar(o_eserunordered_set); - oar(o_esplunordered_set); - } - - std::unordered_set i_podunordered_set; - std::unordered_set> i_iserunordered_set; - std::unordered_set> i_isplunordered_set; - std::unordered_set> i_eserunordered_set; - std::unordered_set> i_esplunordered_set; +TEST_SUITE("unordered_set"); - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podunordered_set); - iar(i_iserunordered_set); - iar(i_isplunordered_set); - iar(i_eserunordered_set); - iar(i_esplunordered_set); - } - - for(auto const & p : i_podunordered_set) - { - BOOST_CHECK_EQUAL(o_podunordered_set.count(p), 1lu); - } - - for(auto const & p : i_iserunordered_set) - { - BOOST_CHECK_EQUAL(o_iserunordered_set.count(p), 1lu); - } - - for(auto const & p : i_isplunordered_set) - { - BOOST_CHECK_EQUAL(o_isplunordered_set.count(p), 1lu); - } - - for(auto const & p : i_eserunordered_set) - { - BOOST_CHECK_EQUAL(o_eserunordered_set.count(p), 1lu); - } - - for(auto const & p : i_esplunordered_set) - { - BOOST_CHECK_EQUAL(o_esplunordered_set.count(p), 1lu); - } - } -} - -BOOST_AUTO_TEST_CASE( binary_unordered_set ) +TEST_CASE("binary_unordered_set") { test_unordered_set(); } -BOOST_AUTO_TEST_CASE( portable_binary_unordered_set ) +TEST_CASE("portable_binary_unordered_set") { test_unordered_set(); } -BOOST_AUTO_TEST_CASE( xml_unordered_set ) +TEST_CASE("xml_unordered_set") { test_unordered_set(); } -BOOST_AUTO_TEST_CASE( json_unordered_set ) +TEST_CASE("json_unordered_set") { test_unordered_set(); } - +TEST_SUITE_END(); diff --git a/unittests/unordered_set.hpp b/unittests/unordered_set.hpp new file mode 100644 index 000000000..334731363 --- /dev/null +++ b/unittests/unordered_set.hpp @@ -0,0 +1,114 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_UNORDERED_SET_H_ +#define CEREAL_TEST_UNORDERED_SET_H_ +#include "common.hpp" + +template inline +void test_unordered_set() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::unordered_set o_podunordered_set; + for(int j=0; j<100; ++j) + o_podunordered_set.insert(random_value(gen)); + + std::unordered_set> o_iserunordered_set; + for(int j=0; j<100; ++j) + o_iserunordered_set.insert({ random_value(gen), random_value(gen) }); + + std::unordered_set> o_isplunordered_set; + for(int j=0; j<100; ++j) + o_isplunordered_set.insert({ random_value(gen), random_value(gen) }); + + std::unordered_set> o_eserunordered_set; + for(int j=0; j<100; ++j) + o_eserunordered_set.insert({ random_value(gen), random_value(gen) }); + + std::unordered_set> o_esplunordered_set; + for(int j=0; j<100; ++j) + o_esplunordered_set.insert({ random_value(gen), random_value(gen) }); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podunordered_set); + oar(o_iserunordered_set); + oar(o_isplunordered_set); + oar(o_eserunordered_set); + oar(o_esplunordered_set); + } + + std::unordered_set i_podunordered_set; + std::unordered_set> i_iserunordered_set; + std::unordered_set> i_isplunordered_set; + std::unordered_set> i_eserunordered_set; + std::unordered_set> i_esplunordered_set; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podunordered_set); + iar(i_iserunordered_set); + iar(i_isplunordered_set); + iar(i_eserunordered_set); + iar(i_esplunordered_set); + } + + for(auto const & p : i_podunordered_set) + { + CHECK_EQ(o_podunordered_set.count(p), 1lu); + } + + for(auto const & p : i_iserunordered_set) + { + CHECK_EQ(o_iserunordered_set.count(p), 1lu); + } + + for(auto const & p : i_isplunordered_set) + { + CHECK_EQ(o_isplunordered_set.count(p), 1lu); + } + + for(auto const & p : i_eserunordered_set) + { + CHECK_EQ(o_eserunordered_set.count(p), 1lu); + } + + for(auto const & p : i_esplunordered_set) + { + CHECK_EQ(o_esplunordered_set.count(p), 1lu); + } + } +} + +#endif // CEREAL_TEST_UNORDERED_SET_H_ diff --git a/unittests/user_data_adapters.cpp b/unittests/user_data_adapters.cpp index 429d60500..9a8884806 100644 --- a/unittests/user_data_adapters.cpp +++ b/unittests/user_data_adapters.cpp @@ -24,114 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#define CEREAL_FUTURE_EXPERIMENTAL -#include -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "user_data_adapters.hpp" -struct SomeStruct {}; +TEST_SUITE("user_data_adapters"); -struct UserData -{ - UserData( SomeStruct * pp, SomeStruct & r ) : - p(pp), ref(r) {} - - SomeStruct * p; - std::reference_wrapper ref; -}; - -struct UserStruct -{ - UserStruct( std::int32_t i, - SomeStruct * pointer, - SomeStruct & reference ) : - i32( i ), - p( pointer ), - ref( reference ) - { } - - UserStruct & operator=( UserStruct const & ) = delete; - - std::int32_t i32; - SomeStruct const * p; - SomeStruct & ref; - - template - void serialize( Archive & ar ) - { - ar( i32 ); - } - - template - static void load_and_construct( Archive & ar, cereal::construct & construct ) - { - std::int32_t ii; - ar( ii ); - auto & data = cereal::get_user_data( ar ); - construct( ii, data.p, data.ref.get() ); - } -}; - -template -void test_user_data_adapters() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - auto rng = [&](){ return random_value(gen); }; - - for(int ii=0; ii<100; ++ii) - { - SomeStruct ss; - std::unique_ptr o_ptr( new UserStruct( rng(), &ss, ss ) ); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_ptr); - } - - decltype( o_ptr ) i_ptr; - - std::istringstream is(os.str()); - { - UserData ud(&ss, ss); - cereal::UserDataAdapter iar(ud, is); - - iar(i_ptr); - } - - BOOST_CHECK_EQUAL( i_ptr->p == o_ptr->p, true ); - BOOST_CHECK_EQUAL( std::addressof(i_ptr->ref) == std::addressof(o_ptr->ref), true ); - BOOST_CHECK_EQUAL( i_ptr->i32, o_ptr->i32 ); - - std::istringstream bad_is(os.str()); - { - IArchive iar(bad_is); - - BOOST_CHECK_THROW( iar(i_ptr), ::cereal::Exception ); - } - } -} - -BOOST_AUTO_TEST_CASE( binary_user_data_adapters ) +TEST_CASE("binary_user_data_adapters") { test_user_data_adapters(); } -BOOST_AUTO_TEST_CASE( portable_binary_user_data_adapters ) +TEST_CASE("portable_binary_user_data_adapters") { test_user_data_adapters(); } -BOOST_AUTO_TEST_CASE( xml_user_data_adapters ) +TEST_CASE("xml_user_data_adapters") { test_user_data_adapters(); } -BOOST_AUTO_TEST_CASE( json_user_data_adapters ) +TEST_CASE("json_user_data_adapters") { test_user_data_adapters(); } +TEST_SUITE_END(); diff --git a/unittests/user_data_adapters.hpp b/unittests/user_data_adapters.hpp new file mode 100644 index 000000000..23a2510c0 --- /dev/null +++ b/unittests/user_data_adapters.hpp @@ -0,0 +1,120 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_USER_DATA_ADAPTERS_H_ +#define CEREAL_TEST_USER_DATA_ADAPTERS_H_ + +#include "common.hpp" +#define CEREAL_FUTURE_EXPERIMENTAL +#include + +struct SomeStruct {}; + +struct UserData +{ + UserData( SomeStruct * pp, SomeStruct & r ) : + p(pp), ref(r) {} + + SomeStruct * p; + std::reference_wrapper ref; +}; + +struct UserStruct +{ + UserStruct( std::int32_t i, + SomeStruct * pointer, + SomeStruct & reference ) : + i32( i ), + p( pointer ), + ref( reference ) + { } + + UserStruct & operator=( UserStruct const & ) = delete; + + std::int32_t i32; + SomeStruct const * p; + SomeStruct & ref; + + template + void serialize( Archive & ar ) + { + ar( i32 ); + } + + template + static void load_and_construct( Archive & ar, cereal::construct & construct ) + { + std::int32_t ii; + ar( ii ); + auto & data = cereal::get_user_data( ar ); + construct( ii, data.p, data.ref.get() ); + } +}; + +template inline +void test_user_data_adapters() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + auto rng = [&](){ return random_value(gen); }; + + for(int ii=0; ii<100; ++ii) + { + SomeStruct ss; + std::unique_ptr o_ptr( new UserStruct( rng(), &ss, ss ) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_ptr); + } + + decltype( o_ptr ) i_ptr; + + std::istringstream is(os.str()); + { + UserData ud(&ss, ss); + cereal::UserDataAdapter iar(ud, is); + + iar(i_ptr); + } + + CHECK_EQ( i_ptr->p, o_ptr->p ); + CHECK_EQ( std::addressof(i_ptr->ref), std::addressof(o_ptr->ref) ); + CHECK_EQ( i_ptr->i32, o_ptr->i32 ); + + std::istringstream bad_is(os.str()); + { + IArchive iar(bad_is); + + CHECK_THROWS_AS( iar(i_ptr), ::cereal::Exception ); + } + } +} + +#endif // CEREAL_TEST_USER_DATA_ADAPTERS_H_ diff --git a/unittests/valarray.cpp b/unittests/valarray.cpp index 7a1fbd1f5..4866c0297 100644 --- a/unittests/valarray.cpp +++ b/unittests/valarray.cpp @@ -24,96 +24,29 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "valarray.hpp" -#include "common.hpp" -#include +TEST_SUITE("valarray"); -template -void test_valarray() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for (int ii = 0; ii<100; ++ii) - { - std::valarray o_podvalarray(100); - for (auto & elem : o_podvalarray) - elem = random_value(gen); - - std::valarray o_iservalarray(100); - for (auto & elem : o_iservalarray) - elem = StructInternalSerialize(random_value(gen), random_value(gen)); - - std::valarray o_isplvalarray(100); - for (auto & elem : o_isplvalarray) - elem = StructInternalSplit(random_value(gen), random_value(gen)); - - std::valarray o_eservalarray(100); - for (auto & elem : o_eservalarray) - elem = StructExternalSerialize(random_value(gen), random_value(gen)); - - std::valarray o_esplvalarray(100); - for (auto & elem : o_esplvalarray) - elem = StructExternalSplit(random_value(gen), random_value(gen)); - - std::ostringstream os; - { - OArchive oar(os); - - oar(o_podvalarray); - oar(o_iservalarray); - oar(o_isplvalarray); - oar(o_eservalarray); - oar(o_esplvalarray); - } - - std::valarray i_podvalarray; - std::valarray i_iservalarray; - std::valarray i_isplvalarray; - std::valarray i_eservalarray; - std::valarray i_esplvalarray; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podvalarray); - iar(i_iservalarray); - iar(i_isplvalarray); - iar(i_eservalarray); - iar(i_esplvalarray); - } - - BOOST_CHECK_EQUAL(i_podvalarray.size(), o_podvalarray.size()); - BOOST_CHECK_EQUAL(i_iservalarray.size(), o_iservalarray.size()); - BOOST_CHECK_EQUAL(i_isplvalarray.size(), o_isplvalarray.size()); - BOOST_CHECK_EQUAL(i_eservalarray.size(), o_eservalarray.size()); - BOOST_CHECK_EQUAL(i_esplvalarray.size(), o_esplvalarray.size()); - - BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_podvalarray), std::end(i_podvalarray), std::begin(o_podvalarray), std::end(o_podvalarray)); - BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_iservalarray), std::end(i_iservalarray), std::begin(o_iservalarray), std::end(o_iservalarray)); - BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_isplvalarray), std::end(i_isplvalarray), std::begin(o_isplvalarray), std::end(o_isplvalarray)); - BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_eservalarray), std::end(i_eservalarray), std::begin(o_eservalarray), std::end(o_eservalarray)); - BOOST_CHECK_EQUAL_COLLECTIONS(std::begin(i_esplvalarray), std::end(i_esplvalarray), std::begin(o_esplvalarray), std::end(o_esplvalarray)); - } -} - -BOOST_AUTO_TEST_CASE(binary_valarray) +TEST_CASE("binary_valarray") { test_valarray(); } -BOOST_AUTO_TEST_CASE(portable_binary_valarray) +TEST_CASE("portable_binary_valarray") { test_valarray(); } -BOOST_AUTO_TEST_CASE(xml_valarray) +TEST_CASE("xml_valarray") { test_valarray(); } -BOOST_AUTO_TEST_CASE(json_valarray) +TEST_CASE("json_valarray") { test_valarray(); } + +TEST_SUITE_END(); diff --git a/unittests/valarray.hpp b/unittests/valarray.hpp new file mode 100644 index 000000000..19df153be --- /dev/null +++ b/unittests/valarray.hpp @@ -0,0 +1,101 @@ +/* +Copyright (c) 2014, Randolph Voorhies, Shane Grant +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of cereal nor the +names of its contributors may be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_VALARRAY_H_ +#define CEREAL_TEST_VALARRAY_H_ +#include "common.hpp" + +template inline +void test_valarray() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for (int ii = 0; ii<100; ++ii) + { + std::valarray o_podvalarray(100); + for (auto & elem : o_podvalarray) + elem = random_value(gen); + + std::valarray o_iservalarray(100); + for (auto & elem : o_iservalarray) + elem = StructInternalSerialize(random_value(gen), random_value(gen)); + + std::valarray o_isplvalarray(100); + for (auto & elem : o_isplvalarray) + elem = StructInternalSplit(random_value(gen), random_value(gen)); + + std::valarray o_eservalarray(100); + for (auto & elem : o_eservalarray) + elem = StructExternalSerialize(random_value(gen), random_value(gen)); + + std::valarray o_esplvalarray(100); + for (auto & elem : o_esplvalarray) + elem = StructExternalSplit(random_value(gen), random_value(gen)); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podvalarray); + oar(o_iservalarray); + oar(o_isplvalarray); + oar(o_eservalarray); + oar(o_esplvalarray); + } + + std::valarray i_podvalarray; + std::valarray i_iservalarray; + std::valarray i_isplvalarray; + std::valarray i_eservalarray; + std::valarray i_esplvalarray; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podvalarray); + iar(i_iservalarray); + iar(i_isplvalarray); + iar(i_eservalarray); + iar(i_esplvalarray); + } + + CHECK_EQ(i_podvalarray.size(), o_podvalarray.size()); + CHECK_EQ(i_iservalarray.size(), o_iservalarray.size()); + CHECK_EQ(i_isplvalarray.size(), o_isplvalarray.size()); + CHECK_EQ(i_eservalarray.size(), o_eservalarray.size()); + CHECK_EQ(i_esplvalarray.size(), o_esplvalarray.size()); + + check_collection(i_podvalarray , o_podvalarray ); + check_collection(i_iservalarray, o_iservalarray); + check_collection(i_isplvalarray, o_isplvalarray); + check_collection(i_eservalarray, o_eservalarray); + check_collection(i_esplvalarray, o_esplvalarray); + } +} + +#endif // CEREAL_TEST_VALARRAY_H_ diff --git a/unittests/vector.cpp b/unittests/vector.cpp index fdb686951..be172ba58 100644 --- a/unittests/vector.cpp +++ b/unittests/vector.cpp @@ -24,106 +24,29 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "vector.hpp" -template -void test_vector() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(int ii=0; ii<100; ++ii) - { - std::vector o_podvector(100); - for(auto & elem : o_podvector) - elem = random_value(gen); - - std::vector o_boolvector; o_boolvector.resize(100); - for( size_t i = 0; i < 100; ++i ) - o_boolvector[i] = (random_value(gen) % 2) == 0; - - std::vector o_iservector(100); - for(auto & elem : o_iservector) - elem = StructInternalSerialize( random_value(gen), random_value(gen) ); - - std::vector o_isplvector(100); - for(auto & elem : o_isplvector) - elem = StructInternalSplit( random_value(gen), random_value(gen) ); - - std::vector o_eservector(100); - for(auto & elem : o_eservector) - elem = StructExternalSerialize( random_value(gen), random_value(gen) ); - - std::vector o_esplvector(100); - for(auto & elem : o_esplvector) - elem = StructExternalSplit( random_value(gen), random_value(gen) ); - - std::ostringstream os; - { - OArchive oar(os); +TEST_SUITE("vector"); - oar(o_podvector); - oar(o_boolvector); - oar(o_iservector); - oar(o_isplvector); - oar(o_eservector); - oar(o_esplvector); - } - - std::vector i_podvector; - std::vector i_boolvector; - std::vector i_iservector; - std::vector i_isplvector; - std::vector i_eservector; - std::vector i_esplvector; - - std::istringstream is(os.str()); - { - IArchive iar(is); - - iar(i_podvector); - iar(i_boolvector); - iar(i_iservector); - iar(i_isplvector); - iar(i_eservector); - iar(i_esplvector); - } - - BOOST_CHECK_EQUAL(i_podvector.size(), o_podvector.size()); - BOOST_CHECK_EQUAL(i_boolvector.size(), o_boolvector.size()); - BOOST_CHECK_EQUAL(i_iservector.size(), o_iservector.size()); - BOOST_CHECK_EQUAL(i_isplvector.size(), o_isplvector.size()); - BOOST_CHECK_EQUAL(i_eservector.size(), o_eservector.size()); - BOOST_CHECK_EQUAL(i_esplvector.size(), o_esplvector.size()); - - BOOST_CHECK_EQUAL_COLLECTIONS(i_podvector.begin(), i_podvector.end(), o_podvector.begin(), o_podvector.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_boolvector.begin(), i_boolvector.end(), o_boolvector.begin(), o_boolvector.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_iservector.begin(), i_iservector.end(), o_iservector.begin(), o_iservector.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_isplvector.begin(), i_isplvector.end(), o_isplvector.begin(), o_isplvector.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_eservector.begin(), i_eservector.end(), o_eservector.begin(), o_eservector.end()); - BOOST_CHECK_EQUAL_COLLECTIONS(i_esplvector.begin(), i_esplvector.end(), o_esplvector.begin(), o_esplvector.end()); - } -} - -BOOST_AUTO_TEST_CASE( binary_vector ) +TEST_CASE("binary_vector") { test_vector(); } -BOOST_AUTO_TEST_CASE( portable_binary_vector ) +TEST_CASE("portable_binary_vector") { test_vector(); } -BOOST_AUTO_TEST_CASE( xml_vector ) +TEST_CASE("xml_vector") { test_vector(); } -BOOST_AUTO_TEST_CASE( json_vector ) +TEST_CASE("json_vector") { test_vector(); } - +TEST_SUITE_END(); diff --git a/unittests/vector.hpp b/unittests/vector.hpp new file mode 100644 index 000000000..a0297905b --- /dev/null +++ b/unittests/vector.hpp @@ -0,0 +1,110 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_VECTOR_H_ +#define CEREAL_TEST_VECTOR_H_ +#include "common.hpp" + +template inline +void test_vector() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + for(int ii=0; ii<100; ++ii) + { + std::vector o_podvector(100); + for(auto & elem : o_podvector) + elem = random_value(gen); + + std::vector o_boolvector; o_boolvector.resize(100); + for( size_t i = 0; i < 100; ++i ) + o_boolvector[i] = (random_value(gen) % 2) == 0; + + std::vector o_iservector(100); + for(auto & elem : o_iservector) + elem = StructInternalSerialize( random_value(gen), random_value(gen) ); + + std::vector o_isplvector(100); + for(auto & elem : o_isplvector) + elem = StructInternalSplit( random_value(gen), random_value(gen) ); + + std::vector o_eservector(100); + for(auto & elem : o_eservector) + elem = StructExternalSerialize( random_value(gen), random_value(gen) ); + + std::vector o_esplvector(100); + for(auto & elem : o_esplvector) + elem = StructExternalSplit( random_value(gen), random_value(gen) ); + + std::ostringstream os; + { + OArchive oar(os); + + oar(o_podvector); + oar(o_boolvector); + oar(o_iservector); + oar(o_isplvector); + oar(o_eservector); + oar(o_esplvector); + } + + std::vector i_podvector; + std::vector i_boolvector; + std::vector i_iservector; + std::vector i_isplvector; + std::vector i_eservector; + std::vector i_esplvector; + + std::istringstream is(os.str()); + { + IArchive iar(is); + + iar(i_podvector); + iar(i_boolvector); + iar(i_iservector); + iar(i_isplvector); + iar(i_eservector); + iar(i_esplvector); + } + + CHECK_EQ(i_podvector.size(), o_podvector.size()); + CHECK_EQ(i_boolvector.size(), o_boolvector.size()); + CHECK_EQ(i_iservector.size(), o_iservector.size()); + CHECK_EQ(i_isplvector.size(), o_isplvector.size()); + CHECK_EQ(i_eservector.size(), o_eservector.size()); + CHECK_EQ(i_esplvector.size(), o_esplvector.size()); + + check_collection(i_podvector, o_podvector ); + check_collection(i_boolvector, o_boolvector); + check_collection(i_iservector, o_iservector); + check_collection(i_isplvector, o_isplvector); + check_collection(i_eservector, o_eservector); + check_collection(i_esplvector, o_esplvector); + } +} + +#endif // CEREAL_TEST_VECTOR_H_ diff --git a/unittests/versioning.cpp b/unittests/versioning.cpp index 218a0ea86..872742644 100644 --- a/unittests/versioning.cpp +++ b/unittests/versioning.cpp @@ -24,227 +24,51 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "common.hpp" -#include +#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN +#include "versioning.hpp" -#if CEREAL_THREAD_SAFE -#include -static std::mutex boostTestMutex; -#endif - -namespace Nested -{ - struct NestedClass - { - int x; - - template - void serialize( Archive & ar ) - { ar( x ); } - }; -} - -CEREAL_CLASS_VERSION( Nested::NestedClass, 1 ) - -class VersionStructMS -{ - public: - bool x; - std::uint32_t v; - - private: - friend class cereal::access; - template - void serialize( Archive & ar, std::uint32_t const version ) - { - ar( x ); - v = version; - } -}; - -struct VersionStructMSP -{ - uint8_t x; - std::uint32_t v; - template - void save( Archive & ar, std::uint32_t const /*version*/ ) const - { - ar( x ); - } - - template - void load( Archive & ar, std::uint32_t const version ) - { - ar( x ); - v = version; - } -}; - -struct VersionStructNMS -{ - std::int32_t x; - std::uint32_t v; -}; - -template -void serialize( Archive & ar, VersionStructNMS & vnms, const std::uint32_t version ) -{ - ar( vnms.x ); - vnms.v = version; -} - -struct VersionStructNMSP -{ - double x; - std::uint32_t v; -}; - -template -void save( Archive & ar, VersionStructNMSP const & vnms, const std::uint32_t /*version*/ ) -{ - ar( vnms.x ); -} - -template -void load( Archive & ar, VersionStructNMSP & vnms, const std::uint32_t version ) -{ - ar( vnms.x ); - vnms.v = version; -} - -CEREAL_CLASS_VERSION( VersionStructMSP, 33 ) -CEREAL_CLASS_VERSION( VersionStructNMS, 66 ) -CEREAL_CLASS_VERSION( VersionStructNMSP, 99 ) +TEST_SUITE("versioning"); -template -void test_versioning() -{ - std::random_device rd; - std::mt19937 gen(rd()); - - for(size_t i=0; i<100; ++i) - { - VersionStructMS o_MS = {random_value(gen) % 2 ? true : false, 1}; - VersionStructMSP o_MSP = {random_value(gen), 1}; - VersionStructNMS o_NMS = {random_value(gen), 1}; - VersionStructNMSP o_NMSP = {random_value(gen), 1}; - VersionStructMS o_MS2 = {random_value(gen) % 2 ? true : false, 1}; - VersionStructMSP o_MSP2 = {random_value(gen), 1}; - VersionStructNMS o_NMS2 = {random_value(gen), 1}; - VersionStructNMSP o_NMSP2 = {random_value(gen), 1}; - - std::ostringstream os; - { - OArchive oar(os); - oar( o_MS ); - oar( o_MSP ); - oar( o_NMS ); - oar( o_NMSP ); - oar( o_MS2 ); - oar( o_MSP2 ); - oar( o_NMS2 ); - oar( o_NMSP2 ); - } - - decltype(o_MS) i_MS; - decltype(o_MSP) i_MSP; - decltype(o_NMS) i_NMS; - decltype(o_NMSP) i_NMSP; - decltype(o_MS2) i_MS2; - decltype(o_MSP2) i_MSP2; - decltype(o_NMS2) i_NMS2; - decltype(o_NMSP2) i_NMSP2; - - std::istringstream is(os.str()); - { - IArchive iar(is); - iar( i_MS ); - iar( i_MSP ); - iar( i_NMS ); - iar( i_NMSP ); - iar( i_MS2 ); - iar( i_MSP2 ); - iar( i_NMS2 ); - iar( i_NMSP2 ); - } - - #if CEREAL_THREAD_SAFE - std::lock_guard lock( boostTestMutex ); - #endif - - BOOST_CHECK_EQUAL(o_MS.x, i_MS.x); - BOOST_CHECK_EQUAL(i_MS.v, 0u); - BOOST_CHECK_EQUAL(o_MSP.x, i_MSP.x); - BOOST_CHECK_EQUAL(i_MSP.v, 33u); - BOOST_CHECK_EQUAL(o_NMS.x, i_NMS.x); - BOOST_CHECK_EQUAL(i_NMS.v, 66u); - BOOST_CHECK_CLOSE(o_NMSP.x, i_NMSP.x, 1e-5); - BOOST_CHECK_EQUAL(i_NMSP.v, 99u); - - BOOST_CHECK_EQUAL(o_MS2.x, i_MS2.x); - BOOST_CHECK_EQUAL(i_MS2.v, 0u); - BOOST_CHECK_EQUAL(o_MSP2.x, i_MSP2.x); - BOOST_CHECK_EQUAL(i_MSP2.v, 33u); - BOOST_CHECK_EQUAL(o_NMS2.x, i_NMS2.x); - BOOST_CHECK_EQUAL(i_NMS2.v, 66u); - BOOST_CHECK_CLOSE(o_NMSP2.x, i_NMSP2.x, 1e-5); - BOOST_CHECK_EQUAL(i_NMSP2.v, 99u); - } -} - -BOOST_AUTO_TEST_CASE( binary_versioning ) +TEST_CASE("binary_versioning") { test_versioning(); } -BOOST_AUTO_TEST_CASE( portable_binary_versioning ) +TEST_CASE("portable_binary_versioning") { test_versioning(); } -BOOST_AUTO_TEST_CASE( xml_versioning ) +TEST_CASE("xml_versioning") { test_versioning(); } -BOOST_AUTO_TEST_CASE( json_versioning ) +TEST_CASE("json_versioning") { test_versioning(); } #if CEREAL_THREAD_SAFE -template -void test_versioning_threading() -{ - std::vector> pool; - for( size_t i = 0; i < 100; ++i ) - pool.emplace_back( std::async( std::launch::async, - [](){ test_versioning(); return true; } ) ); - - for( auto & future : pool ) - future.wait(); - - for( auto & future : pool ) - BOOST_CHECK( future.get() == true ); -} - -BOOST_AUTO_TEST_CASE( binary_versioning_threading ) +TEST_CASE("binary_versioning_threading") { test_versioning_threading(); } -BOOST_AUTO_TEST_CASE( portable_binary_versioning_threading ) +TEST_CASE("portable_binary_versioning_threading") { test_versioning_threading(); } -BOOST_AUTO_TEST_CASE( xml_versioning_threading ) +TEST_CASE("xml_versioning_threading") { test_versioning_threading(); } -BOOST_AUTO_TEST_CASE( json_versioning_threading ) +TEST_CASE("json_versioning_threading") { test_versioning_threading(); } #endif // CEREAL_THREAD_SAFE + +TEST_SUITE_END(); diff --git a/unittests/versioning.hpp b/unittests/versioning.hpp new file mode 100644 index 000000000..33e21d261 --- /dev/null +++ b/unittests/versioning.hpp @@ -0,0 +1,217 @@ +/* + Copyright (c) 2014, Randolph Voorhies, Shane Grant + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of cereal nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#ifndef CEREAL_TEST_VERSIONING_H_ +#define CEREAL_TEST_VERSIONING_H_ +#include "common.hpp" + +#if CEREAL_THREAD_SAFE +#include +#endif + +namespace Nested +{ + struct NestedClass + { + int x; + + template + void serialize( Archive & ar ) + { ar( x ); } + }; +} + +CEREAL_CLASS_VERSION( Nested::NestedClass, 1 ) + +class VersionStructMS +{ + public: + bool x; + std::uint32_t v; + + private: + friend class cereal::access; + template + void serialize( Archive & ar, std::uint32_t const version ) + { + ar( x ); + v = version; + } +}; + +struct VersionStructMSP +{ + uint8_t x; + std::uint32_t v; + template + void save( Archive & ar, std::uint32_t const /*version*/ ) const + { + ar( x ); + } + + template + void load( Archive & ar, std::uint32_t const version ) + { + ar( x ); + v = version; + } +}; + +struct VersionStructNMS +{ + std::int32_t x; + std::uint32_t v; +}; + +template +void serialize( Archive & ar, VersionStructNMS & vnms, const std::uint32_t version ) +{ + ar( vnms.x ); + vnms.v = version; +} + +struct VersionStructNMSP +{ + double x; + std::uint32_t v; +}; + +template +void save( Archive & ar, VersionStructNMSP const & vnms, const std::uint32_t /*version*/ ) +{ + ar( vnms.x ); +} + +template +void load( Archive & ar, VersionStructNMSP & vnms, const std::uint32_t version ) +{ + ar( vnms.x ); + vnms.v = version; +} + +CEREAL_CLASS_VERSION( VersionStructMSP, 33 ) +CEREAL_CLASS_VERSION( VersionStructNMS, 66 ) +CEREAL_CLASS_VERSION( VersionStructNMSP, 99 ) + +template inline +void test_versioning() +{ + std::random_device rd; + std::mt19937 gen(rd()); + + #if CEREAL_THREAD_SAFE + #include + static std::mutex testMutex; + #endif + + for(size_t i=0; i<100; ++i) + { + VersionStructMS o_MS = {random_value(gen) % 2 ? true : false, 1}; + VersionStructMSP o_MSP = {random_value(gen), 1}; + VersionStructNMS o_NMS = {random_value(gen), 1}; + VersionStructNMSP o_NMSP = {random_value(gen), 1}; + VersionStructMS o_MS2 = {random_value(gen) % 2 ? true : false, 1}; + VersionStructMSP o_MSP2 = {random_value(gen), 1}; + VersionStructNMS o_NMS2 = {random_value(gen), 1}; + VersionStructNMSP o_NMSP2 = {random_value(gen), 1}; + + std::ostringstream os; + { + OArchive oar(os); + oar( o_MS ); + oar( o_MSP ); + oar( o_NMS ); + oar( o_NMSP ); + oar( o_MS2 ); + oar( o_MSP2 ); + oar( o_NMS2 ); + oar( o_NMSP2 ); + } + + decltype(o_MS) i_MS; + decltype(o_MSP) i_MSP; + decltype(o_NMS) i_NMS; + decltype(o_NMSP) i_NMSP; + decltype(o_MS2) i_MS2; + decltype(o_MSP2) i_MSP2; + decltype(o_NMS2) i_NMS2; + decltype(o_NMSP2) i_NMSP2; + + std::istringstream is(os.str()); + { + IArchive iar(is); + iar( i_MS ); + iar( i_MSP ); + iar( i_NMS ); + iar( i_NMSP ); + iar( i_MS2 ); + iar( i_MSP2 ); + iar( i_NMS2 ); + iar( i_NMSP2 ); + } + + #if CEREAL_THREAD_SAFE + std::lock_guard lock( testMutex ); + #endif + + CHECK_EQ(o_MS.x, i_MS.x); + CHECK_EQ(i_MS.v, 0u); + CHECK_EQ(o_MSP.x, i_MSP.x); + CHECK_EQ(i_MSP.v, 33u); + CHECK_EQ(o_NMS.x, i_NMS.x); + CHECK_EQ(i_NMS.v, 66u); + CHECK_EQ(o_NMSP.x, doctest::Approx(i_NMSP.x).epsilon(1e-5)); + CHECK_EQ(i_NMSP.v, 99u); + + CHECK_EQ(o_MS2.x, i_MS2.x); + CHECK_EQ(i_MS2.v, 0u); + CHECK_EQ(o_MSP2.x, i_MSP2.x); + CHECK_EQ(i_MSP2.v, 33u); + CHECK_EQ(o_NMS2.x, i_NMS2.x); + CHECK_EQ(i_NMS2.v, 66u); + CHECK_EQ(o_NMSP2.x, doctest::Approx(i_NMSP2.x).epsilon(1e-5)); + CHECK_EQ(i_NMSP2.v, 99u); + } +} + +#if CEREAL_THREAD_SAFE +template inline +void test_versioning_threading() +{ + std::vector> pool; + for( size_t i = 0; i < 100; ++i ) + pool.emplace_back( std::async( std::launch::async, + [](){ test_versioning(); return true; } ) ); + + for( auto & future : pool ) + future.wait(); + + for( auto & future : pool ) + CHECK_UNARY( future.get() ); +} +#endif // CEREAL_THREAD_SAFE + +#endif // CEREAL_TEST_VERSIONING_H_