diff --git a/test/exception/Jamfile.v2 b/test/exception/Jamfile.v2 index 9ce892f4..961e3f34 100644 --- a/test/exception/Jamfile.v2 +++ b/test/exception/Jamfile.v2 @@ -5,7 +5,8 @@ import testing ; -alias framework : /boost/test//boost_unit_test_framework ; +#alias framework : /boost/test//boost_unit_test_framework ; +alias framework : ; project unordered-test/exception-tests : requirements diff --git a/test/exception/assign_exception_tests.cpp b/test/exception/assign_exception_tests.cpp index 826c12ad..eac1b200 100644 --- a/test/exception/assign_exception_tests.cpp +++ b/test/exception/assign_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" diff --git a/test/exception/constructor_exception_tests.cpp b/test/exception/constructor_exception_tests.cpp index d822e315..0b8b81ff 100644 --- a/test/exception/constructor_exception_tests.cpp +++ b/test/exception/constructor_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include "../helpers/random_values.hpp" #include "../helpers/input_iterator.hpp" diff --git a/test/exception/copy_exception_tests.cpp b/test/exception/copy_exception_tests.cpp index 53a66514..bf751a05 100644 --- a/test/exception/copy_exception_tests.cpp +++ b/test/exception/copy_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include "../helpers/random_values.hpp" test::seed_t seed(73041); diff --git a/test/exception/erase_exception_tests.cpp b/test/exception/erase_exception_tests.cpp index 102ab9e2..1df8a4b1 100644 --- a/test/exception/erase_exception_tests.cpp +++ b/test/exception/erase_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" #include "../helpers/helpers.hpp" @@ -29,7 +25,7 @@ struct erase_test_base : public test::exception_base void check(T const& x) const { std::string scope(test::scope); - HASH_CHECK(scope.find("hash::") != std::string::npos || + UNORDERED_CHECK(scope.find("hash::") != std::string::npos || scope.find("equal_to::") != std::string::npos || scope == "operator==(object, object)"); diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index 0da35192..7c055a72 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -4,16 +4,12 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" #include "../helpers/strong.hpp" #include "../helpers/input_iterator.hpp" - +#include #include test::seed_t seed(747373); @@ -105,17 +101,18 @@ struct insert_test_rehash1 : public insert_test_base insert_test_rehash1() : insert_test_base(1000) {} T init() const { + using namespace std; typedef BOOST_DEDUCED_TYPENAME T::size_type size_type; T x; x.max_load_factor(0.25); size_type bucket_count = x.bucket_count(); size_type initial_elements = static_cast( - std::ceil(bucket_count * x.max_load_factor()) - 1); - BOOST_REQUIRE(initial_elements < this->values.size()); + ceil(bucket_count * (double) x.max_load_factor()) - 1); + UNORDERED_REQUIRE(initial_elements < this->values.size()); x.insert(this->values.begin(), boost::next(this->values.begin(), initial_elements)); - BOOST_REQUIRE(bucket_count == x.bucket_count()); + UNORDERED_REQUIRE(bucket_count == x.bucket_count()); return x; } @@ -134,7 +131,7 @@ struct insert_test_rehash1 : public insert_test_base // This isn't actually a failure, but it means the test isn't doing its // job. - BOOST_REQUIRE(x.bucket_count() != bucket_count); + UNORDERED_REQUIRE(x.bucket_count() != bucket_count); } }; @@ -157,7 +154,7 @@ struct insert_test_rehash2 : public insert_test_rehash1 // This isn't actually a failure, but it means the test isn't doing its // job. - BOOST_REQUIRE(x.bucket_count() != bucket_count); + UNORDERED_REQUIRE(x.bucket_count() != bucket_count); } }; @@ -169,6 +166,7 @@ struct insert_test_rehash3 : public insert_test_base insert_test_rehash3() : insert_test_base(1000) {} T init() const { + using namespace std; typedef BOOST_DEDUCED_TYPENAME T::size_type size_type; T x; @@ -176,14 +174,14 @@ struct insert_test_rehash3 : public insert_test_base original_bucket_count = x.bucket_count(); rehash_bucket_count = static_cast( - std::ceil(original_bucket_count * x.max_load_factor())) - 1; + ceil(original_bucket_count * (double) x.max_load_factor())) - 1; size_type initial_elements = rehash_bucket_count - 5; - BOOST_REQUIRE(initial_elements < this->values.size()); + UNORDERED_REQUIRE(initial_elements < this->values.size()); x.insert(this->values.begin(), boost::next(this->values.begin(), initial_elements)); - BOOST_REQUIRE(original_bucket_count == x.bucket_count()); + UNORDERED_REQUIRE(original_bucket_count == x.bucket_count()); return x; } @@ -195,7 +193,7 @@ struct insert_test_rehash3 : public insert_test_base // This isn't actually a failure, but it means the test isn't doing its // job. - BOOST_REQUIRE(x.bucket_count() != bucket_count); + UNORDERED_REQUIRE(x.bucket_count() != bucket_count); } void check(T const& x) const { diff --git a/test/exception/rehash_exception_tests.cpp b/test/exception/rehash_exception_tests.cpp index 1178f4ef..ef3284e8 100644 --- a/test/exception/rehash_exception_tests.cpp +++ b/test/exception/rehash_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" diff --git a/test/exception/swap_exception_tests.cpp b/test/exception/swap_exception_tests.cpp index b20119c1..baaac7b6 100644 --- a/test/exception/swap_exception_tests.cpp +++ b/test/exception/swap_exception_tests.cpp @@ -4,10 +4,6 @@ // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #include "./containers.hpp" - -#define BOOST_TEST_MAIN -#include -#include #include "../helpers/random_values.hpp" #include "../helpers/invariants.hpp" @@ -26,7 +22,7 @@ struct self_swap_base : public test::exception_base std::string scope(test::scope); #if BOOST_UNORDERED_SWAP_METHOD != 2 - HASH_CHECK( + UNORDERED_CHECK( scope == "hash::operator(hash)" || scope == "hash::operator=(hash)" || scope == "equal_to::operator(equal_to)" || @@ -77,7 +73,7 @@ struct swap_base : public test::exception_base std::string scope(test::scope); #if BOOST_UNORDERED_SWAP_METHOD != 2 - HASH_CHECK( + UNORDERED_CHECK( scope == "hash::operator(hash)" || scope == "hash::operator=(hash)" || scope == "equal_to::operator(equal_to)" || diff --git a/test/helpers/test.hpp b/test/helpers/test.hpp new file mode 100644 index 00000000..332dd87a --- /dev/null +++ b/test/helpers/test.hpp @@ -0,0 +1,19 @@ + +// Copyright 2006-2007 Daniel James. +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_UNORDERED_TEST_TEST_HEADER) +#define BOOST_UNORDERED_TEST_TEST_HEADER + +#if defined(BOOST_UNORDERED_USE_TEST) +#include +#define UNORDERED_CHECK(x) BOOST_CHECK(x) +#define UNORDERED_REQUIRE(x) BOOST_REQUIRE(x) +#else +#include +#define UNORDERED_CHECK(x) BOOST_TEST(x) +#define UNORDERED_REQUIRE(x) if(!(x)) { BOOST_ERROR(BOOST_STRINGIZE(x)); throw test::lightweight::test_failure(); } +#endif + +#endif diff --git a/test/objects/exception.hpp b/test/objects/exception.hpp index ff99b6ed..e8ca6158 100644 --- a/test/objects/exception.hpp +++ b/test/objects/exception.hpp @@ -6,24 +6,32 @@ #if !defined(BOOST_UNORDERED_TEST_OBJECTS_HEADER) #define BOOST_UNORDERED_TEST_OBJECTS_HEADER -#include -#include -#include +#if defined(BOOST_UNORDERED_USE_TEST) +#define BOOST_TEST_MAIN #include +#include +#include +#else +#include +#endif + +#include +#include +#include #include #include #include -#include #include "../helpers/fwd.hpp" #include "../helpers/allocator.hpp" -#include "memory.hpp" -#include +#include "./memory.hpp" #define RUN_EXCEPTION_TESTS(test_seq, param_seq) \ - BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, (test_seq)(param_seq)) + UNORDERED_EXCEPTION_TEST_PREFIX \ + BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_EXCEPTION_TESTS_OP, (test_seq)(param_seq)) \ + UNORDERED_EXCEPTION_TEST_POSTFIX #define RUN_EXCEPTION_TESTS_OP(r, product) \ - RUN_EXCEPTION_TESTS_OP2( \ + UNORDERED_EXCEPTION_TEST_CASE( \ BOOST_PP_CAT(BOOST_PP_SEQ_ELEM(0, product), \ BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(1, product)) \ ), \ @@ -31,12 +39,25 @@ BOOST_PP_SEQ_ELEM(1, product) \ ) -#define RUN_EXCEPTION_TESTS_OP2(name, test_func, type) \ + +#if defined(BOOST_UNORDERED_USE_TEST) +#define UNORDERED_EXCEPTION_TEST_PREFIX +#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \ BOOST_AUTO_TEST_CASE(name) \ { \ test_func< type > fixture; \ ::test::exception_safety(fixture, BOOST_STRINGIZE(test_func)); \ } +#define UNORDERED_EXCEPTION_TEST_POSTFIX +#else +#define UNORDERED_EXCEPTION_TEST_PREFIX int main() { +#define UNORDERED_EXCEPTION_TEST_CASE(name, test_func, type) \ + { \ + test_func< type > fixture; \ + ::test::lightweight::exception_safety(fixture, BOOST_STRINGIZE(test_func)); \ + } +#define UNORDERED_EXCEPTION_TEST_POSTFIX return boost::report_errors(); } +#endif #define SCOPE(scope_name) \ for(::test::scope_guard unordered_test_guard( \ @@ -44,10 +65,17 @@ !unordered_test_guard.dismissed(); \ unordered_test_guard.dismiss()) +#if defined(BOOST_UNORDERED_USE_TEST) #define EPOINT(name) \ if(::test::exceptions_enabled) { \ BOOST_ITEST_EPOINT(name); \ } +#else +#define EPOINT(name) \ + if(::test::exceptions_enabled) { \ + ::test::lightweight::epoint(name); \ + } +#endif #define ENABLE_EXCEPTIONS \ ::test::exceptions_enable BOOST_PP_CAT(ENABLE_EXCEPTIONS_, __LINE__)(true) @@ -155,21 +183,71 @@ namespace test { strong.store(x); try { ENABLE_EXCEPTIONS; - call_ignore_extra_parameters(&Test::run, test_, x, strong); + call_ignore_extra_parameters(&Test::run, test_, x, strong); } catch(...) { - call_ignore_extra_parameters(&Test::check, test_, + call_ignore_extra_parameters(&Test::check, test_, constant(x), constant(strong)); throw; } } }; + + +#if defined(BOOST_UNORDERED_USE_TEST) template void exception_safety(Test const& f, char const* name) { test_runner runner(f); ::boost::itest::exception_safety(runner, name); } +#else + + // Quick exception testing based on lightweight test + + namespace lightweight { + static int iteration; + static int count; + + struct test_exception { + char const* name; + test_exception(char const* n) : name(n) {} + }; + + struct test_failure { + }; + + void epoint(char const* name) { + ++count; + if(count == iteration) { + throw test_exception(name); + } + } + + template + void exception_safety(Test const& f, char const* name) { + test_runner runner(f); + + iteration = 0; + bool success = false; + do { + ++iteration; + count = 0; + + try { + runner(); + success = true; + } + catch(test_failure) { + break; + } + catch(...) { + } + } while(!success); + } + } +#endif + } namespace test @@ -550,5 +628,15 @@ namespace exception } } +// Workaround for ADL deficient compilers +#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) +namespace test +{ + test::exception::object generate(test::exception::object const* x) { + return test::exception::generate(x); + } +} +#endif + #endif diff --git a/test/objects/memory.hpp b/test/objects/memory.hpp index ed18fd38..49815ce7 100644 --- a/test/objects/memory.hpp +++ b/test/objects/memory.hpp @@ -6,7 +6,11 @@ #if !defined(BOOST_UNORDERED_TEST_MEMORY_HEADER) #define BOOST_UNORDERED_TEST_MEMORY_HEADER -#define HASH_CHECK(test) if(!(test)) BOOST_ERROR(BOOST_STRINGIZE(test)) +#include +#include +#include +#include +#include "../helpers/test.hpp" namespace test { @@ -58,8 +62,7 @@ namespace test template struct memory_tracker { typedef std::map >::type + BOOST_DEDUCED_TYPENAME boost::mpl::apply1 >::type > allocated_memory_type; allocated_memory_type allocated_memory; @@ -84,7 +87,7 @@ namespace test void allocator_unref() { - HASH_CHECK(count_allocators > 0); + UNORDERED_CHECK(count_allocators > 0); if(count_allocators > 0) { --count_allocators; if(count_allocators == 0) { @@ -97,9 +100,9 @@ namespace test count_constructions = 0; allocated_memory.clear(); - HASH_CHECK(no_allocations_left); - HASH_CHECK(no_constructions_left); - HASH_CHECK(allocated_memory_empty); + UNORDERED_CHECK(no_allocations_left); + UNORDERED_CHECK(no_constructions_left); + UNORDERED_CHECK(allocated_memory_empty); } } } @@ -111,8 +114,10 @@ namespace test } else { ++count_allocations; - allocated_memory[memory_area(ptr, (char*) ptr + n * size)] = - memory_track(tag); + allocated_memory.insert( + std::pair( + memory_area(ptr, (char*) ptr + n * size), + memory_track(tag))); } } @@ -123,12 +128,12 @@ namespace test if(pos == allocated_memory.end()) { BOOST_ERROR("Deallocating unknown pointer."); } else { - HASH_CHECK(pos->first.start == ptr); - HASH_CHECK(pos->first.end == (char*) ptr + n * size); - HASH_CHECK(pos->second.tag_ == tag); + UNORDERED_CHECK(pos->first.start == ptr); + UNORDERED_CHECK(pos->first.end == (char*) ptr + n * size); + UNORDERED_CHECK(pos->second.tag_ == tag); allocated_memory.erase(pos); } - HASH_CHECK(count_allocations > 0); + UNORDERED_CHECK(count_allocations > 0); if(count_allocations > 0) --count_allocations; } @@ -139,7 +144,7 @@ namespace test void track_destroy(void* ptr, std::size_t /*size*/, int tag) { - HASH_CHECK(count_constructions > 0); + UNORDERED_CHECK(count_constructions > 0); if(count_constructions > 0) --count_constructions; } };