From d16f88da40b51b872ffd8a428bddeedaaca194e6 Mon Sep 17 00:00:00 2001 From: dlardi Date: Thu, 25 Aug 2016 16:12:41 +0300 Subject: [PATCH 01/58] Register of chainable relations fix --- include/cereal/details/polymorphic_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index e15075882..248ce2e15 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -232,7 +232,7 @@ namespace cereal } // Find all chainable unregistered relations - std::map>> unregisteredRelations; + std::multimap>> unregisteredRelations; { auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo) { From cd37b64b788d4a3f864e38b97fde3dc76ec8720c Mon Sep 17 00:00:00 2001 From: dlardi Date: Tue, 30 Aug 2016 15:12:37 +0300 Subject: [PATCH 02/58] Iterative searching of chainable relations added --- include/cereal/details/polymorphic_impl.hpp | 100 +++++++++++--------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 248ce2e15..8fc547b9a 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -232,57 +232,67 @@ namespace cereal } // Find all chainable unregistered relations - std::multimap>> unregisteredRelations; { - auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo) + using Relations = std::multimap>>; + auto findChainableRelations = [&baseMap]() -> Relations { - const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo ); - return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) : - std::vector{} ); - }; - - for( auto baseIt : baseMap ) - for( auto derivedIt : baseIt.second ) + auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo) { - for( auto otherBaseIt : baseMap ) + const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo ); + return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) : + std::vector{} ); + }; + + Relations unregisteredRelations; + for( auto baseIt : baseMap ) + for( auto derivedIt : baseIt.second ) { - if( baseIt.first == otherBaseIt.first ) // only interested in chained relations - continue; - - // Check if there exists a mapping otherBase -> base -> derived that is shorter than - // any existing otherBase -> derived direct mapping - auto otherBaseItToDerived = checkRelation( otherBaseIt.first, derivedIt.first ); - auto baseToDerived = checkRelation( baseIt.first, derivedIt.first ); - auto otherBaseToBase = checkRelation( otherBaseIt.first, baseIt.first ); - - const size_t newLength = otherBaseToBase.second.size() + baseToDerived.second.size(); - const bool isShorterOrFirstPath = !otherBaseItToDerived.first || (newLength < derivedIt.second.size()); - - if( isShorterOrFirstPath && - baseToDerived.first && - otherBaseToBase.first ) + for( auto otherBaseIt : baseMap ) { - std::vector path = otherBaseToBase.second; - path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() ); - - #ifdef CEREAL_OLDER_GCC - unregisteredRelations.insert( std::make_pair(otherBaseIt.first, - std::pair>{derivedIt.first, std::move(path)}) ); - #else // NOT CEREAL_OLDER_GCC - unregisteredRelations.emplace( otherBaseIt.first, - std::pair>{derivedIt.first, std::move(path)} ); - #endif // NOT CEREAL_OLDER_GCC - } - } // end otherBaseIt - } // end derivedIt + if( baseIt.first == otherBaseIt.first ) // only interested in chained relations + continue; + + // Check if there exists a mapping otherBase -> base -> derived that is shorter than + // any existing otherBase -> derived direct mapping + auto otherBaseItToDerived = checkRelation( otherBaseIt.first, derivedIt.first ); + auto baseToDerived = checkRelation( baseIt.first, derivedIt.first ); + auto otherBaseToBase = checkRelation( otherBaseIt.first, baseIt.first ); + + const size_t newLength = otherBaseToBase.second.size() + baseToDerived.second.size(); + const bool isShorterOrFirstPath = !otherBaseItToDerived.first || (newLength < derivedIt.second.size()); + + if( isShorterOrFirstPath && + baseToDerived.first && + otherBaseToBase.first ) + { + std::vector path = otherBaseToBase.second; + path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() ); + + #ifdef CEREAL_OLDER_GCC + unregisteredRelations.insert( std::make_pair(otherBaseIt.first, + std::pair>{derivedIt.first, std::move(path)}) ); + #else // NOT CEREAL_OLDER_GCC + unregisteredRelations.emplace( otherBaseIt.first, + std::pair>{derivedIt.first, std::move(path)} ); + #endif // NOT CEREAL_OLDER_GCC + } + } // end otherBaseIt + } // end derivedIt + return unregisteredRelations; + }; // end findChainableRelations + + Relations unregisteredRelations; + do + { + unregisteredRelations = findChainableRelations(); + // Insert chained relations + for( auto it : unregisteredRelations ) + { + auto & derivedMap = baseMap.find( it.first )->second; + derivedMap[it.second.first] = it.second.second; + } + } while ( !unregisteredRelations.empty() ); } // end chain lookup - - // Insert chained relations - for( auto it : unregisteredRelations ) - { - auto & derivedMap = baseMap.find( it.first )->second; - derivedMap[it.second.first] = it.second.second; - } } //! Performs the proper downcast with the templated types From c83a7f99e6f5ee785ccd9e8604e8dcf9758089fe Mon Sep 17 00:00:00 2001 From: dlardi Date: Thu, 1 Sep 2016 18:41:15 +0300 Subject: [PATCH 03/58] 'auto const &' used for range-based loops --- include/cereal/details/polymorphic_impl.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 8fc547b9a..906b88f49 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -244,10 +244,10 @@ namespace cereal }; Relations unregisteredRelations; - for( auto baseIt : baseMap ) - for( auto derivedIt : baseIt.second ) + for( auto const & baseIt : baseMap ) + for( auto const & derivedIt : baseIt.second ) { - for( auto otherBaseIt : baseMap ) + for( auto const & otherBaseIt : baseMap ) { if( baseIt.first == otherBaseIt.first ) // only interested in chained relations continue; @@ -286,7 +286,7 @@ namespace cereal { unregisteredRelations = findChainableRelations(); // Insert chained relations - for( auto it : unregisteredRelations ) + for( auto const & it : unregisteredRelations ) { auto & derivedMap = baseMap.find( it.first )->second; derivedMap[it.second.first] = it.second.second; From b9c424e06a589096e4db18badda96bedc9ac2a95 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Wed, 7 Sep 2016 11:55:28 -0700 Subject: [PATCH 04/58] Avoid accidentally using the "check" macro on OSX Fix for #341, #273, and #104. Replace usages of "check(" with "(check)(", which will prevent us from colliding with the macro defined in OSX's Assert macros. --- include/cereal/details/traits.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp index f7e301cc8..9676d530d 100644 --- a/include/cereal/details/traits.hpp +++ b/include/cereal/details/traits.hpp @@ -1180,9 +1180,9 @@ namespace cereal struct shared_from_this_wrapper { template - static auto check( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() ); + static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() ); - static auto check( ... ) -> decltype( std::false_type() ); + static auto (check)( ... ) -> decltype( std::false_type() ); template static auto get( U const & t ) -> decltype( t.shared_from_this() ); @@ -1191,7 +1191,7 @@ namespace cereal //! Determine if T or any base class of T has inherited from std::enable_shared_from_this template - struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval())) + struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval())) { }; //! Get the type of the base class of T which inherited from std::enable_shared_from_this From b8d9acc502378bb7ceb5e35d21de853bf19f04b0 Mon Sep 17 00:00:00 2001 From: Christoph Junghans Date: Wed, 31 Aug 2016 15:06:17 -0600 Subject: [PATCH 05/58] cmake: allow dropping -Werror from c++ flags --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f3f604b4..d50e29dff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,11 @@ else() endif() if(NOT MSVC) - set(CMAKE_CXX_FLAGS "-Wall -Werror -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}") + option(DONT_INJECT_WERROR "Don't inject '-Werror' into the C++ compiler flags" OFF) + if(NOT DONT_INJECT_WERROR) + set(CMAKE_CXX_FLAGS "-Werror ${CMAKE_CXX_FLAGS}") + endif(NOT DONT_INJECT_WERROR) if(CMAKE_VERSION VERSION_LESS 3.1) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") else() From adea360c7ae8cd3166d00b25796c7b2b00800cb4 Mon Sep 17 00:00:00 2001 From: Igor Date: Fri, 16 Sep 2016 20:18:49 +0300 Subject: [PATCH 06/58] Use statics initialization on demand fixed #331 Fixed crash CEREAL_THREAD_SAFE=1 with polymorphic class. Crash happened because StaticObject::instanceMutex not initialized when StaticObject::lock() called for the first time. Basically it is better to use static vars inside static functions to have predefined order of construction like it is done in StaticObject::getInstance(), which calls create and forces instantiation at pre-execution time. Also in this commit removed static T &instance; since it is possible that there were be two instances created 1) template T & StaticObject::instance = StaticObject::create(); 2) inside StaticObject::create() --- include/cereal/details/static_object.hpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index 6afdb75d1..b40694081 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -73,7 +73,7 @@ namespace cereal static T & create() { static T t; - instantiate(instance); + instantiate(t); return t; } @@ -109,23 +109,15 @@ namespace cereal static LockGuard lock() { #if CEREAL_THREAD_SAFE + std::mutex instanceMutex; return LockGuard{instanceMutex}; #else return LockGuard{}; #endif } - private: - static T & instance; - #if CEREAL_THREAD_SAFE - static std::mutex instanceMutex; - #endif }; - template T & StaticObject::instance = StaticObject::create(); - #if CEREAL_THREAD_SAFE - template std::mutex StaticObject::instanceMutex; - #endif } // namespace detail } // namespace cereal From 3d5a77d2c3779aab8a2ba9e0e7d81457530fd986 Mon Sep 17 00:00:00 2001 From: KKlouzal Date: Tue, 20 Sep 2016 23:29:05 -0700 Subject: [PATCH 07/58] Fixed Internal Cereal Includes --- include/cereal/access.hpp | 4 ++-- include/cereal/archives/adapters.hpp | 2 +- include/cereal/archives/binary.hpp | 2 +- include/cereal/archives/json.hpp | 14 +++++++------- include/cereal/archives/portable_binary.hpp | 2 +- include/cereal/archives/xml.hpp | 10 +++++----- include/cereal/cereal.hpp | 10 +++++----- include/cereal/details/helpers.hpp | 4 ++-- include/cereal/details/polymorphic_impl.hpp | 8 ++++---- include/cereal/details/static_object.hpp | 2 +- include/cereal/details/traits.hpp | 4 ++-- include/cereal/types/array.hpp | 2 +- include/cereal/types/base_class.hpp | 4 ++-- include/cereal/types/bitset.hpp | 4 ++-- include/cereal/types/boost_variant.hpp | 2 +- include/cereal/types/common.hpp | 2 +- .../types/concepts/pair_associative_container.hpp | 2 +- include/cereal/types/deque.hpp | 2 +- include/cereal/types/forward_list.hpp | 2 +- include/cereal/types/list.hpp | 2 +- include/cereal/types/map.hpp | 2 +- include/cereal/types/memory.hpp | 4 ++-- include/cereal/types/polymorphic.hpp | 12 ++++++------ include/cereal/types/queue.hpp | 6 +++--- include/cereal/types/set.hpp | 2 +- include/cereal/types/stack.hpp | 4 ++-- include/cereal/types/string.hpp | 2 +- include/cereal/types/tuple.hpp | 2 +- include/cereal/types/unordered_map.hpp | 2 +- include/cereal/types/unordered_set.hpp | 2 +- include/cereal/types/utility.hpp | 2 +- include/cereal/types/valarray.hpp | 2 +- include/cereal/types/vector.hpp | 2 +- 33 files changed, 64 insertions(+), 64 deletions(-) diff --git a/include/cereal/access.hpp b/include/cereal/access.hpp index 407ffcc83..63c1f74af 100644 --- a/include/cereal/access.hpp +++ b/include/cereal/access.hpp @@ -34,8 +34,8 @@ #include #include -#include -#include +#include "cereal/macros.hpp" +#include "cereal/details/helpers.hpp" namespace cereal { diff --git a/include/cereal/archives/adapters.hpp b/include/cereal/archives/adapters.hpp index d9558adeb..0191e3239 100644 --- a/include/cereal/archives/adapters.hpp +++ b/include/cereal/archives/adapters.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_ #define CEREAL_ARCHIVES_ADAPTERS_HPP_ -#include +#include "cereal/details/helpers.hpp" #include namespace cereal diff --git a/include/cereal/archives/binary.hpp b/include/cereal/archives/binary.hpp index 74342b3a7..7e0032268 100644 --- a/include/cereal/archives/binary.hpp +++ b/include/cereal/archives/binary.hpp @@ -29,7 +29,7 @@ #ifndef CEREAL_ARCHIVES_BINARY_HPP_ #define CEREAL_ARCHIVES_BINARY_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/archives/json.hpp b/include/cereal/archives/json.hpp index 3eb95db5f..ce5151dc7 100644 --- a/include/cereal/archives/json.hpp +++ b/include/cereal/archives/json.hpp @@ -29,8 +29,8 @@ #ifndef CEREAL_ARCHIVES_JSON_HPP_ #define CEREAL_ARCHIVES_JSON_HPP_ -#include -#include +#include "cereal/cereal.hpp" +#include "cereal/details/util.hpp" namespace cereal { @@ -50,11 +50,11 @@ namespace cereal #define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag #define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag -#include -#include -#include -#include -#include +#include "cereal/external/rapidjson/prettywriter.h" +#include "cereal/external/rapidjson/ostreamwrapper.h" +#include "cereal/external/rapidjson/istreamwrapper.h" +#include "cereal/external/rapidjson/document.h" +#include "cereal/external/base64.hpp" #include #include diff --git a/include/cereal/archives/portable_binary.hpp b/include/cereal/archives/portable_binary.hpp index f9d72d224..76e634ba6 100644 --- a/include/cereal/archives/portable_binary.hpp +++ b/include/cereal/archives/portable_binary.hpp @@ -29,7 +29,7 @@ #ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_ #define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_ -#include +#include "cereal/cereal.hpp" #include #include diff --git a/include/cereal/archives/xml.hpp b/include/cereal/archives/xml.hpp index 63f737acc..c520f02e2 100644 --- a/include/cereal/archives/xml.hpp +++ b/include/cereal/archives/xml.hpp @@ -28,12 +28,12 @@ */ #ifndef CEREAL_ARCHIVES_XML_HPP_ #define CEREAL_ARCHIVES_XML_HPP_ -#include -#include +#include "cereal/cereal.hpp" +#include "cereal/details/util.hpp" -#include -#include -#include +#include "cereal/external/rapidxml/rapidxml.hpp" +#include "cereal/external/rapidxml/rapidxml_print.hpp" +#include "cereal/external/base64.hpp" #include #include diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp index f6640d477..4b9a9c11e 100644 --- a/include/cereal/cereal.hpp +++ b/include/cereal/cereal.hpp @@ -39,10 +39,10 @@ #include #include -#include -#include -#include -#include +#include "cereal/macros.hpp" +#include "cereal/details/traits.hpp" +#include "cereal/details/helpers.hpp" +#include "cereal/types/base_class.hpp" namespace cereal { @@ -954,6 +954,6 @@ namespace cereal } // namespace cereal // This include needs to come after things such as binary_data, make_nvp, etc -#include +#include "cereal/types/common.hpp" #endif // CEREAL_CEREAL_HPP_ diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp index 527c7c62b..11088d33e 100644 --- a/include/cereal/details/helpers.hpp +++ b/include/cereal/details/helpers.hpp @@ -37,8 +37,8 @@ #include #include -#include -#include +#include "cereal/macros.hpp" +#include "cereal/details/static_object.hpp" namespace cereal { diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index e15075882..3d29a1a09 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -45,10 +45,10 @@ #ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_ #define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_ -#include -#include -#include -#include +#include "cereal/details/polymorphic_impl_fwd.hpp" +#include "cereal/details/static_object.hpp" +#include "cereal/types/memory.hpp" +#include "cereal/types/string.hpp" #include #include #include diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index 6afdb75d1..658d1b1bf 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -28,7 +28,7 @@ #ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_ #define CEREAL_DETAILS_STATIC_OBJECT_HPP_ -#include +#include "cereal/macros.hpp" #if CEREAL_THREAD_SAFE #include diff --git a/include/cereal/details/traits.hpp b/include/cereal/details/traits.hpp index f7e301cc8..6c668874c 100644 --- a/include/cereal/details/traits.hpp +++ b/include/cereal/details/traits.hpp @@ -39,8 +39,8 @@ #include #include -#include -#include +#include "cereal/macros.hpp" +#include "cereal/access.hpp" namespace cereal { diff --git a/include/cereal/types/array.hpp b/include/cereal/types/array.hpp index 34766e9af..f5d510abf 100644 --- a/include/cereal/types/array.hpp +++ b/include/cereal/types/array.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_ARRAY_HPP_ #define CEREAL_TYPES_ARRAY_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/base_class.hpp b/include/cereal/types/base_class.hpp index 10441ab95..37b551ede 100644 --- a/include/cereal/types/base_class.hpp +++ b/include/cereal/types/base_class.hpp @@ -30,8 +30,8 @@ #ifndef CEREAL_TYPES_BASE_CLASS_HPP_ #define CEREAL_TYPES_BASE_CLASS_HPP_ -#include -#include +#include "cereal/details/traits.hpp" +#include "cereal/details/polymorphic_impl_fwd.hpp" namespace cereal { diff --git a/include/cereal/types/bitset.hpp b/include/cereal/types/bitset.hpp index fe389a8af..349ea1229 100644 --- a/include/cereal/types/bitset.hpp +++ b/include/cereal/types/bitset.hpp @@ -30,8 +30,8 @@ #ifndef CEREAL_TYPES_BITSET_HPP_ #define CEREAL_TYPES_BITSET_HPP_ -#include -#include +#include "cereal/cereal.hpp" +#include "cereal/types/string.hpp" #include namespace cereal diff --git a/include/cereal/types/boost_variant.hpp b/include/cereal/types/boost_variant.hpp index f74123828..e1863c14f 100644 --- a/include/cereal/types/boost_variant.hpp +++ b/include/cereal/types/boost_variant.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_ #define CEREAL_TYPES_BOOST_VARIANT_HPP_ -#include +#include "cereal/cereal.hpp" #include #include diff --git a/include/cereal/types/common.hpp b/include/cereal/types/common.hpp index 57ab204b1..b239daa76 100644 --- a/include/cereal/types/common.hpp +++ b/include/cereal/types/common.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_COMMON_HPP_ #define CEREAL_TYPES_COMMON_HPP_ -#include +#include "cereal/cereal.hpp" namespace cereal { diff --git a/include/cereal/types/concepts/pair_associative_container.hpp b/include/cereal/types/concepts/pair_associative_container.hpp index 9936e5bc0..5f0fd746c 100644 --- a/include/cereal/types/concepts/pair_associative_container.hpp +++ b/include/cereal/types/concepts/pair_associative_container.hpp @@ -31,7 +31,7 @@ #ifndef CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ #define CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ -#include +#include "cereal/cereal.hpp" namespace cereal { diff --git a/include/cereal/types/deque.hpp b/include/cereal/types/deque.hpp index df93e64d4..0491d28d0 100644 --- a/include/cereal/types/deque.hpp +++ b/include/cereal/types/deque.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_DEQUE_HPP_ #define CEREAL_TYPES_DEQUE_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/forward_list.hpp b/include/cereal/types/forward_list.hpp index 72a8b8822..db87e1f5c 100644 --- a/include/cereal/types/forward_list.hpp +++ b/include/cereal/types/forward_list.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_FORWARD_LIST_HPP_ #define CEREAL_TYPES_FORWARD_LIST_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/list.hpp b/include/cereal/types/list.hpp index d071e72f8..6008204ff 100644 --- a/include/cereal/types/list.hpp +++ b/include/cereal/types/list.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_LIST_HPP_ #define CEREAL_TYPES_LIST_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/map.hpp b/include/cereal/types/map.hpp index 3ed99581e..41845e980 100644 --- a/include/cereal/types/map.hpp +++ b/include/cereal/types/map.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_MAP_HPP_ #define CEREAL_TYPES_MAP_HPP_ -#include +#include "cereal/types/concepts/pair_associative_container.hpp" #include #endif // CEREAL_TYPES_MAP_HPP_ diff --git a/include/cereal/types/memory.hpp b/include/cereal/types/memory.hpp index 6b0324085..40c965a6c 100644 --- a/include/cereal/types/memory.hpp +++ b/include/cereal/types/memory.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_SHARED_PTR_HPP_ #define CEREAL_TYPES_SHARED_PTR_HPP_ -#include +#include "cereal/cereal.hpp" #include #include @@ -419,7 +419,7 @@ namespace cereal } // namespace cereal // automatically include polymorphic support -#include +#include "cereal/types/polymorphic.hpp" #undef CEREAL_ALIGNOF #endif // CEREAL_TYPES_SHARED_PTR_HPP_ \ No newline at end of file diff --git a/include/cereal/types/polymorphic.hpp b/include/cereal/types/polymorphic.hpp index a7754ca81..5acc11f8a 100644 --- a/include/cereal/types/polymorphic.hpp +++ b/include/cereal/types/polymorphic.hpp @@ -30,13 +30,13 @@ #ifndef CEREAL_TYPES_POLYMORPHIC_HPP_ #define CEREAL_TYPES_POLYMORPHIC_HPP_ -#include -#include +#include "cereal/cereal.hpp" +#include "cereal/types/memory.hpp" -#include -#include -#include -#include +#include "cereal/details/util.hpp" +#include "cereal/details/helpers.hpp" +#include "cereal/details/traits.hpp" +#include "cereal/details/polymorphic_impl.hpp" #ifdef _MSC_VER #define CEREAL_STATIC_CONSTEXPR static diff --git a/include/cereal/types/queue.hpp b/include/cereal/types/queue.hpp index c0e41a201..52d26a2f0 100644 --- a/include/cereal/types/queue.hpp +++ b/include/cereal/types/queue.hpp @@ -30,13 +30,13 @@ #ifndef CEREAL_TYPES_QUEUE_HPP_ #define CEREAL_TYPES_QUEUE_HPP_ -#include +#include "cereal/details/helpers.hpp" #include // The default container for queue is deque, so let's include that too -#include +#include "cereal/types/deque.hpp" // The default comparator for queue is less -#include +#include "cereal/types/functional.hpp" namespace cereal { diff --git a/include/cereal/types/set.hpp b/include/cereal/types/set.hpp index a5b3bc6ae..149a5b45a 100644 --- a/include/cereal/types/set.hpp +++ b/include/cereal/types/set.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_SET_HPP_ #define CEREAL_TYPES_SET_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/stack.hpp b/include/cereal/types/stack.hpp index d2a666760..b69b66000 100644 --- a/include/cereal/types/stack.hpp +++ b/include/cereal/types/stack.hpp @@ -30,11 +30,11 @@ #ifndef CEREAL_TYPES_STACK_HPP_ #define CEREAL_TYPES_STACK_HPP_ -#include +#include "cereal/cereal.hpp" #include // The default container for stack is deque, so let's include that too -#include +#include "cereal/types/deque.hpp" namespace cereal { diff --git a/include/cereal/types/string.hpp b/include/cereal/types/string.hpp index 55ebe722a..e7488a9c2 100644 --- a/include/cereal/types/string.hpp +++ b/include/cereal/types/string.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_STRING_HPP_ #define CEREAL_TYPES_STRING_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/tuple.hpp b/include/cereal/types/tuple.hpp index 2831728ae..7e56f0dc1 100644 --- a/include/cereal/types/tuple.hpp +++ b/include/cereal/types/tuple.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_TUPLE_HPP_ #define CEREAL_TYPES_TUPLE_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/unordered_map.hpp b/include/cereal/types/unordered_map.hpp index 68ee9c4a8..3b0f80ba4 100644 --- a/include/cereal/types/unordered_map.hpp +++ b/include/cereal/types/unordered_map.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_UNORDERED_MAP_HPP_ #define CEREAL_TYPES_UNORDERED_MAP_HPP_ -#include +#include "cereal/types/concepts/pair_associative_container.hpp" #include #endif // CEREAL_TYPES_UNORDERED_MAP_HPP_ diff --git a/include/cereal/types/unordered_set.hpp b/include/cereal/types/unordered_set.hpp index f3cdebda8..b86d8e5c1 100644 --- a/include/cereal/types/unordered_set.hpp +++ b/include/cereal/types/unordered_set.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_UNORDERED_SET_HPP_ #define CEREAL_TYPES_UNORDERED_SET_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/utility.hpp b/include/cereal/types/utility.hpp index 1dc382dc5..076bea893 100644 --- a/include/cereal/types/utility.hpp +++ b/include/cereal/types/utility.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_UTILITY_HPP_ #define CEREAL_TYPES_UTILITY_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/valarray.hpp b/include/cereal/types/valarray.hpp index eade2fe3b..dcc471d77 100644 --- a/include/cereal/types/valarray.hpp +++ b/include/cereal/types/valarray.hpp @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef CEREAL_TYPES_VALARRAY_HPP_ #define CEREAL_TYPES_VALARRAY_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal diff --git a/include/cereal/types/vector.hpp b/include/cereal/types/vector.hpp index 36a2a4ccf..8302cb900 100644 --- a/include/cereal/types/vector.hpp +++ b/include/cereal/types/vector.hpp @@ -30,7 +30,7 @@ #ifndef CEREAL_TYPES_VECTOR_HPP_ #define CEREAL_TYPES_VECTOR_HPP_ -#include +#include "cereal/cereal.hpp" #include namespace cereal From 3fb59dbe6c06444dad1cfb38c92799dcbe066f17 Mon Sep 17 00:00:00 2001 From: Caspar Kielwein Date: Sun, 2 Oct 2016 15:53:28 +0200 Subject: [PATCH 08/58] Build doxygen documentation with separate CMakeLists. Extracted CMakelists.txt to doc subdirectory. Changed paths in doxyfile.in and CMakeLists accordingly. added doc as subdirectory in main CMakeLists.txt. --- CMakeLists.txt | 19 +------------------ doc/CMakeLists.txt | 18 ++++++++++++++++++ doc/doxygen.in | 10 +++++----- 3 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 doc/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f3f604b4..89203a135 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,21 +55,4 @@ endif(Boost_FOUND) add_subdirectory(sandbox) -find_package(Doxygen) -if(DOXYGEN_FOUND) - - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doc/doxygen.in" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" @ONLY) - add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - COMMENT "Generating API documentation with Doxygen" VERBATIM - ) - - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/updatedoc.in" "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" @ONLY) - add_custom_target(update-doc - COMMAND "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" - DEPENDS doc - COMMENT "Copying documentation to gh-pages branch" VERBATIM - ) - -endif(DOXYGEN_FOUND) +add_subdirectory(doc) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 000000000..ec0316e97 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,18 @@ +find_package(Doxygen) +if(DOXYGEN_FOUND) + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doxygen.in" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" @ONLY) + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.." + COMMENT "Generating API documentation with Doxygen" VERBATIM + ) + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../scripts/updatedoc.in" "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" @ONLY) + add_custom_target(update-doc + COMMAND "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" + DEPENDS doc + COMMENT "Copying documentation to gh-pages branch" VERBATIM + ) + +endif(DOXYGEN_FOUND) \ No newline at end of file diff --git a/doc/doxygen.in b/doc/doxygen.in index 55fc748a8..4edfb74ff 100644 --- a/doc/doxygen.in +++ b/doc/doxygen.in @@ -52,7 +52,7 @@ PROJECT_LOGO = # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = doc +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -595,7 +595,7 @@ FILE_VERSION_FILTER = # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. -LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/doc/DoxygenLayout.xml" +LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/DoxygenLayout.xml" # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The @@ -668,7 +668,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/doc #include doc +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../include @CMAKE_CURRENT_SOURCE_DIR@/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -701,7 +701,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = external +EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/../external # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -911,7 +911,7 @@ HTML_HEADER = # each generated HTML page. If it is left blank doxygen will generate a # standard footer. -HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/doc/footer.html" +HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/footer.html" # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to From a06680868e10b39514d4637e2eee863e3b886e24 Mon Sep 17 00:00:00 2001 From: Caspar Kielwein Date: Sun, 2 Oct 2016 16:09:04 +0200 Subject: [PATCH 09/58] Add cereal.doxytags as tagfile to allow external projects to link to cereal documentation. --- doc/doxygen.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doxygen.in b/doc/doxygen.in index 4edfb74ff..d5b0463c3 100644 --- a/doc/doxygen.in +++ b/doc/doxygen.in @@ -1626,7 +1626,7 @@ TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = cereal.doxytags # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes From e694a6311ad58ddff58d0509cb1ee4d0258dec84 Mon Sep 17 00:00:00 2001 From: Enhex Date: Sat, 8 Oct 2016 22:58:31 +0300 Subject: [PATCH 10/58] Replaced hardcoded rapidsjon namespacing with CEREAL_RAPIDJSON_NAMESPACE --- include/cereal/archives/json.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/cereal/archives/json.hpp b/include/cereal/archives/json.hpp index 3eb95db5f..081e1dbf3 100644 --- a/include/cereal/archives/json.hpp +++ b/include/cereal/archives/json.hpp @@ -96,8 +96,8 @@ namespace cereal { enum class NodeType { StartObject, InObject, StartArray, InArray }; - using WriteStream = rapidjson::OStreamWrapper; - using JSONWriter = rapidjson::PrettyWriter; + using WriteStream = CEREAL_RAPIDJSON_NAMESPACE::OStreamWrapper; + using JSONWriter = CEREAL_RAPIDJSON_NAMESPACE::PrettyWriter; public: /*! @name Common Functionality @@ -242,7 +242,7 @@ namespace cereal //! Saves a double to the current node void saveValue(double d) { itsWriter.Double(d); } //! Saves a string to the current node - void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast( s.size() )); } + void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast( s.size() )); } //! Saves a const char * to the current node void saveValue(char const * s) { itsWriter.String(s); } //! Saves a nullptr to the current node @@ -406,11 +406,11 @@ namespace cereal class JSONInputArchive : public InputArchive, public traits::TextArchive { private: - using ReadStream = rapidjson::IStreamWrapper; - typedef rapidjson::GenericValue> JSONValue; + using ReadStream = CEREAL_RAPIDJSON_NAMESPACE::IStreamWrapper; + typedef CEREAL_RAPIDJSON_NAMESPACE::GenericValue> JSONValue; typedef JSONValue::ConstMemberIterator MemberIterator; typedef JSONValue::ConstValueIterator ValueIterator; - typedef rapidjson::Document::GenericValue GenericValue; + typedef CEREAL_RAPIDJSON_NAMESPACE::Document::GenericValue GenericValue; public: /*! @name Common Functionality @@ -713,7 +713,7 @@ namespace cereal const char * itsNextName; //!< Next name set by NVP ReadStream itsReadStream; //!< Rapidjson write stream std::vector itsIteratorStack; //!< 'Stack' of rapidJSON iterators - rapidjson::Document itsDocument; //!< Rapidjson document + CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document }; // ###################################################################### From c7b33a5a9c289896667b4ac16a5289f7d0c1b6f1 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Sun, 9 Oct 2016 21:34:44 -0700 Subject: [PATCH 11/58] Add polymorphic dtor for all tests in polymorphic see #349 --- unittests/polymorphic.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/unittests/polymorphic.cpp b/unittests/polymorphic.cpp index 15d282a1b..fbdc25602 100644 --- a/unittests/polymorphic.cpp +++ b/unittests/polymorphic.cpp @@ -42,6 +42,7 @@ struct PolyBaseAA : PolyBaseA { PolyBaseAA() {} PolyBaseAA( long ww ) : w(ww) {} + virtual ~PolyBaseAA() {} long w; void foo() {} @@ -67,6 +68,7 @@ struct PolyBaseB : virtual PolyBaseAA { PolyBaseB() {} PolyBaseB( int xx, long ww ) : PolyBaseAA(ww), x(xx) {} + virtual ~PolyBaseB() {} int x; template @@ -87,6 +89,7 @@ struct PolyBaseC : virtual PolyBaseAA { PolyBaseC() {} PolyBaseC( double yy, long ww ) : PolyBaseAA(ww), y(yy) {} + virtual ~PolyBaseC() {} double y; template @@ -108,6 +111,7 @@ 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 @@ -132,6 +136,7 @@ struct PolyBase { PolyBase() {} PolyBase( int xx, float yy ) : x(xx), y(yy) {} + virtual ~PolyBase() {} int x; float y; @@ -154,6 +159,7 @@ 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; @@ -177,12 +183,15 @@ 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; From c51095f9d3390392766672fa3920c0675643c926 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 11 Oct 2016 11:50:28 -0700 Subject: [PATCH 12/58] Reverse from default negation to avoid potential confusion relates #337 --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d50e29dff..c2c269b56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,10 +16,10 @@ endif() if(NOT MSVC) set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}") - option(DONT_INJECT_WERROR "Don't inject '-Werror' into the C++ compiler flags" OFF) - if(NOT DONT_INJECT_WERROR) + option(WITH_WERROR "Compile with '-Werror' C++ compiler flag" ON) + if(WITH_WERROR) set(CMAKE_CXX_FLAGS "-Werror ${CMAKE_CXX_FLAGS}") - endif(NOT DONT_INJECT_WERROR) + endif(WITH_WERROR) if(CMAKE_VERSION VERSION_LESS 3.1) set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") else() From 383cea57ebce5b1243b6364930e485ba8e793e8f Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 11 Oct 2016 14:57:19 -0700 Subject: [PATCH 13/58] Realized that the multimap was to catch multiple paths within a single iteration. Instead of using a multimap, we really just want the shortest path found per iteration. Went back to a map, if a shorter path is found before we commit the changes, stage the shorter one instead. --- include/cereal/details/polymorphic_impl.hpp | 29 +++++++++++++++------ 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index ac823b590..081064e1f 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -233,7 +233,7 @@ namespace cereal // Find all chainable unregistered relations { - using Relations = std::multimap>>; + using Relations = std::map>>; auto findChainableRelations = [&baseMap]() -> Relations { auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo) @@ -268,13 +268,26 @@ namespace cereal std::vector path = otherBaseToBase.second; path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() ); - #ifdef CEREAL_OLDER_GCC - unregisteredRelations.insert( std::make_pair(otherBaseIt.first, - std::pair>{derivedIt.first, std::move(path)}) ); - #else // NOT CEREAL_OLDER_GCC - unregisteredRelations.emplace( otherBaseIt.first, - std::pair>{derivedIt.first, std::move(path)} ); - #endif // NOT CEREAL_OLDER_GCC + // Check to see if we have a previous uncommitted path in unregisteredRelations + // that is shorter. If so, ignore this path + auto hint = unregisteredRelations.find( otherBaseIt.first ); + const bool uncommittedExists = hint != unregisteredRelations.end(); + if( uncommittedExists && (hint->second.second.size() <= newLength) ) + continue; + + auto newPath = std::pair>{derivedIt.first, std::move(path)}; + + // Insert the new path if it doesn't exist, otherwise this will just lookup where to do the + // replacement + #ifdef CEREAL_OLDER_GCC + auto old = unregisteredRelations.insert( hint, std::make_pair(otherBaseIt.first, newPath) ); + #else // NOT CEREAL_OLDER_GCC + auto old = unregisteredRelations.emplace_hint( hint, otherBaseIt.first, newPath ); + #endif // NOT CEREAL_OLDER_GCC + + // If there was an uncommitted path, we need to perform a replacement + if( uncommittedExists ) + old->second = newPath; } } // end otherBaseIt } // end derivedIt From e715149f4dd18890d0abc36f5cd5df3108ac6810 Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 12 Oct 2016 10:35:38 +0300 Subject: [PATCH 14/58] Update static_object.hpp fixed misprint --- include/cereal/details/static_object.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index b40694081..41ffdcc09 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -109,7 +109,7 @@ namespace cereal static LockGuard lock() { #if CEREAL_THREAD_SAFE - std::mutex instanceMutex; + static std::mutex instanceMutex; return LockGuard{instanceMutex}; #else return LockGuard{}; From 500e7a0188c03db64c671c9cd7502b3258cb373a Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 12 Oct 2016 10:45:37 +0300 Subject: [PATCH 15/58] Update static_object.hpp I cannot understand what is going on here with `static T & instance;`, I propose to do not change `create()`. But it would be better if someone explain what is happening here :) --- include/cereal/details/static_object.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index 41ffdcc09..2624c1083 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -73,7 +73,7 @@ namespace cereal static T & create() { static T t; - instantiate(t); + instantiate(instance); return t; } @@ -115,9 +115,12 @@ namespace cereal return LockGuard{}; #endif } - + private: + static T & instance; }; + template T & StaticObject::instance = StaticObject::create(); + } // namespace detail } // namespace cereal From 74e0b1b698472b69ae2df9489984ea1d367058b7 Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 12 Oct 2016 10:47:01 +0300 Subject: [PATCH 16/58] Update static_object.hpp removed empty extra line --- include/cereal/details/static_object.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index 2624c1083..a904d4538 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -120,7 +120,6 @@ namespace cereal }; template T & StaticObject::instance = StaticObject::create(); - } // namespace detail } // namespace cereal From 96deb7e9d30feacd7ddfe8647ffd71e9f55d625e Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 12 Oct 2016 10:47:33 +0300 Subject: [PATCH 17/58] Update static_object.hpp --- include/cereal/details/static_object.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/cereal/details/static_object.hpp b/include/cereal/details/static_object.hpp index a904d4538..b232880c7 100644 --- a/include/cereal/details/static_object.hpp +++ b/include/cereal/details/static_object.hpp @@ -115,6 +115,7 @@ namespace cereal return LockGuard{}; #endif } + private: static T & instance; }; From bf0f9aee1c378292fc338399882f7df7e1f766c5 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Thu, 27 Oct 2016 12:18:35 -0700 Subject: [PATCH 18/58] New implementation for polymorphic chaining -This version has all of the debug messages left in, next commit will remove them -Algorithm description provided in comments -relates #354 --- include/cereal/details/polymorphic_impl.hpp | 205 +++++++++++++++----- 1 file changed, 158 insertions(+), 47 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 081064e1f..7f8ae30f2 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -52,6 +52,14 @@ #include #include #include +#include +#include +#include + +#include "cereal/types/map.hpp" +#include "cereal/types/vector.hpp" +#include "cereal/types/string.hpp" +#include "cereal/archives/json.hpp" // DEBUG //! Binds a polymorhic type to all registered archives /*! This binds a polymorphic type to all compatible registered archives that @@ -74,6 +82,26 @@ namespace cereal { + template inline + std::string save_minimal( Archive const &, std::type_index const & t ) + { + return util::demangle( t.name() ); + } + + template inline + void load_minimal( Archive const &, std::type_index & t, std::string const & s ) + { + } + + namespace detail + { + struct PolymorphicCaster; + } + + template inline + void serialize( Archive &, detail::PolymorphicCaster const * ) + { } + /* Polymorphic casting support */ namespace detail { @@ -115,6 +143,8 @@ namespace cereal //! Maps from base type index to a map from derived type index to caster std::map>> map; + std::multimap reverseMap; + //! Error message used for unregistered polymorphic casts #define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \ throw cereal::Exception("Trying to " #LoadSave " a registered polymorphic type with an unregistered polymorphic cast.\n" \ @@ -171,6 +201,8 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } ); + std::cerr << "------- DOWNCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; + for( auto const * map : mapping ) dptr = map->downcast( dptr ); @@ -185,9 +217,11 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); + std::cerr << "------- UPCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; + void * uptr = dptr; - for( auto const * map : mapping ) - uptr = map->upcast( uptr ); + for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) + uptr = (*mIter)->upcast( uptr ); return uptr; } @@ -198,9 +232,11 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); + std::cerr << "------- SPTR UPCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; + std::shared_ptr uptr = dptr; - for( auto const * map : mapping ) - uptr = map->upcast( uptr ); + for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) + uptr = (*mIter)->upcast( uptr ); return uptr; } @@ -212,117 +248,192 @@ namespace cereal template struct PolymorphicVirtualCaster : PolymorphicCaster { + template + static void print( std::string const & msg, T const & t ) + { + std::cerr << msg << std::endl; + { + cereal::JSONOutputArchive ar(std::cerr); + ar(t); + } + std::cerr << std::endl; + } + //! Inserts an entry in the polymorphic casting map for this pairing /*! Creates an explicit mapping between Base and Derived in both upwards and downwards directions, allowing void pointers to either to be properly cast assuming dynamic type information is available */ PolymorphicVirtualCaster() { + const auto baseKey = std::type_index(typeid(Base)); + const auto derivedKey = std::type_index(typeid(Derived)); + + // First insert the relation Base->Derived const auto lock = StaticObject::lock(); auto & baseMap = StaticObject::getInstance().map; - auto baseKey = std::type_index(typeid(Base)); auto lb = baseMap.lower_bound(baseKey); { auto & derivedMap = baseMap.insert( lb, {baseKey, {}} )->second; - auto derivedKey = std::type_index(typeid(Derived)); auto lbd = derivedMap.lower_bound(derivedKey); auto & derivedVec = derivedMap.insert( lbd, { std::move(derivedKey), {}} )->second; derivedVec.push_back( this ); } + auto str = [](std::type_index t){ return util::demangle(t.name()); }; + + std::cerr << "Register relation " << str(baseKey) << "->" << str(derivedKey) << std::endl; + + // Insert reverse relation Derived->Base + auto & reverseMap = StaticObject::getInstance().reverseMap; + reverseMap.emplace( derivedKey, baseKey ); + + print( "baseMap", baseMap ); + print( "reverseMap", reverseMap ); + // Find all chainable unregistered relations + /* The strategy here is to process only the nodes in the class hierarchy graph that have been + affected by the new insertion. The aglorithm iteratively processes a node an ensures that it + is updated with all new shortest length paths. It then rocesses the parents of the active node, + with the knowledge that all children have already been processed. + + Note that for the following, we'll use the nomenclature of parent and child to not confuse with + the inserted base derived relationship */ { - using Relations = std::map>>; - auto findChainableRelations = [&baseMap]() -> Relations + // Checks whether there is a path from parent->child and returns a pair + // dist is set to MAX if the path does not exist + auto checkRelation = [](std::type_index const & parentInfo, std::type_index const & childInfo) -> + std::pair> { - auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo) + if( PolymorphicCasters::exists( parentInfo, childInfo ) ) { - const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo ); - return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) : - std::vector{} ); - }; - - Relations unregisteredRelations; - for( auto const & baseIt : baseMap ) - for( auto const & derivedIt : baseIt.second ) + auto const & path = PolymorphicCasters::lookup( parentInfo, childInfo, [](){} ); + return {path.size(), path}; + } + else + return {std::numeric_limits::max(), {}}; + }; + + std::stack parentStack; // Holds the parent nodes to be processed + std::set dirtySet; // Marks child nodes that have been changed + std::set processedParents; // Marks parent nodes that have been processed + + // Begin processing the base key and mark derived as dirty + parentStack.push( baseKey ); + dirtySet.insert( derivedKey ); + + while( !parentStack.empty() ) + { + using Relations = std::multimap>>; + Relations unregisteredRelations; // Defer insertions until after main loop to prevent iterator invalidation + + const auto parent = parentStack.top(); + parentStack.pop(); + + std::cerr << "Processing " << str(parent) << std::endl; + print( "parent stack", parentStack ); + print( "dirty set", dirtySet ); + print( "processed set", processedParents ); + + // Update paths to all children marked dirty + for( auto const & childPair : baseMap[parent] ) + { + const auto child = childPair.first; + if( dirtySet.count( child ) && baseMap.count( child ) ) { - for( auto const & otherBaseIt : baseMap ) + auto parentChildPath = checkRelation( parent, child ); + + std::cerr << "Child has childreN? " << baseMap.count(child) << std::endl; + + // Search all paths from the child to its own children (finalChild), + // looking for a shorter parth from parent to finalChild + for( auto const & finalChildPair : baseMap[child] ) { - if( baseIt.first == otherBaseIt.first ) // only interested in chained relations - continue; + const auto finalChild = finalChildPair.first; - // Check if there exists a mapping otherBase -> base -> derived that is shorter than - // any existing otherBase -> derived direct mapping - auto otherBaseItToDerived = checkRelation( otherBaseIt.first, derivedIt.first ); - auto baseToDerived = checkRelation( baseIt.first, derivedIt.first ); - auto otherBaseToBase = checkRelation( otherBaseIt.first, baseIt.first ); + auto parentFinalChildPath = checkRelation( parent, finalChild ); + auto childFinalChildPath = checkRelation( child, finalChild ); - const size_t newLength = otherBaseToBase.second.size() + baseToDerived.second.size(); - const bool isShorterOrFirstPath = !otherBaseItToDerived.first || (newLength < derivedIt.second.size()); + const size_t newLength = 1u + parentChildPath.first; - if( isShorterOrFirstPath && - baseToDerived.first && - otherBaseToBase.first ) + if( newLength < parentFinalChildPath.first ) { - std::vector path = otherBaseToBase.second; - path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() ); + std::vector path = parentChildPath.second; + path.insert( path.end(), childFinalChildPath.second.begin(), childFinalChildPath.second.end() ); // Check to see if we have a previous uncommitted path in unregisteredRelations // that is shorter. If so, ignore this path - auto hint = unregisteredRelations.find( otherBaseIt.first ); + auto hint = unregisteredRelations.find( parent ); const bool uncommittedExists = hint != unregisteredRelations.end(); if( uncommittedExists && (hint->second.second.size() <= newLength) ) continue; - auto newPath = std::pair>{derivedIt.first, std::move(path)}; + auto newPath = std::pair>{finalChild, std::move(path)}; // Insert the new path if it doesn't exist, otherwise this will just lookup where to do the // replacement #ifdef CEREAL_OLDER_GCC - auto old = unregisteredRelations.insert( hint, std::make_pair(otherBaseIt.first, newPath) ); + auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) ); #else // NOT CEREAL_OLDER_GCC - auto old = unregisteredRelations.emplace_hint( hint, otherBaseIt.first, newPath ); + auto old = unregisteredRelations.emplace_hint( hint, parent, newPath ); #endif // NOT CEREAL_OLDER_GCC // If there was an uncommitted path, we need to perform a replacement if( uncommittedExists ) old->second = newPath; + + std::cerr << "New relation " << str(parent) << "->" << str(finalChild) << ", child: " << str(child) << std::endl; } - } // end otherBaseIt - } // end derivedIt - return unregisteredRelations; - }; // end findChainableRelations + } // end loop over child's children + } // end if dirty and child has children + } // end loop over children - Relations unregisteredRelations; - do - { - unregisteredRelations = findChainableRelations(); // Insert chained relations for( auto const & it : unregisteredRelations ) { auto & derivedMap = baseMap.find( it.first )->second; derivedMap[it.second.first] = it.second.second; + reverseMap.emplace( it.second.first, it.first ); + + std::cerr << "Chained relation" << str(it.first) << "->" << str(it.second.first) << std::endl; } - } while ( !unregisteredRelations.empty() ); - } // end chain lookup - } + + // Mark current parent as modified + dirtySet.insert( parent ); + + // Insert all parents of the current parent node that haven't yet been processed + auto parentRange = reverseMap.equal_range( parent ); + for( auto pIter = parentRange.first; pIter != parentRange.second; ++pIter ) + { + const auto pParent = pIter->second; + if( !processedParents.count( pParent ) ) + { + parentStack.push( pParent ); + processedParents.insert( pParent ); + } + } + } // end loop over parent stack + } // end chainable relations + } // end PolymorphicVirtualCaster() //! Performs the proper downcast with the templated types void const * downcast( void const * const ptr ) const override { + std::cerr << "DOWNCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return dynamic_cast( static_cast( ptr ) ); } //! Performs the proper upcast with the templated types void * upcast( void * const ptr ) const override { + std::cerr << "UPCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return dynamic_cast( static_cast( ptr ) ); } //! Performs the proper upcast with the templated types (shared_ptr version) std::shared_ptr upcast( std::shared_ptr const & ptr ) const override { + std::cerr << "SPTR UPCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return std::dynamic_pointer_cast( std::static_pointer_cast( ptr ) ); } }; From 74030ce9e28f9691b6c1a466e486b73e6c6340e2 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Thu, 27 Oct 2016 12:21:48 -0700 Subject: [PATCH 19/58] Removing debug from prev commit for new polymorphic chaining -Also forgot to mention that I think there was a bug with upcasting before where the casting was incorrectly done in the reverse order. -relates #354 --- include/cereal/details/polymorphic_impl.hpp | 63 --------------------- 1 file changed, 63 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 7f8ae30f2..6ad3746d8 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -56,11 +56,6 @@ #include #include -#include "cereal/types/map.hpp" -#include "cereal/types/vector.hpp" -#include "cereal/types/string.hpp" -#include "cereal/archives/json.hpp" // DEBUG - //! Binds a polymorhic type to all registered archives /*! This binds a polymorphic type to all compatible registered archives that have been registered with CEREAL_REGISTER_ARCHIVE. This must be called @@ -82,26 +77,6 @@ namespace cereal { - template inline - std::string save_minimal( Archive const &, std::type_index const & t ) - { - return util::demangle( t.name() ); - } - - template inline - void load_minimal( Archive const &, std::type_index & t, std::string const & s ) - { - } - - namespace detail - { - struct PolymorphicCaster; - } - - template inline - void serialize( Archive &, detail::PolymorphicCaster const * ) - { } - /* Polymorphic casting support */ namespace detail { @@ -201,8 +176,6 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } ); - std::cerr << "------- DOWNCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; - for( auto const * map : mapping ) dptr = map->downcast( dptr ); @@ -217,8 +190,6 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); - std::cerr << "------- UPCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; - void * uptr = dptr; for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) uptr = (*mIter)->upcast( uptr ); @@ -232,8 +203,6 @@ namespace cereal { auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); - std::cerr << "------- SPTR UPCAST " << util::demangle(baseInfo.name()) << "->" << util::demangledName() << std::endl; - std::shared_ptr uptr = dptr; for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) uptr = (*mIter)->upcast( uptr ); @@ -248,17 +217,6 @@ namespace cereal template struct PolymorphicVirtualCaster : PolymorphicCaster { - template - static void print( std::string const & msg, T const & t ) - { - std::cerr << msg << std::endl; - { - cereal::JSONOutputArchive ar(std::cerr); - ar(t); - } - std::cerr << std::endl; - } - //! Inserts an entry in the polymorphic casting map for this pairing /*! Creates an explicit mapping between Base and Derived in both upwards and downwards directions, allowing void pointers to either to be properly cast @@ -280,17 +238,10 @@ namespace cereal derivedVec.push_back( this ); } - auto str = [](std::type_index t){ return util::demangle(t.name()); }; - - std::cerr << "Register relation " << str(baseKey) << "->" << str(derivedKey) << std::endl; - // Insert reverse relation Derived->Base auto & reverseMap = StaticObject::getInstance().reverseMap; reverseMap.emplace( derivedKey, baseKey ); - print( "baseMap", baseMap ); - print( "reverseMap", reverseMap ); - // Find all chainable unregistered relations /* The strategy here is to process only the nodes in the class hierarchy graph that have been affected by the new insertion. The aglorithm iteratively processes a node an ensures that it @@ -330,11 +281,6 @@ namespace cereal const auto parent = parentStack.top(); parentStack.pop(); - std::cerr << "Processing " << str(parent) << std::endl; - print( "parent stack", parentStack ); - print( "dirty set", dirtySet ); - print( "processed set", processedParents ); - // Update paths to all children marked dirty for( auto const & childPair : baseMap[parent] ) { @@ -343,8 +289,6 @@ namespace cereal { auto parentChildPath = checkRelation( parent, child ); - std::cerr << "Child has childreN? " << baseMap.count(child) << std::endl; - // Search all paths from the child to its own children (finalChild), // looking for a shorter parth from parent to finalChild for( auto const & finalChildPair : baseMap[child] ) @@ -381,8 +325,6 @@ namespace cereal // If there was an uncommitted path, we need to perform a replacement if( uncommittedExists ) old->second = newPath; - - std::cerr << "New relation " << str(parent) << "->" << str(finalChild) << ", child: " << str(child) << std::endl; } } // end loop over child's children } // end if dirty and child has children @@ -394,8 +336,6 @@ namespace cereal auto & derivedMap = baseMap.find( it.first )->second; derivedMap[it.second.first] = it.second.second; reverseMap.emplace( it.second.first, it.first ); - - std::cerr << "Chained relation" << str(it.first) << "->" << str(it.second.first) << std::endl; } // Mark current parent as modified @@ -419,21 +359,18 @@ namespace cereal //! Performs the proper downcast with the templated types void const * downcast( void const * const ptr ) const override { - std::cerr << "DOWNCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return dynamic_cast( static_cast( ptr ) ); } //! Performs the proper upcast with the templated types void * upcast( void * const ptr ) const override { - std::cerr << "UPCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return dynamic_cast( static_cast( ptr ) ); } //! Performs the proper upcast with the templated types (shared_ptr version) std::shared_ptr upcast( std::shared_ptr const & ptr ) const override { - std::cerr << "SPTR UPCAST " << util::demangledName() << "->" << util::demangledName() << std::endl; return std::dynamic_pointer_cast( std::static_pointer_cast( ptr ) ); } }; From d27cc338d244b9a589584f2d609d122bf4233014 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Thu, 27 Oct 2016 13:20:23 -0700 Subject: [PATCH 20/58] g++47 support fix #354 --- include/cereal/details/polymorphic_impl.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 6ad3746d8..513db1476 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -240,7 +240,7 @@ namespace cereal // Insert reverse relation Derived->Base auto & reverseMap = StaticObject::getInstance().reverseMap; - reverseMap.emplace( derivedKey, baseKey ); + reverseMap.insert( {derivedKey, baseKey} ); // Find all chainable unregistered relations /* The strategy here is to process only the nodes in the class hierarchy graph that have been @@ -335,7 +335,7 @@ namespace cereal { auto & derivedMap = baseMap.find( it.first )->second; derivedMap[it.second.first] = it.second.second; - reverseMap.emplace( it.second.first, it.first ); + reverseMap.insert( {it.second.first, it.first} ); } // Mark current parent as modified From e597e03f8adb51dee9413926c7d045756a0d26ae Mon Sep 17 00:00:00 2001 From: drivehappy Date: Fri, 28 Oct 2016 10:44:39 -0700 Subject: [PATCH 21/58] Fix bitset loading when bits are already set. --- include/cereal/types/bitset.hpp | 2 ++ unittests/bitset.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/cereal/types/bitset.hpp b/include/cereal/types/bitset.hpp index 349ea1229..3358179b4 100644 --- a/include/cereal/types/bitset.hpp +++ b/include/cereal/types/bitset.hpp @@ -160,6 +160,8 @@ namespace cereal if( chunk & mask ) bits[i] = 1; + else + bits[i] = 0; mask >>= 1; } diff --git a/unittests/bitset.cpp b/unittests/bitset.cpp index d882fdb71..c731126aa 100644 --- a/unittests/bitset.cpp +++ b/unittests/bitset.cpp @@ -44,6 +44,7 @@ void test_bitset() 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; { @@ -53,12 +54,14 @@ void test_bitset() 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()); { @@ -68,12 +71,15 @@ void test_bitset() 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 ); } } From 34bb0d9494601f36c394c09d15bc667263573b78 Mon Sep 17 00:00:00 2001 From: drivehappy Date: Fri, 28 Oct 2016 11:19:15 -0700 Subject: [PATCH 22/58] Clear all bits first before deserializing, this should be faster than individually clearing them. --- include/cereal/types/bitset.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/cereal/types/bitset.hpp b/include/cereal/types/bitset.hpp index 3358179b4..12d3a8276 100644 --- a/include/cereal/types/bitset.hpp +++ b/include/cereal/types/bitset.hpp @@ -148,6 +148,8 @@ namespace cereal std::uint8_t chunk = 0; std::uint8_t mask = 0; + bits.reset(); + // Load one chunk at a time, rotating through the chunk // to set bits in the bitset for( std::size_t i = 0; i < N; ++i ) @@ -160,8 +162,6 @@ namespace cereal if( chunk & mask ) bits[i] = 1; - else - bits[i] = 0; mask >>= 1; } From 671999e4ea613baf7508127d86a7b5dccb414ac3 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 28 Oct 2016 14:28:37 -0700 Subject: [PATCH 23/58] Initial progress on removing boost test and moving to doctest to better support modules relates #123 --- unittests/array.cpp | 77 +- unittests/array.hpp | 95 + unittests/basic_string.cpp | 128 +- unittests/basic_string.hpp | 114 ++ unittests/bitset.cpp | 70 +- unittests/bitset.hpp | 87 + unittests/common.hpp | 53 +- unittests/doctest.h | 3374 ++++++++++++++++++++++++++++++++++++ 8 files changed, 3724 insertions(+), 274 deletions(-) create mode 100644 unittests/array.hpp create mode 100644 unittests/basic_string.hpp create mode 100644 unittests/bitset.hpp create mode 100644 unittests/doctest.h 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..b1bdcdfc0 --- /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(i_string == o_string); + CHECK(i_string2 == o_string2); + CHECK(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(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..24cfe2724 --- /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( o_bit32 == i_bit32 ); + CHECK( o_bit65 == i_bit65 ); + CHECK( o_bit256 == i_bit256 ); + CHECK( o_bit512 == i_bit512 ); + + CHECK( o_bit32_low == i_bit32_low ); + } +} + +#endif // CEREAL_TEST_BITSET_H_ diff --git a/unittests/common.hpp b/unittests/common.hpp index c126e3f06..2bf0bbdab 100644 --- a/unittests/common.hpp +++ b/unittests/common.hpp @@ -56,32 +56,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 +69,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( std::distance(aIter, aEnd) == std::distance(bIter, bEnd) ); + + for( ; aIter != aEnd; ++aIter, ++bIter ) + CHECK( *aIter == *bIter ); +} + +// Random Number Generation =============================================== template inline typename std::enable_if::value, T>::type random_value(std::mt19937 & gen) @@ -133,6 +128,7 @@ std::string random_binary_string(std::mt19937 & gen) return s; } +// Generic struct useful for testing many serialization functions struct StructBase { StructBase() {} @@ -190,7 +186,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 +198,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 +220,5 @@ struct StructHash { return h1 ^ ( h2 << 1 ); } }; - + #endif // CEREAL_TEST_COMMON_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 From 0a262ece48a8f38e2d3d29d7f6d2943ddeaf4c28 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 1 Nov 2016 11:36:22 -0700 Subject: [PATCH 24/58] More tests split, switch to CHECk_EQ over CHECK see #139 --- unittests/boost_variant.cpp | 51 +++--------------- unittests/boost_variant.hpp | 70 ++++++++++++++++++++++++ unittests/chrono.cpp | 87 +++--------------------------- unittests/chrono.hpp | 105 ++++++++++++++++++++++++++++++++++++ unittests/common.hpp | 1 - unittests/complex.cpp | 60 +++------------------ unittests/complex.hpp | 77 ++++++++++++++++++++++++++ 7 files changed, 272 insertions(+), 179 deletions(-) create mode 100644 unittests/boost_variant.hpp create mode 100644 unittests/chrono.hpp create mode 100644 unittests/complex.hpp 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..32337eb71 100644 --- a/unittests/chrono.cpp +++ b/unittests/chrono.cpp @@ -24,100 +24,25 @@ (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; - - 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(); } - - 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 2bf0bbdab..c417f19e0 100644 --- a/unittests/common.hpp +++ b/unittests/common.hpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff --git a/unittests/complex.cpp b/unittests/complex.cpp index 786e0da10..4a418532c 100644 --- a/unittests/complex.cpp +++ b/unittests/complex.cpp @@ -24,73 +24,25 @@ (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; - - 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(); } - - 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_ From 928cd3633545f03d2f0c229a93dcd3813adde3fd Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 1 Nov 2016 11:41:28 -0700 Subject: [PATCH 25/58] more conversions to CHECK_EQ see #139 --- unittests/basic_string.hpp | 8 ++++---- unittests/bitset.hpp | 10 +++++----- unittests/common.hpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/unittests/basic_string.hpp b/unittests/basic_string.hpp index b1bdcdfc0..5ee37aac1 100644 --- a/unittests/basic_string.hpp +++ b/unittests/basic_string.hpp @@ -61,9 +61,9 @@ void test_string_basic() iar(i_string3); } - CHECK(i_string == o_string); - CHECK(i_string2 == o_string2); - CHECK(i_string3 == o_string3); + CHECK_EQ(i_string, o_string); + CHECK_EQ(i_string2, o_string2); + CHECK_EQ(i_string3, o_string3); } } @@ -104,7 +104,7 @@ void test_string_all() iar(i_u32string); } - CHECK(i_string == o_string); + CHECK_EQ(i_string, o_string); check_collection( i_wstring, o_wstring ); check_collection( i_u16string, o_u16string ); check_collection( i_u32string, o_u32string ); diff --git a/unittests/bitset.hpp b/unittests/bitset.hpp index 24cfe2724..09f597cf3 100644 --- a/unittests/bitset.hpp +++ b/unittests/bitset.hpp @@ -75,12 +75,12 @@ void test_bitset() iar(i_bit32_low); } - CHECK( o_bit32 == i_bit32 ); - CHECK( o_bit65 == i_bit65 ); - CHECK( o_bit256 == i_bit256 ); - CHECK( o_bit512 == i_bit512 ); + 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( o_bit32_low == i_bit32_low ); + CHECK_EQ( o_bit32_low, i_bit32_low ); } } diff --git a/unittests/common.hpp b/unittests/common.hpp index c417f19e0..5376d0a43 100644 --- a/unittests/common.hpp +++ b/unittests/common.hpp @@ -77,10 +77,10 @@ void check_collection( T const & a, T const & b ) auto bIter = std::begin(b); auto bEnd = std::end(b); - CHECK( std::distance(aIter, aEnd) == std::distance(bIter, bEnd) ); + CHECK_EQ( std::distance(aIter, aEnd), std::distance(bIter, bEnd) ); for( ; aIter != aEnd; ++aIter, ++bIter ) - CHECK( *aIter == *bIter ); + CHECK_EQ( *aIter, *bIter ); } // Random Number Generation =============================================== From 15c73394a974007f00760e65eed7c83ca0b2fb36 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 1 Nov 2016 11:59:02 -0700 Subject: [PATCH 26/58] more conversions #139 --- unittests/chrono.cpp | 4 + unittests/complex.cpp | 4 + unittests/deque.cpp | 84 ++---------- unittests/forward_list.cpp | 78 ++--------- unittests/list.cpp | 77 ++--------- unittests/load_construct.cpp | 242 ++--------------------------------- 6 files changed, 42 insertions(+), 447 deletions(-) diff --git a/unittests/chrono.cpp b/unittests/chrono.cpp index 32337eb71..b175decdd 100644 --- a/unittests/chrono.cpp +++ b/unittests/chrono.cpp @@ -27,6 +27,8 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "chrono.hpp" +TEST_SUITE("chrono"); + TEST_CASE("binary_chrono") { test_chrono(); @@ -46,3 +48,5 @@ TEST_CASE("json_chrono") { test_chrono(); } + +TEST_SUITE_END(); diff --git a/unittests/complex.cpp b/unittests/complex.cpp index 4a418532c..e7b9ff714 100644 --- a/unittests/complex.cpp +++ b/unittests/complex.cpp @@ -27,6 +27,8 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "complex.hpp" +TEST_SUITE("complex") + TEST_CASE("binary_complex") { test_complex(); @@ -46,3 +48,5 @@ TEST_CASE("json_complex") { test_complex(); } + +TEST_SUITE_END(); 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/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/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/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(); From 38e15480c0b82db4d166b8c41189199dfff411da Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Tue, 1 Nov 2016 11:59:40 -0700 Subject: [PATCH 27/58] headers #139 --- unittests/deque.hpp | 101 ++++++++++++++ unittests/forward_list.hpp | 95 +++++++++++++ unittests/list.hpp | 95 +++++++++++++ unittests/load_construct.hpp | 260 +++++++++++++++++++++++++++++++++++ 4 files changed, 551 insertions(+) create mode 100644 unittests/deque.hpp create mode 100644 unittests/forward_list.hpp create mode 100644 unittests/list.hpp create mode 100644 unittests/load_construct.hpp 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/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.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.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_ From cd46374df8c725907ce117268238faf181845af0 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 2 Nov 2016 12:20:22 -0700 Subject: [PATCH 28/58] more converted for #139 --- unittests/map.cpp | 160 +++------------------------------- unittests/map.hpp | 169 ++++++++++++++++++++++++++++++++++++ unittests/memory.cpp | 108 +++-------------------- unittests/memory.hpp | 116 +++++++++++++++++++++++++ unittests/memory_cycles.cpp | 125 ++------------------------ unittests/memory_cycles.hpp | 142 ++++++++++++++++++++++++++++++ unittests/multimap.cpp | 111 ++--------------------- unittests/multimap.hpp | 129 +++++++++++++++++++++++++++ 8 files changed, 598 insertions(+), 462 deletions(-) create mode 100644 unittests/map.hpp create mode 100644 unittests/memory.hpp create mode 100644 unittests/memory_cycles.hpp create mode 100644 unittests/multimap.hpp 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_ From a6e59d7e060d5a2f787d16b6e48901d5ca2b3b41 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 2 Nov 2016 13:38:33 -0700 Subject: [PATCH 29/58] more for #139 --- unittests/multiset.cpp | 117 +-------- unittests/multiset.hpp | 134 ++++++++++ unittests/pair.cpp | 74 +----- unittests/pair.hpp | 92 +++++++ unittests/pod.cpp | 130 +--------- unittests/pod.hpp | 147 +++++++++++ unittests/polymorphic.cpp | 348 +------------------------ unittests/polymorphic.hpp | 359 ++++++++++++++++++++++++++ unittests/portable_binary_archive.cpp | 143 +--------- unittests/portable_binary_archive.hpp | 156 +++++++++++ 10 files changed, 936 insertions(+), 764 deletions(-) create mode 100644 unittests/multiset.hpp create mode 100644 unittests/pair.hpp create mode 100644 unittests/pod.hpp create mode 100644 unittests/polymorphic.hpp create mode 100644 unittests/portable_binary_archive.hpp 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 4fe5ac81a..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, (float)1e-5); - 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..8dd79e77e --- /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-5)); + CHECK_EQ(i_double , doctest::Approx(o_double).epsilon(1e-5)); + + CHECK_EQ(i_long_double, doctest::Approx(o_long_double).epsilon(1e-5)); + 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 fbdc25602..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(*((PolyDerived*)i_shared.get()), *((PolyDerived*)o_shared.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)i_locked.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_locked.get()), *((PolyDerived*)o_locked.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_unique.get()), *((PolyDerived*)o_unique.get())); - - BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA.get()), *((PolyDerivedLA*)o_sharedLA.get())); - BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA2.get()), *((PolyDerivedLA*)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..18f7ff6ec --- /dev/null +++ b/unittests/polymorphic.hpp @@ -0,0 +1,359 @@ +/* + 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 +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; + } +}; + +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()); + + 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 + + CHECK_EQ(i_shared.get(), i_locked.get()); + CHECK_EQ(*((PolyDerived*)i_shared.get()), *((PolyDerived*)o_shared.get())); + CHECK_EQ(*((PolyDerived*)i_shared.get()), *((PolyDerived*)i_locked.get())); + CHECK_EQ(*((PolyDerived*)i_locked.get()), *((PolyDerived*)o_locked.get())); + CHECK_EQ(*((PolyDerived*)i_unique.get()), *((PolyDerived*)o_unique.get())); + + CHECK_EQ(*((PolyDerivedLA*)i_sharedLA.get()), *((PolyDerivedLA*)o_sharedLA.get())); + CHECK_EQ(*((PolyDerivedLA*)i_sharedLA2.get()), *((PolyDerivedLA*)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 479785abd..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, (float)1e-5); \ - 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..72cc2f038 --- /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-5)); \ + 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_ From b5e500d3b2d3734975e5533c17b2cfd6591d22b6 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 2 Nov 2016 16:32:35 -0700 Subject: [PATCH 30/58] more #139 --- unittests/priority_queue.cpp | 89 +++-------------------------- unittests/priority_queue.hpp | 107 +++++++++++++++++++++++++++++++++++ unittests/queue.cpp | 89 +++-------------------------- unittests/queue.hpp | 107 +++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+), 162 deletions(-) create mode 100644 unittests/priority_queue.hpp create mode 100644 unittests/queue.hpp 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_ From 07818f4527d23f5eb40f7057b6264558925aabf3 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 4 Nov 2016 12:00:16 -0700 Subject: [PATCH 31/58] more #139 --- unittests/set.cpp | 77 ++--------- unittests/set.hpp | 95 +++++++++++++ unittests/stack.cpp | 89 ++---------- unittests/stack.hpp | 107 ++++++++++++++ unittests/structs.cpp | 51 ++----- unittests/structs.hpp | 68 +++++++++ unittests/structs_minimal.cpp | 237 ++----------------------------- unittests/structs_minimal.hpp | 254 ++++++++++++++++++++++++++++++++++ 8 files changed, 558 insertions(+), 420 deletions(-) create mode 100644 unittests/set.hpp create mode 100644 unittests/stack.hpp create mode 100644 unittests/structs.hpp create mode 100644 unittests/structs_minimal.hpp 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..745fdd66b --- /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_STACK_H_ From 13ae5609df0e2c97e06885f67e1ca8eb7a25bae4 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 4 Nov 2016 12:10:24 -0700 Subject: [PATCH 32/58] more #139 --- unittests/structs_specialized.cpp | 443 +--------------------------- unittests/structs_specialized.hpp | 461 ++++++++++++++++++++++++++++++ unittests/tuple.cpp | 83 +----- unittests/tuple.hpp | 101 +++++++ unittests/unordered_loads.cpp | 127 +------- unittests/unordered_loads.hpp | 149 ++++++++++ 6 files changed, 733 insertions(+), 631 deletions(-) create mode 100644 unittests/structs_specialized.hpp create mode 100644 unittests/tuple.hpp create mode 100644 unittests/unordered_loads.hpp diff --git a/unittests/structs_specialized.cpp b/unittests/structs_specialized.cpp index ff92d3d7f..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(((SpecializedMSplitPolymorphic*)i_shared_ispl.get())->x, ((SpecializedMSplitPolymorphic*)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..26ea09607 --- /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(((SpecializedMSplitPolymorphic*)i_shared_ispl.get())->x, doctest::Approx(((SpecializedMSplitPolymorphic*)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_ From 978b3b56b4d615b81cdd51371ead884ffb7e14c5 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 4 Nov 2016 12:11:51 -0700 Subject: [PATCH 33/58] typo fix in comment #139 --- unittests/structs_minimal.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/structs_minimal.hpp b/unittests/structs_minimal.hpp index 745fdd66b..57ccd4999 100644 --- a/unittests/structs_minimal.hpp +++ b/unittests/structs_minimal.hpp @@ -251,4 +251,4 @@ void test_structs_minimal() } } -#endif // CEREAL_TEST_STACK_H_ +#endif // CEREAL_TEST_STRUCTS_MINIMAL_H_ From 66528b68bee4921ca73f5cc6c7aef5097e5f033e Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 4 Nov 2016 15:51:57 -0700 Subject: [PATCH 34/58] last? conversions for #139 --- unittests/polymorphic.hpp | 7 +- unittests/unordered_map.cpp | 106 ++------------- unittests/unordered_map.hpp | 124 ++++++++++++++++++ unittests/unordered_multimap.cpp | 138 ++------------------ unittests/unordered_multimap.hpp | 155 ++++++++++++++++++++++ unittests/unordered_multiset.cpp | 116 ++--------------- unittests/unordered_multiset.hpp | 134 +++++++++++++++++++ unittests/unordered_set.cpp | 97 ++------------ unittests/unordered_set.hpp | 114 ++++++++++++++++ unittests/user_data_adapters.cpp | 101 ++------------ unittests/user_data_adapters.hpp | 120 +++++++++++++++++ unittests/valarray.cpp | 85 ++---------- unittests/valarray.hpp | 101 ++++++++++++++ unittests/vector.cpp | 93 ++----------- unittests/vector.hpp | 110 ++++++++++++++++ unittests/versioning.cpp | 202 ++-------------------------- unittests/versioning.hpp | 217 +++++++++++++++++++++++++++++++ 17 files changed, 1151 insertions(+), 869 deletions(-) create mode 100644 unittests/unordered_map.hpp create mode 100644 unittests/unordered_multimap.hpp create mode 100644 unittests/unordered_multiset.hpp create mode 100644 unittests/unordered_set.hpp create mode 100644 unittests/user_data_adapters.hpp create mode 100644 unittests/valarray.hpp create mode 100644 unittests/vector.hpp create mode 100644 unittests/versioning.hpp diff --git a/unittests/polymorphic.hpp b/unittests/polymorphic.hpp index 18f7ff6ec..788770b70 100644 --- a/unittests/polymorphic.hpp +++ b/unittests/polymorphic.hpp @@ -30,7 +30,6 @@ #if CEREAL_THREAD_SAFE #include -static std::mutex boostTestMutex; #endif struct PolyBaseA @@ -258,6 +257,10 @@ 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 ); }; @@ -319,7 +322,7 @@ void test_polymorphic() auto o_lockedA = o_weakA.lock(); #if CEREAL_THREAD_SAFE - std::lock_guard lock( boostTestMutex ); + std::lock_guard lock( testMutex ); #endif CHECK_EQ(i_shared.get(), i_locked.get()); 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_ From 1d67d440240073336c2f02ba80a9e5d2be13add2 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 4 Nov 2016 16:07:00 -0700 Subject: [PATCH 35/58] Removed boost_test as a requirement -Now build 32 bit unit tests if portability testing is enabled -No more boost+clang issues over std::string abi see #139, #123 --- CMakeLists.txt | 10 ++++++---- unittests/CMakeLists.txt | 25 +++++++++---------------- unittests/complex.cpp | 2 +- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c2c269b56..b77a3f82e 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/complex.cpp b/unittests/complex.cpp index e7b9ff714..168d1038c 100644 --- a/unittests/complex.cpp +++ b/unittests/complex.cpp @@ -27,7 +27,7 @@ #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include "complex.hpp" -TEST_SUITE("complex") +TEST_SUITE("complex"); TEST_CASE("binary_complex") { From 72d79364c9b18676bc8776594fa0f8e582d0dc08 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Fri, 11 Nov 2016 13:45:27 -0800 Subject: [PATCH 36/58] catch empty json, relates #359 --- include/cereal/archives/json.hpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/include/cereal/archives/json.hpp b/include/cereal/archives/json.hpp index fd2e8e07a..9d57434ab 100644 --- a/include/cereal/archives/json.hpp +++ b/include/cereal/archives/json.hpp @@ -471,11 +471,17 @@ namespace cereal Iterator(MemberIterator begin, MemberIterator end) : itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member) - { } + { + if( std::distance( begin, end ) == 0 ) + itsType = Null_; + } Iterator(ValueIterator begin, ValueIterator end) : itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value) - { } + { + if( std::distance( begin, end ) == 0 ) + itsType = Null_; + } //! Advance to the next node Iterator & operator++() @@ -491,7 +497,7 @@ namespace cereal { case Value : return itsValueItBegin[itsIndex]; case Member: return itsMemberItBegin[itsIndex].value; - default: throw cereal::Exception("Invalid Iterator Type!"); + default: throw cereal::Exception("JSONInputArchive internal error: null or empty iterator to object or array!"); } } @@ -528,7 +534,7 @@ namespace cereal MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object) ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array) size_t itsIndex; //!< The current index of this iterator - enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing + enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing }; //! Searches for the expectedName node if it doesn't match the actualName @@ -713,7 +719,7 @@ namespace cereal const char * itsNextName; //!< Next name set by NVP ReadStream itsReadStream; //!< Rapidjson write stream std::vector itsIteratorStack; //!< 'Stack' of rapidJSON iterators - CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document + CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document }; // ###################################################################### From 9376ca605518a287a712344bd80a3c2cfbfdf318 Mon Sep 17 00:00:00 2001 From: Kasper Laudrup Date: Wed, 23 Nov 2016 01:34:53 +0100 Subject: [PATCH 37/58] Don't use C style casts Change C style casts to C++ static casts. This makes the code compile with the -Wold-style-cast warning enabled --- include/cereal/details/polymorphic_impl.hpp | 2 +- include/cereal/external/base64.hpp | 12 ++++++------ sandbox/sandbox.cpp | 4 ++-- sandbox/sandbox_json.cpp | 4 ++-- unittests/pod.cpp | 2 +- unittests/polymorphic.cpp | 12 ++++++------ unittests/portable_binary_archive.cpp | 2 +- unittests/structs_specialized.cpp | 2 +- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index e15075882..bc53792b2 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -645,7 +645,7 @@ namespace cereal //! Binding for non abstract types void bind(std::false_type) const { - instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{}); + instantiate_polymorphic_binding(static_cast(0), 0, Tag{}, adl_tag{}); } //! Binding for abstract types diff --git a/include/cereal/external/base64.hpp b/include/cereal/external/base64.hpp index 32e17cf8d..52f4be362 100644 --- a/include/cereal/external/base64.hpp +++ b/include/cereal/external/base64.hpp @@ -50,10 +50,10 @@ namespace cereal while (in_len--) { char_array_3[i++] = *(bytes_to_encode++); if (i == 3) { - char_array_4[0] = (unsigned char) ((char_array_3[0] & 0xfc) >> 2); - char_array_4[1] = (unsigned char) ( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) ); - char_array_4[2] = (unsigned char) ( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) ); - char_array_4[3] = (unsigned char) ( char_array_3[2] & 0x3f ); + char_array_4[0] = static_cast((char_array_3[0] & 0xfc) >> 2); + char_array_4[1] = static_cast( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) ); + char_array_4[2] = static_cast( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) ); + char_array_4[3] = static_cast( char_array_3[2] & 0x3f ); for(i = 0; (i <4) ; i++) ret += chars[char_array_4[i]]; @@ -95,7 +95,7 @@ namespace cereal char_array_4[i++] = encoded_string[in_]; in_++; if (i ==4) { for (i = 0; i <4; i++) - char_array_4[i] = (unsigned char) chars.find( char_array_4[i] ); + char_array_4[i] = static_cast(chars.find( char_array_4[i] )); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); @@ -112,7 +112,7 @@ namespace cereal char_array_4[j] = 0; for (j = 0; j <4; j++) - char_array_4[j] = (unsigned char) chars.find( char_array_4[j] ); + char_array_4[j] = static_cast(chars.find( char_array_4[j] )); char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); diff --git a/sandbox/sandbox.cpp b/sandbox/sandbox.cpp index b1ca28420..809303a65 100644 --- a/sandbox/sandbox.cpp +++ b/sandbox/sandbox.cpp @@ -651,9 +651,9 @@ int main() iar( d1 ); assert( d1->x == 4 && d1->y == 3 ); iar( d2 ); - assert( ((Derived*)d2.get())->x == 5 && ((Derived*)d2.get())->y == 4 ); + assert( static_cast(d2.get())->x == 5 && static_cast(d2.get())->y == 4 ); iar( d3 ); - assert( ((Derived*)d3.get())->x == 6 && ((Derived*)d3.get())->y == 5 ); + assert( static_cast(d3.get())->x == 6 && static_cast(d3.get())->y == 5 ); } { diff --git a/sandbox/sandbox_json.cpp b/sandbox/sandbox_json.cpp index 83abb8d2f..6171a15fd 100644 --- a/sandbox/sandbox_json.cpp +++ b/sandbox/sandbox_json.cpp @@ -320,13 +320,13 @@ enum Bla template void save( Archive & ar, Bla const & b ) { - ar( (const int &)b ); + ar( static_cast(b) ); } template void load( Archive & ar, Bla & b ) { - ar( (int&)b ); + ar( static_cast(b) ); } CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Bla, cereal::specialization::non_member_load_save ) diff --git a/unittests/pod.cpp b/unittests/pod.cpp index 4fe5ac81a..b55054a53 100644 --- a/unittests/pod.cpp +++ b/unittests/pod.cpp @@ -132,7 +132,7 @@ void test_pod() 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, (float)1e-5); + BOOST_CHECK_CLOSE(i_float , o_float, static_cast(1e-5)); BOOST_CHECK_CLOSE(i_double , o_double, 1e-5); BOOST_CHECK_CLOSE(i_long_double, o_long_double, 1e-5); diff --git a/unittests/polymorphic.cpp b/unittests/polymorphic.cpp index 15d282a1b..b17c02b75 100644 --- a/unittests/polymorphic.cpp +++ b/unittests/polymorphic.cpp @@ -313,13 +313,13 @@ void test_polymorphic() #endif BOOST_CHECK_EQUAL(i_shared.get(), i_locked.get()); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)o_shared.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_shared.get()), *((PolyDerived*)i_locked.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_locked.get()), *((PolyDerived*)o_locked.get())); - BOOST_CHECK_EQUAL(*((PolyDerived*)i_unique.get()), *((PolyDerived*)o_unique.get())); + BOOST_CHECK_EQUAL(*static_cast(i_shared.get()), *static_cast(o_shared.get())); + BOOST_CHECK_EQUAL(*static_cast(i_shared.get()), *static_cast(i_locked.get())); + BOOST_CHECK_EQUAL(*static_cast(i_locked.get()), *static_cast(o_locked.get())); + BOOST_CHECK_EQUAL(*static_cast(i_unique.get()), *static_cast(o_unique.get())); - BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA.get()), *((PolyDerivedLA*)o_sharedLA.get())); - BOOST_CHECK_EQUAL(*((PolyDerivedLA*)i_sharedLA2.get()), *((PolyDerivedLA*)o_sharedLA.get())); + BOOST_CHECK_EQUAL(*static_cast(i_sharedLA.get()), *static_cast(o_sharedLA.get())); + BOOST_CHECK_EQUAL(*static_cast(i_sharedLA2.get()), *static_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())); diff --git a/unittests/portable_binary_archive.cpp b/unittests/portable_binary_archive.cpp index 479785abd..8a54d9d4b 100644 --- a/unittests/portable_binary_archive.cpp +++ b/unittests/portable_binary_archive.cpp @@ -72,7 +72,7 @@ inline void swapBytes( T & t ) 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, (float)1e-5); \ + if( !std::isnan(i_float) && !std::isnan(o_float) ) BOOST_CHECK_CLOSE(i_float , o_float, static_cast(1e-5)); \ 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 diff --git a/unittests/structs_specialized.cpp b/unittests/structs_specialized.cpp index ff92d3d7f..e4f271f85 100644 --- a/unittests/structs_specialized.cpp +++ b/unittests/structs_specialized.cpp @@ -441,7 +441,7 @@ void test_structs_specialized() BOOST_CHECK(i_ispl.x == o_ispl.x); BOOST_CHECK(i_isplv.x == o_isplv.x); - BOOST_CHECK_EQUAL(((SpecializedMSplitPolymorphic*)i_shared_ispl.get())->x, ((SpecializedMSplitPolymorphic*)o_shared_ispl.get())->x); + BOOST_CHECK_EQUAL(static_cast(i_shared_ispl.get())->x, static_cast(o_shared_ispl.get())->x); BOOST_CHECK(i_isplm.x == o_isplm.x); BOOST_CHECK(i_isplvm.x == o_isplvm.x); From 2e96b9915e31fc2b90596e9df597e8fa0f930dee Mon Sep 17 00:00:00 2001 From: David Hirvonen Date: Fri, 25 Nov 2016 16:02:00 -0500 Subject: [PATCH 38/58] Add is_loading and is_saving values to cereal::{Input,Output}Archive This provides compatibility for asymmetric serialize routines when transitioning from boost serialization and associated archive types. See: https://github.com/USCiLab/cereal/issues/360 Example: ``` template void serialize(Archive &ar, const std::uint32_t version) { std::int16_t tmp = foo; if(Archive::is_loading::value) { ar & tmp; foo = tmp; // For illustration only } else { tmp = foo; // For illustration only ar & tmp; } ar & foo; } ``` --- include/cereal/cereal.hpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp index 4b9a9c11e..188acb8c6 100644 --- a/include/cereal/cereal.hpp +++ b/include/cereal/cereal.hpp @@ -255,6 +255,20 @@ namespace cereal a large project from Boost to cereal. The preferred interface for cereal is using operator(). */ //! @{ + //! Indicates this archive is not intended for loading + /*! This ensures compatibility with boost archive types. If you are transitioning + from boost, you can check this value within a member or external serialize function + (i.e., Archive::is_loading::value) to disable behavior specific to loading, until + you can transition to split save/load or save_minimal/load_minimal functions */ + using is_loading = std::false_type; + + //! Indicates this archive is intended for saving + /*! This ensures compatibility with boost archive types. If you are transitioning + from boost, you can check this value within a member or external serialize function + (i.e., Archive::is_saving::value) to enable behavior specific to loading, until + you can transition to split save/load or save_minimal/load_minimal functions */ + using is_saving = std::true_type; + //! Serializes passed in data /*! This is a boost compatability layer and is not the preferred way of using cereal. If you are transitioning from boost, use this until you can @@ -611,6 +625,20 @@ namespace cereal a large project from Boost to cereal. The preferred interface for cereal is using operator(). */ //! @{ + //! Indicates this archive is intended for loading + /*! This ensures compatibility with boost archive types. If you are transitioning + from boost, you can check this value within a member or external serialize function + (i.e., Archive::is_loading::value) to enable behavior specific to loading, until + you can transition to split save/load or save_minimal/load_minimal functions */ +. using is_loading = std::true_type; + + //! Indicates this archive is not intended for saving + /*! This ensures compatibility with boost archive types. If you are transitioning + from boost, you can check this value within a member or external serialize function + (i.e., Archive::is_saving::value) to disable behavior specific to loading, until + you can transition to split save/load or save_minimal/load_minimal functions */ + using is_saving = std::false_type; + //! Serializes passed in data /*! This is a boost compatability layer and is not the preferred way of using cereal. If you are transitioning from boost, use this until you can From 6e717666f36de74977cc1524a59222af75c70a19 Mon Sep 17 00:00:00 2001 From: David Hirvonen Date: Sat, 26 Nov 2016 12:31:56 -0500 Subject: [PATCH 39/58] Remove spurious character --- include/cereal/cereal.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cereal/cereal.hpp b/include/cereal/cereal.hpp index 188acb8c6..a77701037 100644 --- a/include/cereal/cereal.hpp +++ b/include/cereal/cereal.hpp @@ -630,7 +630,7 @@ namespace cereal from boost, you can check this value within a member or external serialize function (i.e., Archive::is_loading::value) to enable behavior specific to loading, until you can transition to split save/load or save_minimal/load_minimal functions */ -. using is_loading = std::true_type; + using is_loading = std::true_type; //! Indicates this archive is not intended for saving /*! This ensures compatibility with boost archive types. If you are transitioning From 608623474001486c136aa89e37e7d64db267f35d Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 27 Nov 2016 13:57:26 +0530 Subject: [PATCH 40/58] Travis configuration updates - Switch to trusty container-based infrastructure for linux systems - Add a job to test with clang compiler (skips portability test) - Add a job to test on macOS with Xcode8 --- .travis.yml | 63 ++++++++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/.travis.yml b/.travis.yml index aa58c5dfc..3daaef67f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,49 +1,38 @@ language: cpp +dist: trusty +sudo: false +group: beta + +addons: + apt: + sources: + - 'ubuntu-toolchain-r-test' + - 'boost-latest' + packages: + - 'g++-multilib' + - 'libboost-serialization-dev' + - 'libboost-test-dev' compiler: - # TODO: Clang is currently giving issues - #- clang - gcc -before_install: - # Always install g++4.8.1 - - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - - # Install recent version of Boost - - sudo add-apt-repository -y ppa:boost-latest/ppa +matrix: + include: + - os: linux + compiler: clang + env: CMAKE_OPTIONS="-DSKIP_PORTABILITY_TEST=ON" - # clang 3.3 - - if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi + # TODO: Add an entry for valgrind + # after_script: make valgrind - - sudo apt-get update -qq - -install: - - sudo apt-get install cmake - - sudo apt-get install libboost1.54-all-dev - - # Always install valgrind - - sudo apt-get install valgrind - - # Always install g++4.8.1 - - sudo apt-get install -qq g++-4.8 - - sudo apt-get install -qq g++-4.8-multilib - - if [ "$CXX" = "g++" ]; then export CMAKE_CXX_COMPILER="g++-4.8"; fi - - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8"; fi - - # clang 3.3 - - if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.3; fi - - if [ "$CXX" == "clang++" ]; then export CMAKE_CXX_COMPILER="clang++-3.3"; fi - - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.3"; fi + - os: osx + osx_image: xcode8 + compiler: clang script: - - mkdir build - - cd build - - cmake .. - - make - -after_script: - - ctest . - # - make valgrind + - mkdir build && cd build + - cmake ${CMAKE_OPTIONS} .. && make -j4 + - ctest . --output-on-failure branches: only: From ad927466b5bd56cf356b23a2fecdd516d6858db1 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 28 Nov 2016 10:41:02 -0800 Subject: [PATCH 41/58] comment out obsolete doxygen --- doc/doxygen.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doxygen.in b/doc/doxygen.in index d5b0463c3..ddf1398b9 100644 --- a/doc/doxygen.in +++ b/doc/doxygen.in @@ -1476,13 +1476,13 @@ XML_OUTPUT = xml # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +# XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +# XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting From e63f08f4d76065d2175d9052e614543503ee351d Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 28 Nov 2016 11:47:24 -0800 Subject: [PATCH 42/58] minor adjustments to casts, see comments on #363 --- include/cereal/details/polymorphic_impl.hpp | 2 +- include/cereal/external/base64.hpp | 2 -- sandbox/sandbox.cpp | 4 ++-- unittests/pod.cpp | 2 +- unittests/polymorphic.cpp | 12 ++++++------ unittests/portable_binary_archive.cpp | 2 +- unittests/structs_specialized.cpp | 2 +- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index bc53792b2..e5b762e87 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -645,7 +645,7 @@ namespace cereal //! Binding for non abstract types void bind(std::false_type) const { - instantiate_polymorphic_binding(static_cast(0), 0, Tag{}, adl_tag{}); + instantiate_polymorphic_binding(static_cast(nullptr), 0, Tag{}, adl_tag{}); } //! Binding for abstract types diff --git a/include/cereal/external/base64.hpp b/include/cereal/external/base64.hpp index 52f4be362..7eee0037b 100644 --- a/include/cereal/external/base64.hpp +++ b/include/cereal/external/base64.hpp @@ -76,11 +76,9 @@ namespace cereal while((i++ < 3)) ret += '='; - } return ret; - } inline std::string decode(std::string const& encoded_string) { diff --git a/sandbox/sandbox.cpp b/sandbox/sandbox.cpp index 809303a65..af28b22c6 100644 --- a/sandbox/sandbox.cpp +++ b/sandbox/sandbox.cpp @@ -651,9 +651,9 @@ int main() iar( d1 ); assert( d1->x == 4 && d1->y == 3 ); iar( d2 ); - assert( static_cast(d2.get())->x == 5 && static_cast(d2.get())->y == 4 ); + assert( dynamic_cast(d2.get())->x == 5 && dynamic_cast(d2.get())->y == 4 ); iar( d3 ); - assert( static_cast(d3.get())->x == 6 && static_cast(d3.get())->y == 5 ); + assert( dynamic_cast(d3.get())->x == 6 && dynamic_cast(d3.get())->y == 5 ); } { diff --git a/unittests/pod.cpp b/unittests/pod.cpp index b55054a53..281d1ed71 100644 --- a/unittests/pod.cpp +++ b/unittests/pod.cpp @@ -132,7 +132,7 @@ void test_pod() 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, static_cast(1e-5)); + 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); diff --git a/unittests/polymorphic.cpp b/unittests/polymorphic.cpp index b17c02b75..71979dab3 100644 --- a/unittests/polymorphic.cpp +++ b/unittests/polymorphic.cpp @@ -313,13 +313,13 @@ void test_polymorphic() #endif BOOST_CHECK_EQUAL(i_shared.get(), i_locked.get()); - BOOST_CHECK_EQUAL(*static_cast(i_shared.get()), *static_cast(o_shared.get())); - BOOST_CHECK_EQUAL(*static_cast(i_shared.get()), *static_cast(i_locked.get())); - BOOST_CHECK_EQUAL(*static_cast(i_locked.get()), *static_cast(o_locked.get())); - BOOST_CHECK_EQUAL(*static_cast(i_unique.get()), *static_cast(o_unique.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(*static_cast(i_sharedLA.get()), *static_cast(o_sharedLA.get())); - BOOST_CHECK_EQUAL(*static_cast(i_sharedLA2.get()), *static_cast(o_sharedLA.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())); diff --git a/unittests/portable_binary_archive.cpp b/unittests/portable_binary_archive.cpp index 8a54d9d4b..af1018b5d 100644 --- a/unittests/portable_binary_archive.cpp +++ b/unittests/portable_binary_archive.cpp @@ -72,7 +72,7 @@ inline void swapBytes( T & t ) 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, static_cast(1e-5)); \ + 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 diff --git a/unittests/structs_specialized.cpp b/unittests/structs_specialized.cpp index e4f271f85..2ee3fa83d 100644 --- a/unittests/structs_specialized.cpp +++ b/unittests/structs_specialized.cpp @@ -441,7 +441,7 @@ void test_structs_specialized() BOOST_CHECK(i_ispl.x == o_ispl.x); BOOST_CHECK(i_isplv.x == o_isplv.x); - BOOST_CHECK_EQUAL(static_cast(i_shared_ispl.get())->x, static_cast(o_shared_ispl.get())->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); From f69ad7cd9e7561cd7c46a95c1ef6c955c76dd15a Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 28 Nov 2016 11:50:23 -0800 Subject: [PATCH 43/58] tab to space --- include/cereal/details/polymorphic_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 828544c67..565281894 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -715,7 +715,7 @@ namespace cereal { //! Binding for non abstract types void bind(std::false_type) const - { + { instantiate_polymorphic_binding(static_cast(nullptr), 0, Tag{}, adl_tag{}); } From 507f97d3ad2d7d109eab9ea805ed814d4e806518 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 28 Nov 2016 11:53:56 -0800 Subject: [PATCH 44/58] add -Wold-style-casts see #363 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e82d00041..49cfbfd31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ else() endif() if(NOT MSVC) - set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}") + set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic -Wold-style-cast ${CMAKE_CXX_FLAGS}") option(WITH_WERROR "Compile with '-Werror' C++ compiler flag" ON) if(WITH_WERROR) set(CMAKE_CXX_FLAGS "-Werror ${CMAKE_CXX_FLAGS}") From 75e50ee1e63635eadc732d9a64d3ec0df2a27787 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 28 Nov 2016 13:48:46 -0800 Subject: [PATCH 45/58] remove old code from sandbox relates #363 --- sandbox/sandbox_json.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/sandbox/sandbox_json.cpp b/sandbox/sandbox_json.cpp index 6171a15fd..e767ca590 100644 --- a/sandbox/sandbox_json.cpp +++ b/sandbox/sandbox_json.cpp @@ -311,31 +311,6 @@ struct OOJson } }; -enum Bla -{ - x, - y -}; - -template -void save( Archive & ar, Bla const & b ) -{ - ar( static_cast(b) ); -} - -template -void load( Archive & ar, Bla & b ) -{ - ar( static_cast(b) ); -} - -CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Bla, cereal::specialization::non_member_load_save ) - -//namespace cereal -//{ -// //template struct specialize {}; -//} - // ###################################################################### int main() { @@ -370,8 +345,6 @@ int main() auto f2 = f; archive( f ); archive( f2 ); - - archive( Bla::x ); } // test out of order From 4a92e2930ee02719c4b9c7766225bd4aa8c77209 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 25 Jan 2017 11:04:24 -0800 Subject: [PATCH 46/58] no longer need boost test in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3daaef67f..ae12dbcc1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ addons: packages: - 'g++-multilib' - 'libboost-serialization-dev' - - 'libboost-test-dev' +# - 'libboost-test-dev' compiler: - gcc From 0a908bc8c857ed51f5886066efd459884ff63544 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sat, 10 Dec 2016 17:27:28 +0530 Subject: [PATCH 47/58] Make tests pass with Windows --- CMakeLists.txt | 6 ++++-- sandbox/CMakeLists.txt | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0d53dbd2..ad4b7e902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,8 +14,10 @@ else() set(CEREAL_THREAD_LIBS "") endif() -if(NOT MSVC) - set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic -Wold-style-cast ${CMAKE_CXX_FLAGS}") +if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") +else() + set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic -Wold-style-cast ${CMAKE_CXX_FLAGS}") option(WITH_WERROR "Compile with '-Werror' C++ compiler flag" ON) if(WITH_WERROR) set(CMAKE_CXX_FLAGS "-Werror ${CMAKE_CXX_FLAGS}") diff --git a/sandbox/CMakeLists.txt b/sandbox/CMakeLists.txt index 5008e420f..52c8df890 100644 --- a/sandbox/CMakeLists.txt +++ b/sandbox/CMakeLists.txt @@ -10,5 +10,8 @@ include_directories(sandbox_shared_lib) if(Boost_FOUND) add_executable(performance performance.cpp) + if(MSVC) + set_target_properties(performance PROPERTIES COMPILE_DEFINITIONS "BOOST_SERIALIZATION_DYN_LINK") + endif() target_link_libraries(performance ${Boost_LIBRARIES}) endif(Boost_FOUND) From df44243badd997642693c98541a408459009fe64 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 11 Dec 2016 01:01:10 +0530 Subject: [PATCH 48/58] Enable cross-platform portability test CMake fix 32-bit executable with generator Win64 --- unittests/CMakeLists.txt | 28 +++++++++++++++++++++------- unittests/run_portability_test.cmake | 16 ++++++++++++++++ unittests/run_portability_test.sh | 9 --------- 3 files changed, 37 insertions(+), 16 deletions(-) create mode 100644 unittests/run_portability_test.cmake delete mode 100755 unittests/run_portability_test.sh diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index a5a91ae30..3212fb488 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -3,16 +3,30 @@ file(GLOB TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) # 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) -if((${CMAKE_SIZEOF_VOID_P} EQUAL 8) AND (NOT SKIP_PORTABILITY_TEST)) - add_executable(portability_test32 portability_test.cpp) - set_target_properties(portability_test32 PROPERTIES COMPILE_FLAGS "-m32") - set_target_properties(portability_test32 PROPERTIES LINK_FLAGS "-m32") +if(CMAKE_VERSION VERSION_LESS 2.8) + # Portability test uses the `TARGET_FILE_DIR` generator expression which is available from CMake 2.8. + set(SKIP_PORTABILITY_TEST ON) +endif() + +if(NOT SKIP_PORTABILITY_TEST) + # Build the portability test only if we are on a 64-bit machine (void* is 8 bytes) + if((${CMAKE_SIZEOF_VOID_P} EQUAL 8)) + if(NOT MSVC) + add_executable(portability_test32 portability_test.cpp) + set_target_properties(portability_test32 PROPERTIES COMPILE_FLAGS "-m32") + set_target_properties(portability_test32 PROPERTIES LINK_FLAGS "-m32") + endif() - add_executable(portability_test64 portability_test.cpp) + add_executable(portability_test64 portability_test.cpp) - add_test(NAME portability_test COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/run_portability_test.sh") + add_test(NAME portability_test + COMMAND ${CMAKE_COMMAND} + -DPORTABILITY_TEST_DIR=$ + -P "${CMAKE_CURRENT_SOURCE_DIR}/run_portability_test.cmake") + elseif(MSVC) + add_executable(portability_test32 portability_test.cpp) + endif() endif() # Build all of the non-special tests diff --git a/unittests/run_portability_test.cmake b/unittests/run_portability_test.cmake new file mode 100644 index 000000000..2841e6c35 --- /dev/null +++ b/unittests/run_portability_test.cmake @@ -0,0 +1,16 @@ +macro(EXEC_CMD_CHECK) + message("running ${ARGN}") + execute_process(COMMAND ${ARGN} RESULT_VARIABLE CMD_RESULT) + if(CMD_RESULT) + message(FATAL_ERROR "Error running ${ARGN}") + endif() +endmacro() + +set(PORTABILITY_TEST_32 "${PORTABILITY_TEST_DIR}/portability_test32") +set(PORTABILITY_TEST_64 "${PORTABILITY_TEST_DIR}/portability_test64") + +exec_cmd_check(${PORTABILITY_TEST_64} save 64) +exec_cmd_check(${PORTABILITY_TEST_32} load 32) +exec_cmd_check(${PORTABILITY_TEST_32} save 32) +exec_cmd_check(${PORTABILITY_TEST_64} load 64) +exec_cmd_check(${PORTABILITY_TEST_64} remove 64) diff --git a/unittests/run_portability_test.sh b/unittests/run_portability_test.sh deleted file mode 100755 index 718440284..000000000 --- a/unittests/run_portability_test.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -e - -./portability_test64 save 64 -./portability_test32 load 32 -./portability_test32 save 32 -./portability_test64 load 64 -./portability_test64 remove 64 From 655696ad8119b2dad041d5d1fa955ed9a67a2a7c Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 11 Dec 2016 15:42:00 +0530 Subject: [PATCH 49/58] AppVeyor integration --- appveyor.yml | 32 +++++++++++++++++++ scripts/appveyor.bat | 75 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 appveyor.yml create mode 100644 scripts/appveyor.bat diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..c45695d83 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,32 @@ +# can use variables like {build} and {branch} +version: 1.2.{build} + +branches: + only: + - develop + +configuration: + - Debug + - Release + +environment: + matrix: + - VS_VERSION_MAJOR: 12 + - VS_VERSION_MAJOR: 14 + +platform: + - Win32 + - x64 + +before_build: "scripts\\appveyor.bat" + +build: + parallel: true + project: build/cereal.sln + verbosity: minimal + +test_script: "scripts\\appveyor.bat test" + +artifacts: + - path: build\Testing + - path: out diff --git a/scripts/appveyor.bat b/scripts/appveyor.bat new file mode 100644 index 000000000..5e478dece --- /dev/null +++ b/scripts/appveyor.bat @@ -0,0 +1,75 @@ +@echo off +setlocal enabledelayedexpansion + +if not defined APPVEYOR ( + @echo This script is meant to be used with AppVeyor CI. This can be used as reference. + @echo I sincerely recommend not using it for building/testing cereal locally. + exit /b 0 +) + +if not defined BOOST_ROOT ( + set BOOST_ROOT=C:\Libraries\boost +) +if not defined VS_VERSION_MAJOR ( + set VS_VERSION_MAJOR=14 +) +if not defined VS_VERSION_YEAR ( + if "%VS_VERSION_MAJOR%" == "12" ( + set VS_VERSION_YEAR=2013 + ) else if "%VS_VERSION_MAJOR%" == "14" ( + set VS_VERSION_YEAR=2015 + ) else ( + @echo Cannot use Visual Studio version %VS_VERSION_MAJOR% + exit /b 1 + ) +) +if not defined CMAKE_GENERATOR_PREFIX ( + set CMAKE_GENERATOR_PREFIX=Visual Studio %VS_VERSION_MAJOR% %VS_VERSION_YEAR% +) + +@rem CONFIGURATION is (one of the entries) defined in appveyor.yml +if not defined CONFIGURATION ( + set CONFIGURATION=Release +) +@rem PLATFORM is (one of the entries) defined in appveyor.yml +if "%PLATFORM%"=="x64" ( + set BIT_COUNT=64 + set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_PREFIX% Win64 +) else ( + set BIT_COUNT=32 + set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_PREFIX% +) + +set BOOST_LIBRARYDIR=%BOOST_ROOT%\lib%BIT_COUNT%-msvc-%VS_VERSION_MAJOR%.0 + +set START_DIR=%CD% + +if not exist build\NUL mkdir build +cd build + +if "%~1" == "test" ( + @rem overloading the batch script; Run tests if the first argument is `test` (without quotes). + @rem Cereal uses Boost Unit test framework. Rather than modifying the code to load boost test + @rem dll from its location OR copying the boost dlls to the directory of every test being run, + @rem we use another option Windows leaves us - modify the PATH. + for %%i in (ctest.exe) do set CTEST_EXE=%%~$PATH:i + PATH %BOOST_LIBRARYDIR% + "!CTEST_EXE!" -C %CONFIGURATION% + if %errorlevel% neq 0 exit /b %errorlevel% + goto done +) + +if "%PLATFORM%" == "x64" ( + @rem please excuse the hack - CMake is unable to produce multiarch MSVC projects + cmake -G "%CMAKE_GENERATOR_PREFIX%" -DBOOST_ROOT=%BOOST_ROOT% -DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% .. + cmake --build . --config %CONFIGURATION% --target portability_test32 + del CMakeCache.txt + rmdir /s /q CMakeFiles +) + +cmake -G "%CMAKE_GENERATOR_NAME%" -DBOOST_ROOT=%BOOST_ROOT% -DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% .. +@rem left the actual build for later - AppVeyor enables parallel jobs in a much cleaner way than msbuild + +:done +@REM go back home +cd %START_DIR% From 4ff4db8532a41b2cedca069d64c3ef970961c6d3 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 11 Dec 2016 20:03:02 +0530 Subject: [PATCH 50/58] boost new version --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index c45695d83..6540590c1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,6 +13,7 @@ environment: matrix: - VS_VERSION_MAJOR: 12 - VS_VERSION_MAJOR: 14 + BOOST_ROOT: C:\Libraries\boost_1_59_0 platform: - Win32 From 2261feea2f307e3a0102223faff43a6710c93967 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Sun, 18 Dec 2016 17:32:04 +0530 Subject: [PATCH 51/58] Pull requests to not increment build numbers --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 6540590c1..121eba152 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,7 @@ # can use variables like {build} and {branch} version: 1.2.{build} +pull_requests: + do_not_increment_build_number: true branches: only: From e4d543d0b4fbda2d4235defe79fca1944ac9c7c0 Mon Sep 17 00:00:00 2001 From: Tushar Maheshwari Date: Thu, 26 Jan 2017 16:53:47 +0530 Subject: [PATCH 52/58] Fix merge issues --- unittests/CMakeLists.txt | 2 +- unittests/polymorphic.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 3212fb488..4ce2cb62d 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -45,7 +45,7 @@ foreach(TEST_SOURCE ${TESTS}) add_test("${TEST_TARGET}" "${TEST_TARGET}") # 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)) + if((NOT MSVC) AND (${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") diff --git a/unittests/polymorphic.hpp b/unittests/polymorphic.hpp index d882cc0af..52c6ae279 100644 --- a/unittests/polymorphic.hpp +++ b/unittests/polymorphic.hpp @@ -131,6 +131,9 @@ struct PolyDerivedD : PolyBaseB, PolyBaseC }; CEREAL_REGISTER_TYPE(PolyDerivedD) +#ifdef _MSC_VER +CEREAL_REGISTER_POLYMORPHIC_RELATION(PolyBaseA, PolyDerivedD) +#endif struct PolyBase { From fb6606dbb8de9e99a2c82442f869febef29aefcf Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Sun, 5 Feb 2017 18:13:37 -0800 Subject: [PATCH 53/58] Do not build coverage or valgrind for MSVC --- unittests/CMakeLists.txt | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 4ce2cb62d..b7a769be4 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -57,33 +57,35 @@ foreach(TEST_SOURCE ${TESTS}) endforeach() # Add the valgrind target -add_custom_target(valgrind - COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/run_valgrind.sh") - -# Add the coverage target -add_custom_target(coverage) -add_custom_command(TARGET coverage - COMMAND "${CMAKE_SOURCE_DIR}/scripts/updatecoverage.sh" ${CMAKE_SOURCE_DIR} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/coverage") - -# add tests to coverage -foreach(TEST_SOURCE ${TESTS}) - string(REPLACE ".cpp" "" COVERAGE_TARGET "${TEST_SOURCE}") - set(COVERAGE_TARGET "coverage_${COVERAGE_TARGET}") - - # Check to see if our target is listed in "SPECIAL_TESTS" - list(FIND SPECIAL_TESTS "${TEST_SOURCE}" IS_SPECIAL_TEST) - - if(IS_SPECIAL_TEST EQUAL -1) - add_dependencies(coverage ${COVERAGE_TARGET}) - - add_executable(${COVERAGE_TARGET} EXCLUDE_FROM_ALL ${TEST_SOURCE}) - 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} ${CEREAL_THREAD_LIBS}) - endif() -endforeach() +if(NOT MSVC) + add_custom_target(valgrind + COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/run_valgrind.sh") + + # Add the coverage target + add_custom_target(coverage) + add_custom_command(TARGET coverage + COMMAND "${CMAKE_SOURCE_DIR}/scripts/updatecoverage.sh" ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/coverage") + + # add tests to coverage + foreach(TEST_SOURCE ${TESTS}) + string(REPLACE ".cpp" "" COVERAGE_TARGET "${TEST_SOURCE}") + set(COVERAGE_TARGET "coverage_${COVERAGE_TARGET}") + + # Check to see if our target is listed in "SPECIAL_TESTS" + list(FIND SPECIAL_TESTS "${TEST_SOURCE}" IS_SPECIAL_TEST) + + if(IS_SPECIAL_TEST EQUAL -1) + add_dependencies(coverage ${COVERAGE_TARGET}) + + add_executable(${COVERAGE_TARGET} EXCLUDE_FROM_ALL ${TEST_SOURCE}) + 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} ${CEREAL_THREAD_LIBS}) + endif() + endforeach() +endif(NOT MSVC) if(NOT CMAKE_VERSION VERSION_LESS 3.0) add_test(test_cmake_config_module ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake-config-module.cmake) From f577fc4ce4aa2f66d184e31245f0a07e49574d10 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Sun, 5 Feb 2017 22:13:08 -0800 Subject: [PATCH 54/58] Turn on warnings as errors for MSVC, warning level to 3 Can't do level 4 warnings yet - need to make an upstream change to doctest --- CMakeLists.txt | 2 +- unittests/complex.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad4b7e902..dcb9cd677 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ else() endif() if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /W3 /WX") else() set(CMAKE_CXX_FLAGS "-Wall -g -Wextra -Wshadow -pedantic -Wold-style-cast ${CMAKE_CXX_FLAGS}") option(WITH_WERROR "Compile with '-Werror' C++ compiler flag" ON) diff --git a/unittests/complex.hpp b/unittests/complex.hpp index 1f2387900..ebd7e357a 100644 --- a/unittests/complex.hpp +++ b/unittests/complex.hpp @@ -69,8 +69,8 @@ void test_complex() 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) ); + CHECK_EQ( o_ldouble.real(), doctest::Approx(i_ldouble.real()).epsilon(1e-5L) ); + CHECK_EQ( o_ldouble.imag(), doctest::Approx(i_ldouble.imag()).epsilon(1e-5L) ); } } From b827b955f9301d3e10ff715d657e37e8d6b94ff2 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Mon, 6 Feb 2017 22:50:56 -0800 Subject: [PATCH 55/58] Fixes need for special MSVC case, see #373 --- unittests/polymorphic.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/unittests/polymorphic.hpp b/unittests/polymorphic.hpp index 52c6ae279..9309ac4f5 100644 --- a/unittests/polymorphic.hpp +++ b/unittests/polymorphic.hpp @@ -53,17 +53,14 @@ struct PolyBaseAA : PolyBaseA ar( w ); } - static void doesNothing() - { - cereal::detail::RegisterPolymorphicCaster::bind(); - } - bool operator==( PolyBaseAA const & other ) const { return w == other.w; } }; +CEREAL_REGISTER_POLYMORPHIC_RELATION(PolyBaseA, PolyBaseAA) + struct PolyBaseB : virtual PolyBaseAA { PolyBaseB() {} @@ -131,9 +128,6 @@ struct PolyDerivedD : PolyBaseB, PolyBaseC }; CEREAL_REGISTER_TYPE(PolyDerivedD) -#ifdef _MSC_VER -CEREAL_REGISTER_POLYMORPHIC_RELATION(PolyBaseA, PolyDerivedD) -#endif struct PolyBase { From a91737466f238d00f98cb2f44ec666a1ec631c3e Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Wed, 8 Feb 2017 10:47:02 -0800 Subject: [PATCH 56/58] size_type now specified by macro CEREAL_SIZE_TYPE resolves #379 --- include/cereal/details/helpers.hpp | 6 ++++-- include/cereal/macros.hpp | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/cereal/details/helpers.hpp b/include/cereal/details/helpers.hpp index 11088d33e..909268809 100644 --- a/include/cereal/details/helpers.hpp +++ b/include/cereal/details/helpers.hpp @@ -55,8 +55,10 @@ namespace cereal //! The size type used by cereal /*! To ensure compatability between 32, 64, etc bit machines, we need to use a fixed size type instead of size_t, which may vary from machine to - machine. */ - using size_type = uint64_t; + machine. + + The default value for CEREAL_SIZE_TYPE is specified in cereal/macros.hpp */ + using size_type = CEREAL_SIZE_TYPE; // forward decls class BinaryOutputArchive; diff --git a/include/cereal/macros.hpp b/include/cereal/macros.hpp index eb2a05b9a..cfdc14c59 100644 --- a/include/cereal/macros.hpp +++ b/include/cereal/macros.hpp @@ -56,6 +56,20 @@ #define CEREAL_THREAD_SAFE 0 #endif // CEREAL_THREAD_SAFE +#ifndef CEREAL_SIZE_TYPE +//! Determines the data type used for size_type +/*! cereal uses size_type to ensure that the serialized size of + dynamic containers is compatible across different architectures + (e.g. 32 vs 64 bit), which may use different underlying types for + std::size_t. + + More information can be found in cereal/details/helpers.hpp. + + If you choose to modify this type, ensure that you use a fixed + size type (e.g. uint32_t). */ +#define CEREAL_SIZE_TYPE uint64_t +#endif // CEREAL_SIZE_TYPE + // ###################################################################### #ifndef CEREAL_SERIALIZE_FUNCTION_NAME //! The serialization/deserialization function name to search for. From 2590f219a2ca716aab4386d42248317f924ace97 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Sat, 11 Feb 2017 23:47:00 -0800 Subject: [PATCH 57/58] Properly use multimap for lookup in poly casting relates #356, still need final testing on MSVC --- include/cereal/details/polymorphic_impl.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/cereal/details/polymorphic_impl.hpp b/include/cereal/details/polymorphic_impl.hpp index 565281894..81128c8b1 100644 --- a/include/cereal/details/polymorphic_impl.hpp +++ b/include/cereal/details/polymorphic_impl.hpp @@ -307,7 +307,12 @@ namespace cereal // Check to see if we have a previous uncommitted path in unregisteredRelations // that is shorter. If so, ignore this path - auto hint = unregisteredRelations.find( parent ); + auto hintRange = unregisteredRelations.equal_range( parent ); + auto hint = hintRange.first; + for( ; hint != hintRange.second; ++hint ) + if( hint->second.first == finalChild ) + break; + const bool uncommittedExists = hint != unregisteredRelations.end(); if( uncommittedExists && (hint->second.second.size() <= newLength) ) continue; From e38d6fecc106955c541a365c9ec633568460bfc5 Mon Sep 17 00:00:00 2001 From: Shane Grant Date: Sun, 12 Feb 2017 13:46:25 -0800 Subject: [PATCH 58/58] fix update doc script --- scripts/updatedoc.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/updatedoc.in b/scripts/updatedoc.in index 5e7a71462..7f6a4a66d 100755 --- a/scripts/updatedoc.in +++ b/scripts/updatedoc.in @@ -8,18 +8,18 @@ set -e tempdir=`mktemp -d` branch=`git rev-parse --abbrev-ref HEAD` -cp -r @CMAKE_CURRENT_BINARY_DIR@/doc/html/ ${tempdir} +cp -r @PROJECT_BINARY_DIR@/doc/html/ ${tempdir} git stash git checkout gh-pages-develop -rm -rf @CMAKE_CURRENT_SOURCE_DIR@/assets/doxygen -mkdir @CMAKE_CURRENT_SOURCE_DIR@/assets/doxygen -cp -r ${tempdir}/html/* @CMAKE_CURRENT_SOURCE_DIR@/assets/doxygen/ +rm -rf @PROJECT_SOURCE_DIR@/assets/doxygen +mkdir @PROJECT_SOURCE_DIR@/assets/doxygen +cp -r ${tempdir}/html/* @PROJECT_SOURCE_DIR@/assets/doxygen/ rm -rf ${tempdir} -git commit @CMAKE_CURRENT_SOURCE_DIR@/assets/doxygen +git commit @PROJECT_SOURCE_DIR@/assets/doxygen git checkout ${branch} git stash apply