From 3f060a70d190d490246d4e7e520b1574fc3366a0 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Wed, 26 Sep 2012 08:09:26 +0000 Subject: [PATCH] Unordered: Fix unnecessary_copy_tests + extra tests. It looks the odd result in unnecessary_copy_tests on Visual C++ 11 is not a bug, but add some extra tests just to make sure. Also some extra rehash and reserve testing thrown in. [SVN r80705] --- test/objects/test.hpp | 120 ++++++++++++++++++++++ test/unordered/insert_tests.cpp | 97 +++++++++++++++-- test/unordered/rehash_tests.cpp | 64 ++++++++++-- test/unordered/unnecessary_copy_tests.cpp | 9 ++ 4 files changed, 270 insertions(+), 20 deletions(-) diff --git a/test/objects/test.hpp b/test/objects/test.hpp index 8e2b3aa6..13462350 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -18,6 +18,7 @@ namespace test // Note that the default hash function will work for any equal_to (but not // very well). class object; + class movable; class implicitly_convertible; class hash; class less; @@ -25,6 +26,7 @@ namespace test template class allocator1; template class allocator2; object generate(object const*); + movable generate(movable const*); implicitly_convertible generate(implicitly_convertible const*); inline void ignore_variable(void const*) {} @@ -67,6 +69,81 @@ namespace test } }; + class movable : private counted_object + { + friend class hash; + friend class equal_to; + friend class less; + int tag1_, tag2_; + + BOOST_COPYABLE_AND_MOVABLE(movable) + public: + explicit movable(int t1 = 0, int t2 = 0) : tag1_(t1), tag2_(t2) {} + + movable(movable const& x) : + counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) + { + BOOST_TEST(x.tag1_ != -1); + } + + movable(BOOST_RV_REF(movable) x) : + counted_object(x), tag1_(x.tag1_), tag2_(x.tag2_) + { + BOOST_TEST(x.tag1_ != -1); + x.tag1_ = -1; + x.tag2_ = -1; + } + + movable& operator=(BOOST_COPY_ASSIGN_REF(movable) x) // Copy assignment + { + BOOST_TEST(x.tag1_ != -1); + tag1_ = x.tag1_; + tag2_ = x.tag2_; + return *this; + } + + movable& operator=(BOOST_RV_REF(movable) x) //Move assignment + { + BOOST_TEST(x.tag1_ != -1); + tag1_ = x.tag1_; + tag2_ = x.tag2_; + x.tag1_ = -1; + x.tag2_ = -1; + return *this; + } + + ~movable() { + tag1_ = -1; + tag2_ = -1; + } + + friend bool operator==(movable const& x1, movable const& x2) { + BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); + return x1.tag1_ == x2.tag1_ && x1.tag2_ == x2.tag2_; + } + + friend bool operator!=(movable const& x1, movable const& x2) { + BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); + return x1.tag1_ != x2.tag1_ || x1.tag2_ != x2.tag2_; + } + + friend bool operator<(movable const& x1, movable const& x2) { + BOOST_TEST(x1.tag1_ != -1 && x2.tag1_ != -1); + return x1.tag1_ < x2.tag1_ || + (x1.tag1_ == x2.tag1_ && x1.tag2_ < x2.tag2_); + } + + friend movable generate(movable const*) { + int* x = 0; + return movable(generate(x), generate(x)); + } + + friend std::ostream& operator<<(std::ostream& out, movable const& o) + { + return out<<"("< @@ -293,8 +294,6 @@ void insert_tests2(X*, test::random_generator generator) } } -#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) - template void unique_emplace_tests1(X*, test::random_generator generator) { @@ -361,7 +360,73 @@ void equivalent_emplace_tests1(X*, test::random_generator generator) test::check_equivalent_keys(x); } -#endif +template +void move_emplace_tests(X*, test::random_generator generator) +{ + typedef BOOST_DEDUCED_TYPENAME X::iterator iterator; + typedef test::ordered ordered; + + std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n"; + + X x; + test::ordered tracker = test::create_ordered(x); + + test::random_values v(1000, generator); + + for(BOOST_DEDUCED_TYPENAME test::random_values::iterator it = v.begin(); + it != v.end(); ++it) + { + + BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count = x.bucket_count(); + float b = x.max_load_factor(); + + typename X::value_type value = *it; + x.emplace(boost::move(value)); + tracker.insert(*it); + tracker.compare_key(x, *it); + + if(static_cast(x.size()) < b * static_cast(old_bucket_count)) + BOOST_TEST(x.bucket_count() == old_bucket_count); + } + + test::check_equivalent_keys(x); + tracker.compare(x); +} + +template +void default_emplace_tests(X*, test::random_generator) +{ + std::cerr<<"emplace() tests.\n"; + bool is_unique = test::has_unique_keys::value; + + X x; + + x.emplace(); + BOOST_TEST(x.size() == 1); + x.emplace(); + BOOST_TEST(x.size() == is_unique ? 1: 2); + x.emplace(); + BOOST_TEST(x.size() == is_unique ? 1: 3); + + typename X::value_type y; + BOOST_TEST(x.count(test::get_key(y)) == is_unique ? 1: 3); + BOOST_TEST(*x.equal_range(test::get_key(y)).first == y); + + x.emplace(y); + BOOST_TEST(x.size() == is_unique ? 1: 4); + BOOST_TEST(x.count(test::get_key(y)) == is_unique ? 1: 4); + BOOST_TEST(*x.equal_range(test::get_key(y)).first == y); + + x.clear(); + BOOST_TEST(x.empty()); + x.emplace(y); + BOOST_TEST(x.size() == 1); + x.emplace(y); + BOOST_TEST(x.size() == is_unique ? 1: 2); + + BOOST_TEST(x.count(test::get_key(y)) == is_unique ? 1: 2); + BOOST_TEST(*x.equal_range(test::get_key(y)).first == y); +} template void map_tests(X*, test::random_generator generator) @@ -434,9 +499,9 @@ void map_insert_range_test2(X*, test::random_generator generator) test::check_equivalent_keys(x); } -boost::unordered_set >* test_set_std_alloc; + std::allocator >* test_set_std_alloc; boost::unordered_multimap >* test_multimap_std_alloc; @@ -444,12 +509,12 @@ boost::unordered_multimap >* test_set; -boost::unordered_multiset >* test_multiset; -boost::unordered_map >* test_multiset; +boost::unordered_map >* test_map; + test::allocator2 >* test_map; boost::unordered_multimap >* test_multimap; @@ -472,7 +537,6 @@ UNORDERED_TEST(insert_tests2, ((default_generator)(generate_collisions)) ) -#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES) UNORDERED_TEST(unique_emplace_tests1, ((test_set_std_alloc)(test_set)(test_map)) ((default_generator)(generate_collisions)) @@ -482,7 +546,18 @@ UNORDERED_TEST(equivalent_emplace_tests1, ((test_multimap_std_alloc)(test_multiset)(test_multimap)) ((default_generator)(generate_collisions)) ) -#endif + +UNORDERED_TEST(move_emplace_tests, + ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map) + (test_multiset)(test_multimap)) + ((default_generator)(generate_collisions)) +) + +UNORDERED_TEST(default_emplace_tests, + ((test_set_std_alloc)(test_multimap_std_alloc)(test_set)(test_map) + (test_multiset)(test_multimap)) + ((default_generator)(generate_collisions)) +) UNORDERED_TEST(map_tests, ((test_map)) diff --git a/test/unordered/rehash_tests.cpp b/test/unordered/rehash_tests.cpp index c77115b5..3746bed3 100644 --- a/test/unordered/rehash_tests.cpp +++ b/test/unordered/rehash_tests.cpp @@ -12,6 +12,7 @@ #include "../helpers/random_values.hpp" #include "../helpers/tracker.hpp" #include "../helpers/metafunctions.hpp" +#include "../objects/test.hpp" namespace rehash_tests { @@ -36,6 +37,9 @@ void rehash_empty_test1(X*) x.rehash(0); BOOST_TEST(postcondition(x, 0)); + + x.rehash(10000000); + BOOST_TEST(postcondition(x, 10000000)); } template @@ -54,6 +58,10 @@ void rehash_empty_test2(X*, test::random_generator generator) tracker.compare(x); BOOST_TEST(postcondition(x, 10000)); + + x.rehash(10000000); + tracker.compare(x); + BOOST_TEST(postcondition(x, 10000000)); } template @@ -74,7 +82,6 @@ void rehash_empty_test3(X*, test::random_generator generator) BOOST_TEST(postcondition(x, 0)); } - template void rehash_test1(X*, test::random_generator generator) { @@ -98,6 +105,35 @@ void rehash_test1(X*, test::random_generator generator) tracker.compare(x); } +template +void reserve_empty_test1(X*) +{ + X x; + + x.reserve(10000); + BOOST_TEST(x.bucket_count() >= 10000); + + x.reserve(0); + + x.reserve(10000000); + BOOST_TEST(x.bucket_count() >= 10000000); +} + +template +void reserve_empty_test2(X*) +{ + X x; + x.max_load_factor(0.25); + + x.reserve(10000); + BOOST_TEST(x.bucket_count() >= 40000); + + x.reserve(0); + + x.reserve(10000000); + BOOST_TEST(x.bucket_count() >= 40000000); +} + template void reserve_test1(X*, test::random_generator generator) { @@ -165,34 +201,44 @@ void reserve_test2(X*, test::random_generator generator) } boost::unordered_set* int_set_ptr; -boost::unordered_multiset* int_multiset_ptr; -boost::unordered_map* int_map_ptr; +boost::unordered_multiset >* test_multiset_ptr; +boost::unordered_map >* test_map_ptr; boost::unordered_multimap* int_multimap_ptr; using test::default_generator; using test::generate_collisions; UNORDERED_TEST(rehash_empty_test1, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ) UNORDERED_TEST(rehash_empty_test2, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ((default_generator)(generate_collisions)) ) UNORDERED_TEST(rehash_empty_test3, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ((default_generator)(generate_collisions)) ) UNORDERED_TEST(rehash_test1, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ((default_generator)(generate_collisions)) ) +UNORDERED_TEST(reserve_empty_test1, + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) +) +UNORDERED_TEST(reserve_empty_test2, + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) +) UNORDERED_TEST(reserve_test1, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ((default_generator)(generate_collisions)) ) UNORDERED_TEST(reserve_test2, - ((int_set_ptr)(int_multiset_ptr)(int_map_ptr)(int_multimap_ptr)) + ((int_set_ptr)(test_multiset_ptr)(test_map_ptr)(int_multimap_ptr)) ((default_generator)(generate_collisions)) ) diff --git a/test/unordered/unnecessary_copy_tests.cpp b/test/unordered/unnecessary_copy_tests.cpp index 8cb66049..13bea90e 100644 --- a/test/unordered/unnecessary_copy_tests.cpp +++ b/test/unordered/unnecessary_copy_tests.cpp @@ -374,7 +374,16 @@ namespace unnecessary_copy_tests // COPY_COUNT(1) would be okay here. reset(); x.emplace(); +# if BOOST_WORKAROUND(BOOST_MSVC, >= 1800) + // This is a little odd, Visual C++ 11 seems to move the pair, which + // results in one copy (for the const key) and one move (for the + // non-const mapped value). Since 'emplace(boost::move(a))' (see below) + // has the normal result, it must be some odd consequence of how + // Visual C++ 11 handles calling move for default arguments. + COPY_COUNT(3); MOVE_COUNT(1); +# else COPY_COUNT(2); MOVE_COUNT(0); +# endif #endif reset();