$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r80705 - in trunk/libs/unordered/test: objects unordered
From: dnljms_at_[hidden]
Date: 2012-09-26 04:09:32
Author: danieljames
Date: 2012-09-26 04:09:26 EDT (Wed, 26 Sep 2012)
New Revision: 80705
URL: http://svn.boost.org/trac/boost/changeset/80705
Log:
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.
Text files modified: 
   trunk/libs/unordered/test/objects/test.hpp                     |   120 ++++++++++++++++++++++++++++++++++++++++
   trunk/libs/unordered/test/unordered/insert_tests.cpp           |    97 ++++++++++++++++++++++++++++---         
   trunk/libs/unordered/test/unordered/rehash_tests.cpp           |    64 ++++++++++++++++++---                   
   trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp |     9 +++                                     
   4 files changed, 270 insertions(+), 20 deletions(-)
Modified: trunk/libs/unordered/test/objects/test.hpp
==============================================================================
--- trunk/libs/unordered/test/objects/test.hpp	(original)
+++ trunk/libs/unordered/test/objects/test.hpp	2012-09-26 04:09:26 EDT (Wed, 26 Sep 2012)
@@ -18,6 +18,7 @@
     // 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 @@
     template <class T> class allocator1;
     template <class T> 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 @@
         }
     };
 
+    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<<"("<<o.tag1_<<","<<o.tag2_<<")";
+        }
+    };
+
     class implicitly_convertible : private counted_object
     {
         int tag1_, tag2_;
@@ -81,6 +158,11 @@
             return object(tag1_, tag2_);
         }
 
+        operator movable() const
+        {
+            return movable(tag1_, tag2_);
+        }
+
         friend implicitly_convertible generate(implicitly_convertible const*) {
             int* x = 0;
             return implicitly_convertible(generate(x), generate(x));
@@ -92,6 +174,7 @@
         }
     };
 
+    // Note: This is a deliberately bad hash function.
     class hash
     {
         int type_;
@@ -109,6 +192,17 @@
             }
         }
 
+        std::size_t operator()(movable const& x) const {
+            switch(type_) {
+            case 1:
+                return x.tag1_;
+            case 2:
+                return x.tag2_;
+            default:
+                return x.tag1_ + x.tag2_; 
+            }
+        }
+
         std::size_t operator()(int x) const {
             return x;
         }
@@ -126,6 +220,10 @@
         return hash()(x);
     }
 
+    std::size_t hash_value(test::movable const& x) {
+        return hash()(x);
+    }
+
     class less
     {
         int type_;
@@ -143,6 +241,17 @@
             }
         }
 
+        bool operator()(movable const& x1, movable const& x2) const {
+            switch(type_) {
+            case 1:
+                return x1.tag1_ < x2.tag1_;
+            case 2:
+                return x1.tag2_ < x2.tag2_;
+            default:
+                return x1 < x2;
+            }
+        }
+
         std::size_t operator()(int x1, int x2) const {
             return x1 < x2;
         }
@@ -169,6 +278,17 @@
             }
         }
 
+        bool operator()(movable const& x1, movable const& x2) const {
+            switch(type_) {
+            case 1:
+                return x1.tag1_ == x2.tag1_;
+            case 2:
+                return x1.tag2_ == x2.tag2_;
+            default:
+                return x1 == x2;
+            }
+        }
+
         std::size_t operator()(int x1, int x2) const {
             return x1 == x2;
         }
Modified: trunk/libs/unordered/test/unordered/insert_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/insert_tests.cpp	(original)
+++ trunk/libs/unordered/test/unordered/insert_tests.cpp	2012-09-26 04:09:26 EDT (Wed, 26 Sep 2012)
@@ -16,6 +16,7 @@
 #include "../helpers/equivalent.hpp"
 #include "../helpers/invariants.hpp"
 #include "../helpers/input_iterator.hpp"
+#include "../helpers/helpers.hpp"
 
 #include <iostream>
 
@@ -293,8 +294,6 @@
     }
 }
 
-#if !defined(BOOST_NO_RVALUE_REFERENCES) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
-
 template <class X>
 void unique_emplace_tests1(X*, test::random_generator generator)
 {
@@ -361,7 +360,73 @@
     test::check_equivalent_keys(x);
 }
 
-#endif
+template <class X>
+void move_emplace_tests(X*, test::random_generator generator)
+{
+    typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
+    typedef test::ordered<X> ordered;
+
+    std::cerr<<"emplace(move(value)) tests for containers with unique keys.\n";
+
+    X x;
+    test::ordered<X> tracker = test::create_ordered(x);
+
+    test::random_values<X> v(1000, generator);
+
+    for(BOOST_DEDUCED_TYPENAME test::random_values<X>::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<double>(x.size()) < b * static_cast<double>(old_bucket_count))
+            BOOST_TEST(x.bucket_count() == old_bucket_count);
+    }
+
+    test::check_equivalent_keys(x);
+    tracker.compare(x);
+}
+
+template <class X>
+void default_emplace_tests(X*, test::random_generator)
+{
+    std::cerr<<"emplace() tests.\n";
+    bool is_unique = test::has_unique_keys<X>::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<X>(y)) ==  is_unique ? 1: 3);
+    BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
+
+    x.emplace(y);
+    BOOST_TEST(x.size() ==  is_unique ? 1: 4);
+    BOOST_TEST(x.count(test::get_key<X>(y)) ==  is_unique ? 1: 4);
+    BOOST_TEST(*x.equal_range(test::get_key<X>(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<X>(y)) == is_unique ? 1: 2);
+    BOOST_TEST(*x.equal_range(test::get_key<X>(y)).first == y);
+}
 
 template <class X>
 void map_tests(X*, test::random_generator generator)
@@ -434,9 +499,9 @@
     test::check_equivalent_keys(x);
 }
 
-boost::unordered_set<test::object,
+boost::unordered_set<test::movable,
     test::hash, test::equal_to,
-    std::allocator<test::object> >* test_set_std_alloc;
+    std::allocator<test::movable> >* test_set_std_alloc;
 boost::unordered_multimap<test::object, test::object,
     test::hash, test::equal_to,
     std::allocator<test::object> >* test_multimap_std_alloc;
@@ -444,12 +509,12 @@
 boost::unordered_set<test::object,
     test::hash, test::equal_to,
     test::allocator1<test::object> >* test_set;
-boost::unordered_multiset<test::object,
+boost::unordered_multiset<test::movable,
     test::hash, test::equal_to,
-    test::allocator2<test::object> >* test_multiset;
-boost::unordered_map<test::object, test::object,
+    test::allocator2<test::movable> >* test_multiset;
+boost::unordered_map<test::movable, test::movable,
     test::hash, test::equal_to,
-    test::allocator2<test::object> >* test_map;
+    test::allocator2<test::movable> >* test_map;
 boost::unordered_multimap<test::object, test::object,
     test::hash, test::equal_to,
     test::allocator1<test::object> >* test_multimap;
@@ -472,7 +537,6 @@
     ((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 @@
     ((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))
Modified: trunk/libs/unordered/test/unordered/rehash_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/rehash_tests.cpp	(original)
+++ trunk/libs/unordered/test/unordered/rehash_tests.cpp	2012-09-26 04:09:26 EDT (Wed, 26 Sep 2012)
@@ -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 @@
 
     x.rehash(0);
     BOOST_TEST(postcondition(x, 0));
+
+    x.rehash(10000000);
+    BOOST_TEST(postcondition(x, 10000000));
 }
 
 template <class X>
@@ -54,6 +58,10 @@
     tracker.compare(x);
 
     BOOST_TEST(postcondition(x, 10000));
+    
+    x.rehash(10000000);
+    tracker.compare(x);
+    BOOST_TEST(postcondition(x, 10000000));
 }
 
 template <class X>
@@ -74,7 +82,6 @@
     BOOST_TEST(postcondition(x, 0));
 }
 
-
 template <class X>
 void rehash_test1(X*, test::random_generator generator)
 {
@@ -99,6 +106,35 @@
 }
 
 template <class X>
+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 <class X>
+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 <class X>
 void reserve_test1(X*, test::random_generator generator)
 {
     for (int random_mlf = 0; random_mlf < 2; ++random_mlf)
@@ -165,34 +201,44 @@
 }
 
 boost::unordered_set<int>* int_set_ptr;
-boost::unordered_multiset<int>* int_multiset_ptr;
-boost::unordered_map<int, int>* int_map_ptr;
+boost::unordered_multiset<test::object,
+    test::hash, test::equal_to,
+    test::allocator2<test::object> >* test_multiset_ptr;
+boost::unordered_map<test::movable, test::movable,
+    test::hash, test::equal_to,
+    test::allocator2<test::movable> >* test_map_ptr;
 boost::unordered_multimap<int, int>* 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))
 )
 
Modified: trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp
==============================================================================
--- trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp	(original)
+++ trunk/libs/unordered/test/unordered/unnecessary_copy_tests.cpp	2012-09-26 04:09:26 EDT (Wed, 26 Sep 2012)
@@ -374,7 +374,16 @@
         // 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();