Merge exception tests

This commit is contained in:
Daniel James
2017-05-07 17:54:34 +01:00
parent b6c6bfbe7f
commit 31c5b5bfa1
4 changed files with 182 additions and 1 deletions

View File

@ -92,4 +92,5 @@ test-suite unordered-exception
[ run exception/rehash_exception_tests.cpp framework ]
[ run exception/swap_exception_tests.cpp framework : : :
<define>BOOST_UNORDERED_SWAP_METHOD=2 ]
[ run exception/merge_exception_tests.cpp framework ]
;

View File

@ -0,0 +1,108 @@
#include "../helpers/exception_test.hpp"
#include "../helpers/invariants.hpp"
#include "../helpers/metafunctions.hpp"
#include "../helpers/random_values.hpp"
#include "./containers.hpp"
template <typename T1, typename T2> void merge_exception_test(T1 x, T2 y)
{
std::size_t size = x.size() + y.size();
try {
ENABLE_EXCEPTIONS;
x.merge(y);
} catch (...) {
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
throw;
}
// Not a full check, just want to make sure the merge completed.
BOOST_TEST(size == x.size() + y.size());
if (y.size()) {
BOOST_TEST(test::has_unique_keys<T1>::value);
for (typename T2::iterator it = y.begin(); it != y.end(); ++it) {
BOOST_TEST(x.find(test::get_key<T2>(*it)) != x.end());
}
}
test::check_equivalent_keys(x);
test::check_equivalent_keys(y);
}
template <typename T1, typename T2>
void merge_exception_test(T1 const*, T2 const*, std::size_t count1,
std::size_t count2, int tag1, int tag2, test::random_generator gen1,
test::random_generator gen2)
{
test::random_values<T1> v1(count1, gen1);
test::random_values<T2> v2(count2, gen2);
T1 x(v1.begin(), v1.end(), 0, test::exception::hash(tag1),
test::exception::equal_to(tag1));
T2 y(v2.begin(), v2.end(), 0, test::exception::hash(tag2),
test::exception::equal_to(tag2));
EXCEPTION_LOOP(merge_exception_test(x, y))
}
boost::unordered_set<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_set_;
boost::unordered_multiset<test::exception::object, test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> >* test_multiset_;
boost::unordered_map<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_map_;
boost::unordered_multimap<test::exception::object, test::exception::object,
test::exception::hash, test::exception::equal_to,
test::exception::allocator2<test::exception::object> >* test_multimap_;
using test::default_generator;
using test::generate_collisions;
using test::limited_range;
// clang-format off
UNORDERED_TEST(merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((0)(10)(100))
((0)(10)(100))
((0)(1)(2))
((0)(1)(2))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
UNORDERED_TEST(merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((0)(10)(100))
((0)(10)(100))
((0)(1)(2))
((0)(1)(2))
((default_generator)(limited_range))
((default_generator)(limited_range))
)
// Run fewer generate_collisions tests, as they're slow.
UNORDERED_TEST(merge_exception_test,
((test_set_)(test_multiset_))
((test_set_)(test_multiset_))
((10))
((10))
((0)(1)(2))
((0)(1)(2))
((generate_collisions))
((generate_collisions))
)
UNORDERED_TEST(merge_exception_test,
((test_map_)(test_multimap_))
((test_map_)(test_multimap_))
((10))
((10))
((0)(1)(2))
((0)(1)(2))
((generate_collisions))
((generate_collisions))
)
// clang-format on
RUN_TESTS()

View File

@ -275,6 +275,77 @@ template <class Test> void exception_safety(Test const& f, char const* /*name*/)
}
runner.end();
}
//
// An alternative way to run exception tests.
// See merge_exception_tests.cpp for an example.
struct exception_looper
{
bool success;
unsigned int failure_count;
char const* error_msg;
int error_count;
exception_looper() : success(false), failure_count(0), error_msg(0) {}
void start() { iteration = 0; }
bool loop_condition() const
{
return !error_msg && !success && failure_count < 5;
}
void start_iteration()
{
error_count = boost::detail::test_errors();
++iteration;
count = 0;
}
void successful_run() { success = true; }
void test_failure_caught(test_failure const&)
{
error_msg = "test_failure caught.";
}
void test_exception_caught(test_exception const& e)
{
if (error_count != boost::detail::test_errors()) {
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< "Iteration: " << iteration
<< " Error found for epoint: " << e.name << std::endl;
}
}
void unexpected_exception_caught() { error_msg = "Unexpected exception."; }
void end()
{
if (error_msg) {
BOOST_ERROR(error_msg);
}
}
};
#define EXCEPTION_LOOP(op) \
test::lightweight::exception_looper looper; \
looper.start(); \
while (looper.loop_condition()) { \
looper.start_iteration(); \
try { \
op; \
looper.successful_run(); \
} catch (test::lightweight::test_failure e) { \
looper.test_failure_caught(e); \
} catch (test::lightweight::test_exception e) { \
looper.test_exception_caught(e); \
} catch (...) { \
looper.unexpected_exception_caught(); \
} \
} \
looper.end();
}
}

View File

@ -10,8 +10,9 @@
#include "../helpers/count.hpp"
#include "../helpers/fwd.hpp"
#include "../helpers/generators.hpp"
#include "../helpers/memory.hpp"
#include "../objects/fwd.hpp"
#include "./fwd.hpp"
#include <boost/limits.hpp>
#include <cstddef>
#include <iostream>