Squashed 'third_party/boostorg/container/' content from commit 1ad6431

Change-Id: I7d095db3455264c03446268e5675b926bebedb0a
git-subtree-dir: third_party/boostorg/container
git-subtree-split: 1ad64316a432a7f021b4956acf88abc6aaa8a77e
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
new file mode 100644
index 0000000..2b4995b
--- /dev/null
+++ b/test/Jamfile.v2
@@ -0,0 +1,40 @@
+# Boost Container Library Test Jamfile
+
+#  (C) Copyright Ion Gaztanaga 2009-2013.
+# Use, modification and distribution are subject to 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)
+
+# Adapted from John Maddock's TR1 Jamfile.v2
+# Copyright John Maddock 2005.
+# Use, modification and distribution are subject to 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)
+
+project
+    : requirements 
+      <link>shared:<define>BOOST_CONTAINER_DYN_LINK=1 
+      <toolset>gcc-cygwin:<link>static
+    ;
+
+# this rule enumerates through all the sources and invokes
+# the run rule for each source, the result is a list of all
+# the run rules, which we can pass on to the test_suite rule:
+
+rule test_all
+{
+   local all_rules = ;
+
+   for local fileb in [ glob *.cpp ]
+   {
+      all_rules += [ run $(fileb)  /boost/container//boost_container
+      :  # additional args
+      :  # test-files
+      :  # requirements
+      ] ;
+   }
+
+   return $(all_rules) ;
+}
+
+test-suite container_test : [ test_all r ] ;
diff --git a/test/alloc_basic_test.cpp b/test/alloc_basic_test.cpp
new file mode 100644
index 0000000..4bfdcf4
--- /dev/null
+++ b/test/alloc_basic_test.cpp
@@ -0,0 +1,119 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/dlmalloc.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/list.hpp>
+
+using namespace boost::container;
+
+bool basic_test()
+{
+   size_t received = 0;
+   if(!dlmalloc_all_deallocated())
+      return false;
+   void *ptr = dlmalloc_alloc(50, 98, &received);
+   if(dlmalloc_size(ptr) != received)
+      return false;
+   if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+      return false;
+
+   if(dlmalloc_all_deallocated())
+      return false;
+
+   dlmalloc_grow(ptr, received + 20, received + 30, &received);
+
+   if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+      return false;
+
+   if(dlmalloc_size(ptr) != received)
+      return false;
+
+   if(!dlmalloc_shrink(ptr, 100, 140, &received, 1))
+      return false;
+
+   if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+      return false;
+
+   if(!dlmalloc_shrink(ptr, 0, 140, &received, 1))
+      return false;
+
+   if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+      return false;
+
+   if(dlmalloc_shrink(ptr, 0, received/2, &received, 1))
+      return false;
+
+   if(dlmalloc_allocated_memory() != dlmalloc_chunksize(ptr))
+      return false;
+
+   if(dlmalloc_size(ptr) != received)
+      return false;
+
+   dlmalloc_free(ptr);
+
+   dlmalloc_malloc_check();
+   if(!dlmalloc_all_deallocated())
+      return false;
+   return true;
+}
+
+bool vector_test()
+{
+   typedef boost::container::vector<int, allocator<int> > Vector;
+   if(!dlmalloc_all_deallocated())
+      return false;
+   {
+      const int NumElem = 1000;
+      Vector v;
+      v.resize(NumElem);
+      int *orig_buf = &v[0];
+      int *new_buf  = &v[0];
+      while(orig_buf == new_buf){
+         Vector::size_type cl = v.capacity() - v.size();
+         while(cl--){
+            v.push_back(0);
+         }
+         v.push_back(0);
+         new_buf = &v[0];
+      }
+   }
+   if(!dlmalloc_all_deallocated())
+      return false;
+   return true;
+}
+
+bool list_test()
+{
+   typedef boost::container::list<int, allocator<int> > List;
+   if(!dlmalloc_all_deallocated())
+      return false;
+   {
+      const int NumElem = 1000;
+      List l;
+      int values[NumElem];
+      l.insert(l.end(), &values[0], &values[NumElem]);
+   }
+   if(!dlmalloc_all_deallocated())
+      return false;
+   return true;
+}
+
+int main()
+{
+   if(!basic_test())
+      return 1;
+   if(!vector_test())
+      return 1;
+   if(!list_test())
+      return 1;
+   return 0;
+}
diff --git a/test/alloc_full_test.cpp b/test/alloc_full_test.cpp
new file mode 100644
index 0000000..54e1160
--- /dev/null
+++ b/test/alloc_full_test.cpp
@@ -0,0 +1,849 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+
+#ifdef _MSC_VER
+#pragma warning (disable:4702)
+#endif
+
+#include <vector>
+#include <iostream>
+#include <cstring>
+#include <algorithm>    //std::remove
+#include <boost/container/detail/dlmalloc.hpp>
+
+namespace boost { namespace container { namespace test {
+
+static const int NumIt = 200;
+
+enum deallocation_type { DirectDeallocation, InverseDeallocation, MixedDeallocation, EndDeallocationType };
+
+//This test allocates until there is no more memory
+//and after that deallocates all in the inverse order
+
+bool test_allocation()
+{
+   if(!dlmalloc_all_deallocated())
+      return false;
+   dlmalloc_malloc_check();
+   for( deallocation_type t = DirectDeallocation
+      ; t != EndDeallocationType
+      ; t = (deallocation_type)((int)t + 1)){
+      std::vector<void*> buffers;
+      //std::size_t free_memory = a.get_free_memory();
+
+      for(int i = 0; i != NumIt; ++i){
+         void *ptr = dlmalloc_malloc(i);
+         if(!ptr)
+            break;
+         buffers.push_back(ptr);
+      }
+
+      switch(t){
+         case DirectDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case InverseDeallocation:
+         {
+            for(int j = (int)buffers.size()
+               ;j--
+               ;){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case MixedDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               int pos = (j%4)*((int)buffers.size())/4;
+               dlmalloc_free(buffers[pos]);
+               buffers.erase(buffers.begin()+pos);
+            }
+         }
+         break;
+         default:
+         break;
+      }
+      if(!dlmalloc_all_deallocated())
+         return false;
+      //bool ok = free_memory == a.get_free_memory() &&
+               //a.all_memory_deallocated() && a.check_sanity();
+      //if(!ok)  return ok;
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to shrink all the buffers to the
+//half of the original size
+
+bool test_allocation_shrink()
+{
+   dlmalloc_malloc_check();
+   std::vector<void*> buffers;
+
+   //Allocate buffers with extra memory
+   for(int i = 0; i != NumIt; ++i){
+      void *ptr = dlmalloc_malloc(i*2);
+      if(!ptr)
+         break;
+      buffers.push_back(ptr);
+   }
+
+   //Now shrink to half
+   for(int i = 0, max = (int)buffers.size()
+      ;i < max
+      ; ++i){
+      std::size_t try_received_size = 0;
+      void* try_result = dlmalloc_allocation_command
+               ( BOOST_CONTAINER_TRY_SHRINK_IN_PLACE, 1, i*2
+               , i, &try_received_size, (char*)buffers[i]).first;
+
+      std::size_t received_size = 0;
+      void* result = dlmalloc_allocation_command
+         ( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, i*2
+         , i, &received_size, (char*)buffers[i]).first;
+
+      if(result != try_result)
+         return false;
+
+      if(received_size != try_received_size)
+         return false;
+
+      if(result){
+         if(received_size > std::size_t(i*2)){
+            return false;
+         }
+         if(received_size < std::size_t(i)){
+            return false;
+         }
+      }
+   }
+
+   //Deallocate it in non sequential order
+   for(int j = 0, max = (int)buffers.size()
+      ;j < max
+      ;++j){
+      int pos = (j%4)*((int)buffers.size())/4;
+      dlmalloc_free(buffers[pos]);
+      buffers.erase(buffers.begin()+pos);
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to expand all the buffers to
+//avoid the wasted internal fragmentation
+
+bool test_allocation_expand()
+{
+   dlmalloc_malloc_check();
+   std::vector<void*> buffers;
+
+   //Allocate buffers with extra memory
+   for(int i = 0; i != NumIt; ++i){
+      void *ptr = dlmalloc_malloc(i);
+      if(!ptr)
+         break;
+      buffers.push_back(ptr);
+   }
+
+   //Now try to expand to the double of the size
+   for(int i = 0, max = (int)buffers.size()
+      ;i < max
+      ;++i){
+      std::size_t received_size = 0;
+      std::size_t min_size = i+1;
+      std::size_t preferred_size = i*2;
+      preferred_size = min_size > preferred_size ? min_size : preferred_size;
+      while(dlmalloc_allocation_command
+         ( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
+         , preferred_size, &received_size, (char*)buffers[i]).first){
+         //Check received size is bigger than minimum
+         if(received_size < min_size){
+            return false;
+         }
+         //Now, try to expand further
+         min_size       = received_size+1;
+         preferred_size = min_size*2;
+      }
+   }
+
+   //Deallocate it in non sequential order
+   for(int j = 0, max = (int)buffers.size()
+      ;j < max
+      ;++j){
+      int pos = (j%4)*((int)buffers.size())/4;
+      dlmalloc_free(buffers[pos]);
+      buffers.erase(buffers.begin()+pos);
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that tries to expand all the buffers to
+//avoid the wasted internal fragmentation
+bool test_allocation_shrink_and_expand()
+{
+   std::vector<void*> buffers;
+   std::vector<std::size_t> received_sizes;
+   std::vector<bool>        size_reduced;
+
+   //Allocate buffers wand store received sizes
+   for(int i = 0; i != NumIt; ++i){
+      std::size_t received_size = 0;
+      void *ptr = dlmalloc_allocation_command
+         (BOOST_CONTAINER_ALLOCATE_NEW, 1, i, i*2, &received_size, 0).first;
+      if(!ptr){
+         ptr = dlmalloc_allocation_command
+            ( BOOST_CONTAINER_ALLOCATE_NEW, 1, 1, i*2, &received_size, 0).first;
+         if(!ptr)
+            break;
+      }
+      buffers.push_back(ptr);
+      received_sizes.push_back(received_size);
+   }
+
+   //Now shrink to half
+   for(int i = 0, max = (int)buffers.size()
+      ; i < max
+      ; ++i){
+      std::size_t received_size = 0;
+      bool size_reduced_flag;
+      if(true == (size_reduced_flag = !!
+         dlmalloc_allocation_command
+         ( BOOST_CONTAINER_SHRINK_IN_PLACE, 1, received_sizes[i]
+         , i, &received_size, (char*)buffers[i]).first)){
+         if(received_size > std::size_t(received_sizes[i])){
+            return false;
+         }
+         if(received_size < std::size_t(i)){
+            return false;
+         }
+      }
+      size_reduced.push_back(size_reduced_flag);
+   }
+
+   //Now try to expand to the original size
+   for(int i = 0, max = (int)buffers.size()
+      ;i < max
+      ;++i){
+      if(!size_reduced[i])  continue;
+      std::size_t received_size = 0;
+      std::size_t request_size =  received_sizes[i];
+      if(dlmalloc_allocation_command
+         ( BOOST_CONTAINER_EXPAND_FWD, 1, request_size
+         , request_size, &received_size, (char*)buffers[i]).first){
+         if(received_size != request_size){
+            return false;
+         }
+      }
+      else{
+         return false;
+      }
+   }
+
+   //Deallocate it in non sequential order
+   for(int j = 0, max = (int)buffers.size()
+      ;j < max
+      ;++j){
+      int pos = (j%4)*((int)buffers.size())/4;
+      dlmalloc_free(buffers[pos]);
+      buffers.erase(buffers.begin()+pos);
+   }
+
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that deallocates the odd buffers to
+//make room for expansions. The expansion will probably
+//success since the deallocation left room for that.
+
+bool test_allocation_deallocation_expand()
+{
+   dlmalloc_malloc_check();
+   std::vector<void*> buffers;
+
+   //Allocate buffers with extra memory
+   for(int i = 0; i != NumIt; ++i){
+      void *ptr = dlmalloc_malloc(i);
+      if(!ptr)
+         break;
+      buffers.push_back(ptr);
+   }
+
+   //Now deallocate the half of the blocks
+   //so expand maybe can merge new free blocks
+   for(int i = 0, max = (int)buffers.size()
+      ;i < max
+      ;++i){
+      if(i%2){
+         dlmalloc_free(buffers[i]);
+         buffers[i] = 0;
+      }
+   }
+
+   //Now try to expand to the double of the size
+   for(int i = 0, max = (int)buffers.size()
+      ;i < max
+      ;++i){
+      //
+      if(buffers[i]){
+         std::size_t received_size = 0;
+         std::size_t min_size = i+1;
+         std::size_t preferred_size = i*2;
+         preferred_size = min_size > preferred_size ? min_size : preferred_size;
+
+         while(dlmalloc_allocation_command
+            ( BOOST_CONTAINER_EXPAND_FWD, 1, min_size
+            , preferred_size, &received_size, (char*)buffers[i]).first){
+            //Check received size is bigger than minimum
+            if(received_size < min_size){
+               return false;
+            }
+            //Now, try to expand further
+            min_size       = received_size+1;
+            preferred_size = min_size*2;
+         }
+      }
+   }
+
+   //Now erase null values from the vector
+   buffers.erase(std::remove(buffers.begin(), buffers.end(), (void*)0)
+                ,buffers.end());
+
+   //Deallocate it in non sequential order
+   for(int j = 0, max = (int)buffers.size()
+      ;j < max
+      ;++j){
+      int pos = (j%4)*((int)buffers.size())/4;
+      dlmalloc_free(buffers[pos]);
+      buffers.erase(buffers.begin()+pos);
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates until there is no more memory
+//and after that deallocates all except the last.
+//If the allocation algorithm is a bottom-up algorithm
+//the last buffer will be in the end of the segment.
+//Then the test will start expanding backwards, until
+//the buffer fills all the memory
+
+bool test_allocation_with_reuse()
+{
+   dlmalloc_malloc_check();
+   //We will repeat this test for different sized elements
+   for(int sizeof_object = 1; sizeof_object < 20; ++sizeof_object){
+      std::vector<void*> buffers;
+
+      //Allocate buffers with extra memory
+      for(int i = 0; i != NumIt; ++i){
+         void *ptr = dlmalloc_malloc(i*sizeof_object);
+         if(!ptr)
+            break;
+         buffers.push_back(ptr);
+      }
+
+      //Now deallocate all except the latest
+      //Now try to expand to the double of the size
+      for(int i = 0, max = (int)buffers.size() - 1
+         ;i < max
+         ;++i){
+         dlmalloc_free(buffers[i]);
+      }
+
+      //Save the unique buffer and clear vector
+      void *ptr = buffers.back();
+      buffers.clear();
+
+      //Now allocate with reuse
+      std::size_t received_size = 0;
+      for(int i = 0; i != NumIt; ++i){
+         std::size_t min_size = (received_size/sizeof_object + 1)*sizeof_object;
+         std::size_t prf_size = (received_size/sizeof_object + (i+1)*2)*sizeof_object;
+         dlmalloc_command_ret_t ret = dlmalloc_allocation_command
+            ( BOOST_CONTAINER_EXPAND_BWD, sizeof_object, min_size
+            , prf_size, &received_size, (char*)ptr);
+         //If we have memory, this must be a buffer reuse
+         if(!ret.first)
+            break;
+         //If we have memory, this must be a buffer reuse
+         if(!ret.second)
+            return false;
+         if(received_size < min_size)
+            return false;
+         ptr = ret.first;
+      }
+      //There should be only a single block so deallocate it
+      dlmalloc_free(ptr);
+      dlmalloc_malloc_check();
+      if(!dlmalloc_all_deallocated())
+         return false;
+   }
+   return true;
+}
+
+
+//This test allocates memory with different alignments
+//and checks returned memory is aligned.
+
+bool test_aligned_allocation()
+{
+   dlmalloc_malloc_check();
+   //Allocate aligned buffers in a loop
+   //and then deallocate it
+   for(unsigned int i = 1; i != (1 << (sizeof(int)/2)); i <<= 1){
+      for(unsigned int j = 1; j != 512; j <<= 1){
+         void *ptr = dlmalloc_memalign(i-1, j);
+         if(!ptr){
+            return false;
+         }
+
+         if(((std::size_t)ptr & (j - 1)) != 0)
+            return false;
+         dlmalloc_free(ptr);
+         //if(!a.all_memory_deallocated() || !a.check_sanity()){
+         //   return false;
+         //}
+      }
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates memory with different alignments
+//and checks returned memory is aligned.
+
+bool test_continuous_aligned_allocation()
+{
+   dlmalloc_malloc_check();
+   std::vector<void*> buffers;
+   //Allocate aligned buffers in a loop
+   //and then deallocate it
+   bool continue_loop = true;
+   unsigned int MaxAlign = 4096;
+   unsigned int MaxSize  = 4096;
+   for(unsigned i = 1; i < MaxSize; i <<= 1){
+      for(unsigned int j = 1; j < MaxAlign; j <<= 1){
+         for(int k = 0; k != NumIt; ++k){
+            void *ptr = dlmalloc_memalign(i-1, j);
+            buffers.push_back(ptr);
+            if(!ptr){
+               continue_loop = false;
+               break;
+            }
+
+            if(((std::size_t)ptr & (j - 1)) != 0)
+               return false;
+         }
+         //Deallocate all
+         for(int k = (int)buffers.size(); k--;){
+            dlmalloc_free(buffers[k]);
+         }
+         buffers.clear();
+         //if(!a.all_memory_deallocated() && a.check_sanity())
+         //   return false;
+         if(!continue_loop)
+            break;
+      }
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();//a.all_memory_deallocated() && a.check_sanity();
+}
+
+//This test allocates multiple values until there is no more memory
+//and after that deallocates all in the inverse order
+bool test_many_equal_allocation()
+{
+   dlmalloc_malloc_check();
+   for( deallocation_type t = DirectDeallocation
+      ; t != EndDeallocationType
+      ; t = (deallocation_type)((int)t + 1)){
+      //std::size_t free_memory = a.get_free_memory();
+
+      std::vector<void*> buffers2;
+
+      //Allocate buffers with extra memory
+      for(int i = 0; i != NumIt; ++i){
+         void *ptr = dlmalloc_malloc(i);
+         if(!ptr)
+            break;
+         //if(!a.check_sanity())
+            //return false;
+         buffers2.push_back(ptr);
+      }
+
+      //Now deallocate the half of the blocks
+      //so expand maybe can merge new free blocks
+      for(int i = 0, max = (int)buffers2.size()
+         ;i < max
+         ;++i){
+         if(i%2){
+            dlmalloc_free(buffers2[i]);
+            buffers2[i] = 0;
+         }
+      }
+
+      //if(!a.check_sanity())
+         //return false;
+
+      std::vector<void*> buffers;
+      for(int i = 0; i != NumIt/10; ++i){
+         dlmalloc_memchain chain;
+         BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+         dlmalloc_multialloc_nodes((i+1)*2, i+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+         dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+         if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+            break;
+
+         std::size_t n = 0;
+         for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
+            buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
+            BOOST_CONTAINER_MEMIT_NEXT(it);
+         }
+         if(n != std::size_t((i+1)*2))
+            return false;
+      }
+
+      //if(!a.check_sanity())
+         //return false;
+
+      switch(t){
+         case DirectDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case InverseDeallocation:
+         {
+            for(int j = (int)buffers.size()
+               ;j--
+               ;){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case MixedDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               int pos = (j%4)*((int)buffers.size())/4;
+               dlmalloc_free(buffers[pos]);
+               buffers.erase(buffers.begin()+pos);
+            }
+         }
+         break;
+         default:
+         break;
+      }
+
+      //Deallocate the rest of the blocks
+
+      //Deallocate it in non sequential order
+      for(int j = 0, max = (int)buffers2.size()
+         ;j < max
+         ;++j){
+         int pos = (j%4)*((int)buffers2.size())/4;
+         dlmalloc_free(buffers2[pos]);
+         buffers2.erase(buffers2.begin()+pos);
+      }
+
+      //bool ok = free_memory == a.get_free_memory() &&
+               //a.all_memory_deallocated() && a.check_sanity();
+      //if(!ok)  return ok;
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();
+}
+
+//This test allocates multiple values until there is no more memory
+//and after that deallocates all in the inverse order
+
+bool test_many_different_allocation()
+{
+   dlmalloc_malloc_check();
+   const std::size_t ArraySize = 11;
+   std::size_t requested_sizes[ArraySize];
+   for(std::size_t i = 0; i < ArraySize; ++i){
+      requested_sizes[i] = 4*i;
+   }
+
+   for( deallocation_type t = DirectDeallocation
+      ; t != EndDeallocationType
+      ; t = (deallocation_type)((int)t + 1)){
+      //std::size_t free_memory = a.get_free_memory();
+
+      std::vector<void*> buffers2;
+
+      //Allocate buffers with extra memory
+      for(int i = 0; i != NumIt; ++i){
+         void *ptr = dlmalloc_malloc(i);
+         if(!ptr)
+            break;
+         buffers2.push_back(ptr);
+      }
+
+      //Now deallocate the half of the blocks
+      //so expand maybe can merge new free blocks
+      for(int i = 0, max = (int)buffers2.size()
+         ;i < max
+         ;++i){
+         if(i%2){
+            dlmalloc_free(buffers2[i]);
+            buffers2[i] = 0;
+         }
+      }
+
+      std::vector<void*> buffers;
+      for(int i = 0; i != NumIt; ++i){
+         dlmalloc_memchain chain;
+         BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+         dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+         dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+         if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+            break;
+         std::size_t n = 0;
+         for(; !BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it); ++n){
+            buffers.push_back(BOOST_CONTAINER_MEMIT_ADDR(it));
+            BOOST_CONTAINER_MEMIT_NEXT(it);
+         }
+         if(n != ArraySize)
+            return false;
+      }
+
+      switch(t){
+         case DirectDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case InverseDeallocation:
+         {
+            for(int j = (int)buffers.size()
+               ;j--
+               ;){
+               dlmalloc_free(buffers[j]);
+            }
+         }
+         break;
+         case MixedDeallocation:
+         {
+            for(int j = 0, max = (int)buffers.size()
+               ;j < max
+               ;++j){
+               int pos = (j%4)*((int)buffers.size())/4;
+               dlmalloc_free(buffers[pos]);
+               buffers.erase(buffers.begin()+pos);
+            }
+         }
+         break;
+         default:
+         break;
+      }
+
+      //Deallocate the rest of the blocks
+
+      //Deallocate it in non sequential order
+      for(int j = 0, max = (int)buffers2.size()
+         ;j < max
+         ;++j){
+         int pos = (j%4)*((int)buffers2.size())/4;
+         dlmalloc_free(buffers2[pos]);
+         buffers2.erase(buffers2.begin()+pos);
+      }
+
+      //bool ok = free_memory == a.get_free_memory() &&
+               //a.all_memory_deallocated() && a.check_sanity();
+      //if(!ok)  return ok;
+   }
+   dlmalloc_malloc_check();
+   return 0 != dlmalloc_all_deallocated();
+}
+
+bool test_many_deallocation()
+{
+   const std::size_t ArraySize = 11;
+   std::vector<dlmalloc_memchain> buffers;
+   std::size_t requested_sizes[ArraySize];
+   for(std::size_t i = 0; i < ArraySize; ++i){
+      requested_sizes[i] = 4*i;
+   }
+
+   for(int i = 0; i != NumIt; ++i){
+      dlmalloc_memchain chain;
+      BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+      dlmalloc_multialloc_arrays(ArraySize, requested_sizes, 1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+      dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+      if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+         return false;
+      buffers.push_back(chain);
+   }
+   for(int i = 0; i != NumIt; ++i){
+      dlmalloc_multidealloc(&buffers[i]);
+   }
+   buffers.clear();
+
+   dlmalloc_malloc_check();
+   if(!dlmalloc_all_deallocated())
+      return false;
+
+   for(int i = 0; i != NumIt; ++i){
+      dlmalloc_memchain chain;
+      BOOST_CONTAINER_MEMCHAIN_INIT(&chain);
+      dlmalloc_multialloc_nodes(ArraySize, i*4+1, DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &chain);
+      dlmalloc_memchain_it it = BOOST_CONTAINER_MEMCHAIN_BEGIN_IT(&chain);
+      if(BOOST_CONTAINER_MEMCHAIN_IS_END_IT(chain, it))
+         return false;
+      buffers.push_back(chain);
+   }
+   for(int i = 0; i != NumIt; ++i){
+      dlmalloc_multidealloc(&buffers[i]);
+   }
+   buffers.clear();
+
+   dlmalloc_malloc_check();
+   if(!dlmalloc_all_deallocated())
+      return false;
+
+   return true;
+}
+
+//This function calls all tests
+
+bool test_all_allocation()
+{
+   std::cout << "Starting test_allocation"
+             << std::endl;
+
+   if(!test_allocation()){
+      std::cout << "test_allocation_direct_deallocation failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_many_equal_allocation"
+             << std::endl;
+
+   if(!test_many_equal_allocation()){
+      std::cout << "test_many_equal_allocation failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_many_different_allocation"
+             << std::endl;
+
+   if(!test_many_different_allocation()){
+      std::cout << "test_many_different_allocation failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_allocation_shrink"
+             << std::endl;
+
+   if(!test_allocation_shrink()){
+      std::cout << "test_allocation_shrink failed"
+                << std::endl;
+      return false;
+   }
+
+   if(!test_allocation_shrink_and_expand()){
+      std::cout << "test_allocation_shrink_and_expand failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_allocation_expand"
+             << std::endl;
+
+   if(!test_allocation_expand()){
+      std::cout << "test_allocation_expand failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_allocation_deallocation_expand"
+             << std::endl;
+
+   if(!test_allocation_deallocation_expand()){
+      std::cout << "test_allocation_deallocation_expand failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_allocation_with_reuse"
+             << std::endl;
+
+   if(!test_allocation_with_reuse()){
+      std::cout << "test_allocation_with_reuse failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_aligned_allocation"
+             << std::endl;
+
+   if(!test_aligned_allocation()){
+      std::cout << "test_aligned_allocation failed"
+                << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_continuous_aligned_allocation"
+             << std::endl;
+
+   if(!test_continuous_aligned_allocation()){
+      std::cout << "test_continuous_aligned_allocation failed"
+                << std::endl;
+      return false;
+   }
+
+   if(!test_many_deallocation()){
+      std::cout << "test_many_deallocation failed"
+                << std::endl;
+      return false;
+   }
+
+   return 0 != dlmalloc_all_deallocated();
+}
+
+}}}   //namespace boost { namespace container { namespace test {
+
+
+int main()
+{
+   if(!boost::container::test::test_all_allocation())
+      return 1;
+   return 0;
+}
diff --git a/test/allocator_argument_tester.hpp b/test/allocator_argument_tester.hpp
new file mode 100644
index 0000000..7399328
--- /dev/null
+++ b/test/allocator_argument_tester.hpp
@@ -0,0 +1,233 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+
+#include <boost/container/uses_allocator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/core.hpp>
+
+template<class T, unsigned int Id, bool HasTrueTypes = false>
+class propagation_test_allocator
+{
+   BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+   public:
+
+   template<class U>
+   struct rebind
+   {
+      typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
+   };
+
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_copy_assignment;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_move_assignment;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_swap;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  is_always_equal;
+   typedef T value_type;
+
+   propagation_test_allocator()
+      : m_move_contructed(false), m_move_assigned(false)
+   {}
+
+   propagation_test_allocator(const propagation_test_allocator&)
+      : m_move_contructed(false), m_move_assigned(false)
+   {}
+
+   propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
+      : m_move_contructed(true), m_move_assigned(false)
+   {}
+
+   template<class U>
+   propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
+      : m_move_contructed(true), m_move_assigned(false)
+   {}
+
+   template<class U>
+   propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
+   {}
+
+   propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
+   {
+      return *this;
+   }
+
+   propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
+   {
+      m_move_assigned = true;
+      return *this;
+   }
+
+   std::size_t max_size() const
+   {  return std::size_t(-1);  }
+
+   T* allocate(std::size_t n)
+   {  return (T*)::new char[n*sizeof(T)];  }
+
+   void deallocate(T*p, std::size_t)
+   {  delete []static_cast<char*>(static_cast<void*>(p));  }
+
+   bool m_move_contructed;
+   bool m_move_assigned;
+};
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+               , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{  return true;   }
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+               , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{  return false;   }
+
+//This enum lists the construction options
+//for an allocator-aware type
+enum ConstructionTypeEnum
+{
+   ConstructiblePrefix,
+   ConstructibleSuffix,
+   NotUsesAllocator
+};
+
+//This base class provices types for
+//the derived class to implement each construction
+//type. If a construction type does not apply
+//the typedef is set to an internal nat
+//so that the class is not constructible from
+//the user arguments.
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct uses_allocator_base;
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
+{
+   typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+   typedef allocator_type allocator_constructor_type;
+   struct nat{};
+   typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
+{
+   typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+   typedef allocator_type allocator_constructor_type;
+   typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
+{
+   struct nat{};
+   typedef nat allocator_constructor_type;
+   typedef nat allocator_arg_type;
+};
+
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct allocator_argument_tester
+   : uses_allocator_base<ConstructionType, AllocatorTag>
+{
+   private:
+   BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
+
+   public:
+
+   typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
+
+   //0 user argument constructors
+   allocator_argument_tester()
+      : construction_type(NotUsesAllocator), value(0)
+   {}
+
+   explicit allocator_argument_tester
+      (typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(0)
+   {}
+
+   explicit allocator_argument_tester
+      (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
+      : construction_type(ConstructiblePrefix), value(0)
+   {}
+
+   //1 user argument constructors
+   explicit allocator_argument_tester(int i)
+      : construction_type(NotUsesAllocator), value(i)
+   {}
+
+   allocator_argument_tester
+      (int i, typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(i)
+   {}
+
+   allocator_argument_tester
+      ( typename base_type::allocator_arg_type
+      , typename base_type::allocator_constructor_type
+      , int i)
+      : construction_type(ConstructiblePrefix), value(i)
+   {}
+
+   //Copy constructors
+   allocator_argument_tester(const allocator_argument_tester &other)
+      : construction_type(NotUsesAllocator), value(other.value)
+   {}
+
+   allocator_argument_tester( const allocator_argument_tester &other
+                            , typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(other.value)
+   {}
+
+   allocator_argument_tester( typename base_type::allocator_arg_type
+                            , typename base_type::allocator_constructor_type
+                            , const allocator_argument_tester &other)
+      : construction_type(ConstructiblePrefix), value(other.value)
+   {}
+
+   //Move constructors
+   allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
+      : construction_type(NotUsesAllocator), value(other.value)
+   {  other.value = 0;  other.construction_type = NotUsesAllocator;  }
+
+   allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
+                            , typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(other.value)
+   {  other.value = 0;  other.construction_type = ConstructibleSuffix;  }
+
+   allocator_argument_tester( typename base_type::allocator_arg_type
+                            , typename base_type::allocator_constructor_type
+                            , BOOST_RV_REF(allocator_argument_tester) other)
+      : construction_type(ConstructiblePrefix), value(other.value)
+   {  other.value = 0;  other.construction_type = ConstructiblePrefix;  }
+
+   ConstructionTypeEnum construction_type;
+   int                  value;
+};
+
+namespace boost {
+namespace container {
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+   < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+   < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+}  //namespace container {
+}  //namespace boost {
+
+#endif   //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
diff --git a/test/allocator_traits_test.cpp b/test/allocator_traits_test.cpp
new file mode 100644
index 0000000..4014424
--- /dev/null
+++ b/test/allocator_traits_test.cpp
@@ -0,0 +1,447 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <cstddef>
+#include <boost/container/allocator_traits.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/function_detector.hpp>
+#include <boost/move/utility_core.hpp>
+#include <memory>
+#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+#include <boost/move/detail/fwd_macros.hpp>
+#endif
+#include <boost/core/lightweight_test.hpp>
+
+template<class T>
+class SimpleAllocator
+{
+   public:
+   bool allocate_called_;
+   bool deallocate_called_;
+
+   typedef boost::container::dtl::
+      true_type                                 is_always_equal;
+
+   typedef T value_type;
+
+   template <class U>
+   SimpleAllocator(SimpleAllocator<U>)
+      : allocate_called_(false)
+      , deallocate_called_(false)
+   {}
+
+   SimpleAllocator()
+      : allocate_called_(false)
+      , deallocate_called_(false)
+   {}
+
+   T* allocate(std::size_t)
+   {  allocate_called_ = true; return 0;  }
+
+   void deallocate(T*, std::size_t)
+   {  deallocate_called_ = true;  }
+
+   bool allocate_called() const
+   {  return allocate_called_;  }
+
+   bool deallocate_called() const
+   {  return deallocate_called_;  }
+
+   friend bool operator==(const SimpleAllocator &, const SimpleAllocator &)
+   {  return true;  }
+
+   friend bool operator!=(const SimpleAllocator &, const SimpleAllocator &)
+   {  return false;  }
+};
+
+template<class T>
+class SimpleSmartPtr
+{
+   void unspecified_bool_type_func() const {}
+   typedef void (SimpleSmartPtr::*unspecified_bool_type)() const;
+
+   public:
+
+   typedef T* pointer;
+
+   explicit SimpleSmartPtr(pointer p = 0)
+    : ptr_(p)
+   {}
+
+   SimpleSmartPtr(const SimpleSmartPtr &c)
+   {  this->ptr_ = c.ptr_; }
+
+   SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
+   {  this->ptr_ = c.ptr_; }
+
+   operator unspecified_bool_type() const
+   {  return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0;   }
+
+   private:
+   T *ptr_;
+};
+
+template<class T>
+class ComplexAllocator
+{
+   public:
+   bool allocate_called_;
+   bool deallocate_called_;
+   bool allocate_hint_called_;
+   bool destroy_called_;
+   mutable bool max_size_called_;
+   mutable bool select_on_container_copy_construction_called_;
+   bool construct_called_;
+   mutable bool storage_is_unpropagable_;
+
+   typedef T value_type;
+   typedef SimpleSmartPtr<T>                    pointer;
+   typedef SimpleSmartPtr<const T>              const_pointer;
+   typedef typename ::boost::container::
+      dtl::unvoid_ref<T>::type     reference;
+   typedef typename ::boost::container::
+      dtl::unvoid_ref<const T>::type     const_reference;
+   typedef SimpleSmartPtr<void>                 void_pointer;
+   typedef SimpleSmartPtr<const void>           const_void_pointer;
+   typedef signed short                         difference_type;
+   typedef unsigned short                       size_type;
+   typedef boost::container::dtl::
+      true_type                                 propagate_on_container_copy_assignment;
+   typedef boost::container::dtl::
+      true_type                                 propagate_on_container_move_assignment;
+   typedef boost::container::dtl::
+      true_type                                 propagate_on_container_swap;
+   typedef boost::container::dtl::
+      true_type                                 is_partially_propagable;
+
+   ComplexAllocator()
+      : allocate_called_(false)
+      , deallocate_called_(false)
+      , allocate_hint_called_(false)
+      , destroy_called_(false)
+      , max_size_called_(false)
+      , select_on_container_copy_construction_called_(false)
+      , construct_called_(false)
+   {}
+
+   pointer allocate(size_type)
+   {  allocate_called_ = true; return pointer();  }
+
+   void deallocate(pointer, size_type)
+   {  deallocate_called_ = true;  }
+
+   //optional
+   ComplexAllocator select_on_container_copy_construction() const
+   {  select_on_container_copy_construction_called_ = true; return *this;  }
+
+   pointer allocate(size_type n, const const_void_pointer &)
+   {  allocate_hint_called_ = true; return allocate(n);  }
+
+   template<class U>
+   void destroy(U*)
+   {  destroy_called_ = true;  }
+
+   size_type max_size() const
+   {  max_size_called_ = true; return size_type(size_type(0)-1);  }
+
+   #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+   #define BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL(N)\
+   \
+   template< class U BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
+   void construct(U *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
+   {  construct_called_ = true;  ::new(p) U ( BOOST_MOVE_FWD##N ); }\
+   //
+   BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL)
+   #undef BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL
+   #else
+
+   template< class U, class ...Args>
+   void construct(U *p, BOOST_FWD_REF(Args) ...args)
+   {  construct_called_ = true;  ::new(p) U( ::boost::forward<Args>(args)...); }
+
+   #endif
+
+   template<class U>
+   void construct(U *p, boost::container::default_init_t)
+   {  construct_called_ = true;  ::new(p)U;   }
+
+   bool storage_is_unpropagable(pointer p) const
+   {  storage_is_unpropagable_ = true; return !p;  }
+
+   //getters
+   bool allocate_called() const
+   {  return allocate_called_;  }
+
+   bool deallocate_called() const
+   {  return deallocate_called_;  }
+
+   bool allocate_hint_called() const
+   {  return allocate_hint_called_;  }
+
+   bool destroy_called() const
+   {  return destroy_called_;  }
+
+   bool max_size_called() const
+   {  return max_size_called_;  }
+
+   bool select_on_container_copy_construction_called() const
+   {  return select_on_container_copy_construction_called_;  }
+
+   bool construct_called() const
+   {  return construct_called_;  }
+
+   bool storage_is_unpropagable_called() const
+   {  return storage_is_unpropagable_;  }
+};
+
+class copymovable
+{
+   BOOST_COPYABLE_AND_MOVABLE(copymovable)
+
+   public:
+
+   bool copymoveconstructed_;
+   bool moved_;
+
+   copymovable(int, int, int)
+      : copymoveconstructed_(false), moved_(false)
+   {}
+
+   copymovable()
+      : copymoveconstructed_(false), moved_(false)
+   {}
+
+   copymovable(const copymovable &)
+      : copymoveconstructed_(true), moved_(false)
+   {}
+
+   copymovable(BOOST_RV_REF(copymovable))
+      : copymoveconstructed_(true), moved_(true)
+   {}
+
+   copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; }
+   copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; }
+
+   bool copymoveconstructed() const
+   {  return copymoveconstructed_;  }
+
+   bool moved() const
+   {  return moved_;  }
+};
+
+void test_void_allocator()
+{
+   boost::container::allocator_traits<std::allocator<void>   > stdtraits; (void)stdtraits;
+   boost::container::allocator_traits<SimpleAllocator<void>  > simtraits; (void)simtraits;
+   boost::container::allocator_traits<ComplexAllocator<void> > comtraits; (void)comtraits;
+}
+
+int main()
+{
+   using namespace boost::container::dtl;
+   test_void_allocator();
+
+   //SimpleAllocator
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::value_type, int>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::pointer, int*>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::const_pointer, const int*>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::void_pointer, void*>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::const_void_pointer, const void*>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::difference_type, std::ptrdiff_t>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::size_type, std::size_t>::value ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator<int> >::propagate_on_container_copy_assignment::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator<int> >::propagate_on_container_swap::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator<int> >::is_always_equal::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < SimpleAllocator<int> >::is_partially_propagable::value == false ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::rebind_traits<double>::allocator_type
+                       , SimpleAllocator<double> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < SimpleAllocator<int> >::rebind_alloc<double>::value_type
+                       , double >::value ));
+
+   //ComplexAllocator
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::value_type, int>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::pointer,  SimpleSmartPtr<int> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::const_pointer, SimpleSmartPtr<const int> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::void_pointer, SimpleSmartPtr<void> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::const_void_pointer, SimpleSmartPtr<const void> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::difference_type, signed short>::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::size_type, unsigned short>::value ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator<int> >::propagate_on_container_copy_assignment::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator<int> >::propagate_on_container_swap::value == true ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator<int> >::is_always_equal::value == false ));
+   BOOST_STATIC_ASSERT(( boost::container::allocator_traits
+                       < ComplexAllocator<int> >::is_partially_propagable::value == true ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::rebind_traits<double>::allocator_type
+                       , ComplexAllocator<double> >::value ));
+   BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits
+                       < ComplexAllocator<int> >::rebind_alloc<double>::value_type
+                       , double >::value ));
+
+   typedef ComplexAllocator<int> CAlloc;
+   typedef SimpleAllocator<int> SAlloc;
+   typedef boost::container::allocator_traits<CAlloc> CAllocTraits;
+   typedef boost::container::allocator_traits<SAlloc> SAllocTraits;
+   CAlloc c_alloc;
+   SAlloc s_alloc;
+
+   //allocate
+   CAllocTraits::allocate(c_alloc, 1);
+   BOOST_TEST(c_alloc.allocate_called());
+
+   SAllocTraits::allocate(s_alloc, 1);
+   BOOST_TEST(s_alloc.allocate_called());
+
+   //deallocate
+   CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1);
+   BOOST_TEST(c_alloc.deallocate_called());
+
+   SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1);
+   BOOST_TEST(s_alloc.deallocate_called());
+
+   //allocate with hint
+   CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer());
+   BOOST_TEST(c_alloc.allocate_hint_called());
+
+   s_alloc.allocate_called_ = false;
+   SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer());
+   BOOST_TEST(s_alloc.allocate_called());
+
+   //destroy
+   float dummy;
+   CAllocTraits::destroy(c_alloc, &dummy);
+   BOOST_TEST(c_alloc.destroy_called());
+
+   SAllocTraits::destroy(s_alloc, &dummy);
+
+   //max_size
+   CAllocTraits::max_size(c_alloc);
+   BOOST_TEST(c_alloc.max_size_called());
+
+   BOOST_TEST(SAllocTraits::size_type(-1)/sizeof(SAllocTraits::value_type) == SAllocTraits::max_size(s_alloc));
+
+   //select_on_container_copy_construction
+   CAllocTraits::select_on_container_copy_construction(c_alloc);
+   BOOST_TEST(c_alloc.select_on_container_copy_construction_called());
+
+   SAllocTraits::select_on_container_copy_construction(s_alloc);
+
+   //construct
+   {
+      copymovable c;
+      c.copymoveconstructed_ = true;
+      c.copymoveconstructed_ = true;
+      CAllocTraits::construct(c_alloc, &c);
+      BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
+   }
+   {
+      int i = 5;
+      CAllocTraits::construct(c_alloc, &i, boost::container::default_init);
+      BOOST_TEST(c_alloc.construct_called() && i == 5);
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      CAllocTraits::construct(c_alloc, &c, c2);
+      BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && !c.moved());
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      CAllocTraits::construct(c_alloc, &c, ::boost::move(c2));
+      BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && c.moved());
+   }
+   {
+      copymovable c;
+      c.copymoveconstructed_ = true;
+      c.copymoveconstructed_ = true;
+      SAllocTraits::construct(s_alloc, &c);
+      BOOST_TEST(!c.copymoveconstructed() && !c.moved());
+   }
+   {
+      int i = 4;
+      SAllocTraits::construct(s_alloc, &i, boost::container::default_init);
+      BOOST_TEST(i == 4);
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, c2);
+      BOOST_TEST(c.copymoveconstructed() && !c.moved());
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, ::boost::move(c2));
+      BOOST_TEST(c.copymoveconstructed() && c.moved());
+   }
+   {
+      copymovable c;
+      CAllocTraits::construct(c_alloc, &c, 0, 1, 2);
+      BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved());
+   }
+   {
+      copymovable c;
+      copymovable c2;
+      SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
+      BOOST_TEST(!c.copymoveconstructed() && !c.moved());
+   }
+   //storage_is_unpropagable
+   {
+      SAlloc s_alloc2;
+      BOOST_TEST(!SAllocTraits::storage_is_unpropagable(s_alloc, SAllocTraits::pointer()));
+   }
+   {
+      {
+         CAlloc c_alloc2;
+         CAlloc::value_type v;
+         BOOST_TEST(!CAllocTraits::storage_is_unpropagable(c_alloc, CAllocTraits::pointer(&v)));
+         BOOST_TEST(c_alloc.storage_is_unpropagable_called());
+      }
+      {
+         CAlloc c_alloc2;
+         BOOST_TEST( CAllocTraits::storage_is_unpropagable(c_alloc2, CAllocTraits::pointer()));
+         BOOST_TEST(c_alloc2.storage_is_unpropagable_called());
+      }
+
+   }
+
+   return ::boost::report_errors();
+}
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/check_equal_containers.hpp b/test/check_equal_containers.hpp
new file mode 100644
index 0000000..e9b6607
--- /dev/null
+++ b/test/check_equal_containers.hpp
@@ -0,0 +1,128 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
+#define BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/unique_ptr.hpp>
+
+#include <cstddef>
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template< class T1, class T2>
+bool CheckEqual( const T1 &t1, const T2 &t2
+               , typename boost::container::dtl::enable_if_c
+                  <!boost::container::dtl::is_pair<T1>::value &&
+                   !boost::container::dtl::is_pair<T2>::value
+                  >::type* = 0)
+{  return t1 == t2;  }
+
+
+template<class T1, class T2, class C1, class C2>
+bool CheckEqualIt( const T1 &i1, const T2 &i2, const C1 &c1, const C2 &c2 )
+{
+   bool c1end = i1 == c1.end();
+   bool c2end = i2 == c2.end();
+   if( c1end != c2end ){
+      return false;
+   }
+   else if(c1end){
+      return true;
+   }
+   else{
+      return CheckEqual(*i1, *i2);
+   }
+}
+
+template< class Pair1, class Pair2>
+bool CheckEqual( const Pair1 &pair1, const Pair2 &pair2
+               , typename boost::container::dtl::enable_if_c
+                  <boost::container::dtl::is_pair<Pair1>::value &&
+                   boost::container::dtl::is_pair<Pair2>::value
+                  >::type* = 0)
+{
+   return CheckEqual(pair1.first, pair2.first) && CheckEqual(pair1.second, pair2.second);
+}
+
+//Function to check if both containers are equal
+template<class ContA
+        ,class ContB>
+bool CheckEqualContainers(const ContA &cont_a, const ContB &cont_b)
+{
+   if(cont_a.size() != cont_b.size())
+      return false;
+
+   typename ContA::const_iterator itcont_a(cont_a.begin()), itcont_a_end(cont_a.end());
+   typename ContB::const_iterator itcont_b(cont_b.begin()), itcont_b_end(cont_b.end());;
+   typename ContB::size_type dist = (typename ContB::size_type)boost::container::iterator_distance(itcont_a, itcont_a_end);
+   if(dist != cont_a.size()){
+      return false;
+   }
+   typename ContA::size_type dist2 = (typename ContA::size_type)boost::container::iterator_distance(itcont_b, itcont_b_end);
+   if(dist2 != cont_b.size()){
+      return false;
+   }
+   std::size_t i = 0;
+   for(; itcont_a != itcont_a_end; ++itcont_a, ++itcont_b, ++i){
+      if(!CheckEqual(*itcont_a, *itcont_b))
+         return false;
+   }
+   return true;
+}
+
+template<class MyBoostCont
+        ,class MyStdCont>
+bool CheckEqualPairContainers(const MyBoostCont &boostcont, const MyStdCont &stdcont)
+{
+   if(boostcont.size() != stdcont.size())
+      return false;
+
+   typedef typename MyBoostCont::key_type      key_type;
+   typedef typename MyBoostCont::mapped_type   mapped_type;
+
+   typename MyBoostCont::const_iterator itboost(boostcont.begin()), itboostend(boostcont.end());
+   typename MyStdCont::const_iterator itstd(stdcont.begin());
+   for(; itboost != itboostend; ++itboost, ++itstd){
+      key_type k(itstd->first);
+      if(itboost->first != k)
+         return false;
+
+      mapped_type m(itstd->second);
+      if(itboost->second != m)
+         return false;
+   }
+   return true;
+}
+
+struct less_transparent
+{
+   typedef void is_transparent;
+
+   template<class T, class U>
+   bool operator()(const T &t, const U &u) const
+   {
+      return t < u;
+   }
+};
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_CHECK_EQUAL_CONTAINER_HPP
diff --git a/test/comparison_test.hpp b/test/comparison_test.hpp
new file mode 100644
index 0000000..7f3f1b3
--- /dev/null
+++ b/test/comparison_test.hpp
@@ -0,0 +1,58 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2017-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
+#define BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
+
+#include <deque>
+#include <boost/core/lightweight_test.hpp>
+
+namespace boost {
+namespace container {
+namespace test {
+
+
+template<class Cont>
+bool test_container_comparisons()
+{
+   typedef typename Cont::value_type value_type;
+
+   Cont cont;
+   cont.push_back(value_type(1));
+   cont.push_back(value_type(2));
+   cont.push_back(value_type(3));
+
+   Cont cont_equal(cont);
+
+   Cont cont_less;
+   cont_less.push_back(value_type(1));
+   cont_less.push_back(value_type(2));
+   cont_less.push_back(value_type(2));
+
+   BOOST_TEST(cont == cont_equal);
+   BOOST_TEST(!(cont != cont_equal));
+   BOOST_TEST(cont != cont_less);
+   BOOST_TEST(cont_less < cont);
+   BOOST_TEST(cont_less <= cont);
+   BOOST_TEST(!(cont_less > cont));
+   BOOST_TEST(!(cont_less >= cont));
+   BOOST_TEST(!(cont < cont_less));
+   BOOST_TEST(!(cont <= cont_less));
+   BOOST_TEST(cont > cont_less);
+   BOOST_TEST(cont >= cont_less);
+
+   return ::boost::report_errors() == 0;
+}
+
+}  //namespace test {
+}  //namespace container {
+}  //namespace boost {
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_COMPARISON_TEST_HPP
diff --git a/test/container_common_tests.hpp b/test/container_common_tests.hpp
new file mode 100644
index 0000000..63e1547
--- /dev/null
+++ b/test/container_common_tests.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
+#define BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+
+template<class Container>
+const Container &as_const(Container &c)
+{  return c;   }
+
+//nth, index_of
+template<class Container>
+bool test_nth_index_of(Container &c)
+{
+   typename Container::iterator it;
+   typename Container::const_iterator cit;
+   typename Container::size_type sz, csz;
+   //index 0
+   it = c.nth(0);
+   sz = c.index_of(it);
+   cit = (as_const)(c).nth(0);
+   csz = (as_const)(c).index_of(cit);
+
+   if(it != c.begin())
+      return false;
+   if(cit != c.cbegin())
+      return false;
+   if(sz != 0)
+      return false;
+   if(csz != 0)
+      return false;
+
+   //index size()/2
+   const typename Container::size_type sz_div_2 = c.size()/2;
+   it = c.nth(sz_div_2);
+   sz = c.index_of(it);
+   cit = (as_const)(c).nth(sz_div_2);
+   csz = (as_const)(c).index_of(cit);
+
+   if(it != (c.begin()+sz_div_2))
+      return false;
+   if(cit != (c.cbegin()+sz_div_2))
+      return false;
+   if(sz != sz_div_2)
+      return false;
+   if(csz != sz_div_2)
+      return false;
+
+   //index size()
+   it = c.nth(c.size());
+   sz = c.index_of(it);
+   cit = (as_const)(c).nth(c.size());
+   csz = (as_const)(c).index_of(cit);
+
+   if(it != c.end())
+      return false;
+   if(cit != c.cend())
+      return false;
+   if(sz != c.size())
+      return false;
+   if(csz != c.size())
+      return false;
+   return true;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_CONTAINER_TEST_CONTAINER_COMMON_TESTS_HPP
diff --git a/test/default_init_test.hpp b/test/default_init_test.hpp
new file mode 100644
index 0000000..2e83a36
--- /dev/null
+++ b/test/default_init_test.hpp
@@ -0,0 +1,155 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2013-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
+#define BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <cstddef>
+
+namespace boost{
+namespace container {
+namespace test{
+
+//
+template<int Dummy = 0>
+class default_init_allocator_base
+{
+   protected:
+   static unsigned char s_pattern;
+   static bool          s_ascending;
+
+   public:
+   static void reset_pattern(unsigned char value)
+   {  s_pattern = value;   }
+
+   static void set_ascending(bool enable)
+   {  s_ascending = enable;   }
+};
+
+template<int Dummy>
+unsigned char default_init_allocator_base<Dummy>::s_pattern = 0u;
+
+template<int Dummy>
+bool default_init_allocator_base<Dummy>::s_ascending = true;
+
+template<class Integral>
+class default_init_allocator
+   : public default_init_allocator_base<0>
+{
+   typedef default_init_allocator_base<0> base_t;
+   public:
+   typedef Integral value_type;
+
+   default_init_allocator()
+   {}
+
+   template <class U>
+   default_init_allocator(default_init_allocator<U>)
+   {}
+
+   Integral* allocate(std::size_t n)
+   {
+      //Initialize memory to a pattern
+      const std::size_t max = sizeof(Integral)*n;
+      unsigned char *puc_raw = ::new unsigned char[max];
+
+      if(base_t::s_ascending){
+         for(std::size_t i = 0; i != max; ++i){
+            puc_raw[i] = static_cast<unsigned char>(s_pattern++);
+         }
+      }
+      else{
+         for(std::size_t i = 0; i != max; ++i){
+            puc_raw[i] = static_cast<unsigned char>(s_pattern--);
+         }
+      }
+      return (Integral*)puc_raw;;
+   }
+
+   void deallocate(Integral *p, std::size_t)
+   {  delete[] (unsigned char*)p;  }
+};
+
+template<class Integral>
+inline bool check_ascending_byte_pattern(const Integral&t)
+{
+   const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
+   const std::size_t max = sizeof(Integral);
+   for(std::size_t i = 1; i != max; ++i){
+      if( (pch[i-1] != ((unsigned char)(pch[i]-1u))) ){
+         return false;
+      }
+   }
+   return true;
+}
+
+template<class Integral>
+inline bool check_descending_byte_pattern(const Integral&t)
+{
+   const unsigned char *pch = &reinterpret_cast<const unsigned char &>(t);
+   const std::size_t max = sizeof(Integral);
+   for(std::size_t i = 1; i != max; ++i){
+      if( (pch[i-1] != ((unsigned char)(pch[i]+1u))) ){
+         return false;
+      }
+   }
+   return true;
+}
+
+template<class IntDefaultInitAllocVector>
+bool default_init_test()//Test for default initialization
+{
+   const std::size_t Capacity = 100;
+
+   {
+      test::default_init_allocator<int>::reset_pattern(0);
+      test::default_init_allocator<int>::set_ascending(true);
+      IntDefaultInitAllocVector v(Capacity, default_init);
+      typename IntDefaultInitAllocVector::iterator it = v.begin();
+      //Compare with the pattern
+      for(std::size_t i = 0; i != Capacity; ++i, ++it){
+         if(!test::check_ascending_byte_pattern(*it))
+            return false;
+      }
+   }
+   {
+      test::default_init_allocator<int>::reset_pattern(0);
+      test::default_init_allocator<int>::set_ascending(true);
+      IntDefaultInitAllocVector v(Capacity, default_init, typename IntDefaultInitAllocVector::allocator_type());
+      typename IntDefaultInitAllocVector::iterator it = v.begin();
+      //Compare with the pattern
+      for(std::size_t i = 0; i != Capacity; ++i, ++it){
+         if(!test::check_ascending_byte_pattern(*it))
+            return false;
+      }
+   }
+   {
+      test::default_init_allocator<int>::reset_pattern(100);
+      test::default_init_allocator<int>::set_ascending(false);
+      IntDefaultInitAllocVector v;
+      v.resize(Capacity, default_init);
+      typename IntDefaultInitAllocVector::iterator it = v.begin();
+      //Compare with the pattern
+      for(std::size_t i = 0; i != Capacity; ++i, ++it){
+         if(!test::check_descending_byte_pattern(*it))
+            return false;
+      }
+   }
+   return true;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_TEST_DEFAULT_INIT_TEST_HEADER
diff --git a/test/deque_test.cpp b/test/deque_test.cpp
new file mode 100644
index 0000000..b226f8f
--- /dev/null
+++ b/test/deque_test.cpp
@@ -0,0 +1,432 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+#include <deque>
+#include <iostream>
+#include <list>
+
+#include <boost/container/deque.hpp>
+#include <boost/container/allocator.hpp>
+
+#include "print_container.hpp"
+#include "check_equal_containers.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <string>
+#include "emplace_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include <boost/core/no_exceptions_support.hpp>
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::deque
+ < test::movable_and_copyable_int
+ , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::deque
+   < test::movable_and_copyable_int
+   , allocator<test::movable_and_copyable_int> >;
+
+}}
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool deque_copyable_only(V1 &, V2 &, dtl::false_type)
+{
+   return true;
+}
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool deque_copyable_only(V1 &cntdeque, V2 &stddeque, dtl::true_type)
+{
+   typedef typename V1::value_type IntType;
+   std::size_t size = cntdeque.size();
+   stddeque.insert(stddeque.end(), 50, 1);
+   cntdeque.insert(cntdeque.end(), 50, IntType(1));
+   if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+   {
+      IntType move_me(1);
+      stddeque.insert(stddeque.begin()+size/2, 50, 1);
+      cntdeque.insert(cntdeque.begin()+size/2, 50, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+   }
+   {
+      IntType move_me(2);
+      cntdeque.assign(cntdeque.size()/2, boost::move(move_me));
+      stddeque.assign(stddeque.size()/2, 2);
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+   }
+   {
+      IntType move_me(1);
+      stddeque.clear();
+      cntdeque.clear();
+      stddeque.insert(stddeque.begin(), 50, 1);
+      cntdeque.insert(cntdeque.begin(), 50, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      stddeque.insert(stddeque.begin()+20, 50, 1);
+      cntdeque.insert(cntdeque.begin()+20, 50, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      stddeque.insert(stddeque.begin()+20, 20, 1);
+      cntdeque.insert(cntdeque.begin()+20, 20, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+   }
+   {
+      IntType move_me(1);
+      stddeque.clear();
+      cntdeque.clear();
+      stddeque.insert(stddeque.end(), 50, 1);
+      cntdeque.insert(cntdeque.end(), 50, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      stddeque.insert(stddeque.end()-20, 50, 1);
+      cntdeque.insert(cntdeque.end()-20, 50, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      stddeque.insert(stddeque.end()-20, 20, 1);
+      cntdeque.insert(cntdeque.end()-20, 20, boost::move(move_me));
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+   }
+
+   return true;
+}
+
+//Test recursive structures
+class recursive_deque
+{
+public:
+
+   recursive_deque & operator=(const recursive_deque &x)
+   {  this->deque_ = x.deque_;   return *this; }
+
+   int id_;
+   deque<recursive_deque> deque_;
+   deque<recursive_deque>::iterator it_;
+   deque<recursive_deque>::const_iterator cit_;
+   deque<recursive_deque>::reverse_iterator rit_;
+   deque<recursive_deque>::const_reverse_iterator crit_;
+};
+
+template<class IntType>
+bool do_test()
+{
+   //Test for recursive types
+   {
+      deque<recursive_deque> recursive_deque_deque;
+   }
+
+   {
+      //Now test move semantics
+      deque<recursive_deque> original;
+      deque<recursive_deque> move_ctor(boost::move(original));
+      deque<recursive_deque> move_assign;
+      move_assign = boost::move(move_ctor);
+      move_assign.swap(original);
+   }
+
+   //Alias deque types
+   typedef deque<IntType>  MyCntDeque;
+   typedef std::deque<int> MyStdDeque;
+   const int max = 100;
+   {
+      ::boost::movelib::unique_ptr<MyCntDeque> const pcntdeque = ::boost::movelib::make_unique<MyCntDeque>();
+      ::boost::movelib::unique_ptr<MyStdDeque> const pstddeque = ::boost::movelib::make_unique<MyStdDeque>();
+      MyCntDeque &cntdeque = *pcntdeque;
+      MyStdDeque &stddeque = *pstddeque;
+      for(int i = 0; i < max*100; ++i){
+         IntType move_me(i);
+         cntdeque.insert(cntdeque.end(), boost::move(move_me));
+         stddeque.insert(stddeque.end(), i);
+      }
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      cntdeque.clear();
+      stddeque.clear();
+
+      for(int i = 0; i < max*100; ++i){
+         IntType move_me(i);
+         cntdeque.push_back(boost::move(move_me));
+         stddeque.push_back(i);
+      }
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      cntdeque.clear();
+      stddeque.clear();
+
+      for(int i = 0; i < max*100; ++i){
+         IntType move_me(i);
+         cntdeque.push_front(boost::move(move_me));
+         stddeque.push_front(i);
+      }
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      typename MyCntDeque::iterator it;
+      typename MyCntDeque::const_iterator cit = it;
+      (void)cit;
+
+      cntdeque.erase(cntdeque.begin()++);
+      stddeque.erase(stddeque.begin()++);
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      cntdeque.erase(cntdeque.begin());
+      stddeque.erase(stddeque.begin());
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      {
+         //Initialize values
+         IntType aux_vect[50];
+         for(int i = 0; i < 50; ++i){
+            IntType move_me (-1);
+            aux_vect[i] = boost::move(move_me);
+         }
+         int aux_vect2[50];
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = -1;
+         }
+
+         cntdeque.insert(cntdeque.end()
+                           ,boost::make_move_iterator(&aux_vect[0])
+                           ,boost::make_move_iterator(aux_vect + 50));
+         stddeque.insert(stddeque.end(), aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+         for(int i = 0; i < 50; ++i){
+            IntType move_me (i);
+            aux_vect[i] = boost::move(move_me);
+         }
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = i;
+         }
+
+         cntdeque.insert(cntdeque.begin()+cntdeque.size()
+                           ,boost::make_move_iterator(&aux_vect[0])
+                           ,boost::make_move_iterator(aux_vect + 50));
+         stddeque.insert(stddeque.begin()+stddeque.size(), aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+         for(int i = 0, j = static_cast<int>(cntdeque.size()); i < j; ++i){
+            cntdeque.erase(cntdeque.begin());
+            stddeque.erase(stddeque.begin());
+         }
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      }
+      {
+         IntType aux_vect[50];
+         for(int i = 0; i < 50; ++i){
+            IntType move_me(-1);
+            aux_vect[i] = boost::move(move_me);
+         }
+         int aux_vect2[50];
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = -1;
+         }
+         cntdeque.insert(cntdeque.begin()
+                           ,boost::make_move_iterator(&aux_vect[0])
+                           ,boost::make_move_iterator(aux_vect + 50));
+         stddeque.insert(stddeque.begin(), aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+      }
+
+      if(!deque_copyable_only(cntdeque, stddeque
+                     ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+         return false;
+      }
+
+      cntdeque.erase(cntdeque.begin());
+      stddeque.erase(stddeque.begin());
+
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      for(int i = 0; i < max; ++i){
+         IntType move_me(i);
+         cntdeque.insert(cntdeque.begin(), boost::move(move_me));
+         stddeque.insert(stddeque.begin(), i);
+      }
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return false;
+
+      //Test insertion from list
+      {
+         std::list<int> l(50, int(1));
+         cntdeque.insert(cntdeque.begin(), l.begin(), l.end());
+         stddeque.insert(stddeque.begin(), l.begin(), l.end());
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+         cntdeque.assign(l.begin(), l.end());
+         stddeque.assign(l.begin(), l.end());
+         if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+      }
+
+      cntdeque.resize(100);
+      stddeque.resize(100);
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+
+      cntdeque.resize(200);
+      stddeque.resize(200);
+      if(!test::CheckEqualContainers(cntdeque, stddeque)) return 1;
+   }
+
+#if __cplusplus >= 201703L
+   //Check Constructor Template Auto Deduction
+   {
+      auto gold = MyStdDeque{ 1, 2, 3 };
+      auto test = deque(gold.begin(), gold.end());
+      if(!test::CheckEqualContainers(gold, test)) return false;
+   }
+   {
+      auto gold = MyStdDeque{ 1, 2, 3 };
+      auto test = deque(gold.begin(), gold.end(), new_allocator<int>());
+      if(!test::CheckEqualContainers(gold, test)) return false;
+   }
+#endif
+
+   std::cout << std::endl << "Test OK!" << std::endl;
+   return true;
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef deque< ValueType
+                    , typename allocator_traits<VoidAllocator>
+                        ::template portable_rebind_alloc<ValueType>::type
+                    > type;
+   };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+   if(test::vector_test<MyCont>())
+      return 1;
+   if(test::vector_test<MyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyCont>())
+      return 1;
+   return 0;
+}
+
+struct boost_container_deque;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_deque>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::deque<T, Allocator> type;
+   };
+};
+
+}}}   //namespace boost::container::test
+
+int main ()
+{
+   if(!do_test<int>())
+      return 1;
+
+   if(!do_test<test::movable_int>())
+      return 1;
+
+   if(!do_test<test::movable_and_copyable_int>())
+      return 1;
+
+   if(!do_test<test::copyable_int>())
+      return 1;
+
+   //Test non-copy-move operations
+   {
+      deque<test::non_copymovable_int> d;
+      d.emplace_back();
+      d.emplace_front(1);
+      d.resize(10);
+      d.resize(1);
+   }
+
+   ////////////////////////////////////
+   //    Allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_cont_variants< std::allocator<void> >()){
+      std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::allocator
+   if(test_cont_variants< allocator<void> >()){
+      std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   ////////////////////////////////////
+   //    Default init test
+   ////////////////////////////////////
+   if(!test::default_init_test< deque<int, test::default_init_allocator<int> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
+
+   if(!boost::container::test::test_emplace
+      < deque<test::EmplaceInt>, Options>())
+      return 1;
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_deque>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Initializer lists testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+      < boost::container::deque<int> >()) {
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::deque<int> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/derived_from_memory_resource.hpp b/test/derived_from_memory_resource.hpp
new file mode 100644
index 0000000..a8097a7
--- /dev/null
+++ b/test/derived_from_memory_resource.hpp
@@ -0,0 +1,87 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
+#define BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
+
+#include <boost/container/pmr/memory_resource.hpp>
+
+class derived_from_memory_resource
+   : public boost::container::pmr::memory_resource
+{
+   public:
+   explicit derived_from_memory_resource(unsigned i = 0u)
+      : id(i)
+   {}
+
+   virtual ~derived_from_memory_resource()
+   {  destructor_called = true;  }
+
+   virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+   {
+      do_allocate_called = true;
+      do_allocate_bytes = bytes;
+      do_allocate_alignment = alignment;
+      return do_allocate_return;
+   }
+
+   virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+   {
+      do_deallocate_called = true;
+      do_deallocate_p = p;
+      do_deallocate_bytes = bytes;
+      do_deallocate_alignment = alignment;
+   }
+
+   virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
+   {
+      do_is_equal_called = true;
+      do_is_equal_other = &other;
+      return static_cast<const derived_from_memory_resource&>(other).id == this->id;
+   }
+
+   void reset()
+   {
+      destructor_called = false;
+
+      do_allocate_return = 0;
+      do_allocate_called = false;
+      do_allocate_bytes = 0u;
+      do_allocate_alignment = 0u;
+
+      do_deallocate_called = false;
+      do_deallocate_p = 0;
+      do_deallocate_bytes = 0u;
+      do_deallocate_alignment = 0u;
+
+      do_is_equal_called = false;
+      do_is_equal_other = 0;
+   }
+   //checkers
+   static bool destructor_called;
+
+   unsigned id;
+   void *do_allocate_return;
+   mutable bool do_allocate_called;
+   mutable std::size_t do_allocate_bytes;
+   mutable std::size_t do_allocate_alignment;
+
+   mutable bool do_deallocate_called;
+   mutable void *do_deallocate_p;
+   mutable std::size_t do_deallocate_bytes;
+   mutable std::size_t do_deallocate_alignment;
+
+   mutable bool do_is_equal_called;
+   mutable const boost::container::pmr::memory_resource *do_is_equal_other;
+};
+
+bool derived_from_memory_resource::destructor_called = false;
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_DERIVED_FROM_MEMORY_RESOURCE_HPP
diff --git a/test/dummy_test_allocator.hpp b/test/dummy_test_allocator.hpp
new file mode 100644
index 0000000..024ab0e
--- /dev/null
+++ b/test/dummy_test_allocator.hpp
@@ -0,0 +1,232 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+#define BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+#  include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#  pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/container/detail/multiallocation_chain.hpp>
+#include <boost/container/detail/type_traits.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/assert.hpp>
+
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace test {
+
+//Very simple version 1 allocator
+template<class T>
+class simple_allocator
+{
+   public:
+   typedef T value_type;
+
+   simple_allocator()
+   {}
+
+   template<class U>
+   simple_allocator(const simple_allocator<U> &)
+   {}
+
+   T* allocate(std::size_t n)
+   { return (T*)::new char[sizeof(T)*n];  }
+
+   void deallocate(T*p, std::size_t)
+   { delete[] ((char*)p);}
+
+   friend bool operator==(const simple_allocator &, const simple_allocator &)
+   {  return true;  }
+
+   friend bool operator!=(const simple_allocator &, const simple_allocator &)
+   {  return false;  }
+};
+
+template< class T
+        , bool PropagateOnContCopyAssign
+        , bool PropagateOnContMoveAssign
+        , bool PropagateOnContSwap
+        , bool CopyOnPropagateOnContSwap
+        >
+class propagation_test_allocator
+{
+   BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+
+   public:
+   typedef T value_type;
+   typedef boost::container::dtl::bool_<PropagateOnContCopyAssign>
+      propagate_on_container_copy_assignment;
+   typedef boost::container::dtl::bool_<PropagateOnContMoveAssign>
+      propagate_on_container_move_assignment;
+   typedef boost::container::dtl::bool_<PropagateOnContSwap>
+      propagate_on_container_swap;
+
+   template<class T2>
+   struct rebind
+   {  typedef propagation_test_allocator
+         < T2
+         , PropagateOnContCopyAssign
+         , PropagateOnContMoveAssign
+         , PropagateOnContSwap
+         , CopyOnPropagateOnContSwap>   other;
+   };
+
+   propagation_test_allocator select_on_container_copy_construction() const
+   {  return CopyOnPropagateOnContSwap ? propagation_test_allocator(*this) : propagation_test_allocator();  }
+
+   explicit propagation_test_allocator()
+      : id_(++unique_id_)
+      , ctr_copies_(0)
+      , ctr_moves_(0)
+      , assign_copies_(0)
+      , assign_moves_(0)
+      , swaps_(0)
+   {}
+
+   propagation_test_allocator(const propagation_test_allocator &x)
+      : id_(x.id_)
+      , ctr_copies_(x.ctr_copies_+1)
+      , ctr_moves_(x.ctr_moves_)
+      , assign_copies_(x.assign_copies_)
+      , assign_moves_(x.assign_moves_)
+      , swaps_(x.swaps_)
+   {}
+
+   template<class U>
+   propagation_test_allocator(const propagation_test_allocator
+                                       < U
+                                       , PropagateOnContCopyAssign
+                                       , PropagateOnContMoveAssign
+                                       , PropagateOnContSwap
+                                       , CopyOnPropagateOnContSwap> &x)
+      : id_(x.id_)
+      , ctr_copies_(x.ctr_copies_+1)
+      , ctr_moves_(0)
+      , assign_copies_(0)
+      , assign_moves_(0)
+      , swaps_(0)
+   {}
+
+   propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) x)
+      : id_(x.id_)
+      , ctr_copies_(x.ctr_copies_)
+      , ctr_moves_(x.ctr_moves_ + 1)
+      , assign_copies_(x.assign_copies_)
+      , assign_moves_(x.assign_moves_)
+      , swaps_(x.swaps_)
+   {}
+
+   propagation_test_allocator &operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator) x)
+   {
+      id_ = x.id_;
+      ctr_copies_ = x.ctr_copies_;
+      ctr_moves_ = x.ctr_moves_;
+      assign_copies_ = x.assign_copies_+1;
+      assign_moves_ = x.assign_moves_;
+      swaps_ = x.swaps_;
+      return *this;
+   }
+
+   propagation_test_allocator &operator=(BOOST_RV_REF(propagation_test_allocator) x)
+   {
+      id_ = x.id_;
+      ctr_copies_ = x.ctr_copies_;
+      ctr_moves_ = x.ctr_moves_;
+      assign_copies_ = x.assign_copies_;
+      assign_moves_ = x.assign_moves_+1;
+      swaps_ = x.swaps_;
+      return *this;
+   }
+
+   static void reset_unique_id(unsigned id = 0)
+   {  unique_id_ = id;  }
+
+   T* allocate(std::size_t n)
+   {  return (T*)::new char[sizeof(T)*n];  }
+
+   void deallocate(T*p, std::size_t)
+   { delete[] ((char*)p);}
+
+   friend bool operator==(const propagation_test_allocator &, const propagation_test_allocator &)
+   {  return true;  }
+
+   friend bool operator!=(const propagation_test_allocator &, const propagation_test_allocator &)
+   {  return false;  }
+
+   void swap(propagation_test_allocator &r)
+   {
+      ++this->swaps_; ++r.swaps_;
+      boost::adl_move_swap(this->id_, r.id_);
+      boost::adl_move_swap(this->ctr_copies_, r.ctr_copies_);
+      boost::adl_move_swap(this->ctr_moves_, r.ctr_moves_);
+      boost::adl_move_swap(this->assign_copies_, r.assign_copies_);
+      boost::adl_move_swap(this->assign_moves_, r.assign_moves_);
+      boost::adl_move_swap(this->swaps_, r.swaps_);
+   }
+
+   friend void swap(propagation_test_allocator &l, propagation_test_allocator &r)
+   {
+      l.swap(r);
+   }
+
+   unsigned int id_;
+   unsigned int ctr_copies_;
+   unsigned int ctr_moves_;
+   unsigned int assign_copies_;
+   unsigned int assign_moves_;
+   unsigned int swaps_;
+   static unsigned unique_id_;
+};
+
+template< class T
+        , bool PropagateOnContCopyAssign
+        , bool PropagateOnContMoveAssign
+        , bool PropagateOnContSwap
+        , bool CopyOnPropagateOnContSwap
+        >
+unsigned int propagation_test_allocator< T
+                                       , PropagateOnContCopyAssign
+                                       , PropagateOnContMoveAssign
+                                       , PropagateOnContSwap
+                                       , CopyOnPropagateOnContSwap>::unique_id_ = 0;
+
+
+}  //namespace test {
+}  //namespace container {
+}  //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //BOOST_CONTAINER_DUMMY_TEST_ALLOCATOR_HPP
+
diff --git a/test/emplace_test.hpp b/test/emplace_test.hpp
new file mode 100644
index 0000000..cd8147b
--- /dev/null
+++ b/test/emplace_test.hpp
@@ -0,0 +1,683 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
+#define BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
+
+#include <iostream>
+#include <typeinfo>
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+class EmplaceInt
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(EmplaceInt)
+
+   public:
+   EmplaceInt(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0)
+      : a_(a), b_(b), c_(c), d_(d), e_(e)
+   {}
+
+   EmplaceInt(BOOST_RV_REF(EmplaceInt) o)
+      : a_(o.a_), b_(o.b_), c_(o.c_), d_(o.d_), e_(o.e_)
+   {}
+
+   EmplaceInt& operator=(BOOST_RV_REF(EmplaceInt) o)
+   {
+      this->a_ = o.a_;
+      this->b_ = o.b_;
+      this->c_ = o.c_;
+      this->d_ = o.d_;
+      this->e_ = o.e_;
+      return *this;
+   }
+
+   friend bool operator==(const EmplaceInt &l, const EmplaceInt &r)
+   {
+      return l.a_ == r.a_ &&
+             l.b_ == r.b_ &&
+             l.c_ == r.c_ &&
+             l.d_ == r.d_ &&
+             l.e_ == r.e_;
+   }
+
+   friend bool operator<(const EmplaceInt &l, const EmplaceInt &r)
+   {  return l.sum() < r.sum(); }
+
+   friend bool operator>(const EmplaceInt &l, const EmplaceInt &r)
+   {  return l.sum() > r.sum(); }
+
+   friend bool operator!=(const EmplaceInt &l, const EmplaceInt &r)
+   {  return !(l == r); }
+
+   friend std::ostream &operator <<(std::ostream &os, const EmplaceInt &v)
+   {
+      os << "EmplaceInt: " << v.a_ << ' ' << v.b_ << ' ' << v.c_ << ' ' << v.d_ << ' ' << v.e_;
+      return os;
+   }
+
+   ~EmplaceInt()
+   {  a_ = b_ = c_ = d_ = e_ = 0; }
+
+   //private:
+   int sum() const
+   {  return this->a_ + this->b_ + this->c_ + this->d_ + this->e_; }
+
+   int a_, b_, c_, d_, e_;
+   int padding[6];
+};
+
+
+}  //namespace test {
+
+namespace test {
+
+enum EmplaceOptions{
+   EMPLACE_BACK         = 1 << 0,
+   EMPLACE_FRONT        = 1 << 1,
+   EMPLACE_BEFORE       = 1 << 2,
+   EMPLACE_AFTER        = 1 << 3,
+   EMPLACE_ASSOC        = 1 << 4,
+   EMPLACE_HINT         = 1 << 5,
+   EMPLACE_ASSOC_PAIR   = 1 << 6,
+   EMPLACE_HINT_PAIR    = 1 << 7
+};
+
+template<class Container>
+bool test_expected_container(const Container &ec, const EmplaceInt *Expected, unsigned int only_first_n, unsigned int cont_offset = 0)
+{
+   typedef typename Container::const_iterator const_iterator;
+   const_iterator itb(ec.begin()), ite(ec.end());
+   unsigned int cur = 0;
+   if(cont_offset > ec.size()){
+      return false;
+   }
+   if(only_first_n > (ec.size() - cont_offset)){
+      return false;
+   }
+   while(cont_offset--){
+      ++itb;
+   }
+   for(; itb != ite && only_first_n--; ++itb, ++cur){
+      const EmplaceInt & cr = *itb;
+      if(cr != Expected[cur]){
+         return false;
+      }
+   }
+   return true;
+}
+
+template<class Container>
+bool test_expected_container(const Container &ec, const std::pair<EmplaceInt, EmplaceInt> *Expected, unsigned int only_first_n)
+{
+   typedef typename Container::const_iterator const_iterator;
+   const_iterator itb(ec.begin()), ite(ec.end());
+   unsigned int cur = 0;
+   if(only_first_n > ec.size()){
+      return false;
+   }
+   for(; itb != ite && only_first_n--; ++itb, ++cur){
+      if(itb->first != Expected[cur].first){
+         std::cout << "Error in first: " << itb->first << ' ' << Expected[cur].first << std::endl;
+         return false;
+
+      }
+      else if(itb->second != Expected[cur].second){
+         std::cout << "Error in second: " << itb->second << ' ' << Expected[cur].second << std::endl;
+         return false;
+      }
+   }
+   return true;
+}
+
+typedef std::pair<EmplaceInt, EmplaceInt> EmplaceIntPair;
+static boost::container::dtl::aligned_storage<sizeof(EmplaceIntPair)*10>::type pair_storage;
+
+static EmplaceIntPair* initialize_emplace_int_pair()
+{
+   EmplaceIntPair* ret = reinterpret_cast<EmplaceIntPair*>(&pair_storage);
+   for(unsigned int i = 0; i != 10; ++i){
+      new(&ret->first)EmplaceInt();
+      new(&ret->second)EmplaceInt();
+   }
+   return ret;
+}
+
+static EmplaceIntPair * expected_pair = initialize_emplace_int_pair();
+
+
+template<class Container>
+bool test_emplace_back(dtl::true_)
+{
+   std::cout << "Starting test_emplace_back." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+
+   {
+      new(&expected [0]) EmplaceInt();
+      new(&expected [1]) EmplaceInt(1);
+      new(&expected [2]) EmplaceInt(1, 2);
+      new(&expected [3]) EmplaceInt(1, 2, 3);
+      new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+      new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+      Container c;
+      typedef typename Container::reference reference;
+      {
+         reference r = c.emplace_back();
+         if(&r != &c.back() && !test_expected_container(c, &expected[0], 1)){
+            return false;
+         }
+      }
+      {
+         reference r = c.emplace_back(1);
+         if(&r != &c.back() && !test_expected_container(c, &expected[0], 2)){
+            return false;
+         }
+      }
+      c.emplace_back(1, 2);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+      c.emplace_back(1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 4)){
+         return false;
+      }
+      c.emplace_back(1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 5)){
+         return false;
+      }
+      c.emplace_back(1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+   }
+   std::cout << "...OK" << std::endl;
+   return true;
+}
+
+template<class Container>
+bool test_emplace_back(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_front(dtl::true_)
+{
+   std::cout << "Starting test_emplace_front." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+   {
+      new(&expected [0]) EmplaceInt(1, 2, 3, 4, 5);
+      new(&expected [1]) EmplaceInt(1, 2, 3, 4);
+      new(&expected [2]) EmplaceInt(1, 2, 3);
+      new(&expected [3]) EmplaceInt(1, 2);
+      new(&expected [4]) EmplaceInt(1);
+      new(&expected [5]) EmplaceInt();
+      Container c;
+      typedef typename Container::reference reference;
+      {
+         reference r = c.emplace_front();
+         if(&r != &c.front() && !test_expected_container(c, &expected[0] + 5, 1)){
+            return false;
+         }
+      }
+      {
+         reference r = c.emplace_front(1);
+         if(&r != &c.front() && !test_expected_container(c, &expected[0] + 4, 2)){
+            return false;
+         }
+      }
+      c.emplace_front(1, 2);
+      if(!test_expected_container(c, &expected[0] + 3, 3)){
+         return false;
+      }
+      c.emplace_front(1, 2, 3);
+      if(!test_expected_container(c, &expected[0] + 2, 4)){
+         return false;
+      }
+      c.emplace_front(1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0] + 1, 5)){
+         return false;
+      }
+      c.emplace_front(1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0] + 0, 6)){
+         return false;
+      }
+   }
+   std::cout << "...OK" << std::endl;
+   return true;
+}
+
+template<class Container>
+bool test_emplace_front(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_before(dtl::true_)
+{
+   std::cout << "Starting test_emplace_before." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+   {
+      new(&expected [0]) EmplaceInt();
+      new(&expected [1]) EmplaceInt(1);
+      new(&expected [2]) EmplaceInt();
+      Container c;
+      c.emplace(c.cend(), 1);
+      c.emplace(c.cbegin());
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      c.emplace(c.cend());
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+   }
+   {
+      new(&expected [0]) EmplaceInt();
+      new(&expected [1]) EmplaceInt(1);
+      new(&expected [2]) EmplaceInt(1, 2);
+      new(&expected [3]) EmplaceInt(1, 2, 3);
+      new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+      new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+      //emplace_front-like
+      Container c;
+      c.emplace(c.cbegin(), 1, 2, 3, 4, 5);
+      c.emplace(c.cbegin(), 1, 2, 3, 4);
+      c.emplace(c.cbegin(), 1, 2, 3);
+      c.emplace(c.cbegin(), 1, 2);
+      c.emplace(c.cbegin(), 1);
+      c.emplace(c.cbegin());
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      c.clear();
+      //emplace_back-like
+      typename Container::const_iterator i = c.emplace(c.cend());
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      i = c.emplace(++i, 1);
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      i = c.emplace(++i, 1, 2);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+      i = c.emplace(++i, 1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 4)){
+         return false;
+      }
+      i = c.emplace(++i, 1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 5)){
+         return false;
+      }
+      i = c.emplace(++i, 1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      c.clear();
+      //emplace in the middle
+      c.emplace(c.cbegin());
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      i = c.emplace(c.cend(), 1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      if(!test_expected_container(c, &expected[5], 1, 1)){
+         return false;
+      }
+      i = c.emplace(i, 1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      if(!test_expected_container(c, &expected[4], 2, 1)){
+         return false;
+      }
+      i = c.emplace(i, 1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      if(!test_expected_container(c, &expected[3], 3, 1)){
+         return false;
+      }
+      i = c.emplace(i, 1, 2);
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      if(!test_expected_container(c, &expected[2], 4, 1)){
+         return false;
+      }
+      i = c.emplace(i, 1);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+   return true;
+}
+
+template<class Container>
+bool test_emplace_before(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_after(dtl::true_)
+{
+   std::cout << "Starting test_emplace_after." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+   {
+      new(&expected [0]) EmplaceInt();
+      new(&expected [1]) EmplaceInt(1);
+      new(&expected [2]) EmplaceInt();
+      Container c;
+      typename Container::const_iterator i = c.emplace_after(c.cbefore_begin(), 1);
+      c.emplace_after(c.cbefore_begin());
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      c.emplace_after(i);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+   }
+   {
+      new(&expected [0]) EmplaceInt();
+      new(&expected [1]) EmplaceInt(1);
+      new(&expected [2]) EmplaceInt(1, 2);
+      new(&expected [3]) EmplaceInt(1, 2, 3);
+      new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+      new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+      //emplace_front-like
+      Container c;
+      c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4, 5);
+      c.emplace_after(c.cbefore_begin(), 1, 2, 3, 4);
+      c.emplace_after(c.cbefore_begin(), 1, 2, 3);
+      c.emplace_after(c.cbefore_begin(), 1, 2);
+      c.emplace_after(c.cbefore_begin(), 1);
+      c.emplace_after(c.cbefore_begin());
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      c.clear();
+      //emplace_back-like
+      typename Container::const_iterator i = c.emplace_after(c.cbefore_begin());
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      i = c.emplace_after(i, 1);
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      i = c.emplace_after(i, 1, 2);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+      i = c.emplace_after(i, 1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 4)){
+         return false;
+      }
+      i = c.emplace_after(i, 1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 5)){
+         return false;
+      }
+      i = c.emplace_after(i, 1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      c.clear();
+      //emplace_after in the middle
+      i = c.emplace_after(c.cbefore_begin());
+      c.emplace_after(i, 1, 2, 3, 4, 5);
+      c.emplace_after(i, 1, 2, 3, 4);
+      c.emplace_after(i, 1, 2, 3);
+      c.emplace_after(i, 1, 2);
+      c.emplace_after(i, 1);
+
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+   return true;
+}
+
+template<class Container>
+bool test_emplace_after(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_assoc(dtl::true_)
+{
+   std::cout << "Starting test_emplace_assoc." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+   new(&expected [0]) EmplaceInt();
+   new(&expected [1]) EmplaceInt(1);
+   new(&expected [2]) EmplaceInt(1, 2);
+   new(&expected [3]) EmplaceInt(1, 2, 3);
+   new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+   new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+   {
+      Container c;
+      c.emplace();
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      c.emplace(1);
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      c.emplace(1, 2);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+      c.emplace(1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 4)){
+         return false;
+      }
+      c.emplace(1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 5)){
+         return false;
+      }
+      c.emplace(1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+   return true;
+}
+
+template<class Container>
+bool test_emplace_assoc(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_hint(dtl::true_)
+{
+   std::cout << "Starting test_emplace_hint." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+   static EmplaceInt expected [10];
+   new(&expected [0]) EmplaceInt();
+   new(&expected [1]) EmplaceInt(1);
+   new(&expected [2]) EmplaceInt(1, 2);
+   new(&expected [3]) EmplaceInt(1, 2, 3);
+   new(&expected [4]) EmplaceInt(1, 2, 3, 4);
+   new(&expected [5]) EmplaceInt(1, 2, 3, 4, 5);
+
+   {
+      Container c;
+      typename Container::const_iterator it;
+      it = c.emplace_hint(c.begin());
+      if(!test_expected_container(c, &expected[0], 1)){
+         return false;
+      }
+      it = c.emplace_hint(it, 1);
+      if(!test_expected_container(c, &expected[0], 2)){
+         return false;
+      }
+      it = c.emplace_hint(it, 1, 2);
+      if(!test_expected_container(c, &expected[0], 3)){
+         return false;
+      }
+      it = c.emplace_hint(it, 1, 2, 3);
+      if(!test_expected_container(c, &expected[0], 4)){
+         return false;
+      }
+      it = c.emplace_hint(it, 1, 2, 3, 4);
+      if(!test_expected_container(c, &expected[0], 5)){
+         return false;
+      }
+      it = c.emplace_hint(it, 1, 2, 3, 4, 5);
+      if(!test_expected_container(c, &expected[0], 6)){
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+
+   return true;
+}
+
+template<class Container>
+bool test_emplace_hint(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_assoc_pair(dtl::true_)
+{
+   std::cout << "Starting test_emplace_assoc_pair." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+
+   new(&expected_pair[0].first)  EmplaceInt();
+   new(&expected_pair[0].second) EmplaceInt();
+   new(&expected_pair[1].first)  EmplaceInt(1);
+   new(&expected_pair[1].second) EmplaceInt(1);
+   new(&expected_pair[2].first)  EmplaceInt(2);
+   new(&expected_pair[2].second) EmplaceInt(2);
+   {
+      Container c;
+      c.emplace();
+      if(!test_expected_container(c, &expected_pair[0], 1)){
+         std::cout << "Error after c.emplace();\n";
+         return false;
+      }
+      c.emplace(1, 1);
+      if(!test_expected_container(c, &expected_pair[0], 2)){
+         std::cout << "Error after c.emplace(1);\n";
+         return false;
+      }
+      c.emplace(2, 2);
+      if(!test_expected_container(c, &expected_pair[0], 3)){
+         std::cout << "Error after c.emplace(2, 2);\n";
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+   return true;
+}
+
+template<class Container>
+bool test_emplace_assoc_pair(dtl::false_)
+{  return true;   }
+
+template<class Container>
+bool test_emplace_hint_pair(dtl::true_)
+{
+   std::cout << "Starting test_emplace_hint_pair." << std::endl << "  Class: "
+      << typeid(Container).name() << std::endl;
+
+   new(&expected_pair[0].first)  EmplaceInt();
+   new(&expected_pair[0].second) EmplaceInt();
+   new(&expected_pair[1].first)  EmplaceInt(1);
+   new(&expected_pair[1].second) EmplaceInt(1);
+   new(&expected_pair[2].first)  EmplaceInt(2);
+   new(&expected_pair[2].second) EmplaceInt(2);
+   {
+      Container c;
+      typename Container::const_iterator it;
+      it = c.emplace_hint(c.begin());
+      if(!test_expected_container(c, &expected_pair[0], 1)){
+         std::cout << "Error after c.emplace(1);\n";
+         return false;
+      }
+      it = c.emplace_hint(it, 1, 1);
+      if(!test_expected_container(c, &expected_pair[0], 2)){
+         std::cout << "Error after c.emplace(it, 1);\n";
+         return false;
+      }
+      it = c.emplace_hint(it, 2, 2);
+      if(!test_expected_container(c, &expected_pair[0], 3)){
+         std::cout << "Error after c.emplace(it, 2, 2);\n";
+         return false;
+      }
+      std::cout << "...OK" << std::endl;
+   }
+   return true;
+}
+
+template<class Container>
+bool test_emplace_hint_pair(dtl::false_)
+{  return true;   }
+
+template <EmplaceOptions O, EmplaceOptions Mask>
+struct emplace_active
+{
+   static const bool value = (0 != (O & Mask));
+   typedef dtl::bool_<value> type;
+   operator type() const{  return type(); }
+};
+
+template<class Container, EmplaceOptions O>
+bool test_emplace()
+{
+   if(!test_emplace_back<Container>(emplace_active<O, EMPLACE_BACK>())){
+      return false;
+   }
+   if(!test_emplace_front<Container>(emplace_active<O, EMPLACE_FRONT>())){
+      return false;
+   }
+   if(!test_emplace_before<Container>(emplace_active<O, EMPLACE_BEFORE>())){
+      return false;
+   }
+   if(!test_emplace_after<Container>(emplace_active<O, EMPLACE_AFTER>())){
+      return false;
+   }
+   if(!test_emplace_assoc<Container>(emplace_active<O, EMPLACE_ASSOC>())){
+      return false;
+   }
+   if(!test_emplace_hint<Container>(emplace_active<O, EMPLACE_HINT>())){
+      return false;
+   }
+   if(!test_emplace_assoc_pair<Container>(emplace_active<O, EMPLACE_ASSOC_PAIR>())){
+      return false;
+   }
+   if(!test_emplace_hint_pair<Container>(emplace_active<O, EMPLACE_HINT_PAIR>())){
+      return false;
+   }
+   return true;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_EMPLACE_TEST_HPP
diff --git a/test/expand_bwd_test_allocator.hpp b/test/expand_bwd_test_allocator.hpp
new file mode 100644
index 0000000..3a5bb6c
--- /dev/null
+++ b/test/expand_bwd_test_allocator.hpp
@@ -0,0 +1,200 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2005-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+#define BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+
+#ifndef BOOST_CONFIG_HPP
+#  include <boost/config.hpp>
+#endif
+
+#if defined(BOOST_HAS_PRAGMA_ONCE)
+#  pragma once
+#endif
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/container_fwd.hpp>
+
+#include <boost/container/throw_exception.hpp>
+
+#include <boost/container/detail/addressof.hpp>
+#include <boost/container/detail/allocation_type.hpp>
+#include <boost/container/detail/version_type.hpp>
+
+#include <boost/move/adl_move_swap.hpp>
+
+#include <boost/assert.hpp>
+
+#include <memory>
+#include <algorithm>
+#include <cstddef>
+#include <cassert>
+
+namespace boost {
+namespace container {
+namespace test {
+
+//This allocator just allows two allocations. The first one will return
+//mp_buffer + m_offset configured in the constructor. The second one
+//will return mp_buffer.
+template<class T>
+class expand_bwd_test_allocator
+{
+ private:
+   typedef expand_bwd_test_allocator<T> self_t;
+   typedef void *                   aux_pointer_t;
+   typedef const void *             cvoid_ptr;
+
+   template<class T2>
+   expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator<T2>&);
+
+   expand_bwd_test_allocator& operator=(const expand_bwd_test_allocator&);
+
+   public:
+   typedef T                                    value_type;
+   typedef T *                                  pointer;
+   typedef const T *                            const_pointer;
+   typedef typename dtl::add_reference
+                     <value_type>::type         reference;
+   typedef typename dtl::add_reference
+                     <const value_type>::type   const_reference;
+   typedef std::size_t                          size_type;
+   typedef std::ptrdiff_t                       difference_type;
+
+   typedef boost::container::dtl::version_type<expand_bwd_test_allocator, 2>   version;
+
+   //Dummy multiallocation chain
+   struct multiallocation_chain{};
+
+   template<class T2>
+   struct rebind
+   {  typedef expand_bwd_test_allocator<T2>   other;   };
+
+   //!Constructor from the segment manager. Never throws
+   expand_bwd_test_allocator(T *buffer, size_type sz, difference_type offset)
+      : mp_buffer(buffer), m_size(sz)
+      , m_offset(offset),  m_allocations(0){ }
+
+   //!Constructor from other expand_bwd_test_allocator. Never throws
+   expand_bwd_test_allocator(const expand_bwd_test_allocator &other)
+      : mp_buffer(other.mp_buffer), m_size(other.m_size)
+      , m_offset(other.m_offset),  m_allocations(0){ }
+
+   //!Constructor from related expand_bwd_test_allocator. Never throws
+   template<class T2>
+   expand_bwd_test_allocator(const expand_bwd_test_allocator<T2> &other)
+      : mp_buffer(other.mp_buffer), m_size(other.m_size)
+      , m_offset(other.m_offset),  m_allocations(0){ }
+
+   pointer address(reference value)
+   {  return pointer(dtl::addressof(value));  }
+
+   const_pointer address(const_reference value) const
+   {  return const_pointer(dtl::addressof(value));  }
+
+   pointer allocate(size_type , cvoid_ptr hint = 0)
+   {  (void)hint; return 0; }
+
+   void deallocate(const pointer &, size_type)
+   {}
+
+   template<class Convertible>
+   void construct(pointer ptr, const Convertible &value)
+   {  new((void*)ptr) value_type(value);  }
+
+   void destroy(pointer ptr)
+   {  (*ptr).~value_type();  }
+
+   size_type max_size() const
+   {  return m_size;   }
+
+   friend void swap(self_t &alloc1, self_t &alloc2)
+   {
+      boost::adl_move_swap(alloc1.mp_buffer, alloc2.mp_buffer);
+      boost::adl_move_swap(alloc1.m_size,    alloc2.m_size);
+      boost::adl_move_swap(alloc1.m_offset,  alloc2.m_offset);
+   }
+
+   //Experimental version 2 expand_bwd_test_allocator functions
+
+   pointer allocation_command(boost::container::allocation_type command,
+                         size_type limit_size,size_type &prefer_in_recvd_out_size,pointer &reuse)
+   {
+      (void)reuse;   (void)command;
+      //This allocator only expands backwards!
+      assert(m_allocations == 0 || (command & boost::container::expand_bwd));
+
+      prefer_in_recvd_out_size = limit_size;
+
+      if(m_allocations == 0){
+         if((m_offset + limit_size) > m_size){
+            assert(0);
+         }
+         ++m_allocations;
+         reuse = 0;
+         return (mp_buffer + m_offset);
+      }
+      else if(m_allocations == 1){
+         if(limit_size > m_size){
+            assert(0);
+         }
+         ++m_allocations;
+         return mp_buffer;
+      }
+      else{
+         throw_bad_alloc();
+         return mp_buffer;
+      }
+   }
+
+   //!Returns maximum the number of objects the previously allocated memory
+   //!pointed by p can hold.
+   size_type size(const pointer &p) const
+   {  (void)p; return m_size; }
+
+   //!Allocates just one object. Memory allocated with this function
+   //!must be deallocated only with deallocate_one().
+   //!Throws boost::container::bad_alloc if there is no enough memory
+   pointer allocate_one()
+   {  return this->allocate(1);  }
+
+   //!Deallocates memory previously allocated with allocate_one().
+   //!You should never use deallocate_one to deallocate memory allocated
+   //!with other functions different from allocate_one(). Never throws
+   void deallocate_one(const pointer &p)
+   {  return this->deallocate(p, 1);  }
+
+   pointer           mp_buffer;
+   size_type         m_size;
+   difference_type   m_offset;
+   char              m_allocations;
+};
+
+//!Equality test for same type of expand_bwd_test_allocator
+template<class T> inline
+bool operator==(const expand_bwd_test_allocator<T>  &alloc1,
+                const expand_bwd_test_allocator<T>  &alloc2)
+{  return false; }
+
+//!Inequality test for same type of expand_bwd_test_allocator
+template<class T> inline
+bool operator!=(const expand_bwd_test_allocator<T>  &alloc1,
+                const expand_bwd_test_allocator<T>  &alloc2)
+{  return true; }
+
+}  //namespace test {
+}  //namespace container {
+}  //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //BOOST_CONTAINER_EXPAND_BWD_TEST_ALLOCATOR_HPP
+
diff --git a/test/expand_bwd_test_template.hpp b/test/expand_bwd_test_template.hpp
new file mode 100644
index 0000000..1c193ac
--- /dev/null
+++ b/test/expand_bwd_test_template.hpp
@@ -0,0 +1,218 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
+#define BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <vector>
+#include <typeinfo>
+#include <iostream>
+#include "expand_bwd_test_allocator.hpp"
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include "movable_int.hpp"
+#include <boost/move/make_unique.hpp>
+
+namespace boost { namespace container { namespace test {
+
+//Function to check if both sets are equal
+template <class Vector1, class Vector2>
+bool CheckEqualVector(const Vector1 &vector1, const Vector2 &vector2)
+{
+   if(vector1.size() != vector2.size())
+      return false;
+   return boost::container::algo_equal(vector1.begin(), vector1.end(), vector2.begin());
+}
+
+template<class Vector>
+bool CheckUninitializedIsZero(const Vector & v)
+{
+   typedef  typename Vector::value_type value_type;
+   typename Vector::size_type sz    = v.size();
+   typename Vector::size_type extra = v.capacity() - v.size();
+   value_type comp(0);
+
+   const value_type *holder = &v[0] + sz;
+
+   while(extra--){
+      if(*holder++ != comp)
+         return false;
+   }
+   return true;
+}
+
+
+//This function tests all the possible combinations when
+//inserting data in a vector and expanding backwards
+template<class VectorWithExpandBwdAllocator>
+bool test_insert_with_expand_bwd()
+{
+   typedef typename VectorWithExpandBwdAllocator::value_type value_type;
+   typedef std::vector<value_type> Vect;
+   const unsigned int MemorySize = 1000;
+
+   //Distance old and new buffer
+   const unsigned int Offset[]      =
+      {  350, 300, 250, 200, 150, 100, 150, 100,
+         150,  50,  50,  50    };
+   //Initial vector size
+   const unsigned int InitialSize[] =
+      {  200, 200, 200, 200, 200, 200, 200, 200,
+         200, 200, 200, 200   };
+   //Size of the data to insert
+   const unsigned int InsertSize[]  =
+      {  100, 100, 100, 100, 100, 100, 200, 200,
+         300,  25, 100, 200   };
+   //Number of tests
+   const unsigned int Iterations    = sizeof(InsertSize)/sizeof(int);
+
+   //Insert position
+   const int Position[]    =
+      {  0, 100,  200  };
+
+   for(unsigned int pos = 0; pos < sizeof(Position)/sizeof(Position[0]); ++pos){
+      if(!life_count<value_type>::check(0))
+         return false;
+
+      for(unsigned int iteration = 0; iteration < Iterations; ++iteration)
+      {
+         boost::movelib::unique_ptr<char[]> memptr =
+            boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
+         value_type *memory = (value_type*)memptr.get();
+         std::vector<value_type> initial_data;
+         initial_data.resize(InitialSize[iteration]);
+         for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
+            initial_data[i] = i;
+         }
+
+         if(!life_count<value_type>::check(InitialSize[iteration]))
+            return false;
+         Vect data_to_insert;
+         data_to_insert.resize(InsertSize[iteration]);
+         for(unsigned int i = 0; i < InsertSize[iteration]; ++i){
+            data_to_insert[i] = -i;
+         }
+
+         if(!life_count<value_type>::check(InitialSize[iteration]+InsertSize[iteration]))
+            return false;
+
+         expand_bwd_test_allocator<value_type> alloc
+            (memory, MemorySize, Offset[iteration]);
+         VectorWithExpandBwdAllocator vector(alloc);
+         vector.insert( vector.begin()
+                     , initial_data.begin(), initial_data.end());
+         vector.insert( vector.begin() + Position[pos]
+                     , data_to_insert.begin(), data_to_insert.end());
+
+         if(!life_count<value_type>::check(InitialSize[iteration]*2+InsertSize[iteration]*2))
+            return false;
+
+         initial_data.insert(initial_data.begin() + Position[pos]
+                           , data_to_insert.begin(), data_to_insert.end());
+         //Now check that values are equal
+         if(!CheckEqualVector(vector, initial_data)){
+            std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+                     << "   Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+                     << "   Iteration: " << iteration << std::endl;
+            return false;
+         }
+      }
+      if(!life_count<value_type>::check(0))
+         return false;
+   }
+
+   return true;
+}
+
+//This function tests all the possible combinations when
+//inserting data in a vector and expanding backwards
+template<class VectorWithExpandBwdAllocator>
+bool test_assign_with_expand_bwd()
+{
+   typedef typename VectorWithExpandBwdAllocator::value_type value_type;
+   const unsigned int MemorySize = 200;
+
+   const unsigned int Offset[]      = { 50, 50, 50};
+   const unsigned int InitialSize[] = { 25, 25, 25};
+   const unsigned int InsertSize[]  = { 15, 35, 55};
+   const unsigned int Iterations    = sizeof(InsertSize)/sizeof(int);
+
+   for(unsigned int iteration = 0; iteration <Iterations; ++iteration)
+   {
+      boost::movelib::unique_ptr<char[]> memptr =
+         boost::movelib::make_unique_definit<char[]>(MemorySize*sizeof(value_type));
+      value_type *memory = (value_type*)memptr.get();
+      //Create initial data
+      std::vector<value_type> initial_data;
+      initial_data.resize(InitialSize[iteration]);
+      for(unsigned int i = 0; i < InitialSize[iteration]; ++i){
+         initial_data[i] = i;
+      }
+
+      //Create data to assign
+      std::vector<value_type> data_to_insert;
+      data_to_insert.resize(InsertSize[iteration]);
+      for(unsigned int i = 0; i < InsertSize[iteration]; ++i){
+         data_to_insert[i] = -i;
+      }
+
+      //Insert initial data to the vector to test
+      expand_bwd_test_allocator<value_type> alloc
+         (memory, MemorySize, Offset[iteration]);
+      VectorWithExpandBwdAllocator vector(alloc);
+      vector.insert( vector.begin()
+                  , initial_data.begin(), initial_data.end());
+
+      //Assign data
+      vector.insert(vector.cbegin(), data_to_insert.begin(), data_to_insert.end());
+      initial_data.insert(initial_data.begin(), data_to_insert.begin(), data_to_insert.end());
+
+      //Now check that values are equal
+      if(!CheckEqualVector(vector, initial_data)){
+         std::cout << "test_assign_with_expand_bwd::CheckEqualVector failed." << std::endl
+                  << "   Class: " << typeid(VectorWithExpandBwdAllocator).name() << std::endl
+                  << "   Iteration: " << iteration << std::endl;
+         return false;
+      }
+   }
+
+   return true;
+}
+
+//This function calls all tests
+template<class VectorWithExpandBwdAllocator>
+bool test_all_expand_bwd()
+{
+   std::cout << "Starting test_insert_with_expand_bwd." << std::endl << "  Class: "
+             << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+
+   if(!test_insert_with_expand_bwd<VectorWithExpandBwdAllocator>()){
+      std::cout << "test_allocation_direct_deallocation failed. Class: "
+                << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+      return false;
+   }
+
+   std::cout << "Starting test_assign_with_expand_bwd." << std::endl << "  Class: "
+             << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+
+   if(!test_assign_with_expand_bwd<VectorWithExpandBwdAllocator>()){
+      std::cout << "test_allocation_direct_deallocation failed. Class: "
+                << typeid(VectorWithExpandBwdAllocator).name() << std::endl;
+      return false;
+   }
+
+   return true;
+}
+
+}}}   //namespace boost { namespace container { namespace test {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //BOOST_CONTAINER_TEST_ALLOCATION_TEST_TEMPLATE_HEADER
diff --git a/test/explicit_inst_deque_test.cpp b/test/explicit_inst_deque_test.cpp
new file mode 100644
index 0000000..77163db
--- /dev/null
+++ b/test/explicit_inst_deque_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/deque.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::deque<empty>;
+
+int main()
+{
+   ::boost::container::deque<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_flat_map_test.cpp b/test/explicit_inst_flat_map_test.cpp
new file mode 100644
index 0000000..77925d8
--- /dev/null
+++ b/test/explicit_inst_flat_map_test.cpp
@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/flat_map.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::flat_map<empty, empty>;
+template class ::boost::container::flat_multimap<empty, empty>;
+
+int main()
+{
+   ::boost::container::flat_map<empty, empty> dummy;
+   ::boost::container::flat_multimap<empty, empty> dummy2;
+   (void)dummy; (void)dummy2;
+   return 0;
+}
diff --git a/test/explicit_inst_flat_set_test.cpp b/test/explicit_inst_flat_set_test.cpp
new file mode 100644
index 0000000..a9c482f
--- /dev/null
+++ b/test/explicit_inst_flat_set_test.cpp
@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/flat_set.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::flat_set<empty>;
+template class ::boost::container::flat_multiset<empty>;
+
+int main()
+{
+   ::boost::container::flat_set<empty> dummy;
+   ::boost::container::flat_multiset<empty> dummy2;
+   (void)dummy; (void)dummy2;
+   return 0;
+}
diff --git a/test/explicit_inst_list_test.cpp b/test/explicit_inst_list_test.cpp
new file mode 100644
index 0000000..b038594
--- /dev/null
+++ b/test/explicit_inst_list_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/list.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::list<empty>;
+
+int main()
+{
+   ::boost::container::list<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_map_test.cpp b/test/explicit_inst_map_test.cpp
new file mode 100644
index 0000000..4a19429
--- /dev/null
+++ b/test/explicit_inst_map_test.cpp
@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/map.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::map<empty, empty>;
+template class ::boost::container::multimap<empty, empty>;
+
+int main()
+{
+   ::boost::container::map<empty, empty> dummy;
+   ::boost::container::multimap<empty, empty> dummy2;
+   (void)dummy; (void)dummy2;
+   return 0;
+}
diff --git a/test/explicit_inst_set_test.cpp b/test/explicit_inst_set_test.cpp
new file mode 100644
index 0000000..7116c96
--- /dev/null
+++ b/test/explicit_inst_set_test.cpp
@@ -0,0 +1,28 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/set.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::set<empty>;
+template class ::boost::container::multiset<empty>;
+
+int main()
+{
+   ::boost::container::set<empty> dummy;
+   ::boost::container::multiset<empty> dummy2;
+   (void)dummy; (void)dummy2;
+   return 0;
+}
diff --git a/test/explicit_inst_slist_test.cpp b/test/explicit_inst_slist_test.cpp
new file mode 100644
index 0000000..ed4b5ae
--- /dev/null
+++ b/test/explicit_inst_slist_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/slist.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::slist<empty>;
+
+int main()
+{
+   ::boost::container::slist<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_small_vector_test.cpp b/test/explicit_inst_small_vector_test.cpp
new file mode 100644
index 0000000..65d98159
--- /dev/null
+++ b/test/explicit_inst_small_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/small_vector.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::small_vector<empty, 2>;
+
+int main()
+{
+   ::boost::container::small_vector<empty, 2> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_stable_vector_test.cpp b/test/explicit_inst_stable_vector_test.cpp
new file mode 100644
index 0000000..cdd3bdd
--- /dev/null
+++ b/test/explicit_inst_stable_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/stable_vector.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::stable_vector<empty>;
+
+int main()
+{
+   ::boost::container::stable_vector<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_static_vector_test.cpp b/test/explicit_inst_static_vector_test.cpp
new file mode 100644
index 0000000..6681f7c
--- /dev/null
+++ b/test/explicit_inst_static_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/static_vector.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::static_vector<empty, 2>;
+
+int main()
+{
+   ::boost::container::static_vector<empty, 2> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_string_test.cpp b/test/explicit_inst_string_test.cpp
new file mode 100644
index 0000000..f911bb0
--- /dev/null
+++ b/test/explicit_inst_string_test.cpp
@@ -0,0 +1,20 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/string.hpp>
+
+template class ::boost::container::basic_string<char>;
+
+int main()
+{
+   ::boost::container::basic_string<char> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/explicit_inst_vector_test.cpp b/test/explicit_inst_vector_test.cpp
new file mode 100644
index 0000000..b03427c
--- /dev/null
+++ b/test/explicit_inst_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/vector.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::vector<empty>;
+
+int main()
+{
+   ::boost::container::vector<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/flat_map_test.cpp b/test/flat_map_test.cpp
new file mode 100644
index 0000000..7a9a3e7
--- /dev/null
+++ b/test/flat_map_test.cpp
@@ -0,0 +1,712 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/detail/flat_tree.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "print_container.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "container_common_tests.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <map>
+
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//flat_map
+typedef std::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> test_pair_t;
+
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator< test_pair_t >
+   >;
+
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , small_vector< test_pair_t, 10, std::allocator< test_pair_t > >
+   >;
+
+//flat_multimap
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , stable_vector< test_pair_t, allocator< test_pair_t > >
+   >;
+
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , deque<test_pair_t, test::simple_allocator< test_pair_t > >
+   >;
+
+template class flat_multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , static_vector<test_pair_t, 10 >
+   >;
+
+//As flat container iterators are typedefs for vector::[const_]iterator,
+//no need to explicit instantiate them
+
+}} //boost::container
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+
+template class flat_map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , std::vector<test_pair_t>
+>;
+
+}} //boost::container
+
+#endif
+
+class recursive_flat_map
+{
+   public:
+   recursive_flat_map(const recursive_flat_map &c)
+      : id_(c.id_), map_(c.map_)
+   {}
+
+   recursive_flat_map & operator =(const recursive_flat_map &c)
+   {
+      id_ = c.id_;
+      map_= c.map_;
+      return *this;
+   }
+
+   int id_;
+   flat_map<recursive_flat_map, recursive_flat_map> map_;
+   flat_map<recursive_flat_map, recursive_flat_map>::iterator it_;
+   flat_map<recursive_flat_map, recursive_flat_map>::const_iterator cit_;
+   flat_map<recursive_flat_map, recursive_flat_map>::reverse_iterator rit_;
+   flat_map<recursive_flat_map, recursive_flat_map>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_flat_map &a, const recursive_flat_map &b)
+   {  return a.id_ < b.id_;   }
+};
+
+
+class recursive_flat_multimap
+{
+public:
+   recursive_flat_multimap(const recursive_flat_multimap &c)
+      : id_(c.id_), map_(c.map_)
+   {}
+
+   recursive_flat_multimap & operator =(const recursive_flat_multimap &c)
+   {
+      id_ = c.id_;
+      map_= c.map_;
+      return *this;
+   }
+   int id_;
+   flat_multimap<recursive_flat_multimap, recursive_flat_multimap> map_;
+   flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::iterator it_;
+   flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_iterator cit_;
+   flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::reverse_iterator rit_;
+   flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_flat_multimap &a, const recursive_flat_multimap &b)
+   {  return a.id_ < b.id_;   }
+};
+
+template<class C>
+void test_move()
+{
+   //Now test move semantics
+   C original;
+   C move_ctor(boost::move(original));
+   C move_assign;
+   move_assign = boost::move(move_ctor);
+   move_assign.swap(original);
+}
+
+
+namespace boost{
+namespace container {
+namespace test{
+
+bool flat_tree_ordered_insertion_test()
+{
+   using namespace boost::container;
+   const std::size_t NumElements = 100;
+
+   //Ordered insertion multimap
+   {
+      std::multimap<int, int> int_mmap;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      //Construction insertion
+      flat_multimap<int, int> fmmap(ordered_range, int_mmap.begin(), int_mmap.end());
+      if(!CheckEqualContainers(int_mmap, fmmap))
+         return false;
+      //Insertion when empty
+      fmmap.clear();
+      fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
+      if(!CheckEqualContainers(int_mmap, fmmap))
+         return false;
+      //Re-insertion
+      fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
+      std::multimap<int, int> int_mmap2(int_mmap);
+      int_mmap2.insert(int_mmap.begin(), int_mmap.end());
+      if(!CheckEqualContainers(int_mmap2, fmmap))
+         return false;
+      //Re-re-insertion
+      fmmap.insert(ordered_range, int_mmap2.begin(), int_mmap2.end());
+      std::multimap<int, int> int_mmap4(int_mmap2);
+      int_mmap4.insert(int_mmap2.begin(), int_mmap2.end());
+      if(!CheckEqualContainers(int_mmap4, fmmap))
+         return false;
+      //Re-re-insertion of even
+      std::multimap<int, int> int_even_mmap;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      fmmap.insert(ordered_range, int_even_mmap.begin(), int_even_mmap.end());
+      int_mmap4.insert(int_even_mmap.begin(), int_even_mmap.end());
+      if(!CheckEqualContainers(int_mmap4, fmmap))
+         return false;
+   }
+
+   //Ordered insertion map
+   {
+      std::map<int, int> int_map;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      //Construction insertion
+      flat_map<int, int> fmap(ordered_unique_range, int_map.begin(), int_map.end());
+      if(!CheckEqualContainers(int_map, fmap))
+         return false;
+      //Insertion when empty
+      fmap.clear();
+      fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
+      if(!CheckEqualContainers(int_map, fmap))
+         return false;
+      //Re-insertion
+      fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
+      std::map<int, int> int_map2(int_map);
+      int_map2.insert(int_map.begin(), int_map.end());
+      if(!CheckEqualContainers(int_map2, fmap))
+         return false;
+      //Re-re-insertion
+      fmap.insert(ordered_unique_range, int_map2.begin(), int_map2.end());
+      std::map<int, int> int_map4(int_map2);
+      int_map4.insert(int_map2.begin(), int_map2.end());
+      if(!CheckEqualContainers(int_map4, fmap))
+         return false;
+      //Re-re-insertion of even
+      std::map<int, int> int_even_map;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      fmap.insert(ordered_unique_range, int_even_map.begin(), int_even_map.end());
+      int_map4.insert(int_even_map.begin(), int_even_map.end());
+      if(!CheckEqualContainers(int_map4, fmap))
+         return false;
+   }
+
+   return true;
+}
+
+bool constructor_template_auto_deduction_test()
+{
+#if __cplusplus >= 201703L
+   using namespace boost::container;
+   const std::size_t NumElements = 100;
+   //Ordered insertion map
+   {
+      std::map<int, int> int_map;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      //Construction insertion
+      auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end());
+      if(!CheckEqualContainers(int_map, fmap))
+         return false;
+
+      std::multimap<int, int> int_mmap;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
+      }
+      //Construction insertion
+      auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end());
+      if(!CheckEqualContainers(int_mmap, fmmap))
+         return false;
+   }
+#endif
+
+   return true;
+}
+
+template< class RandomIt >
+void random_shuffle( RandomIt first, RandomIt last )
+{
+   typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
+   difference_type n = last - first;
+   for (difference_type i = n-1; i > 0; --i) {
+      difference_type j = std::rand() % (i+1);
+      if(j != i) {
+         boost::adl_move_swap(first[i], first[j]);
+      }
+   }
+}
+
+bool flat_tree_extract_adopt_test()
+{
+   using namespace boost::container;
+   const std::size_t NumElements = 100;
+
+   //extract/adopt map
+   {
+      //Construction insertion
+      flat_map<int, int> fmap;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+      }
+
+      flat_map<int, int> fmap_copy(fmap);
+      flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
+      if(!fmap.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmap_copy))
+         return false;
+
+      seq.insert(seq.end(), fmap_copy.begin(), fmap_copy.end());
+      boost::container::test::random_shuffle(seq.begin(), seq.end());
+      fmap.adopt_sequence(boost::move(seq));
+      if(!CheckEqualContainers(fmap, fmap_copy))
+         return false;
+   }
+
+   //extract/adopt map, ordered_unique_range
+   {
+      //Construction insertion
+      flat_map<int, int> fmap;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+      }
+
+      flat_map<int, int> fmap_copy(fmap);
+      flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
+      if(!fmap.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmap_copy))
+         return false;
+
+      fmap.adopt_sequence(ordered_unique_range, boost::move(seq));
+      if(!CheckEqualContainers(fmap, fmap_copy))
+         return false;
+   }
+
+   //extract/adopt multimap
+   {
+      //Construction insertion
+      flat_multimap<int, int> fmmap;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+         fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+      }
+
+      flat_multimap<int, int> fmmap_copy(fmmap);
+      flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
+      if(!fmmap.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmmap_copy))
+         return false;
+
+      boost::container::test::random_shuffle(seq.begin(), seq.end());
+      fmmap.adopt_sequence(boost::move(seq));
+      if(!CheckEqualContainers(fmmap, fmmap_copy))
+         return false;
+   }
+
+   //extract/adopt multimap, ordered_range
+   {
+      //Construction insertion
+      flat_multimap<int, int> fmmap;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+         fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
+      }
+
+      flat_multimap<int, int> fmmap_copy(fmmap);
+      flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
+      if(!fmmap.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmmap_copy))
+         return false;
+
+      fmmap.adopt_sequence(ordered_range, boost::move(seq));
+      if(!CheckEqualContainers(fmmap, fmmap_copy))
+         return false;
+   }
+
+   return true;
+}
+
+}}}
+
+template<class VoidAllocatorOrContainer>
+struct GetMapContainer
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef std::pair<ValueType, ValueType> type_t;
+      typedef flat_map< ValueType
+                 , ValueType
+                 , std::less<ValueType>
+                 , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+                 > map_type;
+
+      typedef flat_multimap< ValueType
+                 , ValueType
+                 , std::less<ValueType>
+                 , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
+                 > multimap_type;
+   };
+};
+
+struct boost_container_flat_map;
+struct boost_container_flat_multimap;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_flat_map>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef typename boost::container::allocator_traits<Allocator>::
+         template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
+      typedef boost::container::flat_map<T, T, std::less<T>, TypeAllocator> type;
+   };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_flat_multimap>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef typename boost::container::allocator_traits<Allocator>::
+         template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
+      typedef boost::container::flat_multimap<T, T, std::less<T>, TypeAllocator> type;
+   };
+};
+
+template <class Key, class T, class Compare, class Allocator>
+struct get_real_stored_allocator<flat_map<Key, T, Compare, Allocator> >
+{
+   typedef typename flat_map<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
+};
+
+template <class Key, class T, class Compare, class Allocator>
+struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
+{
+   typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
+};
+
+bool test_heterogeneous_lookups()
+{
+   typedef flat_map<int, char, less_transparent> map_t;
+   typedef flat_multimap<int, char, less_transparent> mmap_t;
+   typedef map_t::value_type value_type;
+
+   map_t map1;
+   mmap_t mmap1;
+
+   const map_t &cmap1 = map1;
+   const mmap_t &cmmap1 = mmap1;
+
+   map1.insert_or_assign(1, 'a');
+   map1.insert_or_assign(1, 'b');
+   map1.insert_or_assign(2, 'c');
+   map1.insert_or_assign(2, 'd');
+   map1.insert_or_assign(3, 'e');
+
+   mmap1.insert(value_type(1, 'a'));
+   mmap1.insert(value_type(1, 'b'));
+   mmap1.insert(value_type(2, 'c'));
+   mmap1.insert(value_type(2, 'd'));
+   mmap1.insert(value_type(3, 'e'));
+
+   const test::non_copymovable_int find_me(2);
+
+   //find
+   if(map1.find(find_me)->second != 'd')
+      return false;
+   if(cmap1.find(find_me)->second != 'd')
+      return false;
+   if(mmap1.find(find_me)->second != 'c')
+      return false;
+   if(cmmap1.find(find_me)->second != 'c')
+      return false;
+
+   //count
+   if(map1.count(find_me) != 1)
+      return false;
+   if(cmap1.count(find_me) != 1)
+      return false;
+   if(mmap1.count(find_me) != 2)
+      return false;
+   if(cmmap1.count(find_me) != 2)
+      return false;
+
+   //lower_bound
+   if(map1.lower_bound(find_me)->second != 'd')
+      return false;
+   if(cmap1.lower_bound(find_me)->second != 'd')
+      return false;
+   if(mmap1.lower_bound(find_me)->second != 'c')
+      return false;
+   if(cmmap1.lower_bound(find_me)->second != 'c')
+      return false;
+
+   //upper_bound
+   if(map1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(cmap1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(mmap1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(cmmap1.upper_bound(find_me)->second != 'e')
+      return false;
+
+   //equal_range
+   if(map1.equal_range(find_me).first->second != 'd')
+      return false;
+   if(cmap1.equal_range(find_me).second->second != 'e')
+      return false;
+   if(mmap1.equal_range(find_me).first->second != 'c')
+      return false;
+   if(cmmap1.equal_range(find_me).second->second != 'e')
+      return false;
+
+   return true;
+}
+
+}}}   //namespace boost::container::test
+
+template<class VoidAllocatorOrContainer>
+int test_map_variants()
+{
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<int>::map_type MyMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_int>::map_type MyMoveMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_and_copyable_int>::map_type MyCopyMoveMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::copyable_int>::map_type MyCopyMap;
+
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<int>::multimap_type MyMultiMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::movable_and_copyable_int>::multimap_type MyCopyMoveMultiMap;
+   typedef typename GetMapContainer<VoidAllocatorOrContainer>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
+
+   typedef std::map<int, int>                                     MyStdMap;
+   typedef std::multimap<int, int>                                MyStdMultiMap;
+
+   if (0 != test::map_test<
+                  MyMap
+                  ,MyStdMap
+                  ,MyMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::map_test<
+                  MyMoveMap
+                  ,MyStdMap
+                  ,MyMoveMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::map_test<
+                  MyCopyMoveMap
+                  ,MyStdMap
+                  ,MyCopyMoveMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::map_test<
+                  MyCopyMap
+                  ,MyStdMap
+                  ,MyCopyMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   return 0;
+}
+
+int main()
+{
+   using namespace boost::container::test;
+
+   //Allocator argument container
+   {
+      flat_map<int, int> map_((flat_map<int, int>::allocator_type()));
+      flat_multimap<int, int> multimap_((flat_multimap<int, int>::allocator_type()));
+   }
+   //Now test move semantics
+   {
+      test_move<flat_map<recursive_flat_map, recursive_flat_map> >();
+      test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >();
+   }
+   //Now test nth/index_of
+   {
+      flat_map<int, int> map;
+      flat_multimap<int, int> mmap;
+
+      map.insert(std::pair<int, int>(0, 0));
+      map.insert(std::pair<int, int>(1, 0));
+      map.insert(std::pair<int, int>(2, 0));
+      mmap.insert(std::pair<int, int>(0, 0));
+      mmap.insert(std::pair<int, int>(1, 0));
+      mmap.insert(std::pair<int, int>(2, 0));
+      if(!boost::container::test::test_nth_index_of(map))
+         return 1;
+      if(!boost::container::test::test_nth_index_of(mmap))
+         return 1;
+   }
+
+   ////////////////////////////////////
+   //    Ordered insertion test
+   ////////////////////////////////////
+   if(!flat_tree_ordered_insertion_test()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction test
+   ////////////////////////////////////
+   if(!constructor_template_auto_deduction_test()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Extract/Adopt test
+   ////////////////////////////////////
+   if(!flat_tree_extract_adopt_test()){
+      return 1;
+   }
+
+   if (!boost::container::test::instantiate_constructors<flat_map<int, int>, flat_multimap<int, int> >())
+      return 1;
+
+   if (!test_heterogeneous_lookups())
+      return 1;
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std::allocator
+   if(test_map_variants< std::allocator<void> >()){
+      std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::allocator
+   if(test_map_variants< allocator<void> >()){
+      std::cerr << "test_map_variants< allocator<void> > failed" << std::endl;
+      return 1;
+   }
+
+   if(!boost::container::test::test_map_support_for_initialization_list_for<flat_map<int, int> >())
+      return 1;
+
+   if (!boost::container::test::test_map_support_for_initialization_list_for<flat_multimap<int, int> >())
+      return 1;
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
+
+   if(!boost::container::test::test_emplace<flat_map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+      return 1;
+   if(!boost::container::test::test_emplace<flat_multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_flat_map>())
+      return 1;
+
+   if(!boost::container::test::test_propagate_allocator<boost_container_flat_multimap>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::flat_map<int, int> cont_int;
+      cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+   {
+      typedef boost::container::flat_multimap<int, int> cont_int;
+      cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
+
diff --git a/test/flat_set_test.cpp b/test/flat_set_test.cpp
new file mode 100644
index 0000000..fc8233a
--- /dev/null
+++ b/test/flat_set_test.cpp
@@ -0,0 +1,808 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <set>
+
+#include <boost/container/flat_set.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/detail/container_or_allocator_rebind.hpp>
+
+#include "print_container.hpp"
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "set_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "container_common_tests.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//flat_set
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<test::movable_and_copyable_int>
+   >;
+
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , small_vector<test::movable_and_copyable_int, 10, allocator<test::movable_and_copyable_int> >
+   >;
+
+//flat_multiset
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , stable_vector<test::movable_and_copyable_int, test::simple_allocator<test::movable_and_copyable_int> >
+   >;
+
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , deque<test::movable_and_copyable_int, test::simple_allocator< test::movable_and_copyable_int > >
+   >;
+
+template class flat_multiset
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , static_vector<test::movable_and_copyable_int, 10 >
+   >;
+
+//As flat container iterators are typedefs for vector::[const_]iterator,
+//no need to explicit instantiate them
+
+}} //boost::container
+
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+
+template class flat_set
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , std::vector<test::movable_and_copyable_int>
+>;
+
+}} //boost::container
+
+#endif
+
+//Test recursive structures
+class recursive_flat_set
+{
+   public:
+   recursive_flat_set(const recursive_flat_set &c)
+      : id_(c.id_), flat_set_(c.flat_set_)
+   {}
+
+   recursive_flat_set & operator =(const recursive_flat_set &c)
+   {
+      id_ = c.id_;
+      flat_set_= c.flat_set_;
+      return *this;
+   }
+   int id_;
+   flat_set<recursive_flat_set> flat_set_;
+   flat_set<recursive_flat_set>::iterator it_;
+   flat_set<recursive_flat_set>::const_iterator cit_;
+   flat_set<recursive_flat_set>::reverse_iterator rit_;
+   flat_set<recursive_flat_set>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_flat_set &a, const recursive_flat_set &b)
+   {  return a.id_ < b.id_;   }
+};
+
+
+//Test recursive structures
+class recursive_flat_multiset
+{
+   public:
+   recursive_flat_multiset(const recursive_flat_multiset &c)
+      : id_(c.id_), flat_multiset_(c.flat_multiset_)
+   {}
+
+   recursive_flat_multiset & operator =(const recursive_flat_multiset &c)
+   {
+      id_ = c.id_;
+      flat_multiset_= c.flat_multiset_;
+      return *this;
+   }
+   int id_;
+   flat_multiset<recursive_flat_multiset> flat_multiset_;
+   flat_multiset<recursive_flat_multiset>::iterator it_;
+   flat_multiset<recursive_flat_multiset>::const_iterator cit_;
+   flat_multiset<recursive_flat_multiset>::reverse_iterator rit_;
+   flat_multiset<recursive_flat_multiset>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b)
+   {  return a.id_ < b.id_;   }
+};
+
+
+template<class C>
+void test_move()
+{
+   //Now test move semantics
+   C original;
+   C move_ctor(boost::move(original));
+   C move_assign;
+   move_assign = boost::move(move_ctor);
+   move_assign.swap(original);
+}
+
+namespace boost{
+namespace container {
+namespace test{
+
+bool flat_tree_ordered_insertion_test()
+{
+   using namespace boost::container;
+   const std::size_t NumElements = 100;
+
+   //Ordered insertion multiset
+   {
+      std::multiset<int> int_mset;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_mset.insert(static_cast<int>(i));
+      }
+      //Construction insertion
+      flat_multiset<int> fmset(ordered_range, int_mset.begin(), int_mset.end());
+      if(!CheckEqualContainers(int_mset, fmset))
+         return false;
+      //Insertion when empty
+      fmset.clear();
+      fmset.insert(ordered_range, int_mset.begin(), int_mset.end());
+      if(!CheckEqualContainers(int_mset, fmset))
+         return false;
+      //Re-insertion
+      fmset.insert(ordered_range, int_mset.begin(), int_mset.end());
+      std::multiset<int> int_mset2(int_mset);
+      int_mset2.insert(int_mset.begin(), int_mset.end());
+      if(!CheckEqualContainers(int_mset2, fmset))
+         return false;
+      //Re-re-insertion
+      fmset.insert(ordered_range, int_mset2.begin(), int_mset2.end());
+      std::multiset<int> int_mset4(int_mset2);
+      int_mset4.insert(int_mset2.begin(), int_mset2.end());
+      if(!CheckEqualContainers(int_mset4, fmset))
+         return false;
+      //Re-re-insertion of even
+      std::multiset<int> int_even_mset;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_mset.insert(static_cast<int>(i));
+      }
+      fmset.insert(ordered_range, int_even_mset.begin(), int_even_mset.end());
+      int_mset4.insert(int_even_mset.begin(), int_even_mset.end());
+      if(!CheckEqualContainers(int_mset4, fmset))
+         return false;
+
+      //Re-re-insertion using in-place merge
+      fmset.reserve(fmset.size() + int_mset2.size());
+      fmset.insert(ordered_range, int_mset2.begin(), int_mset2.end());
+      std::multiset<int> int_mset5(int_mset2);
+      int_mset4.insert(int_mset5.begin(), int_mset5.end());
+      if(!CheckEqualContainers(int_mset4, fmset))
+         return false;
+      //Re-re-insertion of even
+      std::multiset<int> int_even_mset2;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_even_mset2.insert(static_cast<int>(i));
+      }
+      fmset.reserve(fmset.size() + int_even_mset2.size());
+      fmset.insert(ordered_range, int_even_mset2.begin(), int_even_mset2.end());
+      int_mset4.insert(int_even_mset2.begin(), int_even_mset2.end());
+      if(!CheckEqualContainers(int_mset4, fmset))
+         return false;
+   }
+
+   //Ordered insertion set
+   {
+      std::set<int> int_set;
+      for(std::size_t i = 0; i != NumElements; ++i){
+         int_set.insert(static_cast<int>(i));
+      }
+      //Construction insertion
+      flat_set<int> fset(ordered_unique_range, int_set.begin(), int_set.end());
+      if(!CheckEqualContainers(int_set, fset))
+         return false;
+      //Insertion when empty
+      fset.clear();
+      fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+      if(!CheckEqualContainers(int_set, fset))
+         return false;
+      //Re-insertion
+      fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+      std::set<int> int_set2(int_set);
+      int_set2.insert(int_set.begin(), int_set.end());
+      if(!CheckEqualContainers(int_set2, fset))
+         return false;
+      //Re-re-insertion
+      fset.insert(ordered_unique_range, int_set2.begin(), int_set2.end());
+      std::set<int> int_set4(int_set2);
+      int_set4.insert(int_set2.begin(), int_set2.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      //Re-re-insertion of even
+      std::set<int> int_even_set;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      //Partial Re-re-insertion of even
+      int_even_set.clear();
+      for(std::size_t i = 0; i < NumElements; i+=4){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      fset.clear();
+      int_set4.clear();
+      //insert 0,4,8,12...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      for(std::size_t i = 2; i < NumElements; i+=4){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      //insert 0,2,4,6,8,10,12...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      int_even_set.clear();
+      for(std::size_t i = 0; i < NumElements; i+=8){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      fset.clear();
+      int_set4.clear();
+      //insert 0,8,16...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      //insert 0,2,4,6,8,10,12...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+
+
+      int_even_set.clear();
+      for(std::size_t i = 0; i < NumElements; i+=8){
+         int_even_set.insert(static_cast<int>(i));
+         int_even_set.insert(static_cast<int>(i+2));
+      }
+      int_even_set.insert(static_cast<int>(NumElements-2));
+      fset.clear();
+      int_set4.clear();
+      //insert 0,2,8,10...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+      for(std::size_t i = 0; i < NumElements; i+=2){
+         int_even_set.insert(static_cast<int>(i));
+      }
+      //insert 0,2,4,6,8,10,12...
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+
+      //add even/odd values with not enough capacity 
+      flat_set<int>().swap(fset);
+      int_set4.clear();
+      int_set.clear();
+
+      fset.reserve(int_even_set.size());
+      fset.insert(ordered_unique_range, int_even_set.begin(), int_even_set.end());
+      int_set4.insert(int_even_set.begin(), int_even_set.end());
+
+      for(std::size_t i = 0; i < NumElements*2; i+=2){
+         int_set.insert(static_cast<int>(i));
+         int_set.insert(static_cast<int>(i+1));
+      }
+
+      fset.insert(ordered_unique_range, int_set.begin(), int_set.end());
+      int_set4.insert(int_set.begin(), int_set.end());
+      if(!CheckEqualContainers(int_set4, fset))
+         return false;
+   }
+
+   return true;
+}
+
+template< class RandomIt >
+void random_shuffle( RandomIt first, RandomIt last )
+{
+   typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
+   difference_type n = last - first;
+   for (difference_type i = n-1; i > 0; --i) {
+      difference_type j = std::rand() % (i+1);
+      if(j != i) {
+         boost::adl_move_swap(first[i], first[j]);
+      }
+   }
+}
+
+bool flat_tree_extract_adopt_test()
+{
+   using namespace boost::container;
+   const std::size_t NumElements = 100;
+
+   //extract/adopt set
+   {
+      //Construction insertion
+      flat_set<int> fset;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fset.insert(static_cast<int>(i));
+      }
+
+      flat_set<int> fset_copy(fset);
+      flat_set<int>::sequence_type seq(fset.extract_sequence());
+      if(!fset.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fset_copy))
+         return false;
+
+      seq.insert(seq.end(), fset_copy.begin(), fset_copy.end());
+      boost::container::test::random_shuffle(seq.begin(), seq.end());
+      fset.adopt_sequence(boost::move(seq));
+      if(!CheckEqualContainers(fset, fset_copy))
+         return false;
+   }
+
+   //extract/adopt set, ordered_unique_range
+   {
+      //Construction insertion
+      flat_set<int> fset;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fset.insert(static_cast<int>(i));
+      }
+
+      flat_set<int> fset_copy(fset);
+      flat_set<int>::sequence_type seq(fset.extract_sequence());
+      if(!fset.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fset_copy))
+         return false;
+
+      fset.adopt_sequence(ordered_unique_range, boost::move(seq));
+      if(!CheckEqualContainers(fset, fset_copy))
+         return false;
+   }
+
+   //extract/adopt multiset
+   {
+      //Construction insertion
+      flat_multiset<int> fmset;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmset.insert(static_cast<int>(i));
+         fmset.insert(static_cast<int>(i));
+      }
+
+      flat_multiset<int> fmset_copy(fmset);
+      flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
+      if(!fmset.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmset_copy))
+         return false;
+
+      boost::container::test::random_shuffle(seq.begin(), seq.end());
+      fmset.adopt_sequence(boost::move(seq));
+      if(!CheckEqualContainers(fmset, fmset_copy))
+         return false;
+   }
+
+   //extract/adopt multiset, ordered_range
+   {
+      //Construction insertion
+      flat_multiset<int> fmset;
+
+      for(std::size_t i = 0; i != NumElements; ++i){
+         fmset.insert(static_cast<int>(i));
+         fmset.insert(static_cast<int>(i));
+      }
+
+      flat_multiset<int> fmset_copy(fmset);
+      flat_multiset<int>::sequence_type seq(fmset.extract_sequence());
+      if(!fmset.empty())
+         return false;
+      if(!CheckEqualContainers(seq, fmset_copy))
+         return false;
+
+      fmset.adopt_sequence(ordered_range, boost::move(seq));
+      if(!CheckEqualContainers(fmset, fmset_copy))
+         return false;
+   }
+
+   return true;
+}
+
+bool test_heterogeneous_lookups()
+{
+   typedef flat_set<int, test::less_transparent> set_t;
+   typedef flat_multiset<int, test::less_transparent> mset_t;
+
+   set_t set1;
+   mset_t mset1;
+
+   const set_t &cset1 = set1;
+   const mset_t &cmset1 = mset1;
+
+   set1.insert(1);
+   set1.insert(1);
+   set1.insert(2);
+   set1.insert(2);
+   set1.insert(3);
+
+   mset1.insert(1);
+   mset1.insert(1);
+   mset1.insert(2);
+   mset1.insert(2);
+   mset1.insert(3);
+
+   const test::non_copymovable_int find_me(2);
+
+   //find
+   if(*set1.find(find_me) != 2)
+      return false;
+   if(*cset1.find(find_me) != 2)
+      return false;
+   if(*mset1.find(find_me) != 2)
+      return false;
+   if(*cmset1.find(find_me) != 2)
+      return false;
+
+   //count
+   if(set1.count(find_me) != 1)
+      return false;
+   if(cset1.count(find_me) != 1)
+      return false;
+   if(mset1.count(find_me) != 2)
+      return false;
+   if(cmset1.count(find_me) != 2)
+      return false;
+
+   //lower_bound
+   if(*set1.lower_bound(find_me) != 2)
+      return false;
+   if(*cset1.lower_bound(find_me) != 2)
+      return false;
+   if(*mset1.lower_bound(find_me) != 2)
+      return false;
+   if(*cmset1.lower_bound(find_me) != 2)
+      return false;
+
+   //upper_bound
+   if(*set1.upper_bound(find_me) != 3)
+      return false;
+   if(*cset1.upper_bound(find_me) != 3)
+      return false;
+   if(*mset1.upper_bound(find_me) != 3)
+      return false;
+   if(*cmset1.upper_bound(find_me) != 3)
+      return false;
+
+   //equal_range
+   if(*set1.equal_range(find_me).first != 2)
+      return false;
+   if(*cset1.equal_range(find_me).second != 3)
+      return false;
+   if(*mset1.equal_range(find_me).first != 2)
+      return false;
+   if(*cmset1.equal_range(find_me).second != 3)
+      return false;
+
+   return true;
+}
+
+}}}
+
+template<class VoidAllocatorOrContainer>
+struct GetSetContainer
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef flat_set < ValueType
+                       , std::less<ValueType>
+                       , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+                        > set_type;
+
+      typedef flat_multiset < ValueType
+                            , std::less<ValueType>
+                            , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type
+                            > multiset_type;
+   };
+};
+
+template<class VoidAllocator>
+int test_set_variants()
+{
+   typedef typename GetSetContainer<VoidAllocator>::template apply<int>::set_type MySet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::set_type MyMoveSet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::set_type MyCopyMoveSet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::set_type MyCopySet;
+
+   typedef typename GetSetContainer<VoidAllocator>::template apply<int>::multiset_type MyMultiSet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::movable_and_copyable_int>::multiset_type MyCopyMoveMultiSet;
+   typedef typename GetSetContainer<VoidAllocator>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
+
+   typedef std::set<int>                                          MyStdSet;
+   typedef std::multiset<int>                                     MyStdMultiSet;
+
+   if (0 != test::set_test<
+                  MySet
+                  ,MyStdSet
+                  ,MyMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::set_test<
+                  MyMoveSet
+                  ,MyStdSet
+                  ,MyMoveMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::set_test<
+                  MyCopyMoveSet
+                  ,MyStdSet
+                  ,MyCopyMoveMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::set_test<
+                  MyCopySet
+                  ,MyStdSet
+                  ,MyCopyMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   return 0;
+}
+
+
+template<typename FlatSetType>
+bool test_support_for_initialization_list_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   const std::initializer_list<int> il
+      = {1, 2};
+
+   const FlatSetType expected(il.begin(), il.end());
+   {
+      const FlatSetType sil = il;
+      if (sil != expected)
+         return false;
+
+      const FlatSetType sil_ordered(ordered_unique_range, il);
+      if(sil_ordered != expected)
+         return false;
+
+      FlatSetType sil_assign = {99};
+      sil_assign = il;
+      if(sil_assign != expected)
+         return false;
+   }
+   {
+      FlatSetType sil;
+      sil.insert(il);
+      if(sil != expected)
+         return false;
+   }
+   return true;
+#endif
+   return true;
+}
+
+struct boost_container_flat_set;
+struct boost_container_flat_multiset;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_flat_set>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::flat_set<T, std::less<T>, Allocator> type;
+   };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_flat_multiset>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::flat_multiset<T, std::less<T>, Allocator> type;
+   };
+};
+
+}}}   //boost::container::test
+
+int main()
+{
+   using namespace boost::container::test;
+
+   //Allocator argument container
+   {
+      flat_set<int> set_((flat_set<int>::allocator_type()));
+      flat_multiset<int> multiset_((flat_multiset<int>::allocator_type()));
+   }
+   //Now test move semantics
+   {
+      test_move<flat_set<recursive_flat_set> >();
+      test_move<flat_multiset<recursive_flat_multiset> >();
+   }
+   //Now test nth/index_of
+   {
+      flat_set<int> set;
+      flat_multiset<int> mset;
+
+      set.insert(0);
+      set.insert(1);
+      set.insert(2);
+      mset.insert(0);
+      mset.insert(1);
+      mset.insert(2);
+      if(!boost::container::test::test_nth_index_of(set))
+         return 1;
+      if(!boost::container::test::test_nth_index_of(mset))
+         return 1;
+   }
+
+   ////////////////////////////////////
+   //    Ordered insertion test
+   ////////////////////////////////////
+   if(!flat_tree_ordered_insertion_test()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Extract/Adopt test
+   ////////////////////////////////////
+   if(!flat_tree_extract_adopt_test()){
+      return 1;
+   }
+
+   if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >())
+      return 1;
+
+   if(!test_heterogeneous_lookups()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std::allocator
+   if(test_set_variants< std::allocator<void> >()){
+      std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::allocator
+   if(test_set_variants< allocator<void> >()){
+      std::cerr << "test_set_variants< allocator<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
+
+   if(!boost::container::test::test_emplace<flat_set<test::EmplaceInt>, SetOptions>())
+      return 1;
+   if(!boost::container::test::test_emplace<flat_multiset<test::EmplaceInt>, SetOptions>())
+      return 1;
+
+   if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_set<int> >())
+      return 1;
+
+   if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_multiset<int> >())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_flat_set>())
+      return 1;
+
+   if(!boost::container::test::test_propagate_allocator<boost_container_flat_multiset>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::flat_set<int> cont_int;
+      cont_int a; a.insert(0); a.insert(1); a.insert(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+   {
+      typedef boost::container::flat_multiset<int> cont_int;
+      cont_int a; a.insert(0); a.insert(1); a.insert(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction
+   ////////////////////////////////////
+   {
+      auto gold = std::set({ 1, 2, 3 });
+      auto test = boost::container::flat_set(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+      test = boost::container::flat_set(ordered_unique_range, gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+   {
+      auto gold = std::multiset({ 1, 2, 3 });
+      auto test = boost::container::flat_multiset(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+      test = boost::container::flat_multiset(ordered_range, gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+#endif
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
+
diff --git a/test/flat_tree_test.cpp b/test/flat_tree_test.cpp
new file mode 100644
index 0000000..b70fb4a
--- /dev/null
+++ b/test/flat_tree_test.cpp
@@ -0,0 +1,124 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/flat_tree.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/static_vector.hpp>
+
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+using namespace boost::container;
+
+typedef boost::container::dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+namespace dtl {
+
+template class flat_tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<pair_t>
+   >;
+
+template class flat_tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::allocator<pair_t>
+   >;
+
+template class flat_tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , small_vector<pair_t, 10>
+   >;
+
+template class flat_tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , stable_vector<pair_t>
+   >;
+
+template class flat_tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<test::movable_and_copyable_int>
+   >;
+
+template class flat_tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::allocator<test::movable_and_copyable_int>
+   >;
+
+template class flat_tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , small_vector<test::movable_and_copyable_int, 10>
+   >;
+
+template class flat_tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , stable_vector<test::movable_and_copyable_int>
+   >;
+
+template class flat_tree
+< test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , static_vector<test::movable_and_copyable_int, 10>
+>;
+
+}  //dtl {
+}} //boost::container
+
+#if (__cplusplus > 201103L)
+#include <vector>
+
+namespace boost{
+namespace container{
+namespace dtl{
+
+template class flat_tree
+< test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::vector<test::movable_and_copyable_int>
+>;
+
+template class flat_tree
+< pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::vector<pair_t>
+>;
+
+}  //dtl {
+}} //boost::container
+
+#endif
+
+int main ()
+{
+   return 0;
+}
diff --git a/test/global_resource_test.cpp b/test/global_resource_test.cpp
new file mode 100644
index 0000000..c04816a
--- /dev/null
+++ b/test/global_resource_test.cpp
@@ -0,0 +1,116 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+
+#include "derived_from_memory_resource.hpp"
+
+#include <cstdlib>
+#include <new>
+
+using namespace boost::container;
+using namespace boost::container::pmr;
+
+std::size_t allocation_count = 0;
+
+#ifdef BOOST_MSVC
+#pragma warning (push)
+#pragma warning (disable : 4290)
+#endif
+
+#if __cplusplus >= 201103L
+#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
+#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER noexcept
+#else
+#define BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER    throw(std::bad_alloc)
+#define BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER throw()
+#endif
+
+#if defined(BOOST_GCC) && (BOOST_GCC >= 50000)
+#pragma GCC diagnostic ignored "-Wsized-deallocation"
+#endif
+
+void* operator new[](std::size_t count) BOOST_CONTAINER_NEW_EXCEPTION_SPECIFIER
+{
+   ++allocation_count;
+   return std::malloc(count);
+}
+
+void operator delete[](void *p) BOOST_CONTAINER_DELETE_EXCEPTION_SPECIFIER
+{
+   --allocation_count;
+   return std::free(p);
+}
+
+#ifdef BOOST_MSVC
+#pragma warning (pop)
+#endif
+
+void test_new_delete_resource()
+{
+   //Make sure new_delete_resource calls new[]/delete[]
+   std::size_t memcount = allocation_count;
+   memory_resource *mr = new_delete_resource();
+   //each time should return the same pointer
+   BOOST_TEST(mr == new_delete_resource());
+   #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING)  //No new delete replacement possible new_delete is a DLL
+   BOOST_TEST(memcount == allocation_count);
+   #endif
+   void *addr = mr->allocate(16, 1);
+   #if !defined(BOOST_CONTAINER_DYNAMIC_LINKING)  //No new delete replacement possible new_delete is a DLL
+   BOOST_TEST((allocation_count - memcount) == 1);
+   #endif
+   mr->deallocate(addr, 16, 1);
+   BOOST_TEST(memcount == allocation_count);
+}
+
+void test_null_memory_resource()
+{
+   //Make sure it throw or returns null
+   memory_resource *mr = null_memory_resource();
+   #if !defined(BOOST_NO_EXCEPTIONS)
+   bool bad_allocexception_thrown = false;
+   try{
+      mr->allocate(1, 1);
+   }
+   catch(std::bad_alloc&) {
+      bad_allocexception_thrown = true;
+   }
+   catch(...) {
+   }
+   BOOST_TEST(bad_allocexception_thrown == true);
+   #else
+   BOOST_TEST(0 == mr->allocate(1, 1));
+   #endif
+}
+
+void test_default_resource()
+{
+   //Default resource must be new/delete before set_default_resource
+   BOOST_TEST(get_default_resource() == new_delete_resource());
+   //Set default resource and obtain previous
+   derived_from_memory_resource d;
+   memory_resource *prev_default = set_default_resource(&d);
+   BOOST_TEST(get_default_resource() == &d);
+   //Set default resource with null, which should be new/delete
+   prev_default = set_default_resource(0);
+   BOOST_TEST(prev_default == &d);
+   BOOST_TEST(get_default_resource() == new_delete_resource());
+}
+
+int main()
+{
+   test_new_delete_resource();
+   test_null_memory_resource();
+   test_default_resource();
+   return ::boost::report_errors();
+}
diff --git a/test/hash_table_test.cppx b/test/hash_table_test.cppx
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/hash_table_test.cppx
diff --git a/test/input_from_forward_iterator.hpp b/test/input_from_forward_iterator.hpp
new file mode 100644
index 0000000..9436cef
--- /dev/null
+++ b/test/input_from_forward_iterator.hpp
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
+#define BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
+
+#include <boost/container/detail/iterator.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class FwdIterator>
+class input_iterator_wrapper
+   : public boost::container::iterator< std::input_iterator_tag
+                         , typename boost::container::iterator_traits<FwdIterator>::value_type
+                         , typename boost::container::iterator_traits<FwdIterator>::difference_type
+                         , typename boost::container::iterator_traits<FwdIterator>::pointer
+                         , typename boost::container::iterator_traits<FwdIterator>::reference
+                         >
+{
+   FwdIterator m_it;
+
+   public:
+   input_iterator_wrapper()
+      : m_it(0)
+   {}
+
+   explicit input_iterator_wrapper(FwdIterator it)
+      : m_it(it)
+   {}
+
+   //Default copy constructor...
+   //input_iterator_wrapper(const input_iterator_wrapper&);
+
+   //Default assignment...
+   //input_iterator_wrapper &operator=(const input_iterator_wrapper&);
+
+   //Default destructor...
+   //~input_iterator_wrapper();
+
+   typename boost::container::iterator_traits<FwdIterator>::reference operator*() const
+   { return *m_it; }
+
+   typename boost::container::iterator_traits<FwdIterator>::pointer operator->() const
+   { return m_it.operator->(); }
+
+   input_iterator_wrapper& operator++()
+   {  ++m_it;  return *this;  }
+
+   input_iterator_wrapper operator++(int )
+   {
+      input_iterator_wrapper tmp(m_it);
+      ++m_it;
+      return tmp;
+   }
+
+   friend bool operator==(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
+   {  return left.m_it == right.m_it;  }
+
+   friend bool operator!=(const input_iterator_wrapper &left, const input_iterator_wrapper &right)
+   {  return left.m_it != right.m_it;  }
+};
+
+template<class FwdIterator>
+input_iterator_wrapper<FwdIterator> make_input_from_forward_iterator(const FwdIterator &it)
+{  return input_iterator_wrapper<FwdIterator>(it); }
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#endif //BOOST_CONTAINER_TEST_FORWARD_TO_INPUT_ITERATOR_HPP
diff --git a/test/insert_test.hpp b/test/insert_test.hpp
new file mode 100644
index 0000000..cb862f3
--- /dev/null
+++ b/test/insert_test.hpp
@@ -0,0 +1,75 @@
+#ifndef BOOST_CONTAINER_TEST_INSERT_TEST_HPP
+#define BOOST_CONTAINER_TEST_INSERT_TEST_HPP
+
+// Copyright (C) 2013 Cromwell D. Enage
+// 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)
+
+#include <deque>
+#include <boost/core/lightweight_test.hpp>
+#include "check_equal_containers.hpp"
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<class SeqContainer>
+void
+    test_insert_range(
+        std::deque<int> &std_deque
+      , SeqContainer &seq_container
+      , std::deque<int> const& input_deque
+      , std::size_t index
+    )
+{
+    BOOST_TEST(CheckEqualContainers(std_deque, seq_container));
+
+    std_deque.insert(
+        std_deque.begin() + index
+      , input_deque.begin()
+      , input_deque.end()
+    );
+
+    seq_container.insert(
+        seq_container.begin() + index
+      , input_deque.begin()
+      , input_deque.end()
+    );
+    BOOST_TEST(CheckEqualContainers(std_deque, seq_container));
+}
+
+template<class SeqContainer>
+bool test_range_insertion()
+{
+   int err_count = boost::report_errors();
+   typedef typename SeqContainer::value_type value_type;
+   std::deque<int> input_deque;
+   for (int element = -10; element < 10; ++element)
+   {
+      input_deque.push_back(element + 20);
+   }
+
+   for (std::size_t i = 0; i <= input_deque.size(); ++i)
+   {
+      std::deque<int> std_deque;
+      ::boost::movelib::unique_ptr<SeqContainer> const pseqcontainer = ::boost::movelib::make_unique<SeqContainer>();
+      SeqContainer &seq_container = *pseqcontainer;
+
+      for (int element = -10; element < 10; ++element)
+      {
+         std_deque.push_back(element);
+         seq_container.push_back(value_type(element));
+      }
+      test_insert_range(std_deque, seq_container, input_deque, i);
+   }
+
+   return err_count == boost::report_errors();
+}
+
+
+}  //namespace test {
+}  //namespace container {
+}  //namespace boost {
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_INSERT_TEST_HPP
diff --git a/test/insert_vs_emplace_test.cpp b/test/insert_vs_emplace_test.cpp
new file mode 100644
index 0000000..b91a693
--- /dev/null
+++ b/test/insert_vs_emplace_test.cpp
@@ -0,0 +1,498 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Howard Hinnant 2014.
+// (C) Copyright Ion Gaztanaga 2014-2014. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// This testcase is based on H. Hinnant's article "Insert vs. Emplace",
+// (http://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html)
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <iostream>
+#include <boost/move/utility_core.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+class X
+{
+   int i_;
+   int* p_;
+
+   BOOST_COPYABLE_AND_MOVABLE(X)
+
+public:
+   struct special
+   {
+      unsigned c;
+      unsigned dt;
+      unsigned cc;
+      unsigned ca;
+      unsigned mc;
+      unsigned ma;
+
+      friend bool operator==(const special &l, const special &r)
+      {  return l.c == r.c && l.dt == r.dt && l.cc == r.cc && l.ca == r.ca && l.mc == r.mc && l.ma == r.ma;  }
+   };
+   static special sp;
+
+   X(int i, int* p)
+      : i_(i)
+      , p_(p)
+   {
+//         std::cout << "X(int i, int* p)\n";
+      sp.c++;
+   }
+
+   ~X()
+   {
+//         std::cout << "~X()\n";
+      sp.dt++;
+   }
+
+   X(const X& x)
+      : i_(x.i_)
+      , p_(x.p_)
+   {
+//         std::cout << "X(const X& x)\n";
+      sp.cc++;
+   }
+
+   X& operator=(BOOST_COPY_ASSIGN_REF(X) x)
+   {
+
+      i_ = x.i_;
+      p_ = x.p_;
+//         std::cout << "X& operator=(const X& x)\n";
+      sp.ca++;
+      return *this;
+   }
+
+   X(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
+      : i_(x.i_)
+      , p_(x.p_)
+   {
+//         std::cout << "X(X&& x)\n";
+      sp.mc++;
+   }
+
+   X& operator=(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
+   {
+
+      i_ = x.i_;
+      p_ = x.p_;
+//         std::cout << "X& operator=(X&& x)\n";
+      sp.ma++;
+      return *this;
+   }
+
+};
+
+std::ostream&
+operator<<(std::ostream& os, X::special const& sp)
+{
+   os << "Const: " << sp.c << '\n';
+   os << "Destr: " << sp.dt << '\n';
+   os << "CopyC: " << sp.cc << '\n';
+   os << "CopyA: " << sp.ca << '\n';
+   os << "MoveC: " << sp.mc << '\n';
+   os << "MoveA: " << sp.ma << '\n';
+   os << "Total: " << (sp.c + sp.dt + sp.cc + sp.ca + sp.mc + sp.ma) << '\n';
+   return os;
+}
+
+X::special X::sp = X::special();
+
+const X produce_const_prvalue()
+{   return X(0, 0);   }
+
+int main()
+{
+   X::special insert_results;
+   X::special emplace_results;
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--insert lvalue no reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace lvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--insert xvalue no reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace xvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace const prvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), produce_const_prvalue());
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace const prvalue no reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), produce_const_prvalue());
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--insert rvalue no reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--emplace rvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   //With emulated move semantics an extra copy is unavoidable
+   #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   #endif
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--insert lvalue reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace lvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--insert xvalue reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace xvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--insert rvalue reallocation--\n";
+      X::sp = X::special();
+      v.insert(v.begin(), X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--emplace rvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace(v.begin(), X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   //With emulated move semantics an extra copy is unavoidable
+   #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   #endif
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--push_back lvalue no reallocation--\n";
+      X::sp = X::special();
+      v.push_back(x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace_back lvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--push_back xvalue no reallocation--\n";
+      X::sp = X::special();
+      v.push_back(boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace_back xvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--push_back rvalue no reallocation--\n";
+      X::sp = X::special();
+      v.push_back(X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(4);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--emplace_back rvalue no reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   //With emulated move semantics an extra copy is unavoidable
+   #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   #endif
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--push_back lvalue reallocation--\n";
+      X::sp = X::special();
+      v.push_back(x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace_back lvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(x);
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--push_back xvalue reallocation--\n";
+      X::sp = X::special();
+      v.push_back(boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      X x(0,0);
+      std::cout << "--emplace_back xvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(boost::move(x));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--push_back rvalue reallocation--\n";
+      X::sp = X::special();
+      v.push_back(X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      insert_results = X::sp;
+   }
+   {
+      boost::container::vector<X> v;
+      v.reserve(3);
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      v.push_back(X(0,0));
+      std::cout << "--emplace_back rvalue reallocation--\n";
+      X::sp = X::special();
+      v.emplace_back(X(0,0));
+      std::cout << X::sp;
+      std::cout << "----\n";
+      emplace_results = X::sp;
+   }
+   //With emulated move semantics an extra copy is unavoidable
+   #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
+   BOOST_TEST_EQ(insert_results == emplace_results, true);
+   #endif
+   return boost::report_errors();
+}
diff --git a/test/list_test.cpp b/test/list_test.cpp
new file mode 100644
index 0000000..aefa008
--- /dev/null
+++ b/test/list_test.cpp
@@ -0,0 +1,255 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include "dummy_test_allocator.hpp"
+#include <memory>
+#include "movable_int.hpp"
+#include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::list
+   < test::movable_and_copyable_int
+   , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::list
+   < test::movable_and_copyable_int
+   , adaptive_pool<test::movable_and_copyable_int> >;
+
+namespace dtl {
+
+template class iterator_from_iiterator
+   <intrusive_list_type< std::allocator<int> >::container_type::iterator, true >;
+template class iterator_from_iiterator
+   <intrusive_list_type< std::allocator<int> >::container_type::iterator, false>;
+
+}
+
+}}
+
+class recursive_list
+{
+public:
+   int id_;
+   list<recursive_list> list_;
+   list<recursive_list>::iterator it_;
+   list<recursive_list>::const_iterator cit_;
+   list<recursive_list>::reverse_iterator rit_;
+   list<recursive_list>::const_reverse_iterator crit_;
+
+   recursive_list &operator=(const recursive_list &o)
+   { list_ = o.list_;  return *this; }
+};
+
+void recursive_list_test()//Test for recursive types
+{
+   list<recursive_list> recursive, copy;
+   //Test to test both move emulations
+   if(!copy.size()){
+      copy = recursive;
+   }
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef list< ValueType
+                  , typename allocator_traits<VoidAllocator>
+                        ::template portable_rebind_alloc<ValueType>::type
+                  > type;
+   };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+   if(test::list_test<MyCont, true>())
+      return 1;
+   if(test::list_test<MyMoveCont, true>())
+      return 1;
+   if(test::list_test<MyCopyMoveCont, true>())
+      return 1;
+   if(test::list_test<MyCopyMoveCont, true>())
+      return 1;
+   if(test::list_test<MyCopyCont, true>())
+      return 1;
+
+   return 0;
+}
+
+bool test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   const std::initializer_list<int> il = {1, 10};
+   const list<int> expectedList(il.begin(), il.end());
+
+   const list<int> testConstructor((il));
+   if(testConstructor != expectedList)
+      return false;
+
+   const list<int> testConstructorAllocator(il, list<int>::allocator_type());
+   if (testConstructorAllocator != expectedList)
+      return false;
+
+   list<int> testAssignOperator = {10, 11};
+   testAssignOperator = il;
+   if(testAssignOperator != expectedList)
+      return false;
+
+   list<int> testAssignMethod = {99};
+   testAssignMethod = il;
+   if(testAssignMethod != expectedList)
+      return false;
+
+   list<int> testInsertMethod;
+   testInsertMethod.insert(testInsertMethod.cbegin(), il);
+   if(testInsertMethod != testInsertMethod)
+      return false;
+
+   return true;
+#endif
+   return true;
+}
+
+struct boost_container_list;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_list>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::list<T, Allocator> type;
+   };
+};
+
+}}}   //namespace boost::container::test
+
+int main ()
+{
+   recursive_list_test();
+   {
+      //Now test move semantics
+      list<recursive_list> original;
+      list<recursive_list> move_ctor(boost::move(original));
+      list<recursive_list> move_assign;
+      move_assign = boost::move(move_ctor);
+      move_assign.swap(original);
+   }
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_cont_variants< std::allocator<void> >()){
+      std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::adaptive_pool
+   if(test_cont_variants< adaptive_pool<void> >()){
+      std::cerr << "test_cont_variants< adaptive_pool<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_FRONT | test::EMPLACE_BEFORE);
+
+   if(!boost::container::test::test_emplace<list<test::EmplaceInt>, Options>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_list>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Initializer lists
+   ////////////////////////////////////
+   if(!test_support_for_initializer_list())
+      return 1;
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::list<int> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction Tests
+   ////////////////////////////////////
+   {
+      auto gold = std::list{ 1, 2, 3 };
+      auto test = boost::container::list(gold.begin(), gold.end());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (test.front() != 1)
+         return 1;
+      test.pop_front();
+      if (test.front() != 2)
+         return 1;
+      test.pop_front();
+      if (test.front() != 3)
+         return 1;
+      test.pop_front();
+   }
+   {
+      auto gold = std::list{ 1, 2, 3 };
+      auto test = boost::container::list(gold.begin(), gold.end(), new_allocator<int>());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (test.front() != 1)
+         return 1;
+      test.pop_front();
+      if (test.front() != 2)
+         return 1;
+      test.pop_front();
+      if (test.front() != 3)
+         return 1;
+      test.pop_front();
+   }
+#endif
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/list_test.hpp b/test/list_test.hpp
new file mode 100644
index 0000000..9640ec0
--- /dev/null
+++ b/test/list_test.hpp
@@ -0,0 +1,469 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_LIST_TEST_HEADER
+#define BOOST_CONTAINER_TEST_LIST_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include "input_from_forward_iterator.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+
+#include <list>
+#include <functional>   //std::greater
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class V1, class V2>
+bool list_copyable_only(V1 &, V2 &, boost::container::dtl::false_type)
+{
+   return true;
+}
+
+//Function to check if both sets are equal
+template<class V1, class V2>
+bool list_copyable_only(V1 &boostlist, V2 &stdlist, boost::container::dtl::true_type)
+{
+   typedef typename V1::value_type IntType;
+   boostlist.insert(boostlist.end(), 50, IntType(1));
+   stdlist.insert(stdlist.end(), 50, 1);
+   if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+
+   {
+      IntType move_me(1);
+      boostlist.insert(boostlist.begin(), 50, boost::move(move_me));
+      stdlist.insert(stdlist.begin(), 50, 1);
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+   }
+   {
+      IntType move_me(2);
+      boostlist.assign(boostlist.size()/2, boost::move(move_me));
+      stdlist.assign(stdlist.size()/2, 2);
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+   }
+   {
+      IntType move_me(3);
+      boostlist.assign(boostlist.size()*3-1, boost::move(move_me));
+      stdlist.assign(stdlist.size()*3-1, 3);
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+   }
+
+   {
+      IntType copy_me(3);
+      const IntType ccopy_me(3);
+      boostlist.push_front(copy_me);
+      stdlist.push_front(int(3));
+      boostlist.push_front(ccopy_me);
+      stdlist.push_front(int(3));
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return false;
+   }
+   {  //List(const List &)
+      ::boost::movelib::unique_ptr<V1> const pv1 = ::boost::movelib::make_unique<V1>(boostlist);
+      ::boost::movelib::unique_ptr<V2> const pv2 = ::boost::movelib::make_unique<V2>(stdlist);
+
+      V1 &v1 = *pv1;
+      V2 &v2 = *pv2;
+
+      boostlist.clear();
+      stdlist.clear();
+      boostlist.assign(v1.begin(), v1.end());
+      stdlist.assign(v2.begin(), v2.end());
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+   }
+   {  //List(const List &, alloc)
+      ::boost::movelib::unique_ptr<V1> const pv1 = ::boost::movelib::make_unique<V1>(boostlist, typename V1::allocator_type());
+      ::boost::movelib::unique_ptr<V2> const pv2 = ::boost::movelib::make_unique<V2>(stdlist);
+
+      V1 &v1 = *pv1;
+      V2 &v2 = *pv2;
+
+      boostlist.clear();
+      stdlist.clear();
+      boostlist.assign(v1.begin(), v1.end());
+      stdlist.assign(v2.begin(), v2.end());
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+   }
+
+   return true;
+}
+
+template<bool DoublyLinked>
+struct list_push_data_function
+{
+   template<class MyBoostList, class MyStdList>
+   static int execute(int max, MyBoostList &boostlist, MyStdList &stdlist)
+   {
+      typedef typename MyBoostList::value_type IntType;
+      for(int i = 0; i < max; ++i){
+         IntType move_me(i);
+         boostlist.push_back(boost::move(move_me));
+         stdlist.push_back(i);
+         boostlist.push_front(IntType(i));
+         stdlist.push_front(int(i));
+      }
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+      return 0;
+   }
+};
+
+template<>
+struct list_push_data_function<false>
+{
+   template<class MyBoostList, class MyStdList>
+   static int execute(int max, MyBoostList &boostlist, MyStdList &stdlist)
+   {
+      typedef typename MyBoostList::value_type IntType;
+      for(int i = 0; i < max; ++i){
+         IntType move_me(i);
+         boostlist.push_front(boost::move(move_me));
+         stdlist.push_front(i);
+         boostlist.push_front(IntType(i));
+         stdlist.push_front(int(i));
+      }
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+      return 0;
+   }
+};
+
+template<bool DoublyLinked>
+struct list_pop_back_function
+{
+   template<class MyStdList, class MyBoostList>
+   static int execute(MyBoostList &boostlist, MyStdList &stdlist)
+   {
+      boostlist.pop_back();
+      stdlist.pop_back();
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+      return 0;
+   }
+};
+
+template<>
+struct list_pop_back_function<false>
+{
+   template<class MyStdList, class MyBoostList>
+   static int execute(MyBoostList &boostlist, MyStdList &stdlist)
+   {
+      (void)boostlist; (void)stdlist;
+      return 0;
+   }
+};
+
+template<class MyBoostList
+        ,bool  DoublyLinked>
+int list_test (bool copied_allocators_equal = true)
+{
+   typedef std::list<int> MyStdList;
+   typedef typename MyBoostList::value_type IntType;
+   const int max = 100;
+   typedef list_push_data_function<DoublyLinked> push_data_t;
+
+   {  //List(n)
+      ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>(100);
+      ::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>(100);
+      if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1;
+   }
+   {  //List(n, alloc)
+      ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>(100, typename MyBoostList::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdList> const pstdlist = ::boost::movelib::make_unique<MyStdList>(100);
+      if(!test::CheckEqualContainers(*pboostlist, *pstdlist)) return 1;
+   }
+   {  //List(List &&)
+      ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>(::boost::move(*boostlistp));
+      if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+   }
+   {  //List(List &&, alloc)
+      ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>
+         (::boost::move(*boostlistp), typename MyBoostList::allocator_type());
+      if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+   }
+   {  //List operator=(List &&)
+      ::boost::movelib::unique_ptr<MyStdList> const stdlistp = ::boost::movelib::make_unique<MyStdList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp = ::boost::movelib::make_unique<MyBoostList>(100);
+      ::boost::movelib::unique_ptr<MyBoostList> const boostlistp2 = ::boost::movelib::make_unique<MyBoostList>();
+      *boostlistp2 = ::boost::move(*boostlistp);
+      if(!test::CheckEqualContainers(*boostlistp2, *stdlistp)) return 1;
+   }
+
+   ::boost::movelib::unique_ptr<MyBoostList> const pboostlist = ::boost::movelib::make_unique<MyBoostList>();
+   ::boost::movelib::unique_ptr<MyStdList>   const pstdlist   = ::boost::movelib::make_unique<MyStdList>();
+
+   MyBoostList &boostlist = *pboostlist;
+   MyStdList  &stdlist    = *pstdlist;
+
+   if(push_data_t::execute(max, boostlist, stdlist)){
+      return 1;
+   }
+
+   boostlist.erase(boostlist.begin()++);
+   stdlist.erase(stdlist.begin()++);
+   if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+   if(list_pop_back_function<DoublyLinked>::execute(boostlist, stdlist)){
+      return 1;
+   }
+
+   boostlist.pop_front();
+   stdlist.pop_front();
+   if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+   {
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+      boostlist.assign(boost::make_move_iterator(&aux_vect[0])
+                        ,boost::make_move_iterator(&aux_vect[50]));
+      stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
+      if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+      boostlist.assign(boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+                        ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
+      stdlist.assign(&aux_vect2[0], &aux_vect2[50]);
+      if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+   }
+
+   if(copied_allocators_equal){
+      boostlist.sort();
+      stdlist.sort();
+      if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+   }
+
+   boostlist.reverse();
+   stdlist.reverse();
+   if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+   boostlist.reverse();
+   stdlist.reverse();
+   if(!CheckEqualContainers(boostlist, stdlist)) return 1;
+
+   {
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+      typename MyBoostList::iterator old_begin = boostlist.begin();
+      typename MyBoostList::iterator it_insert =
+         boostlist.insert(boostlist.begin()
+                     ,boost::make_move_iterator(&aux_vect[0])
+                     ,boost::make_move_iterator(&aux_vect[50]));
+      if(it_insert != boostlist.begin() || boost::container::iterator_distance(it_insert, old_begin) != 50)
+         return 1;
+
+      stdlist.insert(stdlist.begin(), &aux_vect2[0], &aux_vect2[50]);
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+
+      old_begin = boostlist.begin();
+      it_insert = boostlist.insert(boostlist.end()
+                     ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+                     ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[50])));
+      if(boost::container::iterator_distance(it_insert, boostlist.end()) != 50)
+         return 1;
+      stdlist.insert(stdlist.end(), &aux_vect2[0], &aux_vect2[50]);
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+   }
+
+   boostlist.unique();
+   stdlist.unique();
+   if(!CheckEqualContainers(boostlist, stdlist))
+      return 1;
+
+   if(copied_allocators_equal){
+      boostlist.sort(std::greater<IntType>());
+      stdlist.sort(std::greater<int>());
+      if(!CheckEqualContainers(boostlist, stdlist))
+         return 1;
+   }
+
+   for(int i = 0; i < max; ++i){
+      IntType new_int(i);
+      boostlist.insert(boostlist.end(), boost::move(new_int));
+      stdlist.insert(stdlist.end(), i);
+      if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+   }
+   if(!test::CheckEqualContainers(boostlist, stdlist)) return 1;
+
+   boostlist.resize(25);
+   stdlist.resize(25);
+   boostlist.resize(50);
+   stdlist.resize(50);
+   boostlist.resize(0);
+   stdlist.resize(0);
+   if(!CheckEqualContainers(boostlist, stdlist))
+      return 1;
+
+   //some comparison operators
+   if(!(boostlist == boostlist))
+      return 1;
+   if(boostlist != boostlist)
+      return 1;
+   if(boostlist < boostlist)
+      return 1;
+   if(boostlist > boostlist)
+      return 1;
+   if(!(boostlist <= boostlist))
+      return 1;
+   if(!(boostlist >= boostlist))
+      return 1;
+
+   if(push_data_t::execute(max, boostlist, stdlist)){
+      return 1;
+   }
+   {
+      MyBoostList otherboostlist(boostlist.get_allocator());
+      MyStdList otherstdlist;
+
+      int listsize = (int)boostlist.size();
+
+      if(push_data_t::execute(listsize, boostlist, stdlist)){
+         return 1;
+      }
+
+      if(copied_allocators_equal){
+         boostlist.splice(boostlist.begin(), otherboostlist);
+         stdlist.splice(stdlist.begin(), otherstdlist);
+         if(!CheckEqualContainers(boostlist, stdlist))
+            return 1;
+      }
+
+      listsize = (int)boostlist.size();
+
+      if(push_data_t::execute(listsize, boostlist, stdlist)){
+         return 1;
+      }
+
+      if(push_data_t::execute(listsize, otherboostlist, otherstdlist)){
+         return 1;
+      }
+
+      if(copied_allocators_equal){
+         boostlist.sort(std::greater<IntType>());
+         stdlist.sort(std::greater<int>());
+         if(!CheckEqualContainers(boostlist, stdlist))
+            return 1;
+
+         otherboostlist.sort(std::greater<IntType>());
+         otherstdlist.sort(std::greater<int>());
+         if(!CheckEqualContainers(otherboostlist, otherstdlist))
+            return 1;
+
+         boostlist.merge(otherboostlist, std::greater<IntType>());
+         stdlist.merge(otherstdlist, std::greater<int>());
+         if(!CheckEqualContainers(boostlist, stdlist))
+            return 1;
+      }
+
+      if(!list_copyable_only(boostlist, stdlist
+                     ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+         return 1;
+      }
+   }
+   return 0;
+}
+
+template<class List>
+bool test_list_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   const std::initializer_list<int> il = {5, 10, 15};
+   const List expected_list(il.begin(), il.end());
+   {
+      List sl = il;
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+      List sl = {1, 2};
+      sl = il;
+      if(sl != expected_list)
+         return false;
+   }
+   {
+      List sl({ 1, 2 }, typename List::allocator_type());
+      sl = il;
+      if (sl != expected_list)
+         return false;
+   }
+   {
+      List sl = {4, 5};
+      sl.assign(il);
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+      List sl = {15};
+      sl.insert(sl.cbegin(), {5, 10});
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+       List sl = {5};
+       sl.insert_after(sl.cbegin(), {10, 15});
+       if(sl != expected_list)
+          return false;
+   }
+   return true;
+#endif
+   return true;
+}
+
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/test/map_test.cpp b/test/map_test.cpp
new file mode 100644
index 0000000..619646a
--- /dev/null
+++ b/test/map_test.cpp
@@ -0,0 +1,565 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include <map>
+
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include "map_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//map
+template class map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator< pair_t >
+   >;
+
+template class map
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , adaptive_pool< pair_t >
+   >;
+
+template class multimap
+   < test::movable_and_copyable_int
+   , test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , std::allocator< pair_t >
+   >;
+}} //boost::container
+
+class recursive_map
+{
+   public:
+   recursive_map & operator=(const recursive_map &x)
+   {  id_ = x.id_;  map_ = x.map_; return *this;  }
+
+   int id_;
+   map<recursive_map, recursive_map> map_;
+   map<recursive_map, recursive_map>::iterator it_;
+   map<recursive_map, recursive_map>::const_iterator cit_;
+   map<recursive_map, recursive_map>::reverse_iterator rit_;
+   map<recursive_map, recursive_map>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_map &a, const recursive_map &b)
+   {  return a.id_ < b.id_;   }
+};
+
+class recursive_multimap
+{
+   public:
+   recursive_multimap & operator=(const recursive_multimap &x)
+   {  id_ = x.id_;  multimap_ = x.multimap_; return *this;  }
+
+   int id_;
+   multimap<recursive_multimap, recursive_multimap> multimap_;
+   multimap<recursive_multimap, recursive_multimap>::iterator it_;
+   multimap<recursive_multimap, recursive_multimap>::const_iterator cit_;
+   multimap<recursive_multimap, recursive_multimap>::reverse_iterator rit_;
+   multimap<recursive_multimap, recursive_multimap>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_multimap &a, const recursive_multimap &b)
+   {  return a.id_ < b.id_;   }
+};
+
+template<class C>
+void test_move()
+{
+   //Now test move semantics
+   C original;
+   original.emplace();
+   C move_ctor(boost::move(original));
+   C move_assign;
+   move_assign.emplace();
+   move_assign = boost::move(move_ctor);
+   move_assign.swap(original);
+}
+
+bool node_type_test()
+{
+   using namespace boost::container;
+   {
+      typedef map<test::movable_int, test::movable_int> map_type;
+      map_type src;
+      {
+         test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13);
+         src.try_emplace(boost::move(mv_1), boost::move(mv_11)); 
+         src.try_emplace(boost::move(mv_2), boost::move(mv_12)); 
+         src.try_emplace(boost::move(mv_3), boost::move(mv_13)); 
+      }
+      if(src.size() != 3)
+         return false;
+
+      map_type dst;
+      {
+         test::movable_int mv_3(3), mv_33(33);
+         dst.try_emplace(boost::move(mv_3), boost::move(mv_33)); 
+      }
+
+      if(dst.size() != 1)
+         return false;
+
+      const test::movable_int mv_1(1);
+      const test::movable_int mv_2(2);
+      const test::movable_int mv_3(3);
+      const test::movable_int mv_33(33);
+      const test::movable_int mv_13(13);
+      map_type::insert_return_type r;
+
+      r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
+      if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
+         return false;
+      r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
+      if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
+         return false;
+      r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
+      if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
+         return false;
+      r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
+
+      if(!src.empty())
+         return false;
+      if(dst.size() != 3)
+         return false;
+      if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.key() == mv_3 && r.node.mapped() == mv_13) )
+         return false;
+   }
+
+   {
+      typedef multimap<test::movable_int, test::movable_int> multimap_type;
+      multimap_type src;
+      {
+         test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3), mv_11(11), mv_12(12), mv_13(13), mv_23(23);
+         src.emplace(boost::move(mv_1), boost::move(mv_11));
+         src.emplace(boost::move(mv_2), boost::move(mv_12));
+         src.emplace(boost::move(mv_3), boost::move(mv_13));
+         src.emplace_hint(src.begin(), boost::move(mv_3bis), boost::move(mv_23));
+      }
+      if(src.size() != 4)
+         return false;
+
+      multimap_type dst;
+      {
+         test::movable_int mv_3(3), mv_33(33);
+         dst.emplace(boost::move(mv_3), boost::move(mv_33)); 
+      }
+
+      if(dst.size() != 1)
+         return false;
+
+      const test::movable_int mv_1(1);
+      const test::movable_int mv_2(2);
+      const test::movable_int mv_3(3);
+      const test::movable_int mv_4(4);
+      const test::movable_int mv_33(33);
+      const test::movable_int mv_13(13);
+      const test::movable_int mv_23(23);
+      multimap_type::iterator r;
+
+      multimap_type::node_type nt(src.extract(mv_3));
+      r = dst.insert(dst.begin(), boost::move(nt));
+      if(! (r->first == mv_3 && r->second == mv_23 && dst.find(mv_3) == r && nt.empty()) )
+         return false;
+
+      nt = src.extract(src.find(mv_1));
+      r = dst.insert(boost::move(nt)); // Iterator version, successful
+      if(! (r->first == mv_1 && nt.empty()) )
+         return false;
+
+      nt = src.extract(mv_2);
+      r = dst.insert(boost::move(nt)); // Key type version, successful
+      if(! (r->first == mv_2 && nt.empty()) )
+         return false;
+
+      r = dst.insert(src.extract(mv_3)); // Key type version, successful
+      if(! (r->first == mv_3 && r->second == mv_13 && r == --multimap_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
+         return false;
+
+      r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
+      if(! (r == dst.end()) )
+         return false;
+
+      if(!src.empty())
+         return false;
+      if(dst.size() != 5)
+         return false;
+   }
+   return true;
+}
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+struct GetAllocatorMap
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef map< ValueType
+                 , ValueType
+                 , std::less<ValueType>
+                 , typename allocator_traits<VoidAllocator>
+                    ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
+                  , typename boost::container::tree_assoc_options
+                        < boost::container::tree_type<tree_type_value>
+                        >::type
+                 > map_type;
+
+      typedef multimap< ValueType
+                 , ValueType
+                 , std::less<ValueType>
+                 , typename allocator_traits<VoidAllocator>
+                    ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type
+                  , typename boost::container::tree_assoc_options
+                        < boost::container::tree_type<tree_type_value>
+                        >::type
+                 > multimap_type;
+   };
+};
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+int test_map_variants()
+{
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<int>::map_type MyMap;
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_int>::map_type MyMoveMap;
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::map_type MyCopyMap;
+
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<int>::multimap_type MyMultiMap;
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::movable_int>::multimap_type MyMoveMultiMap;
+   typedef typename GetAllocatorMap<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::multimap_type MyCopyMultiMap;
+
+   typedef std::map<int, int>                                     MyStdMap;
+   typedef std::multimap<int, int>                                MyStdMultiMap;
+
+   if (0 != test::map_test<
+                  MyMap
+                  ,MyStdMap
+                  ,MyMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::map_test<
+                  MyMoveMap
+                  ,MyStdMap
+                  ,MyMoveMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::map_test<
+                  MyCopyMap
+                  ,MyStdMap
+                  ,MyCopyMultiMap
+                  ,MyStdMultiMap>()){
+      std::cout << "Error in map_test<MyBoostMap>" << std::endl;
+      return 1;
+   }
+
+   return 0;
+}
+
+struct boost_container_map;
+struct boost_container_multimap;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_map>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef typename boost::container::allocator_traits<Allocator>::
+         template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
+      typedef boost::container::map<T, T, std::less<T>, TypeAllocator> type;
+   };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_multimap>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef typename boost::container::allocator_traits<Allocator>::
+         template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator;
+      typedef boost::container::multimap<T, T, std::less<T>, TypeAllocator> type;
+   };
+};
+
+void test_merge_from_different_comparison()
+{
+   map<int, int> map1;
+   map<int, int, std::greater<int> > map2;
+   map1.merge(map2);
+}
+
+bool test_heterogeneous_lookups()
+{
+   typedef map<int, char, less_transparent> map_t;
+   typedef multimap<int, char, less_transparent> mmap_t;
+   typedef map_t::value_type value_type;
+
+   map_t map1;
+   mmap_t mmap1;
+
+   const map_t &cmap1 = map1;
+   const mmap_t &cmmap1 = mmap1;
+
+   map1.insert_or_assign(1, 'a');
+   map1.insert_or_assign(1, 'b');
+   map1.insert_or_assign(2, 'c');
+   map1.insert_or_assign(2, 'd');
+   map1.insert_or_assign(3, 'e');
+
+   mmap1.insert(value_type(1, 'a'));
+   mmap1.insert(value_type(1, 'b'));
+   mmap1.insert(value_type(2, 'c'));
+   mmap1.insert(value_type(2, 'd'));
+   mmap1.insert(value_type(3, 'e'));
+
+   const test::non_copymovable_int find_me(2);
+
+   //find
+   if(map1.find(find_me)->second != 'd')
+      return false;
+   if(cmap1.find(find_me)->second != 'd')
+      return false;
+   if(mmap1.find(find_me)->second != 'c')
+      return false;
+   if(cmmap1.find(find_me)->second != 'c')
+      return false;
+
+   //count
+   if(map1.count(find_me) != 1)
+      return false;
+   if(cmap1.count(find_me) != 1)
+      return false;
+   if(mmap1.count(find_me) != 2)
+      return false;
+   if(cmmap1.count(find_me) != 2)
+      return false;
+
+   //lower_bound
+   if(map1.lower_bound(find_me)->second != 'd')
+      return false;
+   if(cmap1.lower_bound(find_me)->second != 'd')
+      return false;
+   if(mmap1.lower_bound(find_me)->second != 'c')
+      return false;
+   if(cmmap1.lower_bound(find_me)->second != 'c')
+      return false;
+
+   //upper_bound
+   if(map1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(cmap1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(mmap1.upper_bound(find_me)->second != 'e')
+      return false;
+   if(cmmap1.upper_bound(find_me)->second != 'e')
+      return false;
+
+   //equal_range
+   if(map1.equal_range(find_me).first->second != 'd')
+      return false;
+   if(cmap1.equal_range(find_me).second->second != 'e')
+      return false;
+   if(mmap1.equal_range(find_me).first->second != 'c')
+      return false;
+   if(cmmap1.equal_range(find_me).second->second != 'e')
+      return false;
+
+   return true;
+}
+
+}}}   //namespace boost::container::test
+
+int main ()
+{
+   //Recursive container instantiation
+   {
+      map<recursive_map, recursive_map> map_;
+      multimap<recursive_multimap, recursive_multimap> multimap_;
+   }
+   //Allocator argument container
+   {
+      map<int, int> map_((map<int, int>::allocator_type()));
+      multimap<int, int> multimap_((multimap<int, int>::allocator_type()));
+   }
+   //Now test move semantics
+   {
+      test_move<map<recursive_map, recursive_map> >();
+      test_move<multimap<recursive_multimap, recursive_multimap> >();
+   }
+
+   //Test std::pair value type as tree has workarounds to make old std::pair
+   //implementations movable that can break things
+   {
+      boost::container::map<pair_t, pair_t> s;
+      std::pair<const pair_t,pair_t> p;
+      s.insert(p);
+      s.emplace(p);
+   }
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_map_variants< std::allocator<void>, red_black_tree >()){
+      std::cerr << "test_map_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::adaptive_pool
+   if(test_map_variants< adaptive_pool<void>, red_black_tree >()){
+      std::cerr << "test_map_variants< adaptive_pool<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Tree implementations
+   ////////////////////////////////////
+   //       AVL
+   if(test_map_variants< std::allocator<void>, avl_tree >()){
+      std::cerr << "test_map_variants< std::allocator<void>, avl_tree > failed" << std::endl;
+      return 1;
+   }
+   //    SCAPEGOAT TREE
+   if(test_map_variants< std::allocator<void>, scapegoat_tree >()){
+      std::cerr << "test_map_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl;
+      return 1;
+   }
+   //    SPLAY TREE
+   if(test_map_variants< std::allocator<void>, splay_tree >()){
+      std::cerr << "test_map_variants< std::allocator<void>, splay_tree > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
+   if(!boost::container::test::test_emplace<map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+      return 1;
+   if(!boost::container::test::test_emplace<multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_map>())
+      return 1;
+
+   if(!boost::container::test::test_propagate_allocator<boost_container_multimap>())
+      return 1;
+
+   if (!boost::container::test::test_map_support_for_initialization_list_for<map<int, int> >())
+      return 1;
+
+   if (!boost::container::test::test_map_support_for_initialization_list_for<multimap<int, int> >())
+      return 1;
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::map<int, int> cont_int;
+      cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+      boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+   {
+      typedef boost::container::multimap<int, int> cont_int;
+      cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
+      boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction
+   ////////////////////////////////////
+   {
+      auto gold = std::map<int, int>({ {1,1}, {2,2}, {3,3} } );
+      auto test = boost::container::map(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+   {
+      auto gold = std::multimap<int, int>({ {1,1}, {2,2}, {3,3} } );
+      auto test = boost::container::multimap(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+#endif
+
+   ////////////////////////////////////
+   //    Node extraction/insertion testing functions
+   ////////////////////////////////////
+   if(!node_type_test())
+      return 1;
+
+   if (!boost::container::test::instantiate_constructors<map<int, int>, multimap<int, int> >())
+      return 1;
+
+   test::test_merge_from_different_comparison();
+
+   if(!test::test_heterogeneous_lookups())
+      return 1;
+
+   ////////////////////////////////////
+   //    Test optimize_size option
+   ////////////////////////////////////
+   //
+   // map
+   //
+   typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+              , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmap_size_optimized_no;
+
+   typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+              , tree_assoc_options< optimize_size<true>, tree_type<avl_tree>  >::type > avlmap_size_optimized_yes;
+   //
+   // multimap
+   //
+   typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+                   , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree>  >::type > rbmmap_size_optimized_yes;
+   typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> >
+                   , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmmap_size_optimized_no;
+
+   BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes) < sizeof(rbmap_size_optimized_no));
+   BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes) < sizeof(avlmmap_size_optimized_no));
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/map_test.hpp b/test/map_test.hpp
new file mode 100644
index 0000000..93dbf2f
--- /dev/null
+++ b/test/map_test.hpp
@@ -0,0 +1,1037 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER
+#define BOOST_CONTAINER_TEST_MAP_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include <boost/container/detail/pair.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/make_unique.hpp>
+
+#include <boost/intrusive/detail/minimal_pair_header.hpp>      //pair
+#include <string>
+#include <iostream>
+
+#include <boost/intrusive/detail/mpl.hpp>
+
+namespace boost { namespace container { namespace test {
+
+BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED(has_member_rebalance, rebalance)
+
+}}}
+
+template<class T1, class T2, class T3, class T4>
+bool operator ==(std::pair<T1, T2> &p1, std::pair<T1, T2> &p2)
+{
+   return p1.first == p2.first && p1.second == p2.second;
+}
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class C>
+void map_test_rebalanceable(C &, boost::container::dtl::false_type)
+{}
+
+template<class C>
+void map_test_rebalanceable(C &c, boost::container::dtl::true_type)
+{
+   c.rebalance();
+}
+
+template<class MyBoostMap
+        ,class MyStdMap
+        ,class MyBoostMultiMap
+        ,class MyStdMultiMap>
+int map_test_copyable(boost::container::dtl::false_type)
+{  return 0; }
+
+template<class MyBoostMap
+        ,class MyStdMap
+        ,class MyBoostMultiMap
+        ,class MyStdMultiMap>
+int map_test_copyable(boost::container::dtl::true_type)
+{
+   typedef typename MyBoostMap::key_type    IntType;
+   typedef dtl::pair<IntType, IntType>         IntPairType;
+   typedef typename MyStdMap::value_type  StdPairType;
+
+   const int MaxElem = 50;
+
+   ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
+   ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>();
+   ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>();
+   ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>();
+   MyBoostMap &boostmap = *pboostmap;
+   MyStdMap   &stdmap   = *pstdmap;
+   MyBoostMultiMap &boostmultimap = *pboostmultimap;
+   MyStdMultiMap   &stdmultimap   = *pstdmultimap;
+
+   //Just to test move aware catch conversions
+   boostmap.insert(boostmap.cbegin(), boostmap.cend());
+   boostmultimap.insert(boostmultimap.cbegin(), boostmultimap.cend());
+   boostmap.insert(boostmap.begin(), boostmap.end());
+   boostmultimap.insert(boostmultimap.begin(), boostmultimap.end());
+
+   int i;
+   for(i = 0; i < MaxElem; ++i){
+      {
+      IntType i1(i), i2(i);
+      IntPairType intpair1(boost::move(i1), boost::move(i2));
+      boostmap.insert(boost::move(intpair1));
+      stdmap.insert(StdPairType(i, i));
+      }
+      {
+      IntType i1(i), i2(i);
+      IntPairType intpair2(boost::move(i1), boost::move(i2));
+      boostmultimap.insert(boost::move(intpair2));
+      stdmultimap.insert(StdPairType(i, i));
+      }
+   }
+   if(!CheckEqualContainers(boostmap, stdmap)) return 1;
+   if(!CheckEqualContainers(boostmultimap, stdmultimap)) return 1;
+   {
+      //Now, test copy constructor
+      MyBoostMap boostmapcopy(boostmap);
+      MyStdMap stdmapcopy(stdmap);
+      MyBoostMultiMap boostmmapcopy(boostmultimap);
+      MyStdMultiMap stdmmapcopy(stdmultimap);
+
+      if(!CheckEqualContainers(boostmapcopy, stdmapcopy))
+         return 1;
+      if(!CheckEqualContainers(boostmmapcopy, stdmmapcopy))
+         return 1;
+
+      //And now assignment
+      boostmapcopy  = boostmap;
+      stdmapcopy  = stdmap;
+      boostmmapcopy = boostmultimap;
+      stdmmapcopy = stdmultimap;
+
+      if(!CheckEqualContainers(boostmapcopy, stdmapcopy))
+         return 1;
+      if(!CheckEqualContainers(boostmmapcopy, stdmmapcopy))
+         return 1;
+   }
+
+   return 0;
+}
+
+template<class MyBoostMap
+        ,class MyStdMap
+        ,class MyBoostMultiMap
+        ,class MyStdMultiMap>
+int map_test()
+{
+   typedef typename MyBoostMap::key_type    IntType;
+   typedef dtl::pair<IntType, IntType>         IntPairType;
+   typedef typename MyStdMap::value_type  StdPairType;
+   const int MaxElem = 50;
+   typedef typename MyStdMap::value_type StdValueType;
+   typedef typename MyStdMap::key_type StdKeyType;
+   typedef typename MyStdMap::mapped_type StdMappedType;
+
+
+   //Test construction from a range
+   {
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      StdValueType aux_vect2[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+      }
+
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
+               ( boost::make_move_iterator(&aux_vect[0])
+               , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::key_compare());
+      ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+      if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
+
+      ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
+               ( boost::make_move_iterator(&aux_vect3[0])
+               , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::key_compare());
+      ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+      if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
+   }
+   {
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      StdValueType aux_vect2[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+      }
+
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>
+               ( boost::make_move_iterator(&aux_vect[0])
+               , boost::make_move_iterator(&aux_vect[0] + MaxElem), typename MyBoostMap::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+      if(!CheckEqualContainers(*pboostmap, *pstdmap)) return 1;
+
+      ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>
+               ( boost::make_move_iterator(&aux_vect3[0])
+               , boost::make_move_iterator(&aux_vect3[0] + MaxElem), typename MyBoostMap::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem, typename MyStdMap::key_compare());
+      if(!CheckEqualContainers(*pboostmultimap, *pstdmultimap)) return 1;
+   }
+
+   ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap = ::boost::movelib::make_unique<MyBoostMap>();
+   ::boost::movelib::unique_ptr<MyStdMap> const pstdmap = ::boost::movelib::make_unique<MyStdMap>();
+   ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap = ::boost::movelib::make_unique<MyBoostMultiMap>();
+   ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap = ::boost::movelib::make_unique<MyStdMultiMap>();
+   MyBoostMap &boostmap = *pboostmap;
+   MyStdMap   &stdmap   = *pstdmap;
+   MyBoostMultiMap &boostmultimap = *pboostmultimap;
+   MyStdMultiMap   &stdmultimap   = *pstdmultimap;
+
+   {
+      //This is really nasty, but we have no other simple choice
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      typedef typename MyStdMap::value_type StdValueType;
+      typedef typename MyStdMap::key_type StdKeyType;
+      typedef typename MyStdMap::mapped_type StdMappedType;
+      StdValueType aux_vect2[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         new(&aux_vect2[i])StdValueType(StdKeyType(i/2), StdMappedType(i/2));
+      }
+
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i/2);
+         IntType i2(i/2);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>
+               ( boost::make_move_iterator(&aux_vect[0])
+               , boost::make_move_iterator(&aux_vect[0] + MaxElem));
+      ::boost::movelib::unique_ptr<MyStdMap> const pstdmap2 = ::boost::movelib::make_unique<MyStdMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+      ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>
+               ( boost::make_move_iterator(&aux_vect3[0])
+               , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap2 = ::boost::movelib::make_unique<MyStdMultiMap>
+         (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+      MyBoostMap &boostmap2 = *pboostmap2;
+      MyStdMap   &stdmap2   = *pstdmap2;
+      MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
+      MyStdMultiMap   &stdmultimap2   = *pstdmultimap2;
+
+      if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+      if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1;
+
+      //ordered range insertion
+      //This is really nasty, but we have no other simple choice
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         new(&aux_vect2[i])StdValueType(StdKeyType(i), StdMappedType(i));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+      if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+      if(!CheckEqualContainers(boostmultimap2, stdmultimap2)) return 1;
+
+      //some comparison operators
+      if(!(boostmap2 == boostmap2))
+         return 1;
+      if(boostmap2 != boostmap2)
+         return 1;
+      if(boostmap2 < boostmap2)
+         return 1;
+      if(boostmap2 > boostmap2)
+         return 1;
+      if(!(boostmap2 <= boostmap2))
+         return 1;
+      if(!(boostmap2 >= boostmap2))
+         return 1;
+
+      ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap3 = ::boost::movelib::make_unique<MyBoostMap>
+               ( boost::make_move_iterator(&aux_vect[0])
+               , boost::make_move_iterator(&aux_vect[0] + MaxElem));
+      ::boost::movelib::unique_ptr<MyStdMap> const pstdmap3 = ::boost::movelib::make_unique<MyStdMap>
+               (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+      ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap3 = ::boost::movelib::make_unique<MyBoostMultiMap>
+               ( boost::make_move_iterator(&aux_vect3[0])
+               , boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      ::boost::movelib::unique_ptr<MyStdMultiMap> const pstdmultimap3 = ::boost::movelib::make_unique<MyStdMultiMap>
+               (&aux_vect2[0], &aux_vect2[0] + MaxElem);
+      MyBoostMap &boostmap3 = *pboostmap3;
+      MyStdMap   &stdmap3   = *pstdmap3;
+      MyBoostMultiMap &boostmultimap3 = *pboostmultimap3;
+      MyStdMultiMap   &stdmultimap3   = *pstdmultimap3;
+
+      if(!CheckEqualContainers(boostmap3, stdmap3)){
+         std::cout << "Error in construct<MyBoostMap>(MyBoostMap3)" << std::endl;
+         return 1;
+      }
+      if(!CheckEqualContainers(boostmultimap3, stdmultimap3)){
+         std::cout << "Error in construct<MyBoostMultiMap>(MyBoostMultiMap3)" << std::endl;
+         return 1;
+      }
+
+      {
+         IntType i0(0);
+         boostmap2.erase(i0);
+         boostmultimap2.erase(i0);
+         stdmap2.erase(0);
+         stdmultimap2.erase(0);
+      }
+      {
+         IntType i0(0);
+         IntType i1(1);
+         boostmap2[::boost::move(i0)] = ::boost::move(i1);
+      }
+      {
+         IntType i1(1);
+         boostmap2[IntType(0)] = ::boost::move(i1);
+      }
+      stdmap2[0] = 1;
+      if(!CheckEqualContainers(boostmap2, stdmap2)) return 1;
+   }
+   {
+      //This is really nasty, but we have no other simple choice
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         boostmap.insert(boost::move(aux_vect[i]));
+         stdmap.insert(StdPairType(i, i));
+         boostmultimap.insert(boost::move(aux_vect3[i]));
+         stdmultimap.insert(StdPairType(i, i));
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      typename MyBoostMap::iterator it = boostmap.begin();
+      typename MyBoostMap::const_iterator cit = it;
+      (void)cit;
+
+      boostmap.erase(boostmap.begin());
+      stdmap.erase(stdmap.begin());
+      boostmultimap.erase(boostmultimap.begin());
+      stdmultimap.erase(stdmultimap.begin());
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      boostmap.erase(boostmap.begin());
+      stdmap.erase(stdmap.begin());
+      boostmultimap.erase(boostmultimap.begin());
+      stdmultimap.erase(stdmultimap.begin());
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      //Swapping test
+      MyBoostMap tmpboostemap2;
+      MyStdMap tmpstdmap2;
+      MyBoostMultiMap tmpboostemultimap2;
+      MyStdMultiMap tmpstdmultimap2;
+      boostmap.swap(tmpboostemap2);
+      stdmap.swap(tmpstdmap2);
+      boostmultimap.swap(tmpboostemultimap2);
+      stdmultimap.swap(tmpstdmultimap2);
+      boostmap.swap(tmpboostemap2);
+      stdmap.swap(tmpstdmap2);
+      boostmultimap.swap(tmpboostemultimap2);
+      stdmultimap.swap(tmpstdmultimap2);
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+   //Insertion from other container
+   //Initialize values
+   {
+      //This is really nasty, but we have no other simple choice
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+      boostmultimap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      for(int i = 0; i != MaxElem; ++i){
+         StdPairType stdpairtype(-1, -1);
+         stdmap.insert(stdpairtype);
+         stdmultimap.insert(stdpairtype);
+      }
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      for(int i = 0, j = static_cast<int>(boostmap.size()); i < j; ++i){
+         IntType k(i);
+         boostmap.erase(k);
+         stdmap.erase(i);
+         boostmultimap.erase(k);
+         stdmultimap.erase(i);
+      }
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+   {
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      IntPairType aux_vect4[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect4[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      IntPairType aux_vect5[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(-1);
+         IntType i2(-1);
+         new(&aux_vect5[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+      boostmap.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      boostmultimap.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(aux_vect4 + MaxElem));
+      boostmultimap.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(aux_vect5 + MaxElem));
+
+      for(int i = 0; i != MaxElem; ++i){
+         StdPairType stdpairtype(-1, -1);
+         stdmap.insert(stdpairtype);
+         stdmultimap.insert(stdpairtype);
+         stdmap.insert(stdpairtype);
+         stdmultimap.insert(stdpairtype);
+      }
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      boostmap.erase(boostmap.begin()->first);
+      stdmap.erase(stdmap.begin()->first);
+      boostmultimap.erase(boostmultimap.begin()->first);
+      stdmultimap.erase(stdmultimap.begin()->first);
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+
+   {
+      //This is really nasty, but we have no other simple choice
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+      IntPairType aux_vect3[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         boostmap.insert(boost::move(aux_vect[i]));
+         stdmap.insert(StdPairType(i, i));
+         boostmultimap.insert(boost::move(aux_vect3[i]));
+         stdmultimap.insert(StdPairType(i, i));
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         IntPairType intpair;
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmap.insert(boostmap.begin(), boost::move(intpair));
+         stdmap.insert(stdmap.begin(), StdPairType(i, i));
+         //PrintContainers(boostmap, stdmap);
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmultimap.insert(boostmultimap.begin(), boost::move(intpair));
+         stdmultimap.insert(stdmultimap.begin(), StdPairType(i, i));
+         //PrintContainers(boostmultimap, stdmultimap);
+         if(!CheckEqualPairContainers(boostmap, stdmap))
+            return 1;
+         if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+            return 1;
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmap.insert(boostmap.end(), boost::move(intpair));
+         stdmap.insert(stdmap.end(), StdPairType(i, i));
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmultimap.insert(boostmultimap.end(), boost::move(intpair));
+         stdmultimap.insert(stdmultimap.end(), StdPairType(i, i));
+         if(!CheckEqualPairContainers(boostmap, stdmap))
+            return 1;
+         if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+            return 1;
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         IntType k(i);
+         boostmap.insert(boostmap.lower_bound(k), boost::move(intpair));
+         stdmap.insert(stdmap.lower_bound(i), StdPairType(i, i));
+         //PrintContainers(boostmap, stdmap);
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         {
+            IntType i1(i);
+            boostmultimap.insert(boostmultimap.lower_bound(boost::move(i1)), boost::move(intpair));
+            stdmultimap.insert(stdmultimap.lower_bound(i), StdPairType(i, i));
+         }
+
+         //PrintContainers(boostmultimap, stdmultimap);
+         if(!CheckEqualPairContainers(boostmap, stdmap))
+            return 1;
+         if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+            return 1;
+         {  //Check equal_range
+            std::pair<typename MyBoostMultiMap::iterator, typename MyBoostMultiMap::iterator> bret =
+               boostmultimap.equal_range(boostmultimap.begin()->first);
+
+            std::pair<typename MyStdMultiMap::iterator, typename MyStdMultiMap::iterator>   sret =
+               stdmultimap.equal_range(stdmultimap.begin()->first);
+
+            if( boost::container::iterator_distance(bret.first, bret.second) !=
+                  boost::container::iterator_distance(sret.first, sret.second) ){
+               return 1;
+            }
+         }
+         {
+            IntType i1(i);
+            boostmap.insert(boostmap.upper_bound(boost::move(i1)), boost::move(intpair));
+            stdmap.insert(stdmap.upper_bound(i), StdPairType(i, i));
+         }
+         //PrintContainers(boostmap, stdmap);
+         {
+            IntType i1(i);
+            IntType i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         {
+            IntType i1(i);
+            boostmultimap.insert(boostmultimap.upper_bound(boost::move(i1)), boost::move(intpair));
+            stdmultimap.insert(stdmultimap.upper_bound(i), StdPairType(i, i));
+         }
+         //PrintContainers(boostmultimap, stdmultimap);
+         if(!CheckEqualPairContainers(boostmap, stdmap))
+            return 1;
+         if(!CheckEqualPairContainers(boostmultimap, stdmultimap))
+            return 1;
+
+         map_test_rebalanceable(boostmap
+            , dtl::bool_<has_member_rebalance<MyBoostMap>::value>());
+         if(!CheckEqualContainers(boostmap, stdmap)){
+            std::cout << "Error in boostmap.rebalance()" << std::endl;
+            return 1;
+         }
+         map_test_rebalanceable(boostmultimap
+            , dtl::bool_<has_member_rebalance<MyBoostMap>::value>());
+         if(!CheckEqualContainers(boostmultimap, stdmultimap)){
+            std::cout << "Error in boostmultimap.rebalance()" << std::endl;
+            return 1;
+         }
+      }
+
+      //Compare count with std containers
+      for(int i = 0; i < MaxElem; ++i){
+         IntType k(i);
+         if(boostmap.count(k) != stdmap.count(i)){
+            return -1;
+         }
+
+         if(boostmultimap.count(k) != stdmultimap.count(i)){
+            return -1;
+         }
+      }
+
+      //Now do count exercise
+      boostmap.erase(boostmap.begin(), boostmap.end());
+      boostmultimap.erase(boostmultimap.begin(), boostmultimap.end());
+      boostmap.clear();
+      boostmultimap.clear();
+
+      for(int j = 0; j < 3; ++j)
+      for(int i = 0; i < 100; ++i){
+         IntPairType intpair;
+         {
+         IntType i1(i), i2(i);
+         new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmap.insert(boost::move(intpair));
+         {
+            IntType i1(i), i2(i);
+            new(&intpair)IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmultimap.insert(boost::move(intpair));
+         IntType k(i);
+         if(boostmap.count(k) != typename MyBoostMultiMap::size_type(1))
+            return 1;
+         if(boostmultimap.count(k) != typename MyBoostMultiMap::size_type(j+1))
+            return 1;
+      }
+   }
+
+   {  //operator[] test
+      boostmap.clear();
+      boostmultimap.clear();
+      stdmap.clear();
+      stdmultimap.clear();
+
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         boostmap[boost::move(aux_vect[i].first)] = boost::move(aux_vect[i].second);
+         stdmap[i] = i;
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+
+   {  //insert_or_assign test
+      boostmap.clear();
+      boostmultimap.clear();
+      stdmap.clear();
+      stdmultimap.clear();
+
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      IntPairType aux_vect2[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(MaxElem-i);
+         new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      for(int i = 0; i < MaxElem; ++i){
+         boostmap.insert_or_assign(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
+         stdmap[i] = i;
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         boostmap.insert_or_assign(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
+         stdmap[i] = MaxElem-i;
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+
+   {  //try_emplace
+      boostmap.clear();
+      boostmultimap.clear();
+      stdmap.clear();
+      stdmultimap.clear();
+
+      IntPairType aux_vect[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(i);
+         new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      IntPairType aux_vect2[MaxElem];
+      for(int i = 0; i < MaxElem; ++i){
+         IntType i1(i);
+         IntType i2(MaxElem-i);
+         new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+      }
+
+      typedef typename MyBoostMap::iterator iterator;
+      for(int i = 0; i < MaxElem; ++i){
+         iterator it;
+         if(i&1){
+            std::pair<typename MyBoostMap::iterator, bool> ret =
+               boostmap.try_emplace(boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
+            if(!ret.second)
+               return 1;
+            it = ret.first;
+         }
+         else{
+            it = boostmap.try_emplace
+               (boostmap.upper_bound(aux_vect[i].first), boost::move(aux_vect[i].first), boost::move(aux_vect[i].second));
+         }
+         if(boostmap.end() == it || it->first != aux_vect2[i].first || it->second != aux_vect2[i].first){
+            return 1;
+         }
+         stdmap[i] = i;
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         iterator it;
+         iterator itex = boostmap.find(aux_vect2[i].first);
+         if(itex == boostmap.end())
+            return 1;
+         if(i&1){
+            std::pair<typename MyBoostMap::iterator, bool> ret =
+               boostmap.try_emplace(boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
+            if(ret.second)
+               return 1;
+            it = ret.first;
+         }
+         else{
+            it = boostmap.try_emplace
+               (boostmap.upper_bound(aux_vect2[i].first), boost::move(aux_vect2[i].first), boost::move(aux_vect2[i].second));
+         }
+         const IntType test_int(i);
+         if(boostmap.end() == it || it != itex || it->second != test_int){
+            return 1;
+         }
+      }
+
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+
+   {  //merge
+      ::boost::movelib::unique_ptr<MyBoostMap> const pboostmap2 = ::boost::movelib::make_unique<MyBoostMap>();
+      ::boost::movelib::unique_ptr<MyBoostMultiMap> const pboostmultimap2 = ::boost::movelib::make_unique<MyBoostMultiMap>();
+
+      MyBoostMap &boostmap2 = *pboostmap2;
+      MyBoostMultiMap &boostmultimap2 = *pboostmultimap2;
+
+      boostmap.clear();
+      boostmap2.clear();
+      boostmultimap.clear();
+      boostmultimap2.clear();
+      stdmap.clear();
+      stdmultimap.clear();
+
+      {
+         IntPairType aux_vect[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(i);
+            IntType i2(i);
+            new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+
+         IntPairType aux_vect2[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(MaxElem/2+i);
+            IntType i2(MaxElem-i);
+            new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+         IntPairType aux_vect3[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(MaxElem*2/2+i);
+            IntType i2(MaxElem*2+i);
+            new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+         boostmap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+         boostmultimap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmap.insert(StdPairType(i, i));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
+      }
+
+      boostmap.merge(boost::move(boostmap2));
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         stdmap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
+      }
+
+      boostmap.merge(boost::move(boostmultimap2));
+      if(!CheckEqualPairContainers(boostmap, stdmap)) return 1;
+
+      boostmap.clear();
+      boostmap2.clear();
+      boostmultimap.clear();
+      boostmultimap2.clear();
+      stdmap.clear();
+      stdmultimap.clear();
+      {
+         IntPairType aux_vect[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(i);
+            IntType i2(i);
+            new(&aux_vect[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+
+         IntPairType aux_vect2[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(MaxElem/2+i);
+            IntType i2(MaxElem-i);
+            new(&aux_vect2[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+         IntPairType aux_vect3[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            IntType i1(MaxElem*2/2+i);
+            IntType i2(MaxElem*2+i);
+            new(&aux_vect3[i])IntPairType(boost::move(i1), boost::move(i2));
+         }
+         boostmultimap.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+         boostmultimap2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+         boostmap2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultimap.insert(StdPairType(i, i));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultimap.insert(StdPairType(MaxElem/2+i, MaxElem-i));
+      }
+      boostmultimap.merge(boostmultimap2);
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultimap.insert(StdPairType(MaxElem*2/2+i, MaxElem*2+i));
+      }
+
+      boostmultimap.merge(boostmap2);
+      if(!CheckEqualPairContainers(boostmultimap, stdmultimap)) return 1;
+   }
+
+   if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>
+      (dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+      return 1;
+   }
+   return 0;
+}
+
+template<typename MapType>
+bool test_map_support_for_initialization_list_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   const std::initializer_list<std::pair<typename MapType::value_type::first_type, typename MapType::mapped_type>> il
+      = { std::make_pair(1, 2), std::make_pair(3, 4) };
+
+   const MapType expected_map(il.begin(), il.end());
+   {
+      const MapType sil = il;
+      if (sil != expected_map)
+         return false;
+
+      MapType sila(il, typename MapType::allocator_type());
+      if (sila != expected_map)
+         return false;
+
+      MapType silca(il, typename MapType::key_compare(), typename MapType::allocator_type());
+      if (silca != expected_map)
+         return false;
+
+      const MapType sil_ordered(ordered_unique_range, il);
+      if (sil_ordered != expected_map)
+         return false;
+
+      MapType sil_assign = { std::make_pair(99, 100) };
+      sil_assign = il;
+      if (sil_assign != expected_map)
+         return false;
+   }
+   {
+      MapType sil;
+      sil.insert(il);
+      if (sil != expected_map)
+         return false;
+   }
+   return true;
+#endif
+   return true;
+}
+
+template<typename MapType, typename MultimapType>
+bool instantiate_constructors()
+{
+   {
+      typedef typename MapType::value_type value_type;
+      typename MapType::key_compare comp;
+      typename MapType::allocator_type a;
+      value_type value;
+      {
+         MapType s0;
+         MapType s1(comp);
+         MapType s2(a);
+         MapType s3(comp, a);
+      }
+      {
+         MapType s0(&value, &value);
+         MapType s1(&value, &value ,comp);
+         MapType s2(&value, &value ,a);
+         MapType s3(&value, &value ,comp, a);
+      }
+      #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+      {
+         std::initializer_list<value_type> il;
+         MapType s0(il);
+         MapType s1(il, comp);
+         MapType s2(il, a);
+         MapType s3(il, comp, a);
+      }
+      {
+         std::initializer_list<value_type> il;
+         MapType s0(ordered_unique_range, il);
+         MapType s1(ordered_unique_range, il, comp);
+         MapType s3(ordered_unique_range, il, comp, a);
+      }
+      #endif
+      {
+         MapType s0(ordered_unique_range, &value, &value);
+         MapType s1(ordered_unique_range, &value, &value ,comp);
+         MapType s2(ordered_unique_range, &value, &value ,comp, a);
+      }
+   }
+
+   {
+      typedef typename MultimapType::value_type value_type;
+      typename MultimapType::key_compare comp;
+      typename MultimapType::allocator_type a;
+      value_type value;
+      {
+         MultimapType s0;
+         MultimapType s1(comp);
+         MultimapType s2(a);
+         MultimapType s3(comp, a);
+      }
+      {
+         MultimapType s0(&value, &value);
+         MultimapType s1(&value, &value ,comp);
+         MultimapType s2(&value, &value ,a);
+         MultimapType s3(&value, &value ,comp, a);
+      }
+      #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+      {
+         std::initializer_list<value_type> il;
+         MultimapType s0(il);
+         MultimapType s1(il, comp);
+         MultimapType s2(il, a);
+         MultimapType s3(il, comp, a);
+      }
+      {
+         std::initializer_list<value_type> il;
+         MultimapType s0(ordered_range, il);
+         MultimapType s1(ordered_range, il, comp);
+         MultimapType s3(ordered_range, il, comp, a);
+      }
+      #endif
+      {
+         MultimapType s0(ordered_range, &value, &value);
+         MultimapType s1(ordered_range, &value, &value ,comp);
+         MultimapType s2(ordered_range, &value, &value ,comp, a);
+      }
+   }
+   return true;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_MAP_TEST_HEADER
diff --git a/test/memory_resource_logger.hpp b/test/memory_resource_logger.hpp
new file mode 100644
index 0000000..e8bc405
--- /dev/null
+++ b/test/memory_resource_logger.hpp
@@ -0,0 +1,86 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
+#define BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
+
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/container/vector.hpp>
+#include <cstdlib>
+
+class memory_resource_logger
+   : public boost::container::pmr::memory_resource
+{
+   public:
+   struct allocation_info
+   {
+      char *address;
+      std::size_t bytes;
+      std::size_t alignment;
+   };
+
+   boost::container::vector<allocation_info> m_info;
+   unsigned m_mismatches;
+
+   explicit memory_resource_logger()
+      : m_info()
+      , m_mismatches()
+   {}
+
+   virtual ~memory_resource_logger()
+   {  this->reset();  }
+
+   virtual void* do_allocate(std::size_t bytes, std::size_t alignment)
+   {
+      char *addr =(char*)std::malloc(bytes);
+      if(!addr){
+         throw std::bad_alloc();
+      }
+      allocation_info info;
+      info.address   = addr;
+      info.bytes     = bytes;
+      info.alignment = alignment;
+      m_info.push_back(info);
+      return addr;
+   }
+
+   virtual void do_deallocate(void* p, std::size_t bytes, std::size_t alignment)
+   {
+      std::size_t i = 0, max = m_info.size();
+      while(i != max && m_info[i].address != p){
+         ++i;
+      }
+      if(i == max){
+         ++m_mismatches;
+      }
+      else{
+         const allocation_info &info = m_info[i];
+         m_mismatches += info.bytes != bytes || info.alignment != alignment;
+         std::free(p);
+         m_info.erase(m_info.nth(i));
+      }
+   }
+
+   virtual bool do_is_equal(const boost::container::pmr::memory_resource& other) const BOOST_NOEXCEPT
+   {
+      return static_cast<const memory_resource *>(this) == &other;
+   }
+
+   void reset()
+   {
+      while(!m_info.empty()){
+         std::free(m_info.back().address);
+         m_info.pop_back();
+      }
+      m_mismatches = 0u;
+   }
+};
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_MEMORY_RESOURCE_TESTER_HPP
diff --git a/test/memory_resource_test.cpp b/test/memory_resource_test.cpp
new file mode 100644
index 0000000..4c4cb51
--- /dev/null
+++ b/test/memory_resource_test.cpp
@@ -0,0 +1,135 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/memory_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include "derived_from_memory_resource.hpp"
+
+#include <cstdlib>
+
+using namespace boost::container;
+using namespace boost::container::pmr;
+
+void test_allocate()
+{
+   derived_from_memory_resource d;
+   memory_resource &mr = d;
+
+   d.reset();
+   BOOST_TEST(d.do_allocate_called == false);
+   BOOST_TEST(d.do_allocate_bytes == 0);
+   BOOST_TEST(d.do_allocate_alignment == 0);
+
+   mr.allocate(2, 4);
+   BOOST_TEST(d.do_allocate_called == true);
+   BOOST_TEST(d.do_allocate_bytes == 2);
+   BOOST_TEST(d.do_allocate_alignment == 4);
+}
+
+void test_deallocate()
+{
+   derived_from_memory_resource d;
+   memory_resource &mr = d;
+
+   d.reset();
+   BOOST_TEST(d.do_deallocate_called == false);
+   BOOST_TEST(d.do_deallocate_p == 0);
+   BOOST_TEST(d.do_allocate_bytes == 0);
+   BOOST_TEST(d.do_allocate_alignment == 0);
+
+   mr.deallocate(&d, 2, 4);
+   BOOST_TEST(d.do_deallocate_called == true);
+   BOOST_TEST(d.do_deallocate_p == &d);
+   BOOST_TEST(d.do_deallocate_bytes == 2);
+   BOOST_TEST(d.do_deallocate_alignment == 4);
+}
+
+void test_destructor()
+{
+   {
+   derived_from_memory_resource d;
+   d.reset();
+   BOOST_TEST(derived_from_memory_resource::destructor_called == false);
+   }
+   BOOST_TEST(derived_from_memory_resource::destructor_called == true);
+}
+
+void test_is_equal()
+{
+   derived_from_memory_resource d;
+   memory_resource &mr = d;
+
+   d.reset();
+   BOOST_TEST(d.do_is_equal_called == false);
+   BOOST_TEST(d.do_is_equal_other == 0);
+
+   mr.is_equal(d);
+   BOOST_TEST(d.do_is_equal_called == true);
+   BOOST_TEST(d.do_is_equal_other == &d);
+}
+
+void test_equality_operator()
+{
+   derived_from_memory_resource d;
+   memory_resource &mr = d;
+
+   d.reset();
+   BOOST_TEST(d.do_is_equal_called == false);
+   BOOST_TEST(d.do_is_equal_other == 0);
+
+   //equal addresses are shorcircuited
+   BOOST_TEST((mr == mr) == true);
+   BOOST_TEST(d.do_is_equal_called == false);
+   BOOST_TEST(d.do_is_equal_other == 0);
+
+   //unequal addresses are dispatched to is_equal which in turn calls do_is_equal
+   derived_from_memory_resource d2(1);
+   d.reset();
+   d2.reset();
+   memory_resource &mr2 = d2;
+   BOOST_TEST((mr == mr2) == false);
+   BOOST_TEST(d.do_is_equal_called == true);
+   BOOST_TEST(d.do_is_equal_other == &d2);
+}
+
+void test_inequality_operator()
+{
+   derived_from_memory_resource d;
+   memory_resource &mr = d;
+
+   d.reset();
+   BOOST_TEST(d.do_is_equal_called == false);
+   BOOST_TEST(d.do_is_equal_other == 0);
+
+   //equal addresses are shorcircuited
+   BOOST_TEST((mr != mr) == false);
+   BOOST_TEST(d.do_is_equal_called == false);
+   BOOST_TEST(d.do_is_equal_other == 0);
+
+   //unequal addresses are dispatched to is_equal which in turn calls do_is_equal
+   derived_from_memory_resource d2(1);
+   d.reset();
+   d2.reset();
+   memory_resource &mr2 = d2;
+   BOOST_TEST((mr != mr2) == true);
+   BOOST_TEST(d.do_is_equal_called == true);
+   BOOST_TEST(d.do_is_equal_other == &d2);
+}
+
+int main()
+{
+   test_destructor();
+   test_allocate();
+   test_deallocate();
+   test_is_equal();
+   test_equality_operator();
+   test_inequality_operator();
+   return ::boost::report_errors();
+}
diff --git a/test/monotonic_buffer_resource_test.cpp b/test/monotonic_buffer_resource_test.cpp
new file mode 100644
index 0000000..82e7e54
--- /dev/null
+++ b/test/monotonic_buffer_resource_test.cpp
@@ -0,0 +1,482 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/monotonic_buffer_resource.hpp>
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "derived_from_memory_resource.hpp"
+#include "memory_resource_logger.hpp"
+
+using namespace boost::container::pmr;
+
+static const std::size_t AllocCount = 32u;
+
+namespace test_block_chain{
+
+//explicit block_slist(memory_resource &upstream_rsrc)
+void test_constructor()
+{
+   memory_resource_logger mrl;
+   block_slist bc(mrl);
+   //Resource stored
+   BOOST_TEST(&bc.upstream_resource() == &mrl);
+   //No allocation performed
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+//void *allocate(std::size_t size)
+void test_allocate()
+{
+   memory_resource_logger mrl;
+   block_slist bc(mrl);
+
+   for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+      //Allocate and trace data
+      const std::size_t alloc    = i+1;
+      char *const addr           = (char*)bc.allocate(alloc);
+      //Should have allocated a new entry
+      BOOST_TEST(mrl.m_info.size() == (i+1));
+      //Requested size must be bigger to include metadata
+      BOOST_TEST(mrl.m_info[i].bytes > alloc);
+      BOOST_TEST(mrl.m_info[i].alignment == memory_resource::max_align);
+      //Returned address should be between the allocated buffer
+      BOOST_TEST(mrl.m_info[i].address < addr);
+      BOOST_TEST(addr < (mrl.m_info[i].address + mrl.m_info[i].bytes));
+      //Allocate size should include all requested size
+      BOOST_TEST((addr + alloc) <= (mrl.m_info[i].address + mrl.m_info[i].bytes));
+      //Allocation must be max-aligned
+      BOOST_TEST((std::size_t(addr) % memory_resource::max_align) == 0);
+   }
+}
+
+//void release() BOOST_NOEXCEPT
+void test_release()
+{
+   memory_resource_logger mrl;
+   block_slist bc(mrl);
+
+   //Allocate and trace data
+   char *bufs[AllocCount];
+   for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+      bufs[i]                    = (char*)bc.allocate(i+1);
+   }
+   (void)bufs;
+   //Should have allocated a new entry
+   BOOST_TEST(mrl.m_info.size() == AllocCount);
+
+   //Now release and check all allocations match deallocations
+   bc.release();
+   BOOST_TEST(mrl.m_mismatches == 0);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+//memory_resource* upstream_resource()
+void test_memory_resource()
+{
+   derived_from_memory_resource d;
+   block_slist bc(d);
+   //Resource stored
+   BOOST_TEST(&bc.upstream_resource() == &d);
+}
+
+//~block_slist()   {  this->release();  }
+void test_destructor()
+{
+   memory_resource_logger mrl;
+   {
+      block_slist bc(mrl);
+
+      //Allocate and trace data
+      char *bufs[AllocCount];
+      for(unsigned i = 0; i != unsigned(AllocCount); ++i){
+         bufs[i] = (char*)bc.allocate(i+1);
+      }
+      (void)bufs;
+      //Should have allocated a new entry
+      BOOST_TEST(mrl.m_info.size() == AllocCount);
+
+      //Destructor should release all memory
+   }
+   BOOST_TEST(mrl.m_mismatches == 0);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+}  //namespace test_block_chain {
+
+void test_resource_constructor()
+{
+   //First constructor, null resource
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      monotonic_buffer_resource m;
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(0);
+   }
+   //First constructor, non-null resource
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      monotonic_buffer_resource m(&dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
+      BOOST_TEST(m.current_buffer() == 0);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+void test_initial_size_constructor()
+{
+   //Second constructor, null resource
+   const std::size_t initial_size = monotonic_buffer_resource::initial_next_buffer_size*2;
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      monotonic_buffer_resource m(initial_size);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.next_buffer_size() >= initial_size);
+      BOOST_TEST(m.current_buffer() == 0);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(0);
+   }
+   //Second constructor, non-null resource
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      monotonic_buffer_resource m(initial_size, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.next_buffer_size() >= initial_size);
+      BOOST_TEST(m.current_buffer() == 0);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+void test_buffer_constructor()
+{
+   const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size*2;
+   unsigned char buf[BufSz];
+   //Third constructor, null resource
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      monotonic_buffer_resource m(buf, BufSz);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.next_buffer_size() >= BufSz*2);
+      BOOST_TEST(m.current_buffer() == buf);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(0);
+   }
+   //Third constructor, non-null resource
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      monotonic_buffer_resource m(buf, sizeof(buf), &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.next_buffer_size() >= sizeof(buf)*2);
+      BOOST_TEST(m.current_buffer() == buf);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+   //Check for empty buffers
+   {
+      monotonic_buffer_resource m(buf, 0);
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.next_buffer_size() > 1);
+      BOOST_TEST(m.current_buffer() == buf);
+   }
+}
+
+struct derived_from_monotonic_buffer_resource
+   : public monotonic_buffer_resource
+{
+   explicit derived_from_monotonic_buffer_resource(memory_resource *p)
+      : monotonic_buffer_resource(p)
+   {}
+
+   explicit derived_from_monotonic_buffer_resource(std::size_t initial_size, memory_resource* upstream)
+      : monotonic_buffer_resource(initial_size, upstream)
+   {}
+
+   explicit derived_from_monotonic_buffer_resource(void* buffer, std::size_t buffer_size, memory_resource* upstream)
+      : monotonic_buffer_resource(buffer, buffer_size, upstream)
+   {}
+
+   using monotonic_buffer_resource::do_allocate;
+   using monotonic_buffer_resource::do_deallocate;
+   using monotonic_buffer_resource::do_is_equal;
+};
+
+void test_upstream_resource()
+{
+   //Test stores the resource and uses it to allocate memory
+   derived_from_memory_resource dmr;
+   dmr.reset();
+   derived_from_monotonic_buffer_resource dmbr(&dmr);
+   //Resource must be stored and initial values given (no current buffer)
+   BOOST_TEST(dmbr.upstream_resource() == &dmr);
+   BOOST_TEST(dmbr.next_buffer_size() == monotonic_buffer_resource::initial_next_buffer_size);
+   BOOST_TEST(dmbr.current_buffer() == 0);
+   //Test it does not allocate any memory
+   BOOST_TEST(dmr.do_allocate_called == false);
+   const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size;
+   //Now allocate storage, and stub it as the return buffer
+   //for "derived_from_memory_resource":
+   boost::move_detail::aligned_storage<BufSz+block_slist::header_size>::type buf;
+   dmr.do_allocate_return = &buf;
+   //Test that allocation uses the upstream_resource()
+   void *addr = dmbr.do_allocate(1u, 1u);
+   //Test returns stubbed memory with the internal initial size plus metadata size
+   BOOST_TEST(addr > (char*)&buf);
+   BOOST_TEST(addr < (char*)(&buf+1));
+   BOOST_TEST(dmr.do_allocate_called == true);
+   BOOST_TEST(dmr.do_allocate_bytes > BufSz);
+   //Alignment for the resource must be max_align
+   BOOST_TEST(dmr.do_allocate_alignment == memory_resource::max_align);
+}
+
+void test_do_allocate()
+{
+   memory_resource_logger mrl;
+   {
+      std::size_t remaining_storage = 0u;
+      derived_from_monotonic_buffer_resource dmbr(&mrl);
+      //First test, no buffer
+      {
+         dmbr.do_allocate(1, 1);
+         //It should allocate initial size
+         BOOST_TEST(mrl.m_info.size() == 1u);
+         //... which requests the initial size plus the header size to the allcoator
+         BOOST_TEST(mrl.m_info[0].bytes == monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+         std::size_t remaining = dmbr.remaining_storage(1u);
+         //Remaining storage should be one less than initial, as we requested 1 byte with minimal alignment
+         BOOST_TEST(remaining == monotonic_buffer_resource::initial_next_buffer_size-1u);
+         remaining_storage = remaining;
+      }
+      //Now ask for more internal storage with misaligned current buffer
+      {
+         //Test wasted space
+         std::size_t wasted_due_to_alignment;
+         dmbr.remaining_storage(4u, wasted_due_to_alignment);
+         BOOST_TEST(wasted_due_to_alignment == 3u);
+         dmbr.do_allocate(4, 4);
+         //It should not have allocated
+         BOOST_TEST(mrl.m_info.size() == 1u);
+         std::size_t remaining = dmbr.remaining_storage(1u);
+         //We wasted some bytes due to alignment plus 4 bytes of real storage
+         BOOST_TEST(remaining == remaining_storage - 4 - wasted_due_to_alignment);
+         remaining_storage = remaining;
+      }
+      //Now request the same alignment to test no storage is wasted
+      {
+         std::size_t wasted_due_to_alignment;
+         std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
+         BOOST_TEST(mrl.m_info.size() == 1u);
+         dmbr.do_allocate(4, 4);
+         //It should not have allocated
+         BOOST_TEST(mrl.m_info.size() == 1u);
+         remaining = dmbr.remaining_storage(1u);
+         //We wasted no bytes due to alignment plus 4 bytes of real storage
+         BOOST_TEST(remaining == remaining_storage - 4u);
+         remaining_storage = remaining;
+      }
+      //Now exhaust the remaining storage with 2 byte alignment (the last allocation
+      //was 4 bytes with 4 byte alignment) so it should be already 2-byte aligned.
+      {
+         dmbr.do_allocate(remaining_storage, 2);
+         std::size_t wasted_due_to_alignment;
+         std::size_t remaining = dmbr.remaining_storage(1u, wasted_due_to_alignment);
+         BOOST_TEST(wasted_due_to_alignment == 0u);
+         BOOST_TEST(remaining == 0u);
+         //It should not have allocated
+         BOOST_TEST(mrl.m_info.size() == 1u);
+         remaining_storage = 0u;
+      }
+      //The next allocation should trigger the upstream resource, even with a 1 byte
+      //allocation.
+      {
+         dmbr.do_allocate(1u, 1u);
+         BOOST_TEST(mrl.m_info.size() == 2u);
+         //The next allocation should be geometrically bigger.
+         BOOST_TEST(mrl.m_info[1].bytes == 2*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+         std::size_t wasted_due_to_alignment;
+         //For a 2 byte alignment one byte will be wasted from the previous 1 byte allocation
+         std::size_t remaining = dmbr.remaining_storage(2u, wasted_due_to_alignment);
+         BOOST_TEST(wasted_due_to_alignment == 1u);
+         BOOST_TEST(remaining == (mrl.m_info[1].bytes - 1u  - wasted_due_to_alignment - block_slist::header_size));
+         //It should not have allocated
+         remaining_storage = dmbr.remaining_storage(1u);
+      }
+      //Now try a bigger than next allocation and see if next_buffer_size is doubled.
+      {
+         std::size_t next_alloc = 5*monotonic_buffer_resource::initial_next_buffer_size;
+         dmbr.do_allocate(next_alloc, 1u);
+         BOOST_TEST(mrl.m_info.size() == 3u);
+         //The next allocation should be geometrically bigger.
+         BOOST_TEST(mrl.m_info[2].bytes == 8*monotonic_buffer_resource::initial_next_buffer_size+block_slist::header_size);
+         remaining_storage = dmbr.remaining_storage(1u);
+      }
+   }
+   //derived_from_monotonic_buffer_resource dmbr(&mrl) is destroyed
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+
+   //Now use a local buffer
+   {
+      boost::move_detail::aligned_storage
+         <monotonic_buffer_resource::initial_next_buffer_size>::type buf;
+      //Supply an external buffer
+      derived_from_monotonic_buffer_resource dmbr(&buf, sizeof(buf), &mrl);
+      BOOST_TEST(dmbr.remaining_storage(1u) == sizeof(buf));
+      //Allocate all remaining storage
+      dmbr.do_allocate(dmbr.remaining_storage(1u), 1u);
+      //No new allocation should have ocurred
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      BOOST_TEST(dmbr.remaining_storage(1u) == 0u);
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+void test_do_deallocate()
+{
+   memory_resource_logger mrl;
+   const std::size_t initial_size = 1u;
+   {
+      derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+      //First test, no buffer
+      const unsigned iterations = 8;
+      char *bufs[iterations];
+      std::size_t sizes[iterations];
+      //Test each iteration allocates memory
+      for(unsigned i = 0; i != iterations; ++i)
+      {
+         sizes[i] = dmbr.remaining_storage()+1;
+         bufs[i]  = (char*)dmbr.do_allocate(sizes[i], 1);
+         BOOST_TEST(mrl.m_info.size() == (i+1));
+      }
+      std::size_t remaining = dmbr.remaining_storage();
+      //Test do_deallocate does not release any storage
+      for(unsigned i = 0; i != iterations; ++i)
+      {
+         dmbr.do_deallocate(bufs[i], sizes[i], 1u);
+         BOOST_TEST(mrl.m_info.size() == iterations);
+         BOOST_TEST(remaining == dmbr.remaining_storage());
+         BOOST_TEST(mrl.m_mismatches == 0u);
+      }
+   }
+}
+
+void test_do_is_equal()
+{
+   //! <b>Returns</b>:
+   //!   `this == dynamic_cast<const monotonic_buffer_resource*>(&other)`.
+   memory_resource_logger mrl;
+   derived_from_monotonic_buffer_resource dmbr(&mrl);
+   derived_from_monotonic_buffer_resource dmbr2(&mrl);
+   BOOST_TEST(true == dmbr.do_is_equal(dmbr));
+   BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
+   //A different type should be always different
+   derived_from_memory_resource dmr;
+   BOOST_TEST(false == dmbr.do_is_equal(dmr));
+}
+
+void test_release()
+{
+   {
+      memory_resource_logger mrl;
+      const std::size_t initial_size = 1u;
+      derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+      //First test, no buffer
+      const unsigned iterations = 8;
+      //Test each iteration allocates memory
+      for(unsigned i = 0; i != iterations; ++i)
+      {
+         dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
+         BOOST_TEST(mrl.m_info.size() == (i+1));
+      }
+      //Release and check memory was released
+      dmbr.release();
+      BOOST_TEST(mrl.m_mismatches == 0u);
+      BOOST_TEST(mrl.m_info.size() == 0u);
+   }
+   //Now use a local buffer
+   {
+      boost::move_detail::aligned_storage
+         <monotonic_buffer_resource::initial_next_buffer_size>::type buf;
+      //Supply an external buffer
+      monotonic_buffer_resource monr(&buf, sizeof(buf));
+      memory_resource &mr = monr;
+      BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
+      //Allocate all remaining storage
+      mr.allocate(monr.remaining_storage(1u), 1u);
+      BOOST_TEST(monr.current_buffer() == ((char*)&buf + sizeof(buf)));
+      //No new allocation should have ocurred
+      BOOST_TEST(monr.remaining_storage(1u) == 0u);
+      //Release and check memory was released and the original buffer is back
+      monr.release();
+      BOOST_TEST(monr.remaining_storage(1u) == sizeof(buf));
+      BOOST_TEST(monr.current_buffer() == &buf);
+   }
+}
+
+void test_destructor()
+{
+   memory_resource_logger mrl;
+   const std::size_t initial_size = 1u;
+   {
+      derived_from_monotonic_buffer_resource dmbr(initial_size, &mrl);
+      //First test, no buffer
+      const unsigned iterations = 8;
+      //Test each iteration allocates memory
+      for(unsigned i = 0; i != iterations; ++i)
+      {
+         dmbr.do_allocate(dmbr.remaining_storage()+1, 1);
+         BOOST_TEST(mrl.m_info.size() == (i+1));
+      }
+   }  //dmbr is destroyed, memory should be released
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+int main()
+{
+   test_block_chain::test_constructor();
+   test_block_chain::test_allocate();
+   test_block_chain::test_release();
+   test_block_chain::test_memory_resource();
+   test_block_chain::test_destructor();
+
+   test_resource_constructor();
+   test_initial_size_constructor();
+   test_buffer_constructor();
+
+   test_upstream_resource();
+   test_do_allocate();
+   test_do_deallocate();
+   test_do_is_equal();
+   test_release();
+   test_destructor();
+   return ::boost::report_errors();
+}
diff --git a/test/movable_int.hpp b/test/movable_int.hpp
new file mode 100644
index 0000000..c8513c0
--- /dev/null
+++ b/test/movable_int.hpp
@@ -0,0 +1,425 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2006. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
+#define BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/move/utility_core.hpp>
+#include <ostream>
+#include <climits>
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<class T>
+struct is_copyable;
+
+template<>
+struct is_copyable<int>
+{
+   static const bool value = true;
+};
+
+
+class movable_int
+{
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(movable_int)
+
+   public:
+
+   static unsigned int count;
+
+   movable_int()
+      :  m_int(0)
+   { ++count;  }
+
+   explicit movable_int(int a)
+      :  m_int(a)
+   {
+      //Disallow INT_MIN
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      ++count;
+   }
+
+   movable_int(BOOST_RV_REF(movable_int) mmi)
+      :  m_int(mmi.m_int)
+   {  mmi.m_int = 0; ++count; }
+
+   movable_int & operator= (BOOST_RV_REF(movable_int) mmi)
+   {  this->m_int = mmi.m_int;   mmi.m_int = 0; return *this;  }
+
+   movable_int & operator= (int i)
+   {  this->m_int = i;  BOOST_ASSERT(this->m_int != INT_MIN); return *this;  }
+
+   ~movable_int()
+   {
+      //Double destructor called
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      this->m_int = INT_MIN;
+      --count;
+   }
+
+   friend bool operator ==(const movable_int &l, const movable_int &r)
+   {  return l.m_int == r.m_int;   }
+
+   friend bool operator !=(const movable_int &l, const movable_int &r)
+   {  return l.m_int != r.m_int;   }
+
+   friend bool operator <(const movable_int &l, const movable_int &r)
+   {  return l.m_int < r.m_int;   }
+
+   friend bool operator <=(const movable_int &l, const movable_int &r)
+   {  return l.m_int <= r.m_int;   }
+
+   friend bool operator >=(const movable_int &l, const movable_int &r)
+   {  return l.m_int >= r.m_int;   }
+
+   friend bool operator >(const movable_int &l, const movable_int &r)
+   {  return l.m_int > r.m_int;   }
+
+   int get_int() const
+   {  return m_int;  }
+
+   friend bool operator==(const movable_int &l, int r)
+   {  return l.get_int() == r;   }
+
+   friend bool operator==(int l, const movable_int &r)
+   {  return l == r.get_int();   }
+
+   friend bool operator<(const movable_int &l, int r)
+   {  return l.get_int() < r;   }
+
+   friend bool operator<(int l, const movable_int &r)
+   {  return l < r.get_int();   }
+
+   private:
+   int m_int;
+};
+
+unsigned int movable_int::count = 0;
+
+inline movable_int produce_movable_int()
+{  return movable_int();  }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+   (std::basic_ostream<E, T> & os, movable_int const & p)
+
+{
+    os << p.get_int();
+    return os;
+}
+
+template<>
+struct is_copyable<movable_int>
+{
+   static const bool value = false;
+};
+
+class movable_and_copyable_int
+{
+   BOOST_COPYABLE_AND_MOVABLE(movable_and_copyable_int)
+
+   public:
+
+   static unsigned int count;
+
+   movable_and_copyable_int()
+      :  m_int(0)
+   { ++count; }
+
+   explicit movable_and_copyable_int(int a)
+      :  m_int(a)
+   {
+      //Disallow INT_MIN
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      ++count;
+   }
+
+   movable_and_copyable_int(const movable_and_copyable_int& mmi)
+      :  m_int(mmi.m_int)
+   {  ++count; }
+
+   movable_and_copyable_int(BOOST_RV_REF(movable_and_copyable_int) mmi)
+      :  m_int(mmi.m_int)
+   {  mmi.m_int = 0; ++count; }
+
+   ~movable_and_copyable_int()
+   {
+      //Double destructor called
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      this->m_int = INT_MIN;
+      --count;
+   }
+
+   movable_and_copyable_int &operator= (BOOST_COPY_ASSIGN_REF(movable_and_copyable_int) mi)
+   {  this->m_int = mi.m_int;    return *this;  }
+
+   movable_and_copyable_int & operator= (BOOST_RV_REF(movable_and_copyable_int) mmi)
+   {  this->m_int = mmi.m_int;   mmi.m_int = 0;    return *this;  }
+
+   movable_and_copyable_int & operator= (int i)
+   {  this->m_int = i;  BOOST_ASSERT(this->m_int != INT_MIN); return *this;  }
+
+   friend bool operator ==(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int == r.m_int;   }
+
+   friend bool operator !=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int != r.m_int;   }
+
+   friend bool operator <(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int < r.m_int;   }
+
+   friend bool operator <=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int <= r.m_int;   }
+
+   friend bool operator >=(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int >= r.m_int;   }
+
+   friend bool operator >(const movable_and_copyable_int &l, const movable_and_copyable_int &r)
+   {  return l.m_int > r.m_int;   }
+
+   int get_int() const
+   {  return m_int;  }
+
+   friend bool operator==(const movable_and_copyable_int &l, int r)
+   {  return l.get_int() == r;   }
+
+   friend bool operator==(int l, const movable_and_copyable_int &r)
+   {  return l == r.get_int();   }
+
+   friend bool operator<(const movable_and_copyable_int &l, int r)
+   {  return l.get_int() < r;   }
+
+   friend bool operator<(int l, const movable_and_copyable_int &r)
+   {  return l < r.get_int();   }
+
+   private:
+   int m_int;
+};
+
+unsigned int movable_and_copyable_int::count = 0;
+
+inline movable_and_copyable_int produce_movable_and_copyable_int()
+{  return movable_and_copyable_int();  }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+   (std::basic_ostream<E, T> & os, movable_and_copyable_int const & p)
+
+{
+    os << p.get_int();
+    return os;
+}
+
+template<>
+struct is_copyable<movable_and_copyable_int>
+{
+   static const bool value = true;
+};
+
+class copyable_int
+{
+   public:
+
+   static unsigned int count;
+
+   copyable_int()
+      :  m_int(0)
+   { ++count; }
+
+   explicit copyable_int(int a)
+      :  m_int(a)
+   {
+      //Disallow INT_MIN
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      ++count;
+   }
+
+   copyable_int(const copyable_int& mmi)
+      :  m_int(mmi.m_int)
+   { ++count; }
+
+   copyable_int & operator= (int i)
+   {  this->m_int = i;  BOOST_ASSERT(this->m_int != INT_MIN); return *this;  }
+
+   copyable_int & operator= (const copyable_int &ci)
+   {  this->m_int = ci.m_int;  BOOST_ASSERT(this->m_int != INT_MIN); return *this;  }
+
+   ~copyable_int()
+   {
+      //Double destructor called
+      BOOST_ASSERT(this->m_int != INT_MIN);
+      this->m_int = INT_MIN;
+      --count;
+   }
+
+   friend bool operator ==(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int == r.m_int;   }
+
+   friend bool operator !=(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int != r.m_int;   }
+
+   friend bool operator <(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int < r.m_int;   }
+
+   friend bool operator <=(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int <= r.m_int;   }
+
+   friend bool operator >=(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int >= r.m_int;   }
+
+   friend bool operator >(const copyable_int &l, const copyable_int &r)
+   {  return l.m_int > r.m_int;   }
+
+   int get_int() const
+   {  return m_int;  }
+
+   friend bool operator==(const copyable_int &l, int r)
+   {  return l.get_int() == r;   }
+
+   friend bool operator==(int l, const copyable_int &r)
+   {  return l == r.get_int();   }
+
+   friend bool operator<(const copyable_int &l, int r)
+   {  return l.get_int() < r;   }
+
+   friend bool operator<(int l, const copyable_int &r)
+   {  return l < r.get_int();   }
+
+   private:
+   int m_int;
+};
+
+unsigned int copyable_int::count = 0;
+
+inline copyable_int produce_copyable_int()
+{  return copyable_int();  }
+
+template<class E, class T>
+std::basic_ostream<E, T> & operator<<
+   (std::basic_ostream<E, T> & os, copyable_int const & p)
+
+{
+    os << p.get_int();
+    return os;
+}
+
+template<>
+struct is_copyable<copyable_int>
+{
+   static const bool value = true;
+};
+
+class non_copymovable_int
+{
+   non_copymovable_int(const non_copymovable_int& mmi);
+   non_copymovable_int & operator= (const non_copymovable_int &mi);
+
+   public:
+
+   static unsigned int count;
+
+   non_copymovable_int()
+      :  m_int(0)
+   { ++count; }
+
+   explicit non_copymovable_int(int a)
+      :  m_int(a)
+   { ++count; }
+
+   ~non_copymovable_int()
+   {  m_int = 0;  --count; }
+
+   bool operator ==(const non_copymovable_int &mi) const
+   {  return this->m_int == mi.m_int;   }
+
+   bool operator !=(const non_copymovable_int &mi) const
+   {  return this->m_int != mi.m_int;   }
+
+   bool operator <(const non_copymovable_int &mi) const
+   {  return this->m_int < mi.m_int;   }
+
+   bool operator <=(const non_copymovable_int &mi) const
+   {  return this->m_int <= mi.m_int;   }
+
+   bool operator >=(const non_copymovable_int &mi) const
+   {  return this->m_int >= mi.m_int;   }
+
+   bool operator >(const non_copymovable_int &mi) const
+   {  return this->m_int > mi.m_int;   }
+
+   int get_int() const
+   {  return m_int;  }
+
+   friend bool operator==(const non_copymovable_int &l, int r)
+   {  return l.get_int() == r;   }
+
+   friend bool operator==(int l, const non_copymovable_int &r)
+   {  return l == r.get_int();   }
+
+   friend bool operator<(const non_copymovable_int &l, int r)
+   {  return l.get_int() < r;   }
+
+   friend bool operator<(int l, const non_copymovable_int &r)
+   {  return l < r.get_int();   }
+
+   private:
+   int m_int;
+};
+
+unsigned int non_copymovable_int::count = 0;
+
+template<class T>
+struct life_count
+{
+   static unsigned check(unsigned) {  return true;   }
+};
+
+template<>
+struct life_count< movable_int >
+{
+   static unsigned check(unsigned c)
+   {  return c == movable_int::count;   }
+};
+
+template<>
+struct life_count< copyable_int >
+{
+   static unsigned check(unsigned c)
+   {  return c == copyable_int::count;   }
+};
+
+template<>
+struct life_count< movable_and_copyable_int >
+{
+   static unsigned check(unsigned c)
+   {  return c == movable_and_copyable_int::count;   }
+};
+
+template<>
+struct life_count< non_copymovable_int >
+{
+   static unsigned check(unsigned c)
+   {  return c == non_copymovable_int::count;   }
+};
+
+
+}  //namespace test {
+}  //namespace container {
+}  //namespace boost {
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_CONTAINER_TEST_MOVABLE_INT_HEADER
diff --git a/test/node_handle_test.cpp b/test/node_handle_test.cpp
new file mode 100644
index 0000000..3c26379
--- /dev/null
+++ b/test/node_handle_test.cpp
@@ -0,0 +1,633 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2016-2016. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/core/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/node_handle.hpp>
+#include <boost/container/new_allocator.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+#include <boost/container/detail/pair_key_mapped_of_value.hpp>
+
+using namespace ::boost::container;
+
+enum EAllocState
+{
+   DefaultConstructed,
+   MoveConstructed,
+   MoveAssigned,
+   CopyConstructed,
+   CopyAssigned,
+   Swapped,
+   Destructed
+};
+
+template<class Node>
+class trace_allocator
+   : public new_allocator<Node>
+{
+   BOOST_COPYABLE_AND_MOVABLE(trace_allocator)
+
+   typedef new_allocator<Node> base_t;
+
+   public:
+
+   struct propagate_on_container_move_assignment
+   {
+      static const bool value = true;
+   };
+
+   struct propagate_on_container_swap
+   {
+      static const bool value = true;
+   };
+
+   //!Obtains an new_allocator that allocates
+   //!objects of type T2
+   template<class T2>
+   struct rebind
+   {
+      typedef trace_allocator<T2> other;
+   };
+
+   explicit trace_allocator(unsigned value = 999)
+      : m_state(DefaultConstructed), m_value(value)
+   {
+      ++count;
+   }
+
+   trace_allocator(BOOST_RV_REF(trace_allocator) other)
+      : base_t(boost::move(BOOST_MOVE_BASE(base_t, other))), m_state(MoveConstructed), m_value(other.m_value)
+   {
+      ++count;
+   }
+
+   trace_allocator(const trace_allocator &other)
+      : base_t(other), m_state(CopyConstructed), m_value(other.m_value)
+   {
+      ++count;
+   }
+
+   trace_allocator & operator=(BOOST_RV_REF(trace_allocator) other)
+   {
+      m_value = other.m_value;
+      m_state = MoveAssigned;
+      return *this;
+   }
+
+   template<class OtherNode>
+   trace_allocator(const trace_allocator<OtherNode> &other)
+      : m_state(CopyConstructed), m_value(other.m_value)
+   {
+      ++count;
+   }
+
+   template<class OtherNode>
+   trace_allocator & operator=(BOOST_COPY_ASSIGN_REF(trace_allocator<OtherNode>) other)
+   {
+      m_value = other.m_value;
+      m_state = CopyAssigned;
+      return *this;
+   }
+
+   ~trace_allocator()
+   {
+      m_value = 0u-1u;
+      m_state = Destructed;
+      --count;
+   }
+
+   void swap(trace_allocator &other)
+   {
+      boost::adl_move_swap(m_value, other.m_value);
+      m_state = other.m_state = Swapped;
+   }
+
+   friend void swap(trace_allocator &left, trace_allocator &right)
+   {
+      left.swap(right);
+   }
+
+   EAllocState m_state;
+   unsigned m_value;
+
+   static unsigned int count;
+
+   static void reset_count()
+   {  count = 0;  }
+};
+
+template<class Node>
+unsigned int trace_allocator<Node>::count = 0;
+
+template<class T>
+struct node
+{
+   typedef T value_type;
+   value_type value;
+
+         value_type &get_data()       {  return value; }
+   const value_type &get_data() const {  return value; }
+
+   node()
+   {
+      ++count;
+   }
+
+   ~node()
+   {
+      --count;
+   }
+
+   static unsigned int count;
+
+   static void reset_count()
+   {  count = 0;  }
+};
+
+template<class T1, class T2>
+struct value
+{
+   T1 first;
+   T2 second;
+};
+
+template<class T>
+unsigned int node<T>::count = 0;
+
+
+//Common types
+typedef value<int, unsigned> test_pair;
+typedef pair_key_mapped_of_value<int, unsigned> key_mapped_t;
+typedef node<test_pair> node_t;
+typedef trace_allocator< node_t > node_alloc_t;
+typedef node_handle<node_alloc_t, void>         node_handle_set_t;
+typedef node_handle<node_alloc_t, key_mapped_t> node_handle_map_t;
+typedef allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type value_allocator_type;
+
+void test_types()
+{
+   //set
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::value_type, test_pair>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::key_type, test_pair>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::mapped_type, test_pair>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_set_t::allocator_type, value_allocator_type>::value ));
+
+   //map
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::value_type, test_pair>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::key_type, int>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::mapped_type, unsigned>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<node_handle_map_t::allocator_type, value_allocator_type>::value ));
+}
+
+void test_default_constructor()
+{
+   node_alloc_t::reset_count();
+   {
+      node_handle_set_t nh;
+      BOOST_TEST(node_alloc_t::count == 0);
+   }
+   BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_arg_constructor()
+{
+   //With non-null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_handle_set_t nh(new node_t, al);
+         BOOST_TEST(node_t::count == 1);
+         BOOST_TEST(node_alloc_t::count == 2);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+
+   //With null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_handle_set_t nh(0, al);
+         BOOST_TEST(node_t::count == 0);
+         BOOST_TEST(node_alloc_t::count == 1);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+      BOOST_TEST(node_t::count == 0);
+   }
+   BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_move_constructor()
+{
+   //With non-null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_t *const from_ptr = new node_t;
+         node_handle_set_t nh(from_ptr, al);
+         BOOST_TEST(node_t::count == 1);
+         BOOST_TEST(node_alloc_t::count == 2);
+         {
+            node_handle_set_t nh2(boost::move(nh));
+            BOOST_TEST(nh.empty());
+            BOOST_TEST(!nh2.empty());
+            BOOST_TEST(nh2.get() == from_ptr);
+            BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed);
+            BOOST_TEST(node_t::count == 1);
+            BOOST_TEST(node_alloc_t::count == 2);
+         }
+         BOOST_TEST(node_t::count == 0);
+         BOOST_TEST(node_alloc_t::count == 1);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+
+   //With null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_handle_set_t nh;
+         {
+            node_handle_set_t nh2(boost::move(nh));
+            BOOST_TEST(nh.empty());
+            BOOST_TEST(nh2.empty());
+            BOOST_TEST(node_alloc_t::count == 1);
+         }
+         BOOST_TEST(node_t::count == 0);
+         BOOST_TEST(node_alloc_t::count == 1);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_related_constructor()
+{
+   //With non-null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_t *const from_ptr = new node_t;
+         node_handle_map_t nh(from_ptr, al);
+         BOOST_TEST(node_t::count == 1);
+         BOOST_TEST(node_alloc_t::count == 2);
+         {
+            node_handle_set_t nh2(boost::move(nh));
+            BOOST_TEST(nh.empty());
+            BOOST_TEST(!nh2.empty());
+            BOOST_TEST(nh2.get() == from_ptr);
+            BOOST_TEST(nh2.node_alloc().m_state == MoveConstructed);
+            BOOST_TEST(node_t::count == 1);
+            BOOST_TEST(node_alloc_t::count == 2);
+         }
+         BOOST_TEST(node_t::count == 0);
+         BOOST_TEST(node_alloc_t::count == 1);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+
+   //With null pointer
+   node_alloc_t::reset_count();
+   node_t::reset_count();
+   {
+      const node_alloc_t al;
+      BOOST_TEST(node_alloc_t::count == 1);
+      {
+         node_handle_set_t nh;
+         {
+            node_handle_map_t nh2(boost::move(nh));
+            BOOST_TEST(nh.empty());
+            BOOST_TEST(nh2.empty());
+            BOOST_TEST(node_alloc_t::count == 1);
+         }
+         BOOST_TEST(node_t::count == 0);
+         BOOST_TEST(node_alloc_t::count == 1);
+      }
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+}
+
+void test_move_assignment()
+{
+   //empty = full
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+      node_t *const from_ptr = new node_t;
+      node_handle_set_t nh_from(from_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      node_handle_set_t nh_to;
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      nh_to = boost::move(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(!nh_to.empty());
+      BOOST_TEST(nh_to.get() == from_ptr);
+      BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed);
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+
+   //empty = empty
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_handle_set_t nh_from;
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      node_handle_set_t nh_to;
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      nh_to = boost::move(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+   }
+
+   //full = empty
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_handle_set_t nh_from;
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      node_handle_set_t nh_to(new node_t, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      nh_to = boost::move(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+   }
+
+   //full = full
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_t *const from_ptr = new node_t;
+      node_handle_set_t nh_from(from_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      node_handle_set_t nh_to(new node_t, node_alloc_t());
+      BOOST_TEST(node_t::count == 2);
+      BOOST_TEST(node_alloc_t::count == 2);
+
+      nh_to = boost::move(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(!nh_to.empty());
+      BOOST_TEST(nh_to.get() == from_ptr);
+      BOOST_TEST(nh_to.node_alloc().m_state == MoveAssigned);
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+}
+
+void test_value_key_mapped()
+{
+   //value()
+   {
+      node_t *from_ptr = new node_t;
+      const node_handle_set_t nh_from(from_ptr, node_alloc_t());
+      from_ptr->value.first  = -99;
+      from_ptr->value.second =  99;
+      BOOST_TEST(nh_from.value().first  == -99);
+      BOOST_TEST(nh_from.value().second ==  99);
+   }
+   //key()/mapped()
+   {
+      node_t *from_ptr = new node_t;
+      const node_handle_map_t nh_from(from_ptr, node_alloc_t());
+      from_ptr->value.first  = -98;
+      from_ptr->value.second =  98;
+      BOOST_TEST(nh_from.key()    == -98);
+      BOOST_TEST(nh_from.mapped() ==  98);
+   }
+}
+
+void test_get_allocator()
+{
+   const node_handle_set_t nh(new node_t, node_alloc_t(888));
+   allocator_traits<node_alloc_t>::portable_rebind_alloc<test_pair>::type a = nh.get_allocator();
+   BOOST_TEST(a.m_value == 888);
+}
+
+void test_bool_conversion_empty()
+{
+   const node_handle_set_t nh(new node_t, node_alloc_t(777));
+   const node_handle_set_t nh_null;
+   BOOST_TEST(nh && !nh_null);
+   BOOST_TEST(!(!nh || nh_null));
+   BOOST_TEST(!nh.empty() && nh_null.empty());
+   BOOST_TEST(!(nh.empty() || !nh_null.empty()));
+}
+
+void test_swap()
+{
+   //empty.swap(full)
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+      node_t *const from_ptr = new node_t;
+      node_handle_set_t nh_from(from_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      node_handle_set_t nh_to;
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      nh_to.swap(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(!nh_to.empty());
+      BOOST_TEST(nh_to.get() == from_ptr);
+      BOOST_TEST(nh_to.node_alloc().m_state == MoveConstructed);
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+
+   //empty.swap(empty)
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_handle_set_t nh_from;
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      node_handle_set_t nh_to;
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      nh_to.swap(nh_from);
+
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(nh_to.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+   }
+
+   //full.swap(empty)
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_handle_set_t nh_from;
+      BOOST_TEST(nh_from.empty());
+      BOOST_TEST(node_t::count == 0);
+      BOOST_TEST(node_alloc_t::count == 0);
+
+      node_t *const to_ptr = new node_t;
+      node_handle_set_t nh_to(to_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      nh_to.swap(nh_from);
+
+      BOOST_TEST(!nh_from.empty());
+      BOOST_TEST(nh_from.node_alloc().m_state == MoveConstructed);
+      BOOST_TEST(nh_from.get() == to_ptr);
+      BOOST_TEST(nh_to.empty());
+
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+
+   //full.swap(full)
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_t *const from_ptr = new node_t;
+      node_handle_set_t nh_from(from_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      node_t *const to_ptr = new node_t;
+      node_handle_set_t nh_to(to_ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 2);
+      BOOST_TEST(node_alloc_t::count == 2);
+
+      nh_to.swap(nh_from);
+
+      BOOST_TEST(!nh_from.empty());
+      BOOST_TEST(nh_from.get() == to_ptr);
+      BOOST_TEST(nh_from.node_alloc().m_state == Swapped);
+
+      BOOST_TEST(!nh_to.empty());
+      BOOST_TEST(nh_to.get() == from_ptr);
+      BOOST_TEST(nh_to.node_alloc().m_state == Swapped);
+
+      BOOST_TEST(node_t::count == 2);
+      BOOST_TEST(node_alloc_t::count == 2);
+   }
+}
+
+void test_get_release()
+{
+   //get()
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_t *const ptr = new node_t;
+      const node_handle_set_t nh(ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      BOOST_TEST(nh.get() == ptr);
+      BOOST_TEST(!nh.empty());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+   }
+   BOOST_TEST(node_t::count == 0);
+   BOOST_TEST(node_alloc_t::count == 0);
+
+   //release()
+   {
+      node_alloc_t::reset_count();
+      node_t::reset_count();
+
+      node_t *const ptr = new node_t;
+      node_handle_set_t nh(ptr, node_alloc_t());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 1);
+
+      BOOST_TEST(nh.release() == ptr);
+      BOOST_TEST(nh.empty());
+      BOOST_TEST(node_t::count == 1);
+      BOOST_TEST(node_alloc_t::count == 0);
+      delete ptr;
+   }
+   BOOST_TEST(node_t::count == 0);
+}
+
+int main()
+{
+   test_types();
+   test_default_constructor();
+   test_arg_constructor();
+   test_move_constructor();
+   test_related_constructor();
+   test_move_assignment();
+   test_value_key_mapped();
+   test_get_allocator();
+   test_bool_conversion_empty();
+   test_swap();
+   test_get_release();
+   return ::boost::report_errors();
+}
diff --git a/test/null_iterators_test.cpp b/test/null_iterators_test.cpp
new file mode 100644
index 0000000..f081dbe
--- /dev/null
+++ b/test/null_iterators_test.cpp
@@ -0,0 +1,96 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2014-2014. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/static_vector.hpp>
+#include <boost/container/string.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/set.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/intrusive/detail/mpl.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+#include <boost/static_assert.hpp>
+#include <cstring>
+#include <new>
+
+using namespace boost::container;
+
+typedef boost::container::dtl::aligned_storage<sizeof(void*)*4>::type buffer_t;
+
+static buffer_t buffer_0x00;
+static buffer_t buffer_0xFF;
+
+template<class Iterator>
+const Iterator &on_0x00_buffer()
+{
+   BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
+   return * ::new(std::memset(&buffer_0x00, 0x00, sizeof(buffer_0x00))) Iterator();
+}
+
+template<class Iterator>
+const Iterator &on_0xFF_buffer()
+{
+   BOOST_STATIC_ASSERT(sizeof(buffer_t) >= sizeof(Iterator));
+   return * ::new(std::memset(&buffer_0xFF, 0xFF, sizeof(buffer_0xFF))) Iterator();
+}
+
+namespace boost {
+namespace container {
+namespace test {
+
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reverse_iterator)
+BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(const_reverse_iterator)
+
+}}}   //namespace boost::container::test {
+
+template<class Container>
+void check_null_iterators()
+{
+   typedef typename Container::iterator               iterator;
+   typedef typename Container::const_iterator         const_iterator;
+   typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+      (boost::container::test::, Container
+      ,reverse_iterator, iterator)                    reverse_iterator;
+   typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
+      (boost::container::test::, Container
+      ,const_reverse_iterator, const_iterator)        const_reverse_iterator;
+
+   BOOST_TEST(on_0xFF_buffer<iterator>()               == on_0x00_buffer<iterator>());
+   BOOST_TEST(on_0xFF_buffer<const_iterator>()         == on_0x00_buffer<const_iterator>());
+   BOOST_TEST(on_0xFF_buffer<reverse_iterator>()       == on_0x00_buffer<reverse_iterator>());
+   BOOST_TEST(on_0xFF_buffer<const_reverse_iterator>() == on_0x00_buffer<const_reverse_iterator>());
+}
+
+int main()
+{
+   check_null_iterators< vector<int> >();
+   check_null_iterators< deque<int> >();
+   check_null_iterators< stable_vector<int> >();
+   check_null_iterators< static_vector<int, 1> >();
+   check_null_iterators< string >();
+   check_null_iterators< list<int> >();
+   check_null_iterators< slist<int> >();
+   check_null_iterators< map<int, int> >();
+   check_null_iterators< multimap<int, int> >();
+   check_null_iterators< set<int> >();
+   check_null_iterators< multiset<int> >();
+   check_null_iterators< flat_set<int> >();
+   check_null_iterators< flat_multiset<int> >();
+   check_null_iterators< flat_map<int, int> >();
+   check_null_iterators< flat_multimap<int, int> >();
+
+   return boost::report_errors();
+}
diff --git a/test/pair_test.cpp b/test/pair_test.cpp
new file mode 100644
index 0000000..5ead7a4
--- /dev/null
+++ b/test/pair_test.cpp
@@ -0,0 +1,156 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/pair.hpp>
+#include "movable_int.hpp"
+#include "emplace_test.hpp"
+#include<boost/move/utility_core.hpp>
+#include<boost/move/detail/fwd_macros.hpp>
+#include<boost/core/lightweight_test.hpp>
+
+//non_copymovable_int
+//copyable_int
+//movable_int
+//movable_and_copyable_int
+
+
+#include <boost/tuple/tuple.hpp>
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) || (defined(BOOST_MSVC) && (BOOST_MSVC == 1700 || BOOST_MSVC == 1600))
+#define BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+#endif
+
+#if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+#include <tuple>
+#endif
+
+using namespace ::boost::container;
+
+int main ()
+{
+   {
+      dtl::pair<test::non_copymovable_int, test::non_copymovable_int> p1;
+      dtl::pair<test::copyable_int, test::copyable_int> p2;
+      dtl::pair<test::movable_int, test::movable_int> p3;
+      dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4;
+   }
+   {  //Constructible from two values
+      dtl::pair<test::non_copymovable_int, test::non_copymovable_int> p1(1, 2);
+      dtl::pair<test::copyable_int, test::copyable_int> p2(1, 2);
+      dtl::pair<test::movable_int, test::movable_int> p3(1, 2);
+      dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4(1, 2);
+   }
+
+   {  //Constructible from internal types
+      dtl::pair<test::copyable_int, test::copyable_int> p2(test::copyable_int(1), test::copyable_int(2));
+      {
+         test::movable_int a(1), b(2);
+         dtl::pair<test::movable_int, test::movable_int> p3(::boost::move(a), ::boost::move(b));
+      }
+      {
+         test::movable_and_copyable_int a(1), b(2);
+         dtl::pair<test::movable_and_copyable_int, test::movable_and_copyable_int> p4(::boost::move(a), ::boost::move(b));
+      }
+   }
+   {  //piecewise construct from boost tuple
+      using namespace boost::tuples;
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<>());
+         BOOST_TEST(p.first == 0);
+         BOOST_TEST(p.second == 0.f);
+      }
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<float>(2.f));
+         BOOST_TEST(p.first == 0);
+         BOOST_TEST(p.second == 2.f);
+      }
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<int>(2), tuple<float>(1.f));
+         BOOST_TEST(p.first == 2);
+         BOOST_TEST(p.second == 1.f);
+      }
+      {
+         boost::container::dtl::pair
+            < boost::container::dtl::pair<int, float>
+            , boost::container::dtl::pair<double, char>
+            > p(piecewise_construct, tuple<int, float>(3, 4.f), tuple<double, char>(8.,'a'));
+         BOOST_TEST(p.first.first   == 3);
+         BOOST_TEST(p.first.second  == 4.f);
+         BOOST_TEST(p.second.first  == 8.);
+         BOOST_TEST(p.second.second == 'a');
+      }
+      {
+         boost::container::dtl::pair
+            < tuple<int, float, double>
+            , char
+            > p(piecewise_construct, tuple<int, float, double>(3, 16.f, 32.), tuple<char>('b'));
+         BOOST_TEST(p.first.get<0>() == 3);
+         BOOST_TEST(p.first.get<1>() == 16.f);
+         BOOST_TEST(p.first.get<2>() == 32.);
+         BOOST_TEST(p.second == 'b');
+      }
+   }
+   #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+   {  //piecewise construct from std tuple
+      using std::tuple;
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<>());
+         BOOST_TEST(p.first == 0);
+         BOOST_TEST(p.second == 0.f);
+      }
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<>(), tuple<float>(2.f));
+         BOOST_TEST(p.first == 0);
+         BOOST_TEST(p.second == 2.f);
+      }
+      {
+         boost::container::dtl::pair<int, float> p(piecewise_construct, tuple<int>(2), tuple<float>(1.f));
+         BOOST_TEST(p.first == 2);
+         BOOST_TEST(p.second == 1.f);
+      }
+      {
+         boost::container::dtl::pair
+            < boost::container::dtl::pair<int, float>
+            , boost::container::dtl::pair<double, char>
+            > p(piecewise_construct, tuple<int, float>(3, 4.f), tuple<double, char>(8.,'a'));
+         BOOST_TEST(p.first.first   == 3);
+         BOOST_TEST(p.first.second  == 4.f);
+         BOOST_TEST(p.second.first  == 8.);
+         BOOST_TEST(p.second.second == 'a');
+      }
+      {
+         boost::container::dtl::pair
+            < tuple<int, float, double>
+            , char
+            > p(piecewise_construct, tuple<int, float, double>(3, 16.f, 32.), tuple<char>('b'));
+         BOOST_TEST(std::get<0>(p.first) == 3);
+         BOOST_TEST(std::get<1>(p.first) == 16.f);
+         BOOST_TEST(std::get<2>(p.first) == 32.);
+         BOOST_TEST(p.second == 'b');
+      }
+      #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+      typedef dtl::pair<test::movable_int, test::movable_int> movable_pair_t;
+      typedef dtl::pair<movable_pair_t, movable_pair_t> movable_pair_pair_t;
+      test::movable_int a(1), b(2), c(3), d(4);
+      movable_pair_pair_t p( piecewise_construct
+                           , dtl::forward_as_tuple_impl(boost::move(a), boost::move(b))
+                           , dtl::forward_as_tuple_impl(boost::move(c), boost::move(d))
+                           );
+      BOOST_TEST(p.first.first   == 1);
+      BOOST_TEST(p.first.second  == 2);
+      BOOST_TEST(p.second.first  == 3);
+      BOOST_TEST(p.second.second == 4);
+      #endif
+   }
+   #endif   //#!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_HDR_TUPLE)
+   return ::boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/pmr_deque_test.cpp b/test/pmr_deque_test.cpp
new file mode 100644
index 0000000..15c67e2
--- /dev/null
+++ b/test/pmr_deque_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/deque.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef deque<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::deque<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_flat_map_test.cpp b/test/pmr_flat_map_test.cpp
new file mode 100644
index 0000000..f98e497
--- /dev/null
+++ b/test/pmr_flat_map_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/flat_map.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef flat_map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<int, float> > > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map_of<int, float>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_map<int, float> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_flat_set_test.cpp b/test/pmr_flat_set_test.cpp
new file mode 100644
index 0000000..5c9efe1
--- /dev/null
+++ b/test/pmr_flat_set_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/flat_set.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef flat_set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::flat_set<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_list_test.cpp b/test/pmr_list_test.cpp
new file mode 100644
index 0000000..794ccf5
--- /dev/null
+++ b/test/pmr_list_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/list.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef list<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::list<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_map_test.cpp b/test/pmr_map_test.cpp
new file mode 100644
index 0000000..5db3f10
--- /dev/null
+++ b/test/pmr_map_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/map.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef map<int, float, std::less<int>, pmr::polymorphic_allocator<std::pair<const int, float> > > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map_of<int, float>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::map<int, float> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_set_test.cpp b/test/pmr_set_test.cpp
new file mode 100644
index 0000000..3093fd4
--- /dev/null
+++ b/test/pmr_set_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/set.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef set<int, std::less<int>, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::set<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_slist_test.cpp b/test/pmr_slist_test.cpp
new file mode 100644
index 0000000..ed4b5ae
--- /dev/null
+++ b/test/pmr_slist_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/slist.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::slist<empty>;
+
+int main()
+{
+   ::boost::container::slist<empty> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/pmr_small_vector_test.cpp b/test/pmr_small_vector_test.cpp
new file mode 100644
index 0000000..334588d
--- /dev/null
+++ b/test/pmr_small_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/small_vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef small_vector<int, 2, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector_of<int, 2>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::small_vector<int, 2> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_stable_vector_test.cpp b/test/pmr_stable_vector_test.cpp
new file mode 100644
index 0000000..246f071
--- /dev/null
+++ b/test/pmr_stable_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/stable_vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef stable_vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::stable_vector<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_static_vector_test.cpp b/test/pmr_static_vector_test.cpp
new file mode 100644
index 0000000..6681f7c
--- /dev/null
+++ b/test/pmr_static_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/static_vector.hpp>
+
+struct empty
+{
+   friend bool operator == (const empty &, const empty &){ return true; }
+   friend bool operator <  (const empty &, const empty &){ return true; }
+};
+
+template class ::boost::container::static_vector<empty, 2>;
+
+int main()
+{
+   ::boost::container::static_vector<empty, 2> dummy;
+   (void)dummy;
+   return 0;
+}
diff --git a/test/pmr_string_test.cpp b/test/pmr_string_test.cpp
new file mode 100644
index 0000000..c8d81a5
--- /dev/null
+++ b/test/pmr_string_test.cpp
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/string.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef basic_string<char, std::char_traits<char>, pmr::polymorphic_allocator<char> > string_t;
+   typedef basic_string<wchar_t, std::char_traits<wchar_t>, pmr::polymorphic_allocator<wchar_t> > wstring_t;
+   BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string>::value ));
+   BOOST_STATIC_ASSERT(( is_same<string_t, pmr::basic_string_of<char>::type>::value ));
+   BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring>::value ));
+   BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::basic_string_of<wchar_t>::type>::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<string_t, pmr::string >::value ));
+      BOOST_STATIC_ASSERT(( is_same<wstring_t, pmr::wstring >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/pmr_vector_test.cpp b/test/pmr_vector_test.cpp
new file mode 100644
index 0000000..293291c
--- /dev/null
+++ b/test/pmr_vector_test.cpp
@@ -0,0 +1,26 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/vector.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/detail/type_traits.hpp>
+
+int main()
+{
+   using namespace boost::container;
+   using boost::container::dtl::is_same;
+
+   typedef vector<int, pmr::polymorphic_allocator<int> > intcontainer_t;
+   BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector_of<int>::type >::value ));
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+      BOOST_STATIC_ASSERT(( is_same<intcontainer_t, pmr::vector<int> >::value ));
+   #endif
+   return 0;
+}
diff --git a/test/polymorphic_allocator_test.cpp b/test/polymorphic_allocator_test.cpp
new file mode 100644
index 0000000..10899ca
--- /dev/null
+++ b/test/polymorphic_allocator_test.cpp
@@ -0,0 +1,198 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include "derived_from_memory_resource.hpp"
+#include "propagation_test_allocator.hpp"
+
+using namespace boost::container::pmr;
+using namespace boost::container;
+
+void test_default_constructor()
+{
+   polymorphic_allocator<int> a;
+   BOOST_TEST(a.resource() == get_default_resource());
+}
+
+void test_resource_constructor()
+{
+   polymorphic_allocator<int> a(0);
+   BOOST_TEST(a.resource() == get_default_resource());
+
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> b(&d);
+   BOOST_TEST(&d == b.resource());
+}
+
+void test_copy_constructor()
+{
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> b(&d);
+   polymorphic_allocator<int> c(b);
+   BOOST_TEST(b.resource() == c.resource());
+}
+
+void test_copy_assignment()
+{
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> b(&d);
+   polymorphic_allocator<int> c;
+   BOOST_TEST(c.resource() == get_default_resource());
+   c = b;
+   BOOST_TEST(c.resource() == b.resource());
+}
+
+void test_allocate()
+{
+   int dummy;
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> p(&d);
+   d.reset();
+   d.do_allocate_return = &dummy;
+   p.allocate(2);
+   BOOST_TEST(d.do_allocate_called == true);
+   BOOST_TEST(d.do_allocate_return == &dummy);
+   //It shall allocate 2*sizeof(int), alignment_of<int>
+   BOOST_TEST(d.do_allocate_bytes == 2*sizeof(int));
+   BOOST_TEST(d.do_allocate_alignment == dtl::alignment_of<int>::value);
+}
+
+void test_deallocate()
+{
+   int dummy;
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> p(&d);
+   d.reset();
+   p.deallocate(&dummy, 3);
+   BOOST_TEST(d.do_deallocate_called == true);
+   //It shall deallocate 2*sizeof(int), alignment_of<int>
+   BOOST_TEST(d.do_deallocate_p == &dummy);
+   BOOST_TEST(d.do_deallocate_bytes == 3*sizeof(int));
+   BOOST_TEST(d.do_deallocate_alignment == dtl::alignment_of<int>::value);
+}
+
+void test_construct()
+{
+   //0 arg
+   {
+      typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value);
+      BOOST_TEST(value.construction_type == NotUsesAllocator);
+      BOOST_TEST(value.value == 0);
+      value.~value_type();
+   }
+   {
+      typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value);
+      BOOST_TEST(value.construction_type == ConstructiblePrefix);
+      BOOST_TEST(value.value == 0);
+      value.~value_type();
+   }
+   {
+      typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value);
+      BOOST_TEST(value.construction_type == ConstructibleSuffix);
+      BOOST_TEST(value.value == 0);
+      value.~value_type();
+   }
+   //1 arg
+   {
+      typedef allocator_argument_tester<NotUsesAllocator, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value, 2);
+      BOOST_TEST(value.construction_type == NotUsesAllocator);
+      BOOST_TEST(value.value == 2);
+      value.~value_type();
+   }
+   {
+      typedef allocator_argument_tester<ErasedTypePrefix, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value, 3);
+      BOOST_TEST(value.construction_type == ConstructiblePrefix);
+      BOOST_TEST(value.value == 3);
+      value.~value_type();
+   }
+   {
+      typedef allocator_argument_tester<ErasedTypeSuffix, 0> value_type;
+      value_type value;
+      value.~value_type();
+      polymorphic_allocator<int> pa;
+      pa.construct(&value, 4);
+      BOOST_TEST(value.construction_type == ConstructibleSuffix);
+      BOOST_TEST(value.value == 4);
+      value.~value_type();
+   }
+}
+
+struct char_holder
+{
+   char m_char;
+   ~char_holder()
+   {  destructor_called = true;  }
+   static bool destructor_called;
+};
+
+bool char_holder::destructor_called = false;
+
+void test_destroy()
+{
+   char_holder ch;
+   polymorphic_allocator<int> p;
+   BOOST_TEST(char_holder::destructor_called == false);
+   p.destroy(&ch);
+   BOOST_TEST(char_holder::destructor_called == true);
+}
+
+void test_select_on_container_copy_construction()
+{
+   //select_on_container_copy_construction shall return
+   //a default constructed polymorphic_allocator
+   //which uses the default resource.
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> p(&d);
+   BOOST_TEST(get_default_resource() == p.select_on_container_copy_construction().resource());
+}
+
+void test_resource()
+{
+   derived_from_memory_resource d;
+   polymorphic_allocator<int> p(&d);
+   BOOST_TEST(&d == p.resource());
+}
+
+int main()
+{
+   test_default_constructor();
+   test_resource_constructor();
+   test_copy_constructor();
+   test_copy_assignment();
+   test_allocate();
+   test_deallocate();
+   test_construct();
+   test_destroy();
+   test_select_on_container_copy_construction();
+   test_resource();
+   return ::boost::report_errors();
+}
diff --git a/test/pool_resource_test.hpp b/test/pool_resource_test.hpp
new file mode 100644
index 0000000..110274e
--- /dev/null
+++ b/test/pool_resource_test.hpp
@@ -0,0 +1,493 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/global_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+#include <boost/intrusive/detail/math.hpp>
+
+#include "derived_from_memory_resource.hpp"
+#include "memory_resource_logger.hpp"
+
+using namespace boost::container::pmr;
+
+template<class PoolResource>
+struct derived_from_pool_resource
+   : public PoolResource
+{
+   derived_from_pool_resource(const pool_options& opts, memory_resource* upstream)
+      : PoolResource(opts, upstream)
+   {}
+
+   explicit derived_from_pool_resource(memory_resource *p)
+      : PoolResource(p)
+   {}
+
+   explicit derived_from_pool_resource(const pool_options &opts)
+      : PoolResource(opts)
+   {}
+
+   derived_from_pool_resource()
+      : PoolResource()
+   {}
+
+   using PoolResource::do_allocate;
+   using PoolResource::do_deallocate;
+   using PoolResource::do_is_equal;
+};
+
+template<class PoolResource>
+void test_default_constructor()
+{
+   //With default options/resource
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      PoolResource m;
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+template<class PoolResource>
+void test_upstream_constructor()
+{
+   //With a resource, default options
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      PoolResource m(&dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+template<class PoolResource>
+void test_options_constructor()
+{
+   //Default options
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      pool_options opts;
+      PoolResource m(opts);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+   }
+   //Too large option values
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      pool_options opts;
+      opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
+      opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
+      PoolResource m(opts);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+   }
+   //Too small option values
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      pool_options opts;
+      opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
+      PoolResource m(opts);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+   }
+   //In range option values
+   {
+      memory_resource_logger mrl;
+      BOOST_TEST(mrl.m_info.size() == 0u);
+      set_default_resource(&mrl);
+      pool_options opts;
+      opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
+      opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
+      PoolResource m(opts);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == get_default_resource());
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(mrl.m_info.size() == 0u);
+   }
+}
+
+template<class PoolResource>
+void test_options_upstream_constructor()
+{
+   //Default options
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      pool_options opts;
+      PoolResource m(opts, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+   //Too large option values
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      pool_options opts;
+      opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk+1;
+      opts.largest_required_pool_block = pool_options_default_largest_required_pool_block+1;
+      PoolResource m(opts, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_default_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+   //Too small option values
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      pool_options opts;
+      opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block-1u;
+      PoolResource m(opts, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      BOOST_TEST(m.options().largest_required_pool_block == pool_options_minimum_largest_required_pool_block);
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+   //In range option values
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      pool_options opts;
+      opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk;
+      opts.largest_required_pool_block = pool_options_minimum_largest_required_pool_block;
+      PoolResource m(opts, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      //max blocks is unchanged in this implementation
+      BOOST_TEST(m.options().max_blocks_per_chunk == pool_options_default_max_blocks_per_chunk);
+      //largest block is rounded to pow2
+      BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+template<class PoolResource>
+void test_options()
+{
+   //In range option values
+   {
+      derived_from_memory_resource dmr;
+      dmr.reset();
+      pool_options opts;
+      opts.max_blocks_per_chunk = pool_options_default_max_blocks_per_chunk/2u;
+      opts.largest_required_pool_block = (pool_options_default_largest_required_pool_block
+         - pool_options_minimum_largest_required_pool_block) | std::size_t(1); //guaranteed to be non power of 2.
+      PoolResource m(opts, &dmr);
+      //test postconditions
+      BOOST_TEST(m.upstream_resource() == &dmr);
+      //max blocks is unchanged in this implementation
+      BOOST_TEST(m.options().max_blocks_per_chunk == opts.max_blocks_per_chunk);
+      //largest block is rounded to pow2
+      BOOST_TEST(m.options().largest_required_pool_block == bi::detail::ceil_pow2(opts.largest_required_pool_block));
+      //test it does not allocate any memory
+      BOOST_TEST(dmr.do_allocate_called == false);
+   }
+}
+
+template<class PoolResource>
+void test_do_allocate_deallocate()
+{
+   memory_resource_logger mrl;
+   {
+      derived_from_pool_resource<PoolResource> dmbr(&mrl);
+      {
+         //First block from pool 0
+         dmbr.do_allocate(1, 1);
+         //It should allocate the pool array plus an initial block
+         BOOST_TEST(mrl.m_info.size() == 2u);
+         //Second block from pool 0
+         dmbr.do_allocate(1, 1);
+         //It should allocate again (with 2 chunks per block)
+         BOOST_TEST(mrl.m_info.size() == 3u);
+         //Third block from pool 0
+         dmbr.do_allocate(1, 1);
+         //It should NOT allocate again (previous was a 2 block chunk)
+         BOOST_TEST(mrl.m_info.size() == 3u);
+      }
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+
+   //Allocate and deallocate from the same chunk to test block caching
+   {
+      derived_from_pool_resource<PoolResource> dmbr(&mrl);
+      {
+         //First block from pool 0
+         void *p = dmbr.do_allocate(1, 1);
+         //It should allocate the pool array plus an initial block
+         BOOST_TEST(mrl.m_info.size() == 2u);
+         //No cached, as initial blocks per chunk is 1
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+         //Deallocate and allocate again
+         dmbr.do_deallocate(p, 1, 1);
+         //Cached
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
+         p = dmbr.do_allocate(1, 1);
+         //Reused
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+         //It should have NOT allocated (block reuse)
+         BOOST_TEST(mrl.m_info.size() == 2u);
+
+         //Allocate again 2 times (a 2 block chunk is exhausted)
+         void *p2 = dmbr.do_allocate(1, 1);
+         //1 left cached
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 1u);
+         void *p3 = dmbr.do_allocate(1, 1);
+         //Cache exhausted
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 0u);
+         //Single chunk allocation happened
+         BOOST_TEST(mrl.m_info.size() == 3u);
+
+         //Now deallocate all (no memory is freed, all cached)
+         dmbr.do_deallocate(p2, 1, 1);
+         dmbr.do_deallocate(p3, 1, 1);
+         dmbr.do_deallocate(p, 1, 1);
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == 3u);
+         BOOST_TEST(mrl.m_info.size() == 3u);
+      }
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+
+   //Now test max block per chunk
+   {
+      pool_options opts;
+      //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+      opts.max_blocks_per_chunk = 32u; 
+      derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+      {
+         std::size_t loops = opts.max_blocks_per_chunk*2-1u;
+         while(loops--){
+            dmbr.do_allocate(1, 1);
+         }
+         //pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
+         const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
+         BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
+         //Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
+         dmbr.do_allocate(1, 1);
+         BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+         //Exhaust the chunk and allocate a new one, test max_blocks_per_chunk is not passed again
+         loops = opts.max_blocks_per_chunk;
+         while(loops--){
+            dmbr.do_allocate(1, 1);
+         }
+         BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 2u);
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+      }
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+
+   //Now test max block per chunk
+   {
+      pool_options opts;
+      //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+      opts.max_blocks_per_chunk = 32u; 
+      derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+      {
+         std::size_t loops = opts.max_blocks_per_chunk*2-1u;
+         while(loops--){
+            dmbr.do_allocate(1, 1);
+         }
+         //pool array + log2(max_blocks_per_chunk)+1 chunks (sizes [1, 2, 4, ...])
+         BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
+         const std::size_t num_chunks = bi::detail::floor_log2(opts.max_blocks_per_chunk)+1u;
+         BOOST_TEST(mrl.m_info.size() == 1u + num_chunks);
+         //Next allocation should allocate max_blocks_per_chunk blocks in a chunk so max_blocks_per_chunk-1 should remain free
+         dmbr.do_allocate(1, 1);
+         BOOST_TEST(dmbr.pool_next_blocks_per_chunk(0u) == opts.max_blocks_per_chunk);
+         BOOST_TEST(mrl.m_info.size() == 1u + num_chunks + 1u);
+         BOOST_TEST(dmbr.pool_cached_blocks(0u) == (opts.max_blocks_per_chunk-1u));
+      }
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+
+   //Now test different pool sizes
+   {
+      pool_options opts;
+      //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+      opts.max_blocks_per_chunk = 1u; 
+      derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+      const pool_options &final_opts = dmbr.options();
+
+      //Force pool creation
+      dmbr.do_deallocate(dmbr.do_allocate(1, 1), 1, 1);
+      //pool array plus first pool's chunk allocation
+      BOOST_TEST(mrl.m_info.size() == 2u);
+      //pool count must be:
+      // log2(the maximum block) - log2(the minimum block) + 1. Example if minimum block is 8, and maximum 32:
+      // log(32) - log2(8) + 1u = 3 pools (block sizes: 8, 16, and 32)
+      const std::size_t minimum_size = dmbr.pool_block(0u);
+      const std::size_t maximum_size = final_opts.largest_required_pool_block;
+      BOOST_TEST(dmbr.pool_count() == (1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size)));
+      for(std::size_t i = 0, s = minimum_size, max = dmbr.pool_count(); i != max; ++i, s*=2){
+         //Except in the first pool, each cache should be empty
+         BOOST_TEST(dmbr.pool_cached_blocks(i) == std::size_t(i == 0));
+         dmbr.do_deallocate(dmbr.do_allocate(s/2+1, 1), s/2+1, 1);
+         dmbr.do_deallocate(dmbr.do_allocate(s-1, 1), s-1, 1);
+         dmbr.do_deallocate(dmbr.do_allocate(s, 1), s, 1);
+         //pool array plus each previous chunk allocation
+         BOOST_TEST(mrl.m_info.size() == (1u + i + 1u));
+         //as we limited max_blocks_per_chunk to 1, no cached blocks should be available except one
+         BOOST_TEST(dmbr.pool_cached_blocks(i) == 1u);
+      }
+      //Now test out of maximum values, which should go directly to upstream
+      //it should be directly deallocated.
+      void *p = dmbr.do_allocate(maximum_size+1, 1);
+      BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count() + 1u));
+      dmbr.do_deallocate(p, maximum_size+1, 1);
+      BOOST_TEST(mrl.m_info.size() == (1u + dmbr.pool_count()));
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+template<class PoolResource>
+void test_do_is_equal()
+{
+   //`this == dynamic_cast<const PoolResource*>(&other)`.
+   memory_resource_logger mrl;
+   derived_from_pool_resource<PoolResource> dmbr(&mrl);
+   derived_from_pool_resource<PoolResource> dmbr2(&mrl);
+   BOOST_TEST(true == dmbr.do_is_equal(dmbr));
+   BOOST_TEST(false == dmbr.do_is_equal(dmbr2));
+   //A different type should be always different
+   derived_from_memory_resource dmr;
+   BOOST_TEST(false == dmbr.do_is_equal(dmr));
+}
+
+template<class PoolResource>
+void test_release()
+{
+   memory_resource_logger mrl;
+   {
+      pool_options opts;
+      //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+      opts.max_blocks_per_chunk = 4u; 
+      derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+      const pool_options &final_opts = dmbr.options();
+      const std::size_t minimum_size = dmbr.pool_block(0u);
+      const std::size_t maximum_size = final_opts.largest_required_pool_block;
+      const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
+
+      std::size_t expected_memory_allocs = 0;
+      for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
+         for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+            dmbr.do_allocate(s, 1);
+         }
+         //One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
+         expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
+         //pool array plus each previous chunk allocation
+         BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
+      }
+      //Now with out-of-pool sizes
+      for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+         dmbr.do_allocate(maximum_size+1, 1);
+         BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
+      }
+      //Now release memory and check all memory allocated through do_allocate was deallocated to upstream      
+      dmbr.release();
+      BOOST_TEST(mrl.m_info.size() == 1u);
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+template<class PoolResource>
+void test_destructor()
+{
+   memory_resource_logger mrl;
+   {
+      pool_options opts;
+      //so after max_blocks_per_chunk*2-1 allocations, all new chunks must hold max_blocks_per_chunk blocks
+      opts.max_blocks_per_chunk = 4u; 
+      derived_from_pool_resource<PoolResource> dmbr(opts, &mrl);
+      const pool_options &final_opts = dmbr.options();
+      const std::size_t minimum_size = dmbr.pool_block(0u);
+      const std::size_t maximum_size = final_opts.largest_required_pool_block;
+      const std::size_t pool_count = 1u + bi::detail::floor_log2(maximum_size) - bi::detail::floor_log2(minimum_size);
+
+      std::size_t expected_memory_allocs = 0;
+      for(std::size_t i = 0, imax = pool_count, s = minimum_size; i != imax; s*=2, ++i){
+         for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+            dmbr.do_allocate(s, 1);
+         }
+         //One due to the pool array, and for each pool, log2(max_blocks_per_chunk)+1 allocations
+         expected_memory_allocs = 1 + (bid::floor_log2(opts.max_blocks_per_chunk) + 1u)*(i+1);
+         //pool array plus each previous chunk allocation
+         BOOST_TEST(mrl.m_info.size() == expected_memory_allocs);
+      }
+      //Now with out-of-pool sizes
+      for(std::size_t j = 0, j_max = opts.max_blocks_per_chunk*2u-1u; j != j_max; ++j){
+         dmbr.do_allocate(maximum_size+1, 1);
+         BOOST_TEST(mrl.m_info.size() == ++expected_memory_allocs);
+      }
+      //Don't release, all memory, including internal allocations, should be automatically
+      //released after the destructor is run
+   }
+   BOOST_TEST(mrl.m_mismatches == 0u);
+   BOOST_TEST(mrl.m_info.size() == 0u);
+}
+
+
+template<class PoolResource>
+void test_pool_resource()
+{
+   test_options_upstream_constructor<PoolResource>();
+   test_default_constructor<PoolResource>();
+   test_upstream_constructor<PoolResource>();
+   test_options_constructor<PoolResource>();
+   test_options<PoolResource>();
+   test_do_allocate_deallocate<PoolResource>();
+   test_do_is_equal<PoolResource>();
+   test_release<PoolResource>();
+   test_destructor<PoolResource>();
+}
diff --git a/test/print_container.hpp b/test/print_container.hpp
new file mode 100644
index 0000000..2e49ec6
--- /dev/null
+++ b/test/print_container.hpp
@@ -0,0 +1,46 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_PRINTCONTAINER_HPP
+#define BOOST_PRINTCONTAINER_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <iostream>
+
+namespace boost{
+namespace container {
+namespace test{
+
+//Function to dump data
+template<class MyBoostCont
+        ,class MyStdCont>
+void PrintContainers(MyBoostCont *boostcont, MyStdCont *stdcont)
+{
+   typename MyBoostCont::iterator itboost = boostcont->begin(), itboostend = boostcont->end();
+   typename MyStdCont::iterator itstd = stdcont->begin(), itstdend = stdcont->end();
+
+   std::cout << "MyBoostCont" << std::endl;
+   for(; itboost != itboostend; ++itboost){
+      std::cout << *itboost << std::endl;
+   }
+   std::cout << "MyStdCont" << std::endl;
+
+   for(; itstd != itstdend; ++itstd){
+      std::cout << *itstd << std::endl;
+   }
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //#ifndef BOOST_PRINTCONTAINER_HPP
diff --git a/test/propagate_allocator_test.hpp b/test/propagate_allocator_test.hpp
new file mode 100644
index 0000000..e3a5048
--- /dev/null
+++ b/test/propagate_allocator_test.hpp
@@ -0,0 +1,368 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2008. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
+#define BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "dummy_test_allocator.hpp"
+
+#include <iostream>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class Selector>
+struct alloc_propagate_base;
+
+template<class T, class Allocator, class Selector>
+class alloc_propagate_wrapper
+   : public alloc_propagate_base<Selector>::template apply<T, Allocator>::type
+{
+   BOOST_COPYABLE_AND_MOVABLE(alloc_propagate_wrapper)
+
+   public:   
+   typedef typename alloc_propagate_base
+      <Selector>::template apply<T, Allocator>::type  Base;
+
+   typedef typename Base::allocator_type  allocator_type;
+   typedef typename Base::value_type      value_type;
+   typedef typename Base::size_type       size_type;
+
+   alloc_propagate_wrapper()
+      : Base()
+   {}
+
+   explicit alloc_propagate_wrapper(const allocator_type &a)
+      : Base(a)
+   {}
+/*
+   //sequence containers only
+   explicit alloc_propagate_wrapper(size_type n, const value_type &v, const allocator_type &a)
+      : Base(n, v, a)
+   {}
+
+   alloc_propagate_wrapper(size_type n, const allocator_type &a)
+      : Base(n, a)
+   {}*/
+
+   template<class Iterator>
+   alloc_propagate_wrapper(Iterator b, Iterator e, const allocator_type &a)
+      : Base(b, e, a)
+   {}
+
+   #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   alloc_propagate_wrapper(std::initializer_list<value_type> il, const allocator_type& a)
+      : Base(il, a)
+   {}
+/*
+   //associative containers only
+   alloc_propagate_wrapper(std::initializer_list<value_type> il, const Compare& comp, const allocator_type& a)
+      : Base(il, comp, a)
+   {}*/
+
+   #endif
+
+   alloc_propagate_wrapper(const alloc_propagate_wrapper &x)
+      : Base(x)
+   {}
+
+   alloc_propagate_wrapper(const alloc_propagate_wrapper &x, const allocator_type &a)
+      : Base(x, a)
+   {}
+
+   alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x)
+      : Base(boost::move(static_cast<Base&>(x)))
+   {}
+
+   alloc_propagate_wrapper(BOOST_RV_REF(alloc_propagate_wrapper) x, const allocator_type &a)
+      : Base(boost::move(static_cast<Base&>(x)), a)
+   {}
+
+   alloc_propagate_wrapper &operator=(BOOST_COPY_ASSIGN_REF(alloc_propagate_wrapper) x)
+   {  this->Base::operator=((const Base &)x);  return *this; }
+
+   alloc_propagate_wrapper &operator=(BOOST_RV_REF(alloc_propagate_wrapper) x)
+   {  this->Base::operator=(boost::move(static_cast<Base&>(x)));  return *this; }
+
+   void swap(alloc_propagate_wrapper &x)
+   {  this->Base::swap(x);  }
+};
+
+template<class T>
+struct get_real_stored_allocator
+{
+   typedef typename T::stored_allocator_type type;
+};
+
+template<class Container>
+void test_propagate_allocator_allocator_arg();
+
+template<class Selector>
+bool test_propagate_allocator()
+{
+   {
+      typedef propagation_test_allocator<char, true, true, true, true>  AlwaysPropagate;
+      typedef alloc_propagate_wrapper<char, AlwaysPropagate, Selector>  PropagateCont;
+      typedef typename get_real_stored_allocator<typename PropagateCont::Base>::type StoredAllocator;
+      {
+         //////////////////////////////////////////
+         //Test AlwaysPropagate allocator propagation
+         //////////////////////////////////////////
+         
+         //default constructor
+         StoredAllocator::reset_unique_id(111);
+         PropagateCont c;  //stored 112
+         BOOST_TEST (c.get_stored_allocator().id_ == 112);
+         BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //copy constructor
+         StoredAllocator::reset_unique_id(222);
+         PropagateCont c; //stored 223
+         BOOST_TEST (c.get_stored_allocator().id_ == 223);
+         //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler).
+         //For allocators that copy in select_on_container_copy_construction, at least we must have a copy
+         PropagateCont c2(c); //should propagate 223
+         BOOST_TEST (c2.get_stored_allocator().id_ == 223);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 1);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //move constructor
+         StoredAllocator::reset_unique_id(333);
+         PropagateCont c; //stored 334
+         BOOST_TEST (c.get_stored_allocator().id_ == 334);
+         PropagateCont c2(boost::move(c)); //should propagate 334
+         BOOST_TEST (c2.get_stored_allocator().id_ == 334);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_ > 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //copy assign
+         StoredAllocator::reset_unique_id(444);
+         PropagateCont c; //stored 445
+         BOOST_TEST (c.get_stored_allocator().id_ == 445);
+         PropagateCont c2; //stored 446
+         BOOST_TEST (c2.get_stored_allocator().id_ == 446);
+         c2 = c; //should propagate 445
+         BOOST_TEST (c2.get_stored_allocator().id_ == 445);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 1);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //move assign
+         StoredAllocator::reset_unique_id(555);
+         PropagateCont c; //stored 556
+         BOOST_TEST (c.get_stored_allocator().id_ == 556);
+         PropagateCont c2; //stored 557
+         BOOST_TEST (c2.get_stored_allocator().id_ == 557);
+         c = boost::move(c2); //should propagate 557
+         BOOST_TEST (c.get_stored_allocator().id_ == 557);
+         BOOST_TEST (c.get_stored_allocator().ctr_copies_    == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_moves_     == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_moves_ == 1);
+         BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //swap
+         StoredAllocator::reset_unique_id(666);
+         PropagateCont c; //stored 667
+         BOOST_TEST (c.get_stored_allocator().id_ == 667);
+         PropagateCont c2; //stored 668
+         BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+         c.swap(c2);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_    == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_copies_    == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_     == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_moves_     == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_  == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_moves_  == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_  == 1);
+         BOOST_TEST (c.get_stored_allocator().swaps_  == 1);
+      }
+      //And now allocator argument constructors
+      test_propagate_allocator_allocator_arg<PropagateCont>();
+   }
+
+   //////////////////////////////////////////
+   //Test NeverPropagate allocator propagation
+   //////////////////////////////////////////
+   {
+      typedef propagation_test_allocator<char, false, false, false, false> NeverPropagate;
+      typedef alloc_propagate_wrapper<char, NeverPropagate, Selector>      NoPropagateCont;
+      typedef typename get_real_stored_allocator<typename NoPropagateCont::Base>::type StoredAllocator;
+      {
+         //default constructor
+         StoredAllocator::reset_unique_id(111);
+         NoPropagateCont c; //stored 112
+         BOOST_TEST (c.get_stored_allocator().id_ == 112);
+         BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //copy constructor
+         //propagate_on_copy_constructor produces copies, moves or RVO (depending on the compiler)
+         //For allocators that don't copy in select_on_container_copy_construction we must have a default
+         //construction
+         StoredAllocator::reset_unique_id(222);
+         NoPropagateCont c; //stored 223
+         BOOST_TEST (c.get_stored_allocator().id_ == 223);
+         NoPropagateCont c2(c); //should NOT propagate 223
+         BOOST_TEST (c2.get_stored_allocator().id_ == 224);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //move constructor
+         StoredAllocator::reset_unique_id(333);
+         NoPropagateCont c; //stored 334
+         BOOST_TEST (c.get_stored_allocator().id_ == 334);
+         NoPropagateCont c2(boost::move(c)); // should NOT propagate 334
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ >= 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_ >= 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //copy assign
+         StoredAllocator::reset_unique_id(444);
+         NoPropagateCont c; //stored 445
+         NoPropagateCont c2; //stored 446
+         c2 = c; // should NOT propagate 445
+         BOOST_TEST (c2.get_stored_allocator().id_ == 446);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //move assign
+         StoredAllocator::reset_unique_id(555);
+         NoPropagateCont c; //stored 556
+         NoPropagateCont c2; //stored 557
+         c2 = c; // should NOT propagate 556
+         BOOST_TEST (c2.get_stored_allocator().id_ == 557);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+      }
+      {
+         //swap
+         StoredAllocator::reset_unique_id(666);
+         NoPropagateCont c; //stored 667
+         BOOST_TEST (c.get_stored_allocator().id_ == 667);
+         NoPropagateCont c2; //stored 668
+         BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+         c2.swap(c); // should NOT swap 667 and 668
+         BOOST_TEST (c2.get_stored_allocator().id_ == 668);
+         BOOST_TEST (c2.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().ctr_moves_  == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+         BOOST_TEST (c.get_stored_allocator().id_ == 667);
+         BOOST_TEST (c.get_stored_allocator().ctr_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().ctr_moves_  == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+         BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+         BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+      }
+      //And now allocator argument constructors
+      test_propagate_allocator_allocator_arg<NoPropagateCont>();
+   }
+
+   return report_errors() == 0;
+}
+
+template<class Container>
+void test_propagate_allocator_allocator_arg()
+{
+   typedef typename Container::allocator_type         allocator_type;
+   typedef typename get_real_stored_allocator<typename Container::Base>::type StoredAllocator;
+
+   {  //The allocator must be always propagated
+      //allocator constructor
+      allocator_type::reset_unique_id(111);
+      const allocator_type & a = allocator_type(); //stored 112
+      Container c(a); //should propagate 112
+      BOOST_TEST (c.get_stored_allocator().id_ == 112);
+      BOOST_TEST (c.get_stored_allocator().ctr_copies_ > 0);
+      BOOST_TEST (c.get_stored_allocator().ctr_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c.get_stored_allocator().swaps_ == 0);
+   }
+   {
+      //copy allocator constructor
+      StoredAllocator::reset_unique_id(999);
+      Container c;
+      //stored_allocator_type could be the same type as allocator_type
+      //so reset it again to get a predictable result
+      allocator_type::reset_unique_id(222);
+      Container c2(c, allocator_type()); //should propagate 223
+      BOOST_TEST (c2.get_stored_allocator().id_ == 223);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+   }
+   {
+      //move allocator constructor
+      StoredAllocator::reset_unique_id(999);
+      Container c;
+      //stored_allocator_type could be the same type as allocator_type
+      //so reset it again to get a predictable result
+      allocator_type::reset_unique_id(333);
+      Container c2(boost::move(c), allocator_type()); //should propagate 334
+      BOOST_TEST (c2.get_stored_allocator().id_ == 334);
+      BOOST_TEST (c2.get_stored_allocator().ctr_copies_ > 0);
+      BOOST_TEST (c2.get_stored_allocator().ctr_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_copies_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().assign_moves_ == 0);
+      BOOST_TEST (c2.get_stored_allocator().swaps_ == 0);
+   }
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif   //#ifndef BOOST_CONTAINER_PROPAGATE_ALLOCATOR_TEST_HPP
diff --git a/test/propagation_test_allocator.hpp b/test/propagation_test_allocator.hpp
new file mode 100644
index 0000000..7c8643c
--- /dev/null
+++ b/test/propagation_test_allocator.hpp
@@ -0,0 +1,268 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+#define BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
+
+#include <boost/container/uses_allocator.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/core.hpp>
+#include <boost/container/pmr/polymorphic_allocator.hpp>
+
+
+template<class T, unsigned int Id, bool HasTrueTypes = false>
+class propagation_test_allocator
+{
+   BOOST_COPYABLE_AND_MOVABLE(propagation_test_allocator)
+   public:
+
+   template<class U>
+   struct rebind
+   {
+      typedef propagation_test_allocator<U, Id, HasTrueTypes> other;
+   };
+
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_copy_assignment;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_move_assignment;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  propagate_on_container_swap;
+   typedef boost::container::dtl::bool_<HasTrueTypes>  is_always_equal;
+   typedef T value_type;
+
+   propagation_test_allocator()
+      : m_default_contructed(true), m_move_contructed(false), m_move_assigned(false)
+   {}
+
+   propagation_test_allocator(const propagation_test_allocator&)
+      : m_default_contructed(false), m_move_contructed(false), m_move_assigned(false)
+   {}
+
+   propagation_test_allocator(BOOST_RV_REF(propagation_test_allocator) )
+      : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
+   {}
+
+   template<class U>
+   propagation_test_allocator(BOOST_RV_REF_BEG propagation_test_allocator<U, Id, HasTrueTypes> BOOST_RV_REF_END)
+      : m_default_contructed(false), m_move_contructed(true), m_move_assigned(false)
+   {}
+
+   template<class U>
+   propagation_test_allocator(const propagation_test_allocator<U, Id, HasTrueTypes> &)
+   {}
+
+   propagation_test_allocator & operator=(BOOST_COPY_ASSIGN_REF(propagation_test_allocator))
+   {  return *this;  }
+
+   propagation_test_allocator & operator=(BOOST_RV_REF(propagation_test_allocator))
+   {
+      m_move_assigned = true;
+      return *this;
+   }
+
+   std::size_t max_size() const
+   {  return std::size_t(-1);  }
+
+   T* allocate(std::size_t n)
+   {  return (T*)::new char[n*sizeof(T)];  }
+
+   void deallocate(T*p, std::size_t)
+   {  delete []static_cast<char*>(static_cast<void*>(p));  }
+
+   bool m_default_contructed;
+   bool m_move_contructed;
+   bool m_move_assigned;
+};
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator==( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+               , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{  return true;   }
+
+template <class T1, class T2, unsigned int Id, bool HasTrueTypes>
+bool operator!=( const propagation_test_allocator<T1, Id, HasTrueTypes>&
+               , const propagation_test_allocator<T2, Id, HasTrueTypes>&)
+{  return false;   }
+
+//This enum lists the construction options
+//for an allocator-aware type
+enum ConstructionTypeEnum
+{
+   ConstructiblePrefix,
+   ConstructibleSuffix,
+   ErasedTypePrefix,
+   ErasedTypeSuffix,
+   NotUsesAllocator
+};
+
+//This base class provices types for
+//the derived class to implement each construction
+//type. If a construction type does not apply
+//the typedef is set to an internal nat
+//so that the class is not constructible from
+//the user arguments.
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct uses_allocator_base;
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructibleSuffix, AllocatorTag>
+{
+   typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+   typedef allocator_type allocator_constructor_type;
+   struct nat{};
+   typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ConstructiblePrefix, AllocatorTag>
+{
+   typedef propagation_test_allocator<int, AllocatorTag> allocator_type;
+   typedef allocator_type allocator_constructor_type;
+   typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ErasedTypePrefix, AllocatorTag>
+{
+   typedef boost::container::erased_type allocator_type;
+   typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
+   typedef boost::container::allocator_arg_t allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<ErasedTypeSuffix, AllocatorTag>
+{
+   typedef boost::container::erased_type allocator_type;
+   typedef boost::container::pmr::polymorphic_allocator<int> allocator_constructor_type;
+   struct nat{};
+   typedef nat allocator_arg_type;
+};
+
+template<unsigned int AllocatorTag>
+struct uses_allocator_base<NotUsesAllocator, AllocatorTag>
+{
+   struct nat{};
+   typedef nat allocator_constructor_type;
+   typedef nat allocator_arg_type;
+};
+
+template<ConstructionTypeEnum ConstructionType, unsigned int AllocatorTag>
+struct allocator_argument_tester
+   : uses_allocator_base<ConstructionType, AllocatorTag>
+{
+   private:
+   BOOST_COPYABLE_AND_MOVABLE(allocator_argument_tester)
+
+   public:
+
+   typedef uses_allocator_base<ConstructionType, AllocatorTag> base_type;
+
+   //0 user argument constructors
+   allocator_argument_tester()
+      : construction_type(NotUsesAllocator), value(0)
+   {}
+
+   explicit allocator_argument_tester
+      (typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(0)
+   {}
+
+   explicit allocator_argument_tester
+      (typename base_type::allocator_arg_type, typename base_type::allocator_constructor_type)
+      : construction_type(ConstructiblePrefix), value(0)
+   {}
+
+   //1 user argument constructors
+   explicit allocator_argument_tester(int i)
+      : construction_type(NotUsesAllocator), value(i)
+   {}
+
+   allocator_argument_tester
+      (int i, typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(i)
+   {}
+
+   allocator_argument_tester
+      ( typename base_type::allocator_arg_type
+      , typename base_type::allocator_constructor_type
+      , int i)
+      : construction_type(ConstructiblePrefix), value(i)
+   {}
+
+   //Copy constructors
+   allocator_argument_tester(const allocator_argument_tester &other)
+      : construction_type(NotUsesAllocator), value(other.value)
+   {}
+
+   allocator_argument_tester( const allocator_argument_tester &other
+                            , typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(other.value)
+   {}
+
+   allocator_argument_tester( typename base_type::allocator_arg_type
+                            , typename base_type::allocator_constructor_type
+                            , const allocator_argument_tester &other)
+      : construction_type(ConstructiblePrefix), value(other.value)
+   {}
+
+   //Move constructors
+   allocator_argument_tester(BOOST_RV_REF(allocator_argument_tester) other)
+      : construction_type(NotUsesAllocator), value(other.value)
+   {  other.value = 0;  other.construction_type = NotUsesAllocator;  }
+
+   allocator_argument_tester( BOOST_RV_REF(allocator_argument_tester) other
+                            , typename base_type::allocator_constructor_type)
+      : construction_type(ConstructibleSuffix), value(other.value)
+   {  other.value = 0;  other.construction_type = ConstructibleSuffix;  }
+
+   allocator_argument_tester( typename base_type::allocator_arg_type
+                            , typename base_type::allocator_constructor_type
+                            , BOOST_RV_REF(allocator_argument_tester) other)
+      : construction_type(ConstructiblePrefix), value(other.value)
+   {  other.value = 0;  other.construction_type = ConstructiblePrefix;  }
+
+   ConstructionTypeEnum construction_type;
+   int                  value;
+};
+
+namespace boost {
+namespace container {
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+   < ::allocator_argument_tester<ConstructiblePrefix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_prefix
+   < ::allocator_argument_tester<ErasedTypePrefix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+   < ::allocator_argument_tester<ConstructibleSuffix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+template<unsigned int AllocatorTag>
+struct constructible_with_allocator_suffix
+   < ::allocator_argument_tester<ErasedTypeSuffix, AllocatorTag> >
+{
+   static const bool value = true;
+};
+
+}  //namespace container {
+}  //namespace boost {
+
+#endif   //BOOST_CONTAINER_TEST_ALLOCATOR_ARGUMENT_TESTER_HPP
diff --git a/test/resource_adaptor_test.cpp b/test/resource_adaptor_test.cpp
new file mode 100644
index 0000000..412d471
--- /dev/null
+++ b/test/resource_adaptor_test.cpp
@@ -0,0 +1,190 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/pmr/resource_adaptor.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "propagation_test_allocator.hpp"
+#include "derived_from_memory_resource.hpp"
+
+using namespace boost::container::pmr;
+
+void test_default_constructor()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   resource_adaptor<alloc_t> ra;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+}
+
+void test_copy_constructor()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   resource_adaptor<alloc_t> ra;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   resource_adaptor<alloc_t> rb(ra);
+   BOOST_TEST(rb.get_allocator().m_default_contructed == false);
+   BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+}
+
+void test_move_constructor()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   resource_adaptor<alloc_t> ra;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   resource_adaptor<alloc_t> rb(::boost::move(ra));
+   BOOST_TEST(rb.get_allocator().m_default_contructed == false);
+   BOOST_TEST(rb.get_allocator().m_move_contructed == true);
+}
+
+void test_lvalue_alloc_constructor()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   alloc_t a;
+   resource_adaptor<alloc_t> ra(a);
+   BOOST_TEST(ra.get_allocator().m_default_contructed == false);
+   BOOST_TEST(ra.get_allocator().m_move_contructed == false);
+}
+
+void test_rvalue_alloc_constructor()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   alloc_t a;
+   resource_adaptor<alloc_t> ra(::boost::move(a));
+   BOOST_TEST(ra.get_allocator().m_default_contructed == false);
+   BOOST_TEST(ra.get_allocator().m_move_contructed == true);
+}
+
+void test_copy_assign()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   resource_adaptor<alloc_t> ra;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   resource_adaptor<alloc_t> rb;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   rb = ra;
+   BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+   BOOST_TEST(rb.get_allocator().m_move_assigned == false);
+}
+
+void test_move_assign()
+{
+   typedef propagation_test_allocator<char, 0> alloc_t;
+   resource_adaptor<alloc_t> ra;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   resource_adaptor<alloc_t> rb;
+   BOOST_TEST(ra.get_allocator().m_default_contructed == true);
+   rb = ::boost::move(ra);
+   BOOST_TEST(rb.get_allocator().m_move_contructed == false);
+   BOOST_TEST(rb.get_allocator().m_move_assigned == true);
+}
+
+struct stateful
+{
+   public:
+   typedef char value_type;
+
+   template<class U>
+   struct rebind
+   {  typedef stateful other; };
+
+   stateful()
+      : m_u(0u)
+   {}
+
+   char *allocate(std::size_t n)
+   {  allocate_size = n;   return allocate_return;  }
+
+   void deallocate(char *p, std::size_t n)
+   {  deallocate_p = p;    deallocate_size = n; }
+
+   friend bool operator==(const stateful &l, const stateful &r)
+   {  return l.m_u == r.m_u;   }
+
+   friend bool operator!=(const stateful &l, const stateful &r)
+   {  return l.m_u != r.m_u;   }
+
+   public:
+   unsigned m_u;
+   std::size_t allocate_size;
+   char *allocate_return;
+   std::size_t deallocate_size;
+   char *deallocate_p;
+};
+
+void test_get_allocator()
+{
+   stateful a;
+   a.m_u = 999;
+   resource_adaptor<stateful> ra(a);
+   const resource_adaptor<stateful> & cra = ra;
+   BOOST_TEST( ra.get_allocator().m_u == 999);
+   BOOST_TEST(cra.get_allocator().m_u == 999);
+}
+
+typedef resource_adaptor<stateful> stateful_resource_adaptor_t;
+
+struct derived_from_resource_adaptor_stateful
+   : public stateful_resource_adaptor_t
+{
+   public:
+   typedef stateful_resource_adaptor_t base_t;
+   using base_t::do_allocate;
+   using base_t::do_deallocate;
+   using base_t::do_is_equal;
+};
+
+void test_do_allocate()
+{
+   derived_from_resource_adaptor_stateful dra;
+   char dummy = 0;
+   dra.get_allocator().allocate_return = &dummy;
+   void *allocate_ret = dra.do_allocate(998, 1234);
+   BOOST_TEST(allocate_ret == &dummy);
+   BOOST_TEST(dra.get_allocator().allocate_size == 998);
+}
+
+void test_do_deallocate()
+{
+   derived_from_resource_adaptor_stateful dra;
+   char dummy = 0;
+   dra.do_deallocate(&dummy, 1234, 753);
+   BOOST_TEST(dra.get_allocator().deallocate_p == &dummy);
+   BOOST_TEST(dra.get_allocator().deallocate_size == 1234);
+}
+
+void test_do_is_equal()
+{
+   derived_from_resource_adaptor_stateful dra;
+   derived_from_memory_resource dmr;
+   //Different dynamic type must return false
+   BOOST_TEST(dra.do_is_equal(dmr) == false);
+
+   //Same dynamic type with same state must return true
+   derived_from_resource_adaptor_stateful dra2;
+   BOOST_TEST(dra.do_is_equal(dra2) == true);
+
+   //Same dynamic type with different state must return false
+   dra2.get_allocator().m_u = 1234;
+   BOOST_TEST(dra.do_is_equal(dra2) == false);
+}
+
+int main()
+{
+   test_default_constructor();
+   test_copy_constructor();
+   test_move_constructor();
+   test_lvalue_alloc_constructor();
+   test_rvalue_alloc_constructor();
+   test_copy_assign();
+   test_move_assign();
+   test_get_allocator();
+   test_do_allocate();
+   test_do_deallocate();
+   test_do_is_equal();
+   return ::boost::report_errors();
+}
diff --git a/test/scoped_allocator_adaptor_test.cpp b/test/scoped_allocator_adaptor_test.cpp
new file mode 100644
index 0000000..6a051e2
--- /dev/null
+++ b/test/scoped_allocator_adaptor_test.cpp
@@ -0,0 +1,1377 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/scoped_allocator_fwd.hpp>
+
+// container/detail
+#include <boost/container/detail/mpl.hpp>
+// move
+#include <boost/move/utility_core.hpp>
+#include <boost/move/adl_move_swap.hpp>
+//boost
+#include <boost/tuple/tuple.hpp>
+// std
+#include <memory>
+#include <cstddef>
+
+#if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+#include <tuple>
+#endif
+
+//test
+#include <boost/core/lightweight_test.hpp>
+
+#include "allocator_argument_tester.hpp"
+
+template<unsigned int Type>
+struct tagged_integer
+{};
+
+struct mark_on_destructor
+{
+   mark_on_destructor()
+   {
+      destroyed = false;
+   }
+
+   ~mark_on_destructor()
+   {
+      destroyed = true;
+   }
+
+   static bool destroyed;
+};
+
+bool mark_on_destructor::destroyed = false;
+
+#include <boost/container/scoped_allocator.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/detail/pair.hpp>
+
+int main()
+{
+   using namespace boost::container;
+
+   typedef propagation_test_allocator<tagged_integer<0>, 0>   OuterAlloc;
+   typedef propagation_test_allocator<tagged_integer<0>, 10>  Outer10IdAlloc;
+   typedef propagation_test_allocator<tagged_integer<9>, 0>   Rebound9OuterAlloc;
+   typedef propagation_test_allocator<tagged_integer<1>, 1>   InnerAlloc1;
+   typedef propagation_test_allocator<tagged_integer<2>, 2>   InnerAlloc2;
+   typedef propagation_test_allocator<tagged_integer<1>, 11>  Inner11IdAlloc1;
+
+   typedef propagation_test_allocator<tagged_integer<0>, 0, false>      OuterAllocFalseHasTrueTypes;
+   typedef propagation_test_allocator<tagged_integer<0>, 0, true>       OuterAllocTrueHasTrueTypes;
+   typedef propagation_test_allocator<tagged_integer<1>, 1, false>      InnerAlloc1FalseHasTrueTypes;
+   typedef propagation_test_allocator<tagged_integer<1>, 1, true>       InnerAlloc1TrueHasTrueTypes;
+   typedef propagation_test_allocator<tagged_integer<2>, 2, false>      InnerAlloc2FalseHasTrueTypes;
+   typedef propagation_test_allocator<tagged_integer<2>, 2, true>       InnerAlloc2TrueHasTrueTypes;
+
+   //
+   typedef scoped_allocator_adaptor< OuterAlloc  >          Scoped0Inner;
+   typedef scoped_allocator_adaptor< OuterAlloc
+                                   , InnerAlloc1 >          Scoped1Inner;
+   typedef scoped_allocator_adaptor< OuterAlloc
+                                   , InnerAlloc1
+                                   , InnerAlloc2 >          Scoped2Inner;
+   typedef scoped_allocator_adaptor
+      < scoped_allocator_adaptor
+         <Outer10IdAlloc>
+      >                                                     ScopedScoped0Inner;
+   typedef scoped_allocator_adaptor
+      < scoped_allocator_adaptor
+         <Outer10IdAlloc, Inner11IdAlloc1>
+      , InnerAlloc1
+      >                                                     ScopedScoped1Inner;
+   typedef scoped_allocator_adaptor< Rebound9OuterAlloc  >  Rebound9Scoped0Inner;
+   typedef scoped_allocator_adaptor< Rebound9OuterAlloc
+                                   , InnerAlloc1 >          Rebound9Scoped1Inner;
+   typedef scoped_allocator_adaptor< Rebound9OuterAlloc
+                                   , InnerAlloc1
+                                   , InnerAlloc2 >          Rebound9Scoped2Inner;
+
+   //outer_allocator_type
+   BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+                       , Scoped0Inner::outer_allocator_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+                       , Scoped1Inner::outer_allocator_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< OuterAlloc
+                       , Scoped2Inner::outer_allocator_type>::value ));
+   //value_type
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+                       , Scoped0Inner::value_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+                       , Scoped1Inner::value_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::value_type
+                       , Scoped2Inner::value_type>::value ));
+   //size_type
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+                       , Scoped0Inner::size_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+                       , Scoped1Inner::size_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::size_type
+                       , Scoped2Inner::size_type>::value ));
+
+   //difference_type
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+                       , Scoped0Inner::difference_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+                       , Scoped1Inner::difference_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::difference_type
+                       , Scoped2Inner::difference_type>::value ));
+
+   //pointer
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+                       , Scoped0Inner::pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+                       , Scoped1Inner::pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::pointer
+                       , Scoped2Inner::pointer>::value ));
+
+   //const_pointer
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+                       , Scoped0Inner::const_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+                       , Scoped1Inner::const_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_pointer
+                       , Scoped2Inner::const_pointer>::value ));
+
+   //void_pointer
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+                       , Scoped0Inner::void_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+                       , Scoped1Inner::void_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::void_pointer
+                       , Scoped2Inner::void_pointer>::value ));
+
+   //const_void_pointer
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+                       , Scoped0Inner::const_void_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+                       , Scoped1Inner::const_void_pointer>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< allocator_traits<OuterAlloc>::const_void_pointer
+                       , Scoped2Inner::const_void_pointer>::value ));
+
+   //rebind
+   BOOST_STATIC_ASSERT(( dtl::is_same<Scoped0Inner::rebind< tagged_integer<9> >::other
+                       , Rebound9Scoped0Inner >::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<Scoped1Inner::rebind< tagged_integer<9> >::other
+                       , Rebound9Scoped1Inner >::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same<Scoped2Inner::rebind< tagged_integer<9> >::other
+                       , Rebound9Scoped2Inner >::value ));
+
+   //inner_allocator_type
+   BOOST_STATIC_ASSERT(( dtl::is_same< Scoped0Inner
+                       , Scoped0Inner::inner_allocator_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< scoped_allocator_adaptor<InnerAlloc1>
+                       , Scoped1Inner::inner_allocator_type>::value ));
+   BOOST_STATIC_ASSERT(( dtl::is_same< scoped_allocator_adaptor<InnerAlloc1, InnerAlloc2>
+                       , Scoped2Inner::inner_allocator_type>::value ));
+
+   {
+      //Propagation test
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes  >  Scoped0InnerF;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes  >   Scoped0InnerT;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes >  Scoped1InnerFF;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes >   Scoped1InnerFT;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes >  Scoped1InnerTF;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes >   Scoped1InnerTT;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes
+                                    , InnerAlloc2FalseHasTrueTypes >  Scoped2InnerFFF;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes
+                                    , InnerAlloc2TrueHasTrueTypes >  Scoped2InnerFFT;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes
+                                    , InnerAlloc2FalseHasTrueTypes >  Scoped2InnerFTF;
+      typedef scoped_allocator_adaptor< OuterAllocFalseHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes
+                                    , InnerAlloc2TrueHasTrueTypes >  Scoped2InnerFTT;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes
+                                    , InnerAlloc2FalseHasTrueTypes >  Scoped2InnerTFF;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1FalseHasTrueTypes
+                                    , InnerAlloc2TrueHasTrueTypes >  Scoped2InnerTFT;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes
+                                    , InnerAlloc2FalseHasTrueTypes >  Scoped2InnerTTF;
+      typedef scoped_allocator_adaptor< OuterAllocTrueHasTrueTypes
+                                    , InnerAlloc1TrueHasTrueTypes
+                                    , InnerAlloc2TrueHasTrueTypes >  Scoped2InnerTTT;
+
+      //propagate_on_container_copy_assignment
+      //0 inner
+      BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped0InnerT::propagate_on_container_copy_assignment::value ));
+      //1 inner
+      BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerFT::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTT::propagate_on_container_copy_assignment::value ));
+      //2 inner
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFFT::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTT::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFT::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTF::propagate_on_container_copy_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTT::propagate_on_container_copy_assignment::value ));
+
+      //propagate_on_container_move_assignment
+      //0 inner
+      BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped0InnerT::propagate_on_container_move_assignment::value ));
+      //1 inner
+      BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerFT::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTT::propagate_on_container_move_assignment::value ));
+      //2 inner
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFFT::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTT::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFT::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTF::propagate_on_container_move_assignment::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTT::propagate_on_container_move_assignment::value ));
+
+      //propagate_on_container_swap
+      //0 inner
+      BOOST_STATIC_ASSERT(( !Scoped0InnerF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped0InnerT::propagate_on_container_swap::value ));
+      //1 inner
+      BOOST_STATIC_ASSERT(( !Scoped1InnerFF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerFT::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTT::propagate_on_container_swap::value ));
+      //2 inner
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFFT::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerFTT::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTFT::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTF::propagate_on_container_swap::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTT::propagate_on_container_swap::value ));
+      //is_always_equal
+      //0 inner
+      BOOST_STATIC_ASSERT(( !Scoped0InnerF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT((  Scoped0InnerT::is_always_equal::value ));
+      //1 inner
+      BOOST_STATIC_ASSERT(( !Scoped1InnerFF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped1InnerFT::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped1InnerTF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT((  Scoped1InnerTT::is_always_equal::value ));
+      //2 inner
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFFF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFFT::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFTF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerFTT::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerTFF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerTFT::is_always_equal::value ));
+      BOOST_STATIC_ASSERT(( !Scoped2InnerTTF::is_always_equal::value ));
+      BOOST_STATIC_ASSERT((  Scoped2InnerTTT::is_always_equal::value ));
+   }
+
+   //Default constructor
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+      //Swap
+      {
+         Scoped0Inner s0i2;
+         Scoped1Inner s1i2;
+         boost::adl_move_swap(s0i, s0i2);
+         boost::adl_move_swap(s1i, s1i2);
+      }
+   }
+
+   //Default constructor
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+   }
+
+   //Copy constructor/assignment
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+      Scoped2Inner s2i;
+
+      Scoped0Inner s0i_b(s0i);
+      Scoped1Inner s1i_b(s1i);
+      Scoped2Inner s2i_b(s2i);
+
+      BOOST_TEST(s0i == s0i_b);
+      BOOST_TEST(s1i == s1i_b);
+      BOOST_TEST(s2i == s2i_b);
+
+      s0i_b = s0i;
+      s1i_b = s1i;
+      s2i_b = s2i;
+
+      BOOST_TEST(s0i == s0i_b);
+      BOOST_TEST(s1i == s1i_b);
+      BOOST_TEST(s2i == s2i_b);
+   }
+
+   //Copy/move constructor/assignment
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+      Scoped2Inner s2i;
+
+      Scoped0Inner s0i_b(::boost::move(s0i));
+      Scoped1Inner s1i_b(::boost::move(s1i));
+      Scoped2Inner s2i_b(::boost::move(s2i));
+
+      BOOST_TEST(s0i_b.outer_allocator().m_move_contructed);
+      BOOST_TEST(s1i_b.outer_allocator().m_move_contructed);
+      BOOST_TEST(s2i_b.outer_allocator().m_move_contructed);
+
+      s0i_b = ::boost::move(s0i);
+      s1i_b = ::boost::move(s1i);
+      s2i_b = ::boost::move(s2i);
+
+      BOOST_TEST(s0i_b.outer_allocator().m_move_assigned);
+      BOOST_TEST(s1i_b.outer_allocator().m_move_assigned);
+      BOOST_TEST(s2i_b.outer_allocator().m_move_assigned);
+   }
+
+   //inner_allocator()
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+      Scoped2Inner s2i;
+      const Scoped0Inner const_s0i;
+      const Scoped1Inner const_s1i;
+      const Scoped2Inner const_s2i;
+
+      Scoped0Inner::inner_allocator_type &s0i_inner =             s0i.inner_allocator();
+      (void)s0i_inner;
+      const Scoped0Inner::inner_allocator_type &const_s0i_inner = const_s0i.inner_allocator();
+      (void)const_s0i_inner;
+      Scoped1Inner::inner_allocator_type &s1i_inner =             s1i.inner_allocator();
+      (void)s1i_inner;
+      const Scoped1Inner::inner_allocator_type &const_s1i_inner = const_s1i.inner_allocator();
+      (void)const_s1i_inner;
+      Scoped2Inner::inner_allocator_type &s2i_inner =             s2i.inner_allocator();
+      (void)s2i_inner;
+      const Scoped2Inner::inner_allocator_type &const_s2i_inner = const_s2i.inner_allocator();
+      (void)const_s2i_inner;
+   }
+
+   //operator==/!=
+   {
+      const Scoped0Inner const_s0i;
+      const Rebound9Scoped0Inner const_rs0i;
+
+      BOOST_TEST(const_s0i == const_s0i);
+      BOOST_TEST(const_rs0i == const_s0i);
+      BOOST_TEST(const_s0i == const_s0i);
+      BOOST_TEST(const_s0i == const_rs0i);
+
+      const Scoped1Inner const_s1i;
+      const Rebound9Scoped1Inner const_rs1i;
+
+      BOOST_TEST(const_s1i == const_s1i);
+      BOOST_TEST(const_rs1i == const_s1i);
+
+      BOOST_TEST(const_s1i == const_s1i);
+      BOOST_TEST(const_s1i == const_rs1i);
+
+      const Scoped2Inner const_s2i;
+      const Rebound9Scoped2Inner const_rs2i;
+
+      BOOST_TEST(const_s2i == const_s2i);
+      BOOST_TEST(const_s2i == const_rs2i);
+
+      BOOST_TEST(const_s2i == const_s2i);
+      BOOST_TEST(const_s2i == const_rs2i);
+   }
+
+   //outer_allocator()
+   {
+      Scoped0Inner s0i;
+      Scoped1Inner s1i;
+      Scoped2Inner s2i;
+      const Scoped0Inner const_s0i;
+      const Scoped1Inner const_s1i;
+      const Scoped2Inner const_s2i;
+
+      Scoped0Inner::outer_allocator_type &s0i_inner =             s0i.outer_allocator();
+      (void)s0i_inner;
+      const Scoped0Inner::outer_allocator_type &const_s0i_inner = const_s0i.outer_allocator();
+      (void)const_s0i_inner;
+      Scoped1Inner::outer_allocator_type &s1i_inner =             s1i.outer_allocator();
+      (void)s1i_inner;
+      const Scoped1Inner::outer_allocator_type &const_s1i_inner = const_s1i.outer_allocator();
+      (void)const_s1i_inner;
+      Scoped2Inner::outer_allocator_type &s2i_inner =             s2i.outer_allocator();
+      (void)s2i_inner;
+      const Scoped2Inner::outer_allocator_type &const_s2i_inner = const_s2i.outer_allocator();
+      (void)const_s2i_inner;
+   }
+
+   //max_size()
+   {
+      const Scoped0Inner const_s0i;
+      const Scoped1Inner const_s1i;
+      const Scoped2Inner const_s2i;
+      const OuterAlloc  const_oa;
+      const InnerAlloc1 const_ia1;
+      const InnerAlloc2 const_ia2;
+
+      BOOST_TEST(const_s0i.max_size() == const_oa.max_size());
+      BOOST_TEST(const_s1i.max_size() == const_oa.max_size());
+
+      BOOST_TEST(const_s2i.max_size() == const_oa.max_size());
+      BOOST_TEST(const_s1i.inner_allocator().max_size() == const_ia1.max_size());
+      BOOST_TEST(const_s2i.inner_allocator().inner_allocator().max_size() == const_ia2.max_size());
+   }
+   //Copy and move operations
+   {
+      //Construction
+      {
+         Scoped0Inner s0i_a, s0i_b(s0i_a), s0i_c(::boost::move(s0i_b));
+         Scoped1Inner s1i_a, s1i_b(s1i_a), s1i_c(::boost::move(s1i_b));
+         Scoped2Inner s2i_a, s2i_b(s2i_a), s2i_c(::boost::move(s2i_b));
+      }
+      //Assignment
+      {
+         Scoped0Inner s0i_a, s0i_b;
+         s0i_a = s0i_b;
+         s0i_a = ::boost::move(s0i_b);
+         Scoped1Inner s1i_a, s1i_b;
+         s1i_a = s1i_b;
+         s1i_a = ::boost::move(s1i_b);
+         Scoped2Inner s2i_a, s2i_b;
+         s2i_a = s2i_b;
+         s2i_a = ::boost::move(s2i_b);
+      }
+
+      OuterAlloc  oa;
+      InnerAlloc1 ia1;
+      InnerAlloc2 ia2;
+      Rebound9OuterAlloc roa;
+      Rebound9Scoped0Inner rs0i;
+      Rebound9Scoped1Inner rs1i;
+      Rebound9Scoped2Inner rs2i;
+
+      //Copy from outer
+      {
+         Scoped0Inner s0i(oa);
+         Scoped1Inner s1i(oa, ia1);
+         Scoped2Inner s2i(oa, ia1, ia2);
+      }
+      //Move from outer
+      {
+         Scoped0Inner s0i(::boost::move(oa));
+         Scoped1Inner s1i(::boost::move(oa), ia1);
+         Scoped2Inner s2i(::boost::move(oa), ia1, ia2);
+      }
+      //Copy from rebound outer
+      {
+         Scoped0Inner s0i(roa);
+         Scoped1Inner s1i(roa, ia1);
+         Scoped2Inner s2i(roa, ia1, ia2);
+      }
+      //Move from rebound outer
+      {
+         Scoped0Inner s0i(::boost::move(roa));
+         Scoped1Inner s1i(::boost::move(roa), ia1);
+         Scoped2Inner s2i(::boost::move(roa), ia1, ia2);
+      }
+      //Copy from rebound scoped
+      {
+         Scoped0Inner s0i(rs0i);
+         Scoped1Inner s1i(rs1i);
+         Scoped2Inner s2i(rs2i);
+      }
+      //Move from rebound scoped
+      {
+         Scoped0Inner s0i(::boost::move(rs0i));
+         Scoped1Inner s1i(::boost::move(rs1i));
+         Scoped2Inner s2i(::boost::move(rs2i));
+      }
+   }
+
+   {
+      vector<int, scoped_allocator_adaptor< propagation_test_allocator<int, 0> > > dummy;
+      dummy.push_back(0);
+   }
+
+   //destroy()
+   {
+      {
+         Scoped0Inner s0i;
+         mark_on_destructor mod;
+         s0i.destroy(&mod);
+         BOOST_TEST(mark_on_destructor::destroyed);
+      }
+
+      {
+         Scoped1Inner s1i;
+         mark_on_destructor mod;
+         s1i.destroy(&mod);
+         BOOST_TEST(mark_on_destructor::destroyed);
+      }
+      {
+         Scoped2Inner s2i;
+         mark_on_destructor mod;
+         s2i.destroy(&mod);
+         BOOST_TEST(mark_on_destructor::destroyed);
+      }
+   }
+
+   //construct
+   {
+      ////////////////////////////////////////////////////////////
+      //First check scoped allocator with just OuterAlloc.
+      //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+      //used to construct types.
+      ////////////////////////////////////////////////////////////
+      {
+         Scoped0Inner s0i;
+         //Check construction with 0 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0 );
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+
+         //Check construction with 1 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy, 1);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 1);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy, 2);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 2);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s0i.construct(&dummy, 3);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 3);
+            dummy.~MarkType();
+         }
+      }
+      ////////////////////////////////////////////////////////////
+      //Then check scoped allocator with OuterAlloc and InnerAlloc.
+      //In this case InnerAlloc (propagation_test_allocator with tag 1) should be
+      //used to construct types.
+      ////////////////////////////////////////////////////////////
+      {
+         Scoped1Inner s1i;
+         //Check construction with 0 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+
+         //Check construction with 1 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy, 1);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 1);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy, 2);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 2);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 1> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            s1i.construct(&dummy, 3);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 3);
+            dummy.~MarkType();
+         }
+      }
+
+      //////////////////////////////////////////////////////////////////////////////////
+      //Now test recursive OuterAllocator types (OuterAllocator is a scoped_allocator)
+      //////////////////////////////////////////////////////////////////////////////////
+
+      ////////////////////////////////////////////////////////////
+      //First check scoped allocator with just OuterAlloc.
+      //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+      //used to construct types.
+      ////////////////////////////////////////////////////////////
+      {
+         //Check outer_allocator_type is scoped
+         BOOST_STATIC_ASSERT(( is_scoped_allocator
+            <ScopedScoped0Inner::outer_allocator_type>::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < outermost_allocator<ScopedScoped0Inner>::type
+            , Outer10IdAlloc
+            >::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < ScopedScoped0Inner::outer_allocator_type
+            , scoped_allocator_adaptor<Outer10IdAlloc>
+            >::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < scoped_allocator_adaptor<Outer10IdAlloc>::outer_allocator_type
+            , Outer10IdAlloc
+            >::value ));
+         ScopedScoped0Inner ssro0i;
+         Outer10IdAlloc & val = outermost_allocator<ScopedScoped0Inner>::get(ssro0i);
+         (void)val;
+         //Check construction with 0 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+
+         //Check construction with 1 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy, 1);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 1);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy, 2);
+            BOOST_TEST(dummy.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.value == 2);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro0i.construct(&dummy, 3);
+            BOOST_TEST(dummy.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.value == 3);
+            dummy.~MarkType();
+         }
+      }
+      ////////////////////////////////////////////////////////////
+      //Then check scoped allocator with OuterAlloc and InnerAlloc.
+      //In this case inner_allocator_type is not convertible to
+      //::allocator_argument_tester<XXX, 10> so uses_allocator
+      //should be false on all tests.
+      ////////////////////////////////////////////////////////////
+      {
+         //Check outer_allocator_type is scoped
+         BOOST_STATIC_ASSERT(( is_scoped_allocator
+            <ScopedScoped1Inner::outer_allocator_type>::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < outermost_allocator<ScopedScoped1Inner>::type
+            , Outer10IdAlloc
+            >::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < ScopedScoped1Inner::outer_allocator_type
+            , scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>
+            >::value ));
+         BOOST_STATIC_ASSERT(( dtl::is_same
+            < scoped_allocator_adaptor<Outer10IdAlloc, Inner11IdAlloc1>::outer_allocator_type
+            , Outer10IdAlloc
+            >::value ));
+         BOOST_STATIC_ASSERT(( !
+            uses_allocator
+               < ::allocator_argument_tester<ConstructibleSuffix, 10>
+               , ScopedScoped1Inner::inner_allocator_type::outer_allocator_type
+               >::value ));
+         ScopedScoped1Inner ssro1i;
+         Outer10IdAlloc & val = outermost_allocator<ScopedScoped1Inner>::get(ssro1i);
+         (void)val;
+
+         //Check construction with 0 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 0);
+            dummy.~MarkType();
+         }
+
+         //Check construction with 1 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy, 1);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 1);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy, 2);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 2);
+            dummy.~MarkType();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 10> MarkType;
+            MarkType dummy;
+            dummy.~MarkType();
+            ssro1i.construct(&dummy, 3);
+            BOOST_TEST(dummy.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.value == 3);
+            dummy.~MarkType();
+         }
+      }
+
+      ////////////////////////////////////////////////////////////
+      //Now check propagation to pair
+      ////////////////////////////////////////////////////////////
+      //First check scoped allocator with just OuterAlloc.
+      //In this case OuterAlloc (propagation_test_allocator with tag 0) should be
+      //used to construct types.
+      ////////////////////////////////////////////////////////////
+      {
+         using dtl::pair;
+         typedef propagation_test_allocator< pair< tagged_integer<0>
+                               , tagged_integer<0> >, 0> OuterPairAlloc;
+         //
+         typedef scoped_allocator_adaptor < OuterPairAlloc  >  ScopedPair0Inner;
+
+         ScopedPair0Inner s0i;
+         //Check construction with 0 user arguments
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy);
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+         //Check construction with 0 user arguments and Std tuple
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         #endif   //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+         //Check construction with 1 user arguments for each pair
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, 1, 1);
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, 1, 1);
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, 2, 2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         //Check construction with 1 user arguments for each pair and Boost tuple
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(2), boost::tuple<int>(2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+         //Check construction with 1 user arguments for each pair and Boost tuple
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<int>(2), std::tuple<int>(2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         #endif   //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+         //Check construction with pair copy construction
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2(1, 1);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2(2, 2);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         //Check construction with pair move construction
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2(3, 3);
+            dummy2.first.construction_type = dummy2.second.construction_type = ConstructibleSuffix;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 3);
+            BOOST_TEST(dummy.second.value == 3);
+            BOOST_TEST(dummy2.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy2.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy2.first.value  == 0);
+            BOOST_TEST(dummy2.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2(1, 1);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            BOOST_TEST(dummy2.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy2.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy2.first.value  == 0);
+            BOOST_TEST(dummy2.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy, dummy2(2, 2);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            BOOST_TEST(dummy2.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy2.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy2.first.value  == 0);
+            BOOST_TEST(dummy2.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         //Check construction with related pair copy construction
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2(1, 1);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2(2, 2);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, dummy2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         //Check construction with related pair move construction
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2(3, 3);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 3);
+            BOOST_TEST(dummy.second.value == 3);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2(1, 1);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            pair<int, int> dummy2(2, 2);
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, ::boost::move(dummy2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 2);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         //Check construction with 0/1 arguments for each pair and Boost tuple
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<int>(1), boost::tuple<>());
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, boost::tuple<>(), boost::tuple<int>(2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         #if defined(BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE)
+         //Check construction with 0/1 arguments for each pair and Boost tuple
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<int>(1));
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<int>(1), std::tuple<>());
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 1);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, piecewise_construct, std::tuple<>(), std::tuple<int>(2));
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 0);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+         #endif   //BOOST_CONTAINER_PAIR_TEST_HAS_HEADER_TUPLE
+
+         //Check construction with try_emplace_t 0/1 arguments for each pair
+         {
+            typedef ::allocator_argument_tester<NotUsesAllocator, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, try_emplace_t(), 5, 1);
+            BOOST_TEST(dummy.first.construction_type  == NotUsesAllocator);
+            BOOST_TEST(dummy.second.construction_type == NotUsesAllocator);
+            BOOST_TEST(dummy.first.value  == 5);
+            BOOST_TEST(dummy.second.value == 1);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructibleSuffix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, try_emplace_t(), 6);
+            BOOST_TEST(dummy.first.construction_type  == ConstructibleSuffix);
+            BOOST_TEST(dummy.second.construction_type == ConstructibleSuffix);
+            BOOST_TEST(dummy.first.value  == 6);
+            BOOST_TEST(dummy.second.value == 0);
+            dummy.~MarkTypePair();
+         }
+         {
+            typedef ::allocator_argument_tester<ConstructiblePrefix, 0> MarkType;
+            typedef pair<MarkType, MarkType> MarkTypePair;
+            MarkTypePair dummy;
+            dummy.~MarkTypePair();
+            s0i.construct(&dummy, try_emplace_t(), 7, 2);
+            BOOST_TEST(dummy.first.construction_type  == ConstructiblePrefix);
+            BOOST_TEST(dummy.second.construction_type == ConstructiblePrefix);
+            BOOST_TEST(dummy.first.value  == 7);
+            BOOST_TEST(dummy.second.value == 2);
+            dummy.~MarkTypePair();
+         }
+      }
+   }
+
+   return ::boost::report_errors();
+}
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/scoped_allocator_usage_test.cpp b/test/scoped_allocator_usage_test.cpp
new file mode 100644
index 0000000..6eb1438
--- /dev/null
+++ b/test/scoped_allocator_usage_test.cpp
@@ -0,0 +1,428 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/deque.hpp>
+#include <boost/container/list.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/container/map.hpp>
+#include <boost/container/set.hpp>
+#include <boost/container/detail/mpl.hpp>
+
+#include <boost/container/scoped_allocator.hpp>
+
+template <typename Ty>
+class SimpleAllocator
+{
+public:
+   typedef Ty value_type;
+
+   explicit SimpleAllocator(int value)
+      : m_state(value)
+   {}
+
+   template <typename T>
+   SimpleAllocator(const SimpleAllocator<T> &other)
+      : m_state(other.m_state)
+   {}
+
+   Ty* allocate(std::size_t n)
+   {
+      return m_allocator.allocate(n);
+   }
+
+   void deallocate(Ty* p, std::size_t n)
+   {
+      m_allocator.deallocate(p, n);
+   }
+
+   int get_value() const
+   {  return m_state;   }
+
+   private:
+   int m_state;
+   std::allocator<Ty> m_allocator;
+
+   template <typename T> friend class SimpleAllocator;
+
+   friend bool operator == (const SimpleAllocator &, const SimpleAllocator &)
+   {  return true;  }
+
+   friend bool operator != (const SimpleAllocator &, const SimpleAllocator &)
+   {  return false;  }
+};
+
+class alloc_int
+{
+   private: // Not copyable
+
+   BOOST_MOVABLE_BUT_NOT_COPYABLE(alloc_int)
+
+   public:
+   typedef SimpleAllocator<int> allocator_type;
+
+   alloc_int(BOOST_RV_REF(alloc_int)other)
+      : m_value(other.m_value), m_allocator(boost::move(other.m_allocator))
+   {
+      other.m_value = -1;
+   }
+
+   alloc_int(BOOST_RV_REF(alloc_int)other, const allocator_type &allocator)
+      : m_value(other.m_value), m_allocator(allocator)
+   {
+      other.m_value = -1;
+   }
+
+   alloc_int(int value, const allocator_type &allocator)
+      : m_value(value), m_allocator(allocator)
+   {}
+
+   alloc_int & operator=(BOOST_RV_REF(alloc_int)other)
+   {
+      other.m_value = other.m_value;
+      return *this;
+   }
+
+   int get_allocator_state() const
+   {  return m_allocator.get_value();  }
+
+   int get_value() const
+   {  return m_value;   }
+
+   friend bool operator < (const alloc_int &l, const alloc_int &r)
+   {  return l.m_value < r.m_value;  }
+
+   friend bool operator == (const alloc_int &l, const alloc_int &r)
+   {  return l.m_value == r.m_value;  }
+
+   private:
+   int m_value;
+   allocator_type m_allocator;
+};
+
+using namespace ::boost::container;
+
+//general allocator
+typedef scoped_allocator_adaptor<SimpleAllocator<alloc_int> > AllocIntAllocator;
+
+//[multi]map/set
+typedef std::pair<const alloc_int, alloc_int> MapNode;
+typedef scoped_allocator_adaptor<SimpleAllocator<MapNode> > MapAllocator;
+typedef map<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> Map;
+typedef set<alloc_int, std::less<alloc_int>, AllocIntAllocator> Set;
+typedef multimap<alloc_int, alloc_int, std::less<alloc_int>, MapAllocator> MultiMap;
+typedef multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> MultiSet;
+
+//[multi]flat_map/set
+typedef std::pair<alloc_int, alloc_int> FlatMapNode;
+typedef scoped_allocator_adaptor<SimpleAllocator<FlatMapNode> > FlatMapAllocator;
+typedef flat_map<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMap;
+typedef flat_set<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatSet;
+typedef flat_multimap<alloc_int, alloc_int, std::less<alloc_int>, FlatMapAllocator> FlatMultiMap;
+typedef flat_multiset<alloc_int, std::less<alloc_int>, AllocIntAllocator> FlatMultiSet;
+
+//vector, deque, list, slist, stable_vector.
+typedef vector<alloc_int, AllocIntAllocator>          Vector;
+typedef deque<alloc_int, AllocIntAllocator>           Deque;
+typedef list<alloc_int, AllocIntAllocator>            List;
+typedef slist<alloc_int, AllocIntAllocator>           Slist;
+typedef stable_vector<alloc_int, AllocIntAllocator>   StableVector;
+typedef small_vector<alloc_int, 9, AllocIntAllocator> SmallVector;
+
+/////////
+//is_unique_assoc
+/////////
+
+template<class T>
+struct is_unique_assoc
+{
+   static const bool value = false;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_unique_assoc< map<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_unique_assoc< flat_map<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_unique_assoc< set<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_unique_assoc< flat_set<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+
+/////////
+//is_map
+/////////
+
+template<class T>
+struct is_map
+{
+   static const bool value = false;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< map<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< flat_map<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< multimap<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class T, class Compare, class Allocator>
+struct is_map< flat_multimap<Key, T, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class T>
+struct is_set
+{
+   static const bool value = false;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< set<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< flat_set<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< multiset<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+template<class Key, class Compare, class Allocator>
+struct is_set< flat_multiset<Key, Compare, Allocator> >
+{
+   static const bool value = true;
+};
+
+/////////
+//container_wrapper
+/////////
+
+//Try to define-allocator_aware requirements
+template< class Container
+        , bool Assoc = is_set<Container>::value || is_map<Container>::value
+        , bool UniqueAssoc = is_unique_assoc<Container>::value
+        , bool Map  = is_map<Container>::value
+        >
+struct container_wrapper_inserter
+{
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   template<class Arg>
+   static iterator emplace(Container &c, const_iterator p, const Arg &arg)
+   {  return c.emplace(p, arg);   }
+};
+
+template<class Container>  //map
+struct container_wrapper_inserter<Container, true, true, true>
+{
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   template<class Arg>
+   static iterator emplace(Container &c, const_iterator, const Arg &arg)
+   {  return c.emplace(arg, arg).first;   }
+};
+
+template<class Container>  //set
+struct container_wrapper_inserter<Container, true, true, false>
+{
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   template<class Arg>
+   static iterator emplace(Container &c, const_iterator, const Arg &arg)
+   {  return c.emplace(arg).first;  }
+};
+
+template<class Container>  //multimap
+struct container_wrapper_inserter<Container, true, false, true>
+{
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   template<class Arg>
+   static iterator emplace(Container &c, const_iterator, const Arg &arg)
+   {  return c.emplace(arg, arg);   }
+};
+
+//multiset
+template<class Container>  //multimap
+struct container_wrapper_inserter<Container, true, false, false>
+{
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   template<class Arg>
+   static iterator emplace(Container &c, const_iterator, const Arg &arg)
+   {  return c.emplace(arg);  }
+};
+
+template< class Container>
+struct container_wrapper
+   : public Container
+{
+   private:
+   BOOST_COPYABLE_AND_MOVABLE(container_wrapper)
+
+   public:
+   typedef typename Container::allocator_type   allocator_type;
+   typedef typename Container::const_iterator   const_iterator;
+   typedef typename Container::iterator         iterator;
+
+   container_wrapper(const allocator_type &a)
+      : Container(a)
+   {}
+
+   container_wrapper(BOOST_RV_REF(container_wrapper) o, const allocator_type &a)
+      : Container(BOOST_MOVE_BASE(Container, o), a)
+   {}
+
+   container_wrapper(const container_wrapper &o, const allocator_type &a)
+      : Container(o, a)
+   {}
+
+   template<class Arg>
+   iterator emplace(const_iterator p, const Arg &arg)
+   {  return container_wrapper_inserter<Container>::emplace(*this, p, arg);  }
+};
+
+
+bool test_value_and_state_equals(const alloc_int &r, int value, int state)
+{  return r.get_value() == value && r.get_allocator_state() == state;  }
+
+template<class F, class S>
+bool test_value_and_state_equals(const dtl::pair<F, S> &p, int value, int state)
+{  return test_value_and_state_equals(p.first, value, state) && test_alloc_state_equals(p.second, value, state);  }
+
+template<class F, class S>
+bool test_value_and_state_equals(const std::pair<F, S> &p, int value, int state)
+{  return test_value_and_state_equals(p.first, value, state) && test_value_and_state_equals(p.second, value, state);  }
+
+template<class Container>
+bool one_level_allocator_propagation_test()
+{
+   typedef container_wrapper<Container> ContainerWrapper;
+   typedef typename ContainerWrapper::iterator iterator;
+   typedef typename ContainerWrapper::allocator_type allocator_type;
+   typedef typename ContainerWrapper::value_type value_type;
+   {
+      allocator_type al(SimpleAllocator<value_type>(5));
+      ContainerWrapper c(al);
+
+      c.clear();
+      iterator it = c.emplace(c.cbegin(), 42);
+
+      if(!test_value_and_state_equals(*it, 42, 5))
+         return false;
+   }
+   {
+      allocator_type al(SimpleAllocator<value_type>(4));
+      ContainerWrapper c2(al);
+      ContainerWrapper c(::boost::move(c2), allocator_type(SimpleAllocator<value_type>(5)));
+
+      c.clear();
+      iterator it = c.emplace(c.cbegin(), 42);
+
+      if(!test_value_and_state_equals(*it, 42, 5))
+         return false;
+   }/*
+   {
+      ContainerWrapper c2(allocator_type(SimpleAllocator<value_type>(3)));
+      ContainerWrapper c(c2, allocator_type(SimpleAllocator<value_type>(5)));
+
+      c.clear();
+      iterator it = c.emplace(c.cbegin(), 42);
+
+      if(!test_value_and_state_equals(*it, 42, 5))
+         return false;
+   }*/
+   return true;
+}
+
+int main()
+{
+   //unique assoc
+   if(!one_level_allocator_propagation_test<FlatMap>())
+      return 1;
+   if(!one_level_allocator_propagation_test<Map>())
+      return 1;
+   if(!one_level_allocator_propagation_test<FlatSet>())
+      return 1;
+   if(!one_level_allocator_propagation_test<Set>())
+      return 1;
+   //multi assoc
+   if(!one_level_allocator_propagation_test<FlatMultiMap>())
+      return 1;
+   if(!one_level_allocator_propagation_test<MultiMap>())
+      return 1;
+   if(!one_level_allocator_propagation_test<FlatMultiSet>())
+      return 1;
+   if(!one_level_allocator_propagation_test<MultiSet>())
+      return 1;
+   //sequence containers
+   if(!one_level_allocator_propagation_test<Vector>())
+      return 1;
+   if(!one_level_allocator_propagation_test<Deque>())
+      return 1;
+   if(!one_level_allocator_propagation_test<List>())
+      return 1;
+   if(!one_level_allocator_propagation_test<Slist>())
+      return 1;
+   if(!one_level_allocator_propagation_test<StableVector>())
+      return 1;
+   if(!one_level_allocator_propagation_test<SmallVector>())
+      return 1;
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/set_test.cpp b/test/set_test.cpp
new file mode 100644
index 0000000..6fc311d
--- /dev/null
+++ b/test/set_test.cpp
@@ -0,0 +1,566 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <set>
+#include <boost/container/set.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include "print_container.hpp"
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+#include "set_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+//set
+template class set
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<test::movable_and_copyable_int>
+   >;
+
+template class set
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , new_allocator<test::movable_and_copyable_int>
+   >;
+
+//multiset
+template class multiset
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<test::movable_and_copyable_int>
+   >;
+
+template class multiset
+   < test::movable_and_copyable_int
+   , std::less<test::movable_and_copyable_int>
+   , adaptive_pool<test::movable_and_copyable_int>
+   >;
+
+}} //boost::container
+
+//Test recursive structures
+class recursive_set
+{
+public:
+   recursive_set & operator=(const recursive_set &x)
+   {  id_ = x.id_;  set_ = x.set_; return *this; }
+
+   int id_;
+   set<recursive_set> set_;
+   set<recursive_set>::iterator it_;
+   set<recursive_set>::const_iterator cit_;
+   set<recursive_set>::reverse_iterator rit_;
+   set<recursive_set>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_set &a, const recursive_set &b)
+   {  return a.id_ < b.id_;   }
+};
+
+//Test recursive structures
+class recursive_multiset
+{
+   public:
+   recursive_multiset & operator=(const recursive_multiset &x)
+   {  id_ = x.id_;  multiset_ = x.multiset_; return *this;  }
+
+   int id_;
+   multiset<recursive_multiset> multiset_;
+   multiset<recursive_multiset>::iterator it_;
+   multiset<recursive_multiset>::const_iterator cit_;
+   multiset<recursive_multiset>::reverse_iterator rit_;
+   multiset<recursive_multiset>::const_reverse_iterator crit_;
+
+   friend bool operator< (const recursive_multiset &a, const recursive_multiset &b)
+   {  return a.id_ < b.id_;   }
+};
+
+template<class C>
+void test_move()
+{
+   //Now test move semantics
+   C original;
+   original.emplace();
+   C move_ctor(boost::move(original));
+   C move_assign;
+   move_assign.emplace();
+   move_assign = boost::move(move_ctor);
+   move_assign.swap(original);
+}
+
+bool node_type_test()
+{
+   using namespace boost::container;
+   {
+      typedef set<test::movable_int> set_type;
+      set_type src;
+      {
+         test::movable_int mv_1(1), mv_2(2), mv_3(3);
+         src.emplace(boost::move(mv_1)); 
+         src.emplace(boost::move(mv_2)); 
+         src.emplace(boost::move(mv_3)); 
+      }
+      if(src.size() != 3)
+         return false;
+
+      set_type dst;
+      {
+         test::movable_int mv_3(3);
+         dst.emplace(boost::move(mv_3)); 
+      }
+
+      if(dst.size() != 1)
+         return false;
+
+      const test::movable_int mv_1(1);
+      const test::movable_int mv_2(2);
+      const test::movable_int mv_3(3);
+      const test::movable_int mv_33(33);
+      set_type::insert_return_type r;
+
+      r = dst.insert(src.extract(mv_33)); // Key version, try to insert empty node
+      if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) )
+         return false;
+      r = dst.insert(src.extract(src.find(mv_1))); // Iterator version, successful
+      if(! (r.position == dst.find(mv_1) && r.inserted == true && r.node.empty()) )
+         return false;
+      r = dst.insert(dst.begin(), src.extract(mv_2)); // Key type version, successful
+      if(! (r.position == dst.find(mv_2) && r.inserted == true && r.node.empty()) )
+         return false;
+      r = dst.insert(src.extract(mv_3)); // Key type version, unsuccessful
+
+      if(!src.empty())
+         return false;
+      if(dst.size() != 3)
+         return false;
+      if(! (r.position == dst.find(mv_3) && r.inserted == false && r.node.value() == mv_3) )
+         return false;
+   }
+
+   {
+      typedef multiset<test::movable_int> multiset_type;
+      multiset_type src;
+      {
+         test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3);
+         src.emplace(boost::move(mv_1));
+         src.emplace(boost::move(mv_2));
+         src.emplace(boost::move(mv_3));
+         src.emplace_hint(src.begin(), boost::move(mv_3bis));
+      }
+      if(src.size() != 4)
+         return false;
+
+      multiset_type dst;
+      {
+         test::movable_int mv_3(3);
+         dst.emplace(boost::move(mv_3)); 
+      }
+
+      if(dst.size() != 1)
+         return false;
+
+      const test::movable_int mv_1(1);
+      const test::movable_int mv_2(2);
+      const test::movable_int mv_3(3);
+      const test::movable_int mv_4(4);
+      multiset_type::iterator r;
+
+      multiset_type::node_type nt(src.extract(mv_3));
+      r = dst.insert(dst.begin(), boost::move(nt));
+      if(! (*r == mv_3 && dst.find(mv_3) == r && nt.empty()) )
+         return false;
+
+      nt = src.extract(src.find(mv_1));
+      r = dst.insert(boost::move(nt)); // Iterator version, successful
+      if(! (*r == mv_1 && nt.empty()) )
+         return false;
+
+      nt = src.extract(mv_2);
+      r = dst.insert(boost::move(nt)); // Key type version, successful
+      if(! (*r == mv_2 && nt.empty()) )
+         return false;
+
+      r = dst.insert(src.extract(mv_3)); // Key type version, successful
+      if(! (*r == mv_3 && r == --multiset_type::iterator(dst.upper_bound(mv_3)) && nt.empty()) )
+         return false;
+
+      r = dst.insert(src.extract(mv_4)); // Key type version, unsuccessful
+      if(! (r == dst.end()) )
+         return false;
+
+      if(!src.empty())
+         return false;
+      if(dst.size() != 5)
+         return false;
+   }
+   return true;
+}
+
+struct boost_container_set;
+struct boost_container_multiset;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_set>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::set<T, std::less<T>, Allocator> type;
+   };
+};
+
+template<>
+struct alloc_propagate_base<boost_container_multiset>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::multiset<T, std::less<T>, Allocator> type;
+   };
+};
+
+}}}   //boost::container::test
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+struct GetAllocatorSet
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef set < ValueType
+                  , std::less<ValueType>
+                  , typename allocator_traits<VoidAllocator>
+                     ::template portable_rebind_alloc<ValueType>::type
+                  , typename boost::container::tree_assoc_options
+                        < boost::container::tree_type<tree_type_value>
+                        >::type
+                  > set_type;
+
+      typedef multiset < ValueType
+                  , std::less<ValueType>
+                  , typename allocator_traits<VoidAllocator>
+                     ::template portable_rebind_alloc<ValueType>::type
+                  , typename boost::container::tree_assoc_options
+                        < boost::container::tree_type<tree_type_value>
+                        >::type
+                  > multiset_type;
+   };
+};
+
+template<class VoidAllocator, boost::container::tree_type_enum tree_type_value>
+int test_set_variants()
+{
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<int>::set_type MySet;
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_int>::set_type MyMoveSet;
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::set_type MyCopySet;
+
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<int>::multiset_type MyMultiSet;
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::movable_int>::multiset_type MyMoveMultiSet;
+   typedef typename GetAllocatorSet<VoidAllocator, tree_type_value>::template apply<test::copyable_int>::multiset_type MyCopyMultiSet;
+
+   typedef std::set<int>                                          MyStdSet;
+   typedef std::multiset<int>                                     MyStdMultiSet;
+
+   if (0 != test::set_test<
+                  MySet
+                  ,MyStdSet
+                  ,MyMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::set_test<
+                  MyMoveSet
+                  ,MyStdSet
+                  ,MyMoveMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   if (0 != test::set_test<
+                  MyCopySet
+                  ,MyStdSet
+                  ,MyCopyMultiSet
+                  ,MyStdMultiSet>()){
+      std::cout << "Error in set_test<MyBoostSet>" << std::endl;
+      return 1;
+   }
+
+   return 0;
+}
+
+void test_merge_from_different_comparison()
+{
+   set<int> set1;
+   set<int, std::greater<int> > set2;
+   set1.merge(set2);
+}
+
+bool test_heterogeneous_lookups()
+{
+   typedef set<int, test::less_transparent> set_t;
+   typedef multiset<int, test::less_transparent> mset_t;
+
+   set_t set1;
+   mset_t mset1;
+
+   const set_t &cset1 = set1;
+   const mset_t &cmset1 = mset1;
+
+   set1.insert(1);
+   set1.insert(1);
+   set1.insert(2);
+   set1.insert(2);
+   set1.insert(3);
+
+   mset1.insert(1);
+   mset1.insert(1);
+   mset1.insert(2);
+   mset1.insert(2);
+   mset1.insert(3);
+
+   const test::non_copymovable_int find_me(2);
+
+   //find
+   if(*set1.find(find_me) != 2)
+      return false;
+   if(*cset1.find(find_me) != 2)
+      return false;
+   if(*mset1.find(find_me) != 2)
+      return false;
+   if(*cmset1.find(find_me) != 2)
+      return false;
+
+   //count
+   if(set1.count(find_me) != 1)
+      return false;
+   if(cset1.count(find_me) != 1)
+      return false;
+   if(mset1.count(find_me) != 2)
+      return false;
+   if(cmset1.count(find_me) != 2)
+      return false;
+
+   //lower_bound
+   if(*set1.lower_bound(find_me) != 2)
+      return false;
+   if(*cset1.lower_bound(find_me) != 2)
+      return false;
+   if(*mset1.lower_bound(find_me) != 2)
+      return false;
+   if(*cmset1.lower_bound(find_me) != 2)
+      return false;
+
+   //upper_bound
+   if(*set1.upper_bound(find_me) != 3)
+      return false;
+   if(*cset1.upper_bound(find_me) != 3)
+      return false;
+   if(*mset1.upper_bound(find_me) != 3)
+      return false;
+   if(*cmset1.upper_bound(find_me) != 3)
+      return false;
+
+   //equal_range
+   if(*set1.equal_range(find_me).first != 2)
+      return false;
+   if(*cset1.equal_range(find_me).second != 3)
+      return false;
+   if(*mset1.equal_range(find_me).first != 2)
+      return false;
+   if(*cmset1.equal_range(find_me).second != 3)
+      return false;
+
+   return true;
+}
+
+int main ()
+{
+   //Recursive container instantiation
+   {
+      set<recursive_set> set_;
+      multiset<recursive_multiset> multiset_;
+   }
+   //Allocator argument container
+   {
+      set<int> set_((set<int>::allocator_type()));
+      multiset<int> multiset_((multiset<int>::allocator_type()));
+   }
+   //Now test move semantics
+   {
+      test_move<set<recursive_set> >();
+      test_move<multiset<recursive_multiset> >();
+   }
+   //Test std::pair value type as tree has workarounds to make old std::pair
+   //implementations movable that can break things
+   {
+      boost::container::set<std::pair<int,int> > s;
+      std::pair<int,int> p(0, 0);
+      s.insert(p);
+      s.emplace(p);
+   }
+
+   if (!boost::container::test::instantiate_constructors<set<int>, multiset<int> >())
+      return 1;
+
+   test_merge_from_different_comparison();
+
+   if(!test_heterogeneous_lookups())
+      return 1;
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_set_variants< std::allocator<void>, red_black_tree >()){
+      std::cerr << "test_set_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::adaptive_pool
+   if(test_set_variants< adaptive_pool<void>, red_black_tree>()){
+      std::cerr << "test_set_variants< adaptive_pool<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Tree implementations
+   ////////////////////////////////////
+   //       AVL
+   if(test_set_variants< std::allocator<void>, avl_tree >()){
+      std::cerr << "test_set_variants< std::allocator<void>, avl_tree > failed" << std::endl;
+      return 1;
+   }
+   //    SCAPEGOAT TREE
+   if(test_set_variants< std::allocator<void>, scapegoat_tree >()){
+      std::cerr << "test_set_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl;
+      return 1;
+   }
+   //    SPLAY TREE
+   if(test_set_variants< std::allocator<void>, splay_tree >()){
+      std::cerr << "test_set_variants< std::allocator<void>, splay_tree > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC);
+   if(!boost::container::test::test_emplace<set<test::EmplaceInt>, SetOptions>())
+      return 1;
+   if(!boost::container::test::test_emplace<multiset<test::EmplaceInt>, SetOptions>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_set>())
+      return 1;
+
+   if(!boost::container::test::test_propagate_allocator<boost_container_multiset>())
+      return 1;
+
+   if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<set<int> >())
+      return 1;
+
+   if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<multiset<int> >())
+      return 1;
+
+   ////////////////////////////////////
+   //    Test optimize_size option
+   ////////////////////////////////////
+   //
+   // set
+   //
+   typedef set< int*, std::less<int*>, std::allocator<int*>
+              , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbset_size_optimized_no;
+
+   typedef set< int*, std::less<int*>, std::allocator<int*>
+              , tree_assoc_options< optimize_size<true>, tree_type<avl_tree>  >::type > avlset_size_optimized_yes;
+   //
+   // multiset
+   //
+   typedef multiset< int*, std::less<int*>, std::allocator<int*>
+                   , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree>  >::type > rbmset_size_optimized_yes;
+
+   typedef multiset< int*, std::less<int*>, std::allocator<int*>
+                   , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmset_size_optimized_no;
+
+   BOOST_STATIC_ASSERT(sizeof(rbmset_size_optimized_yes) < sizeof(rbset_size_optimized_no));
+   BOOST_STATIC_ASSERT(sizeof(avlset_size_optimized_yes) < sizeof(avlmset_size_optimized_no));
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::set<int> cont_int;
+      cont_int a; a.insert(0); a.insert(1); a.insert(2);
+      boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+   {
+      typedef boost::container::multiset<int> cont_int;
+      cont_int a; a.insert(0); a.insert(1); a.insert(2);
+      boost::intrusive::test::test_iterator_bidirectional< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+   ////////////////////////////////////
+   //    Node extraction/insertion testing functions
+   ////////////////////////////////////
+   if(!node_type_test())
+      return 1;
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction
+   ////////////////////////////////////
+   {
+      auto gold = std::set({ 1, 2, 3 });
+      auto test = boost::container::set(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+      test = boost::container::set(ordered_unique_range, gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+   {
+      auto gold = std::multiset({ 1, 2, 3 });
+      auto test = boost::container::multiset(gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+      test = boost::container::multiset(ordered_range, gold.begin(), gold.end());
+      if (test.size() != 3)
+         return 1;
+   }
+#endif
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/set_test.hpp b/test/set_test.hpp
new file mode 100644
index 0000000..b8ca649
--- /dev/null
+++ b/test/set_test.hpp
@@ -0,0 +1,932 @@
+////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_SET_TEST_HEADER
+#define BOOST_CONTAINER_TEST_SET_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+#include "check_equal_containers.hpp"
+#include "print_container.hpp"
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME rebalance
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEG namespace boost { namespace container { namespace test {
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END   }}}
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MIN 0
+#define BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_MAX 0
+#include <boost/intrusive/detail/has_member_function_callable_with.hpp>
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class C>
+void set_test_rebalanceable(C &, boost::container::dtl::false_type)
+{}
+
+template<class C>
+void set_test_rebalanceable(C &c, boost::container::dtl::true_type)
+{
+   c.rebalance();
+}
+
+template<class MyBoostSet
+        ,class MyStdSet
+        ,class MyBoostMultiSet
+        ,class MyStdMultiSet>
+int set_test_copyable(boost::container::dtl::false_type)
+{  return 0; }
+
+const int MaxElem = 50;
+
+template<class MyBoostSet
+        ,class MyStdSet
+        ,class MyBoostMultiSet
+        ,class MyStdMultiSet>
+int set_test_copyable(boost::container::dtl::true_type)
+{
+   typedef typename MyBoostSet::value_type IntType;
+
+   ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
+   ::boost::movelib::unique_ptr<MyStdSet>   const pstdset = ::boost::movelib::make_unique<MyStdSet>();
+   ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset = ::boost::movelib::make_unique<MyBoostMultiSet>();
+   ::boost::movelib::unique_ptr<MyStdMultiSet>   const pstdmultiset   = ::boost::movelib::make_unique<MyStdMultiSet>();
+
+   MyBoostSet &boostset = *pboostset;
+   MyStdSet   &stdset   = *pstdset;
+   MyBoostMultiSet &boostmultiset = *pboostmultiset;
+   MyStdMultiSet   &stdmultiset   = *pstdmultiset;
+
+   //Just to test move aware catch conversions
+   boostset.insert(boostset.cbegin(), boostset.cend());
+   boostmultiset.insert(boostmultiset.cbegin(), boostmultiset.cend());
+   boostset.insert(boostset.begin(), boostset.end());
+   boostmultiset.insert(boostmultiset.begin(), boostmultiset.end());
+
+   for(int i = 0; i < MaxElem; ++i){
+      IntType move_me(i);
+      boostset.insert(boost::move(move_me));
+      stdset.insert(i);
+      IntType move_me2(i);
+      boostmultiset.insert(boost::move(move_me2));
+      stdmultiset.insert(i);
+   }
+   if(!CheckEqualContainers(boostset, stdset)) return 1;
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+
+   {
+      //Now, test copy constructor
+      MyBoostSet boostsetcopy(boostset);
+      MyStdSet stdsetcopy(stdset);
+
+      if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+         return 1;
+
+      MyBoostMultiSet boostmsetcopy(boostmultiset);
+      MyStdMultiSet stdmsetcopy(stdmultiset);
+
+      if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+         return 1;
+
+      //And now assignment
+      boostsetcopy  =boostset;
+      stdsetcopy  = stdset;
+
+      if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+         return 1;
+
+      boostmsetcopy = boostmultiset;
+      stdmsetcopy = stdmultiset;
+
+      if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+         return 1;
+   }
+   {
+      //Now, test copy constructor
+      MyBoostSet boostsetcopy(boostset, typename MyBoostSet::allocator_type());
+      MyStdSet stdsetcopy(stdset);
+
+      if(!CheckEqualContainers(boostsetcopy, stdsetcopy))
+         return 1;
+
+      MyBoostMultiSet boostmsetcopy(boostmultiset, typename MyBoostSet::allocator_type());
+      MyStdMultiSet stdmsetcopy(stdmultiset);
+
+      if(!CheckEqualContainers(boostmsetcopy, stdmsetcopy))
+         return 1;
+   }
+   return 0;
+}
+
+
+template<class MyBoostSet
+        ,class MyStdSet
+        ,class MyBoostMultiSet
+        ,class MyStdMultiSet>
+int set_test ()
+{
+   typedef typename MyBoostSet::value_type IntType;
+
+   ::boost::movelib::unique_ptr<MyBoostSet> const pboostset = ::boost::movelib::make_unique<MyBoostSet>();
+   ::boost::movelib::unique_ptr<MyStdSet>   const pstdset = ::boost::movelib::make_unique<MyStdSet>();
+   ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset = ::boost::movelib::make_unique<MyBoostMultiSet>();
+   ::boost::movelib::unique_ptr<MyStdMultiSet>   const pstdmultiset   = ::boost::movelib::make_unique<MyStdMultiSet>();
+
+   MyBoostSet &boostset = *pboostset;
+   MyStdSet   &stdset   = *pstdset;
+   MyBoostMultiSet &boostmultiset = *pboostmultiset;
+   MyStdMultiSet   &stdmultiset   = *pstdmultiset;
+
+   //Test construction from a range
+   {  //Set(beg, end, compare)
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = i/2;
+      }
+      IntType aux_vect3[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect3[i] = boost::move(move_me);
+      }
+      ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+         (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::key_compare());
+      ::boost::movelib::unique_ptr<MyStdSet> const pstdset2 = ::boost::movelib::make_unique<MyStdSet>(&aux_vect2[0], &aux_vect2[0]+50);
+      if(!test::CheckEqualContainers(*pboostset2, *pstdset2)) return 1;
+      ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+         (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::key_compare());
+      ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset2 = ::boost::movelib::make_unique<MyStdMultiSet>(&aux_vect2[0], &aux_vect2[0]+50);
+      if(!test::CheckEqualContainers(*pboostmultiset2, *pstdmultiset2)) return 1;
+   }
+   {  //Set(beg, end, alloc)
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = i/2;
+      }
+      IntType aux_vect3[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect3[i] = boost::move(move_me);
+      }
+      ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+         (boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0]+50), typename MyBoostSet::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdSet> const pstdset2 = ::boost::movelib::make_unique<MyStdSet>(&aux_vect2[0], &aux_vect2[0]+50);
+      if(!test::CheckEqualContainers(*pboostset2, *pstdset2)) return 1;
+      ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+         (boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0]+50), typename MyBoostMultiSet::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdMultiSet> const pstdmultiset2 = ::boost::movelib::make_unique<MyStdMultiSet>(&aux_vect2[0], &aux_vect2[0]+50);
+      if(!test::CheckEqualContainers(*pboostmultiset2, *pstdmultiset2)) return 1;
+   }
+   {
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = i/2;
+      }
+      IntType aux_vect3[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i/2);
+         aux_vect3[i] = boost::move(move_me);
+      }
+
+      ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>
+            ( boost::make_move_iterator(&aux_vect[0])
+            , boost::make_move_iterator(aux_vect + 50));
+      ::boost::movelib::unique_ptr<MyStdSet>  const pstdset2 = ::boost::movelib::make_unique<MyStdSet>
+            (&aux_vect2[0], &aux_vect2[0] + 50);
+      ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>
+            ( boost::make_move_iterator(&aux_vect3[0])
+            , boost::make_move_iterator(aux_vect3 + 50));
+      ::boost::movelib::unique_ptr<MyStdMultiSet>   const pstdmultiset2   = ::boost::movelib::make_unique<MyStdMultiSet>
+            (&aux_vect2[0], &aux_vect2[0] + 50);
+
+      MyBoostSet &boostset2 = *pboostset2;
+      MyStdSet   &stdset2   = *pstdset2;
+      MyBoostMultiSet &boostmultiset2 = *pboostmultiset2;
+      MyStdMultiSet   &stdmultiset2   = *pstdmultiset2;
+
+      if(!CheckEqualContainers(boostset2, stdset2)){
+         std::cout << "Error in construct<MyBoostSet>(MyBoostSet2)" << std::endl;
+         return 1;
+      }
+      if(!CheckEqualContainers(boostmultiset2, stdmultiset2)){
+         std::cout << "Error in construct<MyBoostMultiSet>(MyBoostMultiSet2)" << std::endl;
+         return 1;
+      }
+
+      //ordered range insertion
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i);
+         aux_vect[i] = boost::move(move_me);
+      }
+
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = i;
+      }
+
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(i);
+         aux_vect3[i] = boost::move(move_me);
+      }
+
+      //some comparison operators
+      if(!(boostset2 == boostset2))
+         return 1;
+      if(boostset2 != boostset2)
+         return 1;
+      if(boostset2 < boostset2)
+         return 1;
+      if(boostset2 > boostset2)
+         return 1;
+      if(!(boostset2 <= boostset2))
+         return 1;
+      if(!(boostset2 >= boostset2))
+         return 1;
+
+      ::boost::movelib::unique_ptr<MyBoostSet> const pboostset3 = ::boost::movelib::make_unique<MyBoostSet>
+            ( ordered_unique_range
+            , boost::make_move_iterator(&aux_vect[0])
+            , boost::make_move_iterator(&aux_vect[0] + 50));
+      ::boost::movelib::unique_ptr<MyStdSet>   const pstdset3 = ::boost::movelib::make_unique<MyStdSet>
+            (&aux_vect2[0], &aux_vect2[0] + 50);
+      ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset3 = ::boost::movelib::make_unique<MyBoostMultiSet>
+            ( ordered_range
+            , boost::make_move_iterator(&aux_vect3[0])
+            , boost::make_move_iterator(aux_vect3 + 50));
+      ::boost::movelib::unique_ptr<MyStdMultiSet>   const pstdmultiset3   = ::boost::movelib::make_unique<MyStdMultiSet>
+            (&aux_vect2[0], &aux_vect2[0] + 50);
+
+      MyBoostSet &boostset3 = *pboostset3;
+      MyStdSet   &stdset3   = *pstdset3;
+      MyBoostMultiSet &boostmultiset3 = *pboostmultiset3;
+      MyStdMultiSet   &stdmultiset3   = *pstdmultiset3;
+
+      if(!CheckEqualContainers(boostset3, stdset3)){
+         std::cout << "Error in construct<MyBoostSet>(MyBoostSet3)" << std::endl;
+         return 1;
+      }
+      if(!CheckEqualContainers(boostmultiset3, stdmultiset3)){
+         std::cout << "Error in construct<MyBoostMultiSet>(MyBoostMultiSet3)" << std::endl;
+         return 1;
+      }
+   }
+
+   for(int i = 0; i < MaxElem; ++i){
+      IntType move_me(i);
+      boostset.insert(boost::move(move_me));
+      stdset.insert(i);
+      boostset.insert(IntType(i));
+      stdset.insert(i);
+      IntType move_me2(i);
+      boostmultiset.insert(boost::move(move_me2));
+      stdmultiset.insert(i);
+      boostmultiset.insert(IntType(i));
+      stdmultiset.insert(i);
+   }
+
+   if(!CheckEqualContainers(boostset, stdset)){
+      std::cout << "Error in boostset.insert(boost::move(move_me)" << std::endl;
+      return 1;
+   }
+
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+      std::cout << "Error in boostmultiset.insert(boost::move(move_me)" << std::endl;
+      return 1;
+   }
+
+   typename MyBoostSet::iterator it = boostset.begin();
+   typename MyBoostSet::const_iterator cit = it;
+   (void)cit;
+
+   boostset.erase(boostset.begin());
+   stdset.erase(stdset.begin());
+   boostmultiset.erase(boostmultiset.begin());
+   stdmultiset.erase(stdmultiset.begin());
+   if(!CheckEqualContainers(boostset, stdset)){
+      std::cout << "Error in boostset.erase(boostset.begin())" << std::endl;
+      return 1;
+   }
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+      std::cout << "Error in boostmultiset.erase(boostmultiset.begin())" << std::endl;
+      return 1;
+   }
+
+   boostset.erase(boostset.begin());
+   stdset.erase(stdset.begin());
+   boostmultiset.erase(boostmultiset.begin());
+   stdmultiset.erase(stdmultiset.begin());
+   if(!CheckEqualContainers(boostset, stdset)){
+      std::cout << "Error in boostset.erase(boostset.begin())" << std::endl;
+      return 1;
+   }
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+      std::cout << "Error in boostmultiset.erase(boostmultiset.begin())" << std::endl;
+      return 1;
+   }
+
+   //Swapping test
+   MyBoostSet tmpboosteset2;
+   MyStdSet tmpstdset2;
+   MyBoostMultiSet tmpboostemultiset2;
+   MyStdMultiSet tmpstdmultiset2;
+   boostset.swap(tmpboosteset2);
+   stdset.swap(tmpstdset2);
+   boostmultiset.swap(tmpboostemultiset2);
+   stdmultiset.swap(tmpstdmultiset2);
+   boostset.swap(tmpboosteset2);
+   stdset.swap(tmpstdset2);
+   boostmultiset.swap(tmpboostemultiset2);
+   stdmultiset.swap(tmpstdmultiset2);
+   if(!CheckEqualContainers(boostset, stdset)){
+      std::cout << "Error in boostset.swap(tmpboosteset2)" << std::endl;
+      return 1;
+   }
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+      std::cout << "Error in boostmultiset.swap(tmpboostemultiset2)" << std::endl;
+      return 1;
+   }
+
+   //Insertion from other container
+   //Initialize values
+   {
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+      IntType aux_vect3[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect3[i] = boost::move(move_me);
+      }
+
+      boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
+      stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      if(!CheckEqualContainers(boostset, stdset)){
+         std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
+         return 1;
+      }
+      boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(aux_vect3 + 50));
+      stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+         std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect3[0]), ..." << std::endl;
+         return 1;
+      }
+
+      for(int i = 0, j = static_cast<int>(boostset.size()); i < j; ++i){
+         IntType erase_me(i);
+         boostset.erase(erase_me);
+         stdset.erase(i);
+         boostmultiset.erase(erase_me);
+         stdmultiset.erase(i);
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.erase(erase_me)" << boostset.size() << " " << stdset.size() << std::endl;
+            return 1;
+         }
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.erase(erase_me)" << std::endl;
+            return 1;
+         }
+      }
+   }
+   {
+      IntType aux_vect[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect[i] = boost::move(move_me);
+      }
+      int aux_vect2[50];
+      for(int i = 0; i < 50; ++i){
+         aux_vect2[i] = -1;
+      }
+      IntType aux_vect3[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect3[i] = boost::move(move_me);
+      }
+
+      IntType aux_vect4[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect4[i] = boost::move(move_me);
+      }
+
+      IntType aux_vect5[50];
+      for(int i = 0; i < 50; ++i){
+         IntType move_me(-1);
+         aux_vect5[i] = boost::move(move_me);
+      }
+
+      boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + 50));
+      boostset.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + 50));
+      stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      stdset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      if(!CheckEqualContainers(boostset, stdset)){
+         std::cout << "Error in boostset.insert(boost::make_move_iterator(&aux_vect3[0])..." << std::endl;
+         return 1;
+      }
+      boostmultiset.insert(boost::make_move_iterator(&aux_vect4[0]), boost::make_move_iterator(&aux_vect4[0] + 50));
+      boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0]), boost::make_move_iterator(&aux_vect5[0] + 50));
+      stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      stdmultiset.insert(&aux_vect2[0], &aux_vect2[0] + 50);
+      if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+         std::cout << "Error in boostmultiset.insert(boost::make_move_iterator(&aux_vect5[0])..." << std::endl;
+         return 1;
+      }
+
+      boostset.erase(*boostset.begin());
+      stdset.erase(*stdset.begin());
+      if(!CheckEqualContainers(boostset, stdset)){
+         std::cout << "Error in boostset.erase(*boostset.begin())" << std::endl;
+         return 1;
+      }
+      boostmultiset.erase(*boostmultiset.begin());
+      stdmultiset.erase(*stdmultiset.begin());
+      if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+         std::cout << "Error in boostmultiset.erase(*boostmultiset.begin())" << std::endl;
+         return 1;
+      }
+   }
+
+   for(int i = 0; i < MaxElem; ++i){
+      IntType move_me(i);
+      boostset.insert(boost::move(move_me));
+      stdset.insert(i);
+      IntType move_me2(i);
+      boostmultiset.insert(boost::move(move_me2));
+      stdmultiset.insert(i);
+   }
+
+   if(!CheckEqualContainers(boostset, stdset)){
+      std::cout << "Error in boostset.insert(boost::move(move_me)) try 2" << std::endl;
+      return 1;
+   }
+   if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+      std::cout << "Error in boostmultiset.insert(boost::move(move_me2)) try 2" << std::endl;
+      return 1;
+   }
+
+   for(int i = 0; i < MaxElem; ++i){
+      {
+         IntType move_me(i);
+         boostset.insert(boostset.begin(), boost::move(move_me));
+         stdset.insert(stdset.begin(), i);
+         //PrintContainers(boostset, stdset);
+         IntType move_me2(i);
+         boostmultiset.insert(boostmultiset.begin(), boost::move(move_me2));
+         stdmultiset.insert(stdmultiset.begin(), i);
+         //PrintContainers(boostmultiset, stdmultiset);
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.insert(boostset.begin(), boost::move(move_me))" << std::endl;
+            return 1;
+         }
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.insert(boostmultiset.begin(), boost::move(move_me2))" << std::endl;
+            return 1;
+         }
+
+         IntType move_me3(i);
+         boostset.insert(boostset.end(), boost::move(move_me3));
+         stdset.insert(stdset.end(), i);
+         IntType move_me4(i);
+         boostmultiset.insert(boostmultiset.end(), boost::move(move_me4));
+         stdmultiset.insert(stdmultiset.end(), i);
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.insert(boostset.end(), boost::move(move_me3))" << std::endl;
+            return 1;
+         }
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.insert(boostmultiset.end(), boost::move(move_me4))" << std::endl;
+            return 1;
+         }
+      }
+      {
+         IntType move_me(i);
+         boostset.insert(boostset.upper_bound(move_me), boost::move(move_me));
+         stdset.insert(stdset.upper_bound(i), i);
+         //PrintContainers(boostset, stdset);
+         IntType move_me2(i);
+         boostmultiset.insert(boostmultiset.upper_bound(move_me2), boost::move(move_me2));
+         stdmultiset.insert(stdmultiset.upper_bound(i), i);
+         //PrintContainers(boostmultiset, stdmultiset);
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.insert(boostset.upper_bound(move_me), boost::move(move_me))" << std::endl;
+            return 1;
+         }
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.insert(boostmultiset.upper_bound(move_me2), boost::move(move_me2))" << std::endl;
+            return 1;
+         }
+
+      }
+      {
+         IntType move_me(i);
+         IntType move_me2(i);
+         boostset.insert(boostset.lower_bound(move_me), boost::move(move_me2));
+         stdset.insert(stdset.lower_bound(i), i);
+         //PrintContainers(boostset, stdset);
+         move_me2 = i;
+         boostmultiset.insert(boostmultiset.lower_bound(move_me2), boost::move(move_me2));
+         stdmultiset.insert(stdmultiset.lower_bound(i), i);
+         //PrintContainers(boostmultiset, stdmultiset);
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.insert(boostset.lower_bound(move_me), boost::move(move_me2))" << std::endl;
+            return 1;
+         }
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.insert(boostmultiset.lower_bound(move_me2), boost::move(move_me2))" << std::endl;
+            return 1;
+         }
+         set_test_rebalanceable(boostset
+            , dtl::bool_<has_member_function_callable_with_rebalance<MyBoostSet>::value>());
+         if(!CheckEqualContainers(boostset, stdset)){
+            std::cout << "Error in boostset.rebalance()" << std::endl;
+            return 1;
+         }
+         set_test_rebalanceable(boostmultiset
+            , dtl::bool_<has_member_function_callable_with_rebalance<MyBoostMultiSet>::value>());
+         if(!CheckEqualContainers(boostmultiset, stdmultiset)){
+            std::cout << "Error in boostmultiset.rebalance()" << std::endl;
+            return 1;
+         }
+      }
+   }
+
+   //Compare count with std containers
+   for(int i = 0; i < MaxElem; ++i){
+      IntType count_me(i);
+      if(boostset.count(count_me) != stdset.count(i)){
+         return -1;
+      }
+      if(boostmultiset.count(count_me) != stdmultiset.count(i)){
+         return -1;
+      }
+   }
+
+   //Compare find/lower_bound/upper_bound in set
+   {
+      typename MyBoostSet::iterator bs_b = boostset.begin();
+      typename MyBoostSet::iterator bs_e = boostset.end();
+      typename MyStdSet::iterator ss_b   = stdset.begin();
+
+      std::size_t i = 0;
+      while(bs_b != bs_e){
+         ++i;
+         typename MyBoostSet::iterator bs_i;
+         typename MyStdSet::iterator ss_i;
+         //find
+         bs_i = boostset.find(*bs_b);
+         ss_i = stdset.find(*ss_b);
+         if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+            return -1;
+         }
+         //lower bound
+         bs_i = boostset.lower_bound(*bs_b);
+         ss_i = stdset.lower_bound(*ss_b);
+         if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+            return -1;
+         }
+         //upper bound
+         bs_i = boostset.upper_bound(*bs_b);
+         ss_i = stdset.upper_bound(*ss_b);
+         if(!CheckEqualIt(bs_i, ss_i, boostset, stdset)){
+            return -1;
+         }
+         //equal range
+         std::pair<typename MyBoostSet::iterator
+                  ,typename MyBoostSet::iterator> bs_ip;
+         std::pair<typename MyStdSet::iterator
+                  ,typename MyStdSet::iterator>   ss_ip;
+         bs_ip = boostset.equal_range(*bs_b);
+         ss_ip = stdset.equal_range(*ss_b);
+         if(!CheckEqualIt(bs_ip.first, ss_ip.first, boostset, stdset)){
+            return -1;
+         }
+         if(!CheckEqualIt(bs_ip.second, ss_ip.second, boostset, stdset)){
+            return -1;
+         }
+         ++bs_b;
+         ++ss_b;
+      }
+   }
+   //Compare find/lower_bound/upper_bound in multiset
+   {
+      typename MyBoostMultiSet::iterator bm_b = boostmultiset.begin();
+      typename MyBoostMultiSet::iterator bm_e = boostmultiset.end();
+      typename MyStdMultiSet::iterator sm_b   = stdmultiset.begin();
+
+      while(bm_b != bm_e){
+         typename MyBoostMultiSet::iterator bm_i;
+         typename MyStdMultiSet::iterator sm_i;
+         //find
+         bm_i = boostmultiset.find(*bm_b);
+         sm_i = stdmultiset.find(*sm_b);
+         if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+            return -1;
+         }
+         //lower bound
+         bm_i = boostmultiset.lower_bound(*bm_b);
+         sm_i = stdmultiset.lower_bound(*sm_b);
+         if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+            return -1;
+         }
+         //upper bound
+         bm_i = boostmultiset.upper_bound(*bm_b);
+         sm_i = stdmultiset.upper_bound(*sm_b);
+         if(!CheckEqualIt(bm_i, sm_i, boostmultiset, stdmultiset)){
+            return -1;
+         }
+         //equal range
+         std::pair<typename MyBoostMultiSet::iterator
+                  ,typename MyBoostMultiSet::iterator> bm_ip;
+         std::pair<typename MyStdMultiSet::iterator
+                  ,typename MyStdMultiSet::iterator>   sm_ip;
+         bm_ip = boostmultiset.equal_range(*bm_b);
+         sm_ip = stdmultiset.equal_range(*sm_b);
+         if(!CheckEqualIt(bm_ip.first, sm_ip.first, boostmultiset, stdmultiset)){
+            return -1;
+         }
+         if(!CheckEqualIt(bm_ip.second, sm_ip.second, boostmultiset, stdmultiset)){
+            return -1;
+         }
+         ++bm_b;
+         ++sm_b;
+      }
+   }
+
+   //Now do count exercise
+   boostset.erase(boostset.begin(), boostset.end());
+   boostmultiset.erase(boostmultiset.begin(), boostmultiset.end());
+   boostset.clear();
+   boostmultiset.clear();
+
+   for(int j = 0; j < 3; ++j)
+   for(int i = 0; i < 100; ++i){
+      IntType move_me(i);
+      boostset.insert(boost::move(move_me));
+      IntType move_me2(i);
+      boostmultiset.insert(boost::move(move_me2));
+      IntType count_me(i);
+      if(boostset.count(count_me) != typename MyBoostMultiSet::size_type(1)){
+         std::cout << "Error in boostset.count(count_me)" << std::endl;
+         return 1;
+      }
+      if(boostmultiset.count(count_me) != typename MyBoostMultiSet::size_type(j+1)){
+         std::cout << "Error in boostmultiset.count(count_me)" << std::endl;
+         return 1;
+      }
+   }
+
+   {  //merge
+      ::boost::movelib::unique_ptr<MyBoostSet> const pboostset2 = ::boost::movelib::make_unique<MyBoostSet>();
+      ::boost::movelib::unique_ptr<MyBoostMultiSet> const pboostmultiset2 = ::boost::movelib::make_unique<MyBoostMultiSet>();
+
+      MyBoostSet &boostset2 = *pboostset2;
+      MyBoostMultiSet &boostmultiset2 = *pboostmultiset2;
+
+      boostset.clear();
+      boostset2.clear();
+      boostmultiset.clear();
+      boostmultiset2.clear();
+      stdset.clear();
+      stdmultiset.clear();
+
+      {
+         IntType aux_vect[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect[i] = i;
+         }
+
+         IntType aux_vect2[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect2[i] = MaxElem/2+i;
+         }
+         IntType aux_vect3[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect3[i] = MaxElem*2/2+i;
+         }
+         boostset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+         boostset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+         boostmultiset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdset.insert(i);
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdset.insert(MaxElem/2+i);
+      }
+
+      boostset.merge(boost::move(boostset2));
+      if(!CheckEqualContainers(boostset, stdset)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         stdset.insert(MaxElem*2/2+i);
+      }
+
+      boostset.merge(boost::move(boostmultiset2));
+      if(!CheckEqualContainers(boostset, stdset)) return 1;
+
+      boostset.clear();
+      boostset2.clear();
+      boostmultiset.clear();
+      boostmultiset2.clear();
+      stdset.clear();
+      stdmultiset.clear();
+      {
+         IntType aux_vect[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect[i] = i;
+         }
+
+         IntType aux_vect2[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect2[i] = MaxElem/2+i;
+         }
+         IntType aux_vect3[MaxElem];
+         for(int i = 0; i < MaxElem; ++i){
+            aux_vect3[i] = MaxElem*2/2+i;
+         }
+         boostmultiset.insert(boost::make_move_iterator(&aux_vect[0]), boost::make_move_iterator(&aux_vect[0] + MaxElem));
+         boostmultiset2.insert(boost::make_move_iterator(&aux_vect2[0]), boost::make_move_iterator(&aux_vect2[0] + MaxElem));
+         boostset2.insert(boost::make_move_iterator(&aux_vect3[0]), boost::make_move_iterator(&aux_vect3[0] + MaxElem));
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultiset.insert(i);
+      }
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultiset.insert(MaxElem/2+i);
+      }
+      boostmultiset.merge(boost::move(boostmultiset2));
+      if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+
+      for(int i = 0; i < MaxElem; ++i){
+         stdmultiset.insert(MaxElem*2/2+i);
+      }
+
+      boostmultiset.merge(boost::move(boostset2));
+      if(!CheckEqualContainers(boostmultiset, stdmultiset)) return 1;
+   }
+
+   if(set_test_copyable<MyBoostSet, MyStdSet, MyBoostMultiSet, MyStdMultiSet>
+      (dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+      return 1;
+   }
+
+   return 0;
+}
+
+template<typename SetType>
+bool test_set_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   std::initializer_list<int> il = { 1, 2, 3, 4, 5, 5 };
+   std::initializer_list<int> ilu = { 1, 2, 3, 4, 5 };
+   SetType expected(il.begin(), il.end());
+   SetType expectedu(ilu.begin(), ilu.end());
+   {
+      SetType sil((il));
+      if (sil != expected)
+         return false;
+
+      SetType sila(il, typename SetType::allocator_type());
+      if (sila != expected)
+         return false;
+
+      SetType silca(il, typename SetType::key_compare(), typename SetType::allocator_type());
+      if (silca != expected)
+         return false;
+
+      SetType sil_ordered(ordered_unique_range, ilu);
+      if (sil_ordered != expectedu)
+         return false;
+
+      SetType sil_assign = { 99, 100, 101, 102, 103, 104, 105 };
+      sil_assign = il;
+      if (sil_assign != expected)
+         return false;
+   }
+   {
+      SetType sil;
+      sil.insert(il);
+      if (sil != expected)
+         return false;
+   }
+   return true;
+#endif
+   return true;
+}
+
+template<typename SetType, typename MultisetType>
+bool instantiate_constructors()
+{
+   {
+      typedef typename SetType::value_type value_type;
+      typename SetType::key_compare comp;
+      typename SetType::allocator_type a;
+      value_type value;
+      {
+         SetType s0;
+         SetType s1(comp);
+         SetType s2(a);
+         SetType s3(comp, a);
+      }
+      {
+         SetType s0(&value, &value);
+         SetType s1(&value, &value ,comp);
+         SetType s2(&value, &value ,a);
+         SetType s3(&value, &value ,comp, a);
+      }
+      #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+      {
+         SetType s0({ 0 });
+         SetType s1({ 0 },comp);
+         SetType s2({ 0 },a);
+         SetType s3({ 0 },comp, a);
+      }
+      {
+         std::initializer_list<value_type> il{0};
+         SetType s0(ordered_unique_range, il);
+         SetType s1(ordered_unique_range, il,comp);
+         SetType s3(ordered_unique_range, il,comp, a);
+      }
+      #endif
+      {
+         SetType s0(ordered_unique_range, &value, &value);
+         SetType s1(ordered_unique_range, &value, &value ,comp);
+         SetType s2(ordered_unique_range, &value, &value ,comp, a);
+      }
+   }
+
+   {
+      typedef typename MultisetType::value_type value_type;
+      typename MultisetType::key_compare comp;
+      typename MultisetType::allocator_type a;
+      value_type value;
+      {
+         MultisetType s0;
+         MultisetType s1(comp);
+         MultisetType s2(a);
+         MultisetType s3(comp, a);
+      }
+      {
+         MultisetType s0(&value, &value);
+         MultisetType s1(&value, &value ,comp);
+         MultisetType s2(&value, &value ,a);
+         MultisetType s3(&value, &value ,comp, a);
+      }
+      #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+      {
+         MultisetType s0({ 0 });
+         MultisetType s1({ 0 },comp);
+         MultisetType s2({ 0 },a);
+         MultisetType s3({ 0 },comp, a);
+      }
+      {
+         std::initializer_list<value_type>il{0};
+         MultisetType s0(ordered_range, il);
+         MultisetType s1(ordered_range, il,comp);
+         MultisetType s3(ordered_range, il,comp, a);
+      }
+      #endif
+      {
+         MultisetType s0(ordered_range, &value, &value);
+         MultisetType s1(ordered_range, &value, &value ,comp);
+         MultisetType s2(ordered_range, &value, &value ,comp, a);
+      }
+   }
+   return true;
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif
diff --git a/test/slist_test.cpp b/test/slist_test.cpp
new file mode 100644
index 0000000..3f1f910
--- /dev/null
+++ b/test/slist_test.cpp
@@ -0,0 +1,296 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/slist.hpp>
+#include <boost/container/node_allocator.hpp>
+
+#include <memory>
+#include "dummy_test_allocator.hpp"
+#include "movable_int.hpp"
+#include "list_test.hpp"
+#include "propagate_allocator_test.hpp"
+#include "emplace_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::slist
+   < test::movable_and_copyable_int
+   , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::slist
+   < test::movable_and_copyable_int
+   , node_allocator<test::movable_and_copyable_int> >;
+
+}}
+
+class recursive_slist
+{
+public:
+   int id_;
+   slist<recursive_slist> slist_;
+   slist<recursive_slist>::iterator it_;
+   slist<recursive_slist>::const_iterator cit_;
+
+   recursive_slist &operator=(const recursive_slist &o)
+   { slist_ = o.slist_;  return *this; }
+};
+
+void recursive_slist_test()//Test for recursive types
+{
+   slist<recursive_slist> recursive_list_list;
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef slist< ValueType
+                   , typename allocator_traits<VoidAllocator>
+                        ::template portable_rebind_alloc<ValueType>::type
+                   > type;
+   };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+   if(test::list_test<MyCont, false>())
+      return 1;
+   if(test::list_test<MyMoveCont, false>())
+      return 1;
+   if(test::list_test<MyCopyMoveCont, false>())
+      return 1;
+   if(test::list_test<MyCopyMoveCont, false>())
+      return 1;
+   if(test::list_test<MyCopyCont, false>())
+      return 1;
+
+   return 0;
+}
+
+bool test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   const std::initializer_list<int> il = {5, 10, 15};
+   const slist<int> expected_list(il.begin(), il.end());
+   {
+      slist<int> sl = il;
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+      slist<int> sl = {1, 2};
+      sl = il;
+      if(sl != expected_list)
+         return false;
+   }
+   {
+      slist<int> sl({ 1, 2 }, slist<int>::allocator_type());
+      sl = il;
+      if (sl != expected_list)
+         return false;
+   }
+   {
+      slist<int> sl = {4, 5};
+      sl.assign(il);
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+      slist<int> sl = {15};
+      sl.insert(sl.cbegin(), {5, 10});
+      if(sl != expected_list)
+         return false;
+   }
+
+   {
+       slist<int> sl = {5};
+       sl.insert_after(sl.cbegin(), {10, 15});
+       if(sl != expected_list)
+          return false;
+   }
+   return true;
+#endif
+   return true;
+}
+
+bool test_for_splice()
+{
+   {
+      slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
+      slist<int> list2;
+      slist<int> expected1; expected1.push_front(3); expected1.push_front(2);  expected1.push_front(0);
+      slist<int> expected2; expected2.push_front(1);
+
+      list2.splice(list2.begin(), list1, ++list1.begin());
+
+      if (!(expected1 == list1 && expected2 == list2))
+         return false;
+   }
+   {
+      slist<int> list1; list1.push_front(3); list1.push_front(2); list1.push_front(1); list1.push_front(0);
+      slist<int> list2;
+      slist<int> expected1;
+      slist<int> expected2; expected2.push_front(3); expected2.push_front(2); expected2.push_front(1); expected2.push_front(0);
+
+      list2.splice(list2.begin(), list1, list1.begin(), list1.end());
+
+      if (!(expected1 == list1 && expected2 == list2))
+         return false;
+   }
+   return true;
+}
+
+struct boost_container_slist;
+
+namespace boost {
+namespace container {
+namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_slist>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::slist<T, Allocator> type;
+   };
+};
+
+}}}
+
+int main ()
+{
+   recursive_slist_test();
+   {
+      //Now test move semantics
+      slist<recursive_slist> original;
+      slist<recursive_slist> move_ctor(boost::move(original));
+      slist<recursive_slist> move_assign;
+      move_assign = boost::move(move_ctor);
+      move_assign.swap(original);
+      {
+         slist<recursive_slist> recursive, copy;
+         //Test to test both move emulations
+         if(!copy.size()){
+            copy = recursive;
+         }
+      }
+   }
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_cont_variants< std::allocator<void> >()){
+      std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::node_allocator
+   if(test_cont_variants< node_allocator<void> >()){
+      std::cerr << "test_cont_variants< node_allocator<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)
+      (test::EMPLACE_FRONT | test::EMPLACE_AFTER | test::EMPLACE_BEFORE  | test::EMPLACE_AFTER);
+
+   if(!boost::container::test::test_emplace
+      < slist<test::EmplaceInt>, Options>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_slist>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Initializer lists
+   ////////////////////////////////////
+   if(!test_support_for_initializer_list())
+      return 1;
+
+   ////////////////////////////////////
+   //    Splice testing
+   ////////////////////////////////////
+   if(!test_for_splice())
+      return 1;
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::slist<int> vector_int;
+      vector_int a; a.push_front(2); a.push_front(1); a.push_front(0);
+      boost::intrusive::test::test_iterator_forward< boost::container::slist<int> >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction Tests
+   ////////////////////////////////////
+   {
+      auto gold = std::list{ 1, 2, 3 };
+      auto test = boost::container::slist(gold.begin(), gold.end());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (test.front() != 1)
+         return 1;
+      test.pop_front();
+      if (test.front() != 2)
+         return 1;
+      test.pop_front();
+      if (test.front() != 3)
+         return 1;
+      test.pop_front();
+   }
+   {
+      auto gold = std::list{ 1, 2, 3 };
+      auto test = boost::container::slist(gold.begin(), gold.end(), new_allocator<int>());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (test.front() != 1)
+         return 1;
+      test.pop_front();
+      if (test.front() != 2)
+         return 1;
+      test.pop_front();
+      if (test.front() != 3)
+         return 1;
+      test.pop_front();
+   }
+#endif
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
+
diff --git a/test/small_vector_test.cpp b/test/small_vector_test.cpp
new file mode 100644
index 0000000..adf5f65
--- /dev/null
+++ b/test/small_vector_test.cpp
@@ -0,0 +1,242 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/small_vector.hpp>
+#include "vector_test.hpp"
+#include "movable_int.hpp"
+#include "propagate_allocator_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <boost/container/allocator.hpp>
+
+#include <iostream>
+
+namespace boost {
+namespace container {
+
+template class small_vector<char, 0>;
+template class small_vector<char, 1>;
+template class small_vector<char, 2>;
+template class small_vector<char, 10>;
+
+template class small_vector<int, 0>;
+template class small_vector<int, 1>;
+template class small_vector<int, 2>;
+template class small_vector<int, 10>;
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::small_vector
+   < test::movable_and_copyable_int
+   , 10
+   , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::small_vector
+   < test::movable_and_copyable_int
+   , 10
+   , allocator<test::movable_and_copyable_int> >;
+
+}}
+
+struct boost_container_small_vector;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_small_vector>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::small_vector<T, 10, Allocator> type;
+   };
+};
+
+}}}   //namespace boost::container::test
+
+bool test_small_vector_base_test()
+{
+   typedef boost::container::small_vector_base<int> smb_t;
+   {
+      typedef boost::container::small_vector<int, 5> sm5_t;
+      BOOST_STATIC_ASSERT(sm5_t::static_capacity == 5);
+      sm5_t sm5;
+      smb_t &smb = sm5;
+      smb.push_back(1);
+      sm5_t sm5_copy(sm5);
+      sm5_copy.push_back(1);
+      if (!boost::container::test::CheckEqualContainers(sm5, smb))
+         return false;
+   }
+   {
+      typedef boost::container::small_vector<int, 7> sm7_t;
+      BOOST_STATIC_ASSERT(sm7_t::static_capacity == 7);
+      sm7_t sm7;
+      smb_t &smb = sm7;
+      smb.push_back(2);
+      sm7_t sm7_copy(sm7);
+      sm7_copy.push_back(2);
+      if (!boost::container::test::CheckEqualContainers(sm7, smb))
+         return false;
+   }
+   {
+      typedef boost::container::small_vector<int, 5> sm5_t;
+      sm5_t sm5;
+      smb_t &smb = sm5;
+      smb.push_back(1);
+      sm5_t sm5_copy(smb);
+      if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy))
+         return false;
+      smb.push_back(2);
+      if(smb.size() != 2){
+         return false;
+      }
+      sm5_copy = smb;
+      if (!boost::container::test::CheckEqualContainers(sm5, sm5_copy))
+         return false;
+      sm5_t sm5_move(boost::move(smb));
+      smb.clear();
+      if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy))
+         return false;
+      smb = sm5_copy;
+      sm5_move = boost::move(smb);
+      smb.clear();
+      if (!boost::container::test::CheckEqualContainers(sm5_move, sm5_copy))
+         return false;
+   }
+
+   return true;
+}
+
+//small vector has internal storage so some special swap cases must be tested
+bool test_swap()
+{
+   typedef boost::container::small_vector<int, 10> vec;
+   {  //v bigger than static capacity, w empty
+      vec v;
+      for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){
+         v.push_back(int(i));
+      }
+      vec w;
+      const std::size_t v_size = v.size();
+      const std::size_t w_size = w.size();
+      v.swap(w);
+      if(v.size() != w_size || w.size() != v_size)
+         return false;
+   }
+   {  //v smaller than static capacity, w empty
+      vec v;
+      for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){
+         v.push_back(int(i));
+      }
+      vec w;
+      const std::size_t v_size = v.size();
+      const std::size_t w_size = w.size();
+      v.swap(w);
+      if(v.size() != w_size || w.size() != v_size)
+         return false;
+   }
+   {  //v & w smaller than static capacity
+      vec v;
+      for(std::size_t i = 0, max = v.capacity()-1; i != max; ++i){
+         v.push_back(int(i));
+      }
+      vec w;
+      for(std::size_t i = 0, max = v.capacity()/2; i != max; ++i){
+         w.push_back(int(i));
+      }
+      const std::size_t v_size = v.size();
+      const std::size_t w_size = w.size();
+      v.swap(w);
+      if(v.size() != w_size || w.size() != v_size)
+         return false;
+   }
+   {  //v & w bigger than static capacity
+      vec v;
+      for(std::size_t i = 0, max = v.capacity()+1; i != max; ++i){
+         v.push_back(int(i));
+      }
+      vec w;
+      for(std::size_t i = 0, max = v.capacity()*2; i != max; ++i){
+         w.push_back(int(i));
+      }
+      const std::size_t v_size = v.size();
+      const std::size_t w_size = w.size();
+      v.swap(w);
+      if(v.size() != w_size || w.size() != v_size)
+         return false;
+   }
+   return true;
+}
+
+int main()
+{
+   using namespace boost::container;
+
+   if(!test_swap())
+      return 1;
+
+   if(test::vector_test< small_vector<int, 0> >())
+      return 1;
+
+   if(test::vector_test< small_vector<int, 2000> >())
+      return 1;
+
+   ////////////////////////////////////
+   //    Default init test
+   ////////////////////////////////////
+   if(!test::default_init_test< small_vector<int, 5, test::default_init_allocator<int> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+   if(!boost::container::test::test_emplace< small_vector<test::EmplaceInt, 5>, Options>()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_small_vector>()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Initializer lists testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+      < boost::container::small_vector<int, 5> >()) {
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //       Small vector base
+   ////////////////////////////////////
+   if (!test_small_vector_base_test()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::small_vector<int, 0> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+   return 0;
+}
diff --git a/test/stable_vector_test.cpp b/test/stable_vector_test.cpp
new file mode 100644
index 0000000..16e2ca8
--- /dev/null
+++ b/test/stable_vector_test.cpp
@@ -0,0 +1,215 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#define STABLE_VECTOR_ENABLE_INVARIANT_CHECKING
+#include <boost/container/detail/config_begin.hpp>
+#include <memory>
+
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/node_allocator.hpp>
+
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class stable_vector<test::movable_and_copyable_int,
+   test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class stable_vector
+   < test::movable_and_copyable_int
+   , node_allocator<test::movable_and_copyable_int> >;
+
+template class stable_vector_iterator<int*, false>;
+template class stable_vector_iterator<int*, true >;
+
+}}
+
+class recursive_vector
+{
+   public:
+   int id_;
+   stable_vector<recursive_vector> vector_;
+   stable_vector<recursive_vector>::iterator it_;
+   stable_vector<recursive_vector>::const_iterator cit_;
+   stable_vector<recursive_vector>::reverse_iterator rit_;
+   stable_vector<recursive_vector>::const_reverse_iterator crit_;
+
+   recursive_vector &operator=(const recursive_vector &o)
+   { vector_ = o.vector_;  return *this; }
+};
+
+void recursive_vector_test()//Test for recursive types
+{
+   stable_vector<recursive_vector> recursive, copy;
+   //Test to test both move emulations
+   if(!copy.size()){
+      copy = recursive;
+   }
+}
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef stable_vector< ValueType
+                           , typename allocator_traits<VoidAllocator>
+                              ::template portable_rebind_alloc<ValueType>::type
+                           > type;
+   };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+   if(test::vector_test<MyCont>())
+      return 1;
+   if(test::vector_test<MyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyCont>())
+      return 1;
+
+   return 0;
+}
+
+struct boost_container_stable_vector;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_stable_vector>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::stable_vector<T, Allocator> type;
+   };
+};
+
+}}}   //namespace boost::container::test
+
+
+int main()
+{
+   recursive_vector_test();
+   {
+      //Now test move semantics
+      stable_vector<recursive_vector> original;
+      stable_vector<recursive_vector> move_ctor(boost::move(original));
+      stable_vector<recursive_vector> move_assign;
+      move_assign = boost::move(move_ctor);
+      move_assign.swap(original);
+   }
+
+   //Test non-copy-move operations
+   {
+      stable_vector<test::non_copymovable_int> sv;
+      sv.emplace_back();
+      sv.resize(10);
+      sv.resize(1);
+   }
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_cont_variants< std::allocator<void> >()){
+      std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::node_allocator
+   if(test_cont_variants< node_allocator<void> >()){
+      std::cerr << "test_cont_variants< node_allocator<void> > failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Default init test
+   ////////////////////////////////////
+   if(!test::default_init_test< stable_vector<int, test::default_init_allocator<int> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+   if(!boost::container::test::test_emplace
+      < stable_vector<test::EmplaceInt>, Options>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_stable_vector>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Initializer lists testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for
+      < boost::container::stable_vector<int> >())
+   {
+       std::cerr << "test_methods_with_initializer_list_as_argument failed" << std::endl;
+       return 1;
+   }
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::stable_vector<int> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction testing
+   ////////////////////////////////////
+   {
+      auto gold = std::vector{ 1, 2, 3 };
+      auto test = boost::container::stable_vector(gold.begin(), gold.end());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+         return 1;
+      }
+   }
+#endif
+
+   return 0;
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/static_vector_test.cpp b/test/static_vector_test.cpp
new file mode 100644
index 0000000..a80d0de
--- /dev/null
+++ b/test/static_vector_test.cpp
@@ -0,0 +1,835 @@
+// Boost.Container static_vector
+// Unit Test
+
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2013 Andrew Hundt.
+
+// Use, modification and distribution is subject to 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)
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/stable_vector.hpp>
+#include <boost/container/detail/iterator.hpp>
+#include "../../intrusive/test/iterator_test.hpp"
+
+#include <vector>
+#include <list>
+
+#include "static_vector_test.hpp"
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::static_vector<int, 10>;
+
+}}
+
+
+template <typename T, size_t N>
+void test_ctor_ndc()
+{
+   static_vector<T, N> s;
+   BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+   BOOST_TEST_EQ(s.size() , 0u);
+   BOOST_TEST(s.capacity() == N);
+   BOOST_TEST(s.max_size() == N);
+   BOOST_TEST_THROWS( s.at(0u), std::out_of_range );
+}
+
+template <typename T, size_t N>
+void test_ctor_nc(size_t n)
+{
+   static_vector<T, N> s(n);
+   BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+   BOOST_TEST(s.size() == n);
+   BOOST_TEST(s.capacity() == N);
+   BOOST_TEST(s.max_size() == N);
+   BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+   if ( 1 < n )
+   {
+      T val10(10);
+      s[0] = val10;
+      BOOST_TEST(T(10) == s[0]);
+      BOOST_TEST(T(10) == s.at(0));
+      T val20(20);
+      s.at(1) = val20;
+      BOOST_TEST(T(20) == s[1]);
+      BOOST_TEST(T(20) == s.at(1));
+   }
+}
+
+template <typename T, size_t N>
+void test_ctor_nd(size_t n, T const& v)
+{
+   static_vector<T, N> s(n, v);
+   BOOST_STATIC_ASSERT((static_vector<T, N>::static_capacity) == N);
+   BOOST_TEST(s.size() == n);
+   BOOST_TEST(s.capacity() == N);
+   BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+   if ( 1 < n )
+   {
+      BOOST_TEST(v == s[0]);
+      BOOST_TEST(v == s.at(0));
+      BOOST_TEST(v == s[1]);
+      BOOST_TEST(v == s.at(1));
+      s[0] = T(10);
+      BOOST_TEST(T(10) == s[0]);
+      BOOST_TEST(T(10) == s.at(0));
+      s.at(1) = T(20);
+      BOOST_TEST(T(20) == s[1]);
+      BOOST_TEST(T(20) == s.at(1));
+   }
+}
+
+void test_support_for_initializer_list()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   {
+      static_vector<int, 2> sv = {10, 8};
+      BOOST_TEST(10 == sv[0]);
+      BOOST_TEST(8 == sv[1]);
+
+      typedef static_vector<int, 1> sv_cap_1;
+      BOOST_TEST_THROWS(sv_cap_1({1, 1}), std::bad_alloc);
+   }
+
+   {
+      static_vector<int, 2> sv;
+      sv.assign({1, 2});
+      BOOST_TEST(1 == sv[0]);
+      BOOST_TEST(2 == sv[1]);
+
+      BOOST_TEST_THROWS(sv.assign({1, 2, 3}), std::bad_alloc);
+
+      static_vector<int, 3> greaterThanSv = {1, 2, 3};
+      BOOST_TEST_THROWS(sv = greaterThanSv, std::bad_alloc);
+   }
+
+   {
+      static_vector<int, 2> sv;
+      sv.insert(sv.begin(), {99, 95});
+      BOOST_TEST(99 == sv[0]);
+      BOOST_TEST(95 == sv[1]);
+
+      BOOST_TEST_THROWS(sv.insert(sv.begin(), {101, 102, 103}), std::bad_alloc);
+   }
+#endif
+}
+
+template <typename T, size_t N>
+void test_resize_nc(size_t n)
+{
+   static_vector<T, N> s;
+
+   s.resize(n);
+   BOOST_TEST(s.size() == n);
+   BOOST_TEST(s.capacity() == N);
+   BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+   if ( 1 < n )
+   {
+      T val10(10);
+      s[0] = val10;
+      BOOST_TEST(T(10) == s[0]);
+      BOOST_TEST(T(10) == s.at(0));
+      T val20(20);
+      s.at(1) = val20;
+      BOOST_TEST(T(20) == s[1]);
+      BOOST_TEST(T(20) == s.at(1));
+   }
+}
+
+template <typename T, size_t N>
+void test_resize_nd(size_t n, T const& v)
+{
+   static_vector<T, N> s;
+
+   s.resize(n, v);
+   BOOST_TEST(s.size() == n);
+   BOOST_TEST(s.capacity() == N);
+   BOOST_TEST_THROWS( s.at(n), std::out_of_range );
+   if ( 1 < n )
+   {
+      BOOST_TEST(v == s[0]);
+      BOOST_TEST(v == s.at(0));
+      BOOST_TEST(v == s[1]);
+      BOOST_TEST(v == s.at(1));
+      s[0] = T(10);
+      BOOST_TEST(T(10) == s[0]);
+      BOOST_TEST(T(10) == s.at(0));
+      s.at(1) = T(20);
+      BOOST_TEST(T(20) == s[1]);
+      BOOST_TEST(T(20) == s.at(1));
+   }
+}
+
+template <typename T, size_t N>
+void test_push_back_nd()
+{
+   static_vector<T, N> s;
+
+   BOOST_TEST(s.size() == 0);
+   BOOST_TEST_THROWS( s.at(0), std::out_of_range );
+
+   for ( size_t i = 0 ; i < N ; ++i )
+   {
+      T t(i);
+      s.push_back(t);
+      BOOST_TEST(s.size() == i + 1);
+      BOOST_TEST_THROWS( s.at(i + 1), std::out_of_range );
+      BOOST_TEST(T(i) == s.at(i));
+      BOOST_TEST(T(i) == s[i]);
+      BOOST_TEST(T(i) == s.back());
+      BOOST_TEST(T(0) == s.front());
+      BOOST_TEST(T(i) == *(s.data() + i));
+   }
+}
+
+template <typename T, size_t N>
+void test_pop_back_nd()
+{
+   static_vector<T, N> s;
+
+   for ( size_t i = 0 ; i < N ; ++i )
+   {
+      T t(i);
+      s.push_back(t);
+   }
+
+   for ( size_t i = N ; i > 1 ; --i )
+   {
+      s.pop_back();
+      BOOST_TEST(s.size() == i - 1);
+      BOOST_TEST_THROWS( s.at(i - 1), std::out_of_range );
+      BOOST_TEST(T(i - 2) == s.at(i - 2));
+      BOOST_TEST(T(i - 2) == s[i - 2]);
+      BOOST_TEST(T(i - 2) == s.back());
+      BOOST_TEST(T(0) == s.front());
+   }
+}
+
+template <typename It1, typename It2>
+void test_compare_ranges(It1 first1, It1 last1, It2 first2, It2 last2)
+{
+   BOOST_TEST(boost::container::iterator_distance(first1, last1) == boost::container::iterator_distance(first2, last2));
+   for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2 )
+      BOOST_TEST(*first1 == *first2);
+}
+
+template <typename T, size_t N, typename C>
+void test_copy_and_assign(C const& c)
+{
+   {
+      static_vector<T, N> s(c.begin(), c.end());
+      BOOST_TEST(s.size() == c.size());
+      test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+   }
+   {
+      static_vector<T, N> s;
+      BOOST_TEST(0 == s.size());
+      s.assign(c.begin(), c.end());
+      BOOST_TEST(s.size() == c.size());
+      test_compare_ranges(s.begin(), s.end(), c.begin(), c.end());
+   }
+}
+
+template <typename T, size_t N>
+void test_copy_and_assign_nd(T const& val)
+{
+   static_vector<T, N> s;
+   std::vector<T> v;
+   std::list<T> l;
+
+   for ( size_t i = 0 ; i < N ; ++i )
+   {
+      T t(i);
+      s.push_back(t);
+      v.push_back(t);
+      l.push_back(t);
+   }
+   // copy ctor
+   {
+      static_vector<T, N> s1(s);
+      BOOST_TEST(s.size() == s1.size());
+      test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+   }
+   // copy assignment
+   {
+      static_vector<T, N> s1;
+      BOOST_TEST(0 == s1.size());
+      s1 = s;
+      BOOST_TEST(s.size() == s1.size());
+      test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+   }
+
+   // ctor(Iter, Iter) and assign(Iter, Iter)
+   test_copy_and_assign<T, N>(s);
+   test_copy_and_assign<T, N>(v);
+   test_copy_and_assign<T, N>(l);
+
+   // assign(N, V)
+   {
+      static_vector<T, N> s1(s);
+      test_compare_ranges(s.begin(), s.end(), s1.begin(), s1.end());
+      std::vector<T> a(N, val);
+      s1.assign(N, val);
+      test_compare_ranges(a.begin(), a.end(), s1.begin(), s1.end());
+   }
+
+   stable_vector<T> bsv(s.begin(), s.end());
+   vector<T> bv(s.begin(), s.end());
+   test_copy_and_assign<T, N>(bsv);
+   test_copy_and_assign<T, N>(bv);
+}
+
+template <typename T, size_t N>
+void test_iterators_nd()
+{
+   static_vector<T, N> s;
+   std::vector<T> v;
+
+   for ( size_t i = 0 ; i < N ; ++i )
+   {
+      s.push_back(T(i));
+      v.push_back(T(i));
+   }
+
+   test_compare_ranges(s.begin(), s.end(), v.begin(), v.end());
+   test_compare_ranges(s.rbegin(), s.rend(), v.rbegin(), v.rend());
+
+   s.assign(v.rbegin(), v.rend());
+
+   test_compare_ranges(s.begin(), s.end(), v.rbegin(), v.rend());
+   test_compare_ranges(s.rbegin(), s.rend(), v.begin(), v.end());
+}
+
+template <typename T, size_t N>
+void test_erase_nd()
+{
+   static_vector<T, N> s;
+   typedef typename static_vector<T, N>::iterator It;
+
+   for ( size_t i = 0 ; i < N ; ++i )
+      s.push_back(T(i));
+
+   // erase(pos)
+   {
+      for ( size_t i = 0 ; i < N ; ++i )
+      {
+          static_vector<T, N> s1(s);
+          It it = s1.erase(s1.begin() + i);
+          BOOST_TEST(s1.begin() + i == it);
+          BOOST_TEST(s1.size() == N - 1);
+          for ( size_t j = 0 ; j < i ; ++j )
+              BOOST_TEST(s1[j] == T(j));
+          for ( size_t j = i+1 ; j < N ; ++j )
+              BOOST_TEST(s1[j-1] == T(j));
+      }
+   }
+   // erase(first, last)
+   {
+      size_t n = N/3;
+      for ( size_t i = 0 ; i <= N ; ++i )
+      {
+          static_vector<T, N> s1(s);
+          size_t removed = i + n < N ? n : N - i;
+          It it = s1.erase(s1.begin() + i, s1.begin() + i + removed);
+          BOOST_TEST(s1.begin() + i == it);
+          BOOST_TEST(s1.size() == N - removed);
+          for ( size_t j = 0 ; j < i ; ++j )
+              BOOST_TEST(s1[j] == T(j));
+          for ( size_t j = i+n ; j < N ; ++j )
+              BOOST_TEST(s1[j-n] == T(j));
+      }
+   }
+}
+
+template <typename T, size_t N, typename SV, typename C>
+void test_insert(SV const& s, C const& c)
+{
+   size_t h = N/2;
+   size_t n = size_t(h/1.5f);
+
+   for ( size_t i = 0 ; i <= h ; ++i )
+   {
+      static_vector<T, N> s1(s);
+
+      typename C::const_iterator it = c.begin();
+      boost::container::iterator_advance(it, n);
+      typename static_vector<T, N>::iterator
+          it1 = s1.insert(s1.begin() + i, c.begin(), it);
+
+      BOOST_TEST(s1.begin() + i == it1);
+      BOOST_TEST(s1.size() == h+n);
+      for ( size_t j = 0 ; j < i ; ++j )
+          BOOST_TEST(s1[j] == T(j));
+      for ( size_t j = 0 ; j < n ; ++j )
+          BOOST_TEST(s1[j+i] == T(100 + j));
+      for ( size_t j = 0 ; j < h-i ; ++j )
+          BOOST_TEST(s1[j+i+n] == T(j+i));
+   }
+}
+
+template <typename T, size_t N>
+void test_insert_nd(T const& val)
+{
+   size_t h = N/2;
+
+   static_vector<T, N> s, ss;
+   std::vector<T> v;
+   std::list<T> l;
+
+   typedef typename static_vector<T, N>::iterator It;
+
+   for ( size_t i = 0 ; i < h ; ++i )
+   {
+      s.push_back(T(i));
+      ss.push_back(T(100 + i));
+      v.push_back(T(100 + i));
+      l.push_back(T(100 + i));
+   }
+
+   // insert(pos, val)
+   {
+      for ( size_t i = 0 ; i <= h ; ++i )
+      {
+          static_vector<T, N> s1(s);
+          It it = s1.insert(s1.begin() + i, val);
+          BOOST_TEST(s1.begin() + i == it);
+          BOOST_TEST(s1.size() == h+1);
+          for ( size_t j = 0 ; j < i ; ++j )
+              BOOST_TEST(s1[j] == T(j));
+          BOOST_TEST(s1[i] == val);
+          for ( size_t j = 0 ; j < h-i ; ++j )
+              BOOST_TEST(s1[j+i+1] == T(j+i));
+      }
+   }
+   // insert(pos, n, val)
+   {
+      size_t n = size_t(h/1.5f);
+      for ( size_t i = 0 ; i <= h ; ++i )
+      {
+          static_vector<T, N> s1(s);
+          It it = s1.insert(s1.begin() + i, n, val);
+          BOOST_TEST(s1.begin() + i == it);
+          BOOST_TEST(s1.size() == h+n);
+          for ( size_t j = 0 ; j < i ; ++j )
+              BOOST_TEST(s1[j] == T(j));
+          for ( size_t j = 0 ; j < n ; ++j )
+              BOOST_TEST(s1[j+i] == val);
+          for ( size_t j = 0 ; j < h-i ; ++j )
+              BOOST_TEST(s1[j+i+n] == T(j+i));
+      }
+   }
+   // insert(pos, first, last)
+   test_insert<T, N>(s, ss);
+   test_insert<T, N>(s, v);
+   test_insert<T, N>(s, l);
+
+   stable_vector<T> bsv(ss.begin(), ss.end());
+   vector<T> bv(ss.begin(), ss.end());
+   test_insert<T, N>(s, bv);
+   test_insert<T, N>(s, bsv);
+}
+
+template <typename T>
+void test_capacity_0_nd()
+{
+   static_vector<T, 10> v(5u, T(0));
+
+   static_vector<T, 0 > s;
+   BOOST_TEST(s.size() == 0);
+   BOOST_TEST(s.capacity() == 0);
+   BOOST_TEST_THROWS(s.at(0), std::out_of_range);
+   BOOST_TEST_THROWS(s.resize(5u, T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), 5u, T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.assign(5u, T(0)), std::bad_alloc);
+   typedef static_vector<T, 0> static_vector_0_t;
+   BOOST_TEST_THROWS(static_vector_0_t s2(v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(static_vector_0_t s1(5u, T(0)), std::bad_alloc);
+}
+
+template <typename T, size_t N>
+void test_exceptions_nd()
+{
+   static_vector<T, N> v(N, T(0));
+   static_vector<T, N/2> s(N/2, T(0));
+
+   BOOST_TEST_THROWS(s.resize(N, T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.push_back(T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), N, T(0)), std::bad_alloc);
+   BOOST_TEST_THROWS(s.insert(s.end(), v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(s.assign(v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(s.assign(N, T(0)), std::bad_alloc);
+   typedef static_vector<T, N/2> static_vector_n_half_t;
+   BOOST_TEST_THROWS(static_vector_n_half_t s2(v.begin(), v.end()), std::bad_alloc);
+   BOOST_TEST_THROWS(static_vector_n_half_t s1(N, T(0)), std::bad_alloc);
+}
+
+template <typename T, size_t N>
+void test_swap_and_move_nd()
+{
+   {
+      static_vector<T, N> v1, v2, v3, v4;
+      static_vector<T, N> s1, s2;
+      static_vector<T, N> s4;
+
+      for (size_t i = 0 ; i < N ; ++i )
+      {
+          v1.push_back(T(i));
+          v2.push_back(T(i));
+          v3.push_back(T(i));
+          v4.push_back(T(i));
+      }
+      for (size_t i = 0 ; i < N/2 ; ++i )
+      {
+          s1.push_back(T(100 + i));
+          s2.push_back(T(100 + i));
+          s4.push_back(T(100 + i));
+      }
+
+      s1.swap(v1);
+      s2 = boost::move(v2);
+      static_vector<T, N> s3(boost::move(v3));
+      s4.swap(v4);
+
+      BOOST_TEST(v1.size() == N/2);
+      BOOST_TEST(s1.size() == N);
+      //iG moving does not imply emptying source
+      //BOOST_TEST(v2.size() == 0);
+      BOOST_TEST(s2.size() == N);
+      //iG moving does not imply emptying source
+      //BOOST_TEST(v3.size() == 0);
+      BOOST_TEST(s3.size() == N);
+      BOOST_TEST(v4.size() == N/2);
+      BOOST_TEST(s4.size() == N);
+      for (size_t i = 0 ; i < N/2 ; ++i )
+      {
+          BOOST_TEST(v1[i] == T(100 + i));
+          BOOST_TEST(v4[i] == T(100 + i));
+      }
+      for (size_t i = 0 ; i < N ; ++i )
+      {
+          BOOST_TEST(s1[i] == T(i));
+          BOOST_TEST(s2[i] == T(i));
+          BOOST_TEST(s3[i] == T(i));
+          BOOST_TEST(s4[i] == T(i));
+      }
+   }
+   {
+      static_vector<T, N> v1, v2, v3;
+      static_vector<T, N/2> s1, s2, s3;
+
+      for (size_t i = 0 ; i < N/2 ; ++i )
+      {
+          v1.push_back(T(i));
+          v2.push_back(T(i));
+          v3.push_back(T(i));
+      }
+      for (size_t i = 0 ; i < N/3 ; ++i )
+      {
+          s1.push_back(T(100 + i));
+          s2.push_back(T(100 + i));
+      }
+
+      s1.swap(v1);
+      s3 = v2;
+      s2 = boost::move(v2);
+      static_vector<T, N/2> s4(boost::move(v3));
+
+      BOOST_TEST(v1.size() == N/3);
+      BOOST_TEST(s1.size() == N/2);
+      //iG moving does not imply emptying source
+      //BOOST_TEST(v2.size() == 0);
+      BOOST_TEST(s2.size() == N/2);
+      BOOST_TEST(s3.size() == N/2);
+      //iG moving does not imply emptying source
+      //BOOST_TEST(v3.size() == 0);
+      BOOST_TEST(s4.size() == N/2);
+      for (size_t i = 0 ; i < N/3 ; ++i )
+          BOOST_TEST(v1[i] == T(100 + i));
+      for (size_t i = 0 ; i < N/2 ; ++i )
+      {
+          BOOST_TEST(s1[i] == T(i));
+          BOOST_TEST(s2[i] == T(i));
+          BOOST_TEST(s3[i] == T(i));
+          BOOST_TEST(s4[i] == T(i));
+      }
+   }
+   {
+      typedef static_vector<T, N/2> small_vector_t;
+      static_vector<T, N> v(N, T(0));
+      small_vector_t s(N/2, T(1));
+      BOOST_TEST_THROWS(s.swap(v), std::bad_alloc);
+      v.resize(N, T(0));
+      BOOST_TEST_THROWS(s = boost::move(v), std::bad_alloc);
+      BOOST_TEST_THROWS(s = v, std::bad_alloc);
+      v.resize(N, T(0));
+      BOOST_TEST_THROWS(small_vector_t s2(boost::move(v)), std::bad_alloc);
+   }
+}
+
+template <typename T, size_t N>
+void test_emplace_0p()
+{
+   //emplace_back()
+   {
+      static_vector<T, N> v;
+
+      for (int i = 0 ; i < int(N) ; ++i )
+          v.emplace_back();
+      BOOST_TEST(v.size() == N);
+      BOOST_TEST_THROWS(v.emplace_back(), std::bad_alloc);
+   }
+}
+
+template <typename T, size_t N>
+void test_emplace_2p()
+{
+   //emplace_back(pos, int, int)
+   {
+      static_vector<T, N> v;
+
+      for (int i = 0 ; i < int(N) ; ++i )
+          v.emplace_back(i, 100 + i);
+      BOOST_TEST(v.size() == N);
+      BOOST_TEST_THROWS(v.emplace_back(N, 100 + N), std::bad_alloc);
+      BOOST_TEST(v.size() == N);
+      for (int i = 0 ; i < int(N) ; ++i )
+          BOOST_TEST(v[i] == T(i, 100 + i));
+   }
+
+   // emplace(pos, int, int)
+   {
+      typedef typename static_vector<T, N>::iterator It;
+
+      int h = N / 2;
+
+      static_vector<T, N> v;
+      for ( int i = 0 ; i < h ; ++i )
+          v.emplace_back(i, 100 + i);
+
+      for ( int i = 0 ; i <= h ; ++i )
+      {
+          static_vector<T, N> vv(v);
+          It it = vv.emplace(vv.begin() + i, i+100, i+200);
+          BOOST_TEST(vv.begin() + i == it);
+          BOOST_TEST(vv.size() == size_t(h+1));
+          for ( int j = 0 ; j < i ; ++j )
+              BOOST_TEST(vv[j] == T(j, j+100));
+          BOOST_TEST(vv[i] == T(i+100, i+200));
+          for ( int j = 0 ; j < h-i ; ++j )
+              BOOST_TEST(vv[j+i+1] == T(j+i, j+i+100));
+      }
+   }
+}
+
+template <typename T, size_t N>
+void test_sv_elem(T const& t)
+{
+   typedef static_vector<T, N> V;
+
+   static_vector<V, N> v;
+
+   v.push_back(V(N/2, t));
+   V vvv(N/2, t);
+   v.push_back(boost::move(vvv));
+   v.insert(v.begin(), V(N/2, t));
+   v.insert(v.end(), V(N/2, t));
+   v.emplace_back(N/2, t);
+}
+
+bool default_init_test()//Test for default initialization
+{
+   const std::size_t Capacity = 100;
+
+   typedef static_vector<int, Capacity> di_vector_t;
+
+   {
+      di_vector_t v(Capacity, default_init);
+   }
+   {
+      di_vector_t v;
+      int *p = v.data();
+
+      for(std::size_t i = 0; i != Capacity; ++i, ++p){
+         *p = static_cast<int>(i);
+      }
+
+      //Destroy the vector, p still pointing to the storage
+      v.~di_vector_t();
+
+      di_vector_t &rv = *::new(&v)di_vector_t(Capacity, default_init);
+      di_vector_t::iterator it = rv.begin();
+
+      for(std::size_t i = 0; i != Capacity; ++i, ++it){
+         if(*it != static_cast<int>(i))
+            return false;
+      }
+
+      v.~di_vector_t();
+   }
+   {
+      di_vector_t v;
+
+      int *p = v.data();
+      for(std::size_t i = 0; i != Capacity; ++i, ++p){
+         *p = static_cast<int>(i+100);
+      }
+
+      v.resize(Capacity, default_init);
+
+      di_vector_t::iterator it = v.begin();
+      for(std::size_t i = 0; i != Capacity; ++i, ++it){
+         if(*it != static_cast<int>(i+100))
+            return false;
+      }
+   }
+
+   return true;
+}
+
+
+int main(int, char* [])
+{
+   using boost::container::test::movable_and_copyable_int;
+   using boost::container::test::produce_movable_and_copyable_int;
+   BOOST_TEST(counting_value::count() == 0);
+
+   test_ctor_ndc<int, 10>();
+   test_ctor_ndc<value_ndc, 10>();
+   test_ctor_ndc<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_ctor_ndc<shptr_value, 10>();
+   test_ctor_ndc<movable_and_copyable_int, 10>();
+
+   test_ctor_nc<int, 10>(5);
+   test_ctor_nc<value_nc, 10>(5);
+   test_ctor_nc<counting_value, 10>(5);
+   BOOST_TEST(counting_value::count() == 0);
+   test_ctor_nc<shptr_value, 10>(5);
+   test_ctor_nc<movable_and_copyable_int, 10>(5);
+
+   test_ctor_nd<int, 10>(5, 1);
+   test_ctor_nd<value_nd, 10>(5, value_nd(1));
+   test_ctor_nd<counting_value, 10>(5, counting_value(1));
+   BOOST_TEST(counting_value::count() == 0);
+   test_ctor_nd<shptr_value, 10>(5, shptr_value(1));
+   test_ctor_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+   test_resize_nc<int, 10>(5);
+   test_resize_nc<value_nc, 10>(5);
+   test_resize_nc<counting_value, 10>(5);
+   BOOST_TEST(counting_value::count() == 0);
+   test_resize_nc<shptr_value, 10>(5);
+   test_resize_nc<movable_and_copyable_int, 10>(5);
+
+   test_resize_nd<int, 10>(5, 1);
+   test_resize_nd<value_nd, 10>(5, value_nd(1));
+   test_resize_nd<counting_value, 10>(5, counting_value(1));
+   BOOST_TEST(counting_value::count() == 0);
+   test_resize_nd<shptr_value, 10>(5, shptr_value(1));
+   test_resize_nd<movable_and_copyable_int, 10>(5, produce_movable_and_copyable_int());
+
+   test_push_back_nd<int, 10>();
+   test_push_back_nd<value_nd, 10>();
+   test_push_back_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_push_back_nd<shptr_value, 10>();
+   test_push_back_nd<movable_and_copyable_int, 10>();
+
+   test_pop_back_nd<int, 10>();
+   test_pop_back_nd<value_nd, 10>();
+   test_pop_back_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_pop_back_nd<shptr_value, 10>();
+   test_pop_back_nd<movable_and_copyable_int, 10>();
+
+   test_copy_and_assign_nd<int, 10>(1);
+   test_copy_and_assign_nd<value_nd, 10>(value_nd(1));
+   test_copy_and_assign_nd<counting_value, 10>(counting_value(1));
+   BOOST_TEST(counting_value::count() == 0);
+   test_copy_and_assign_nd<shptr_value, 10>(shptr_value(1));
+   test_copy_and_assign_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+   test_iterators_nd<int, 10>();
+   test_iterators_nd<value_nd, 10>();
+   test_iterators_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_iterators_nd<shptr_value, 10>();
+   test_iterators_nd<movable_and_copyable_int, 10>();
+
+   test_erase_nd<int, 10>();
+   test_erase_nd<value_nd, 10>();
+   test_erase_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_erase_nd<shptr_value, 10>();
+   test_erase_nd<movable_and_copyable_int, 10>();
+
+   test_insert_nd<int, 10>(50);
+   test_insert_nd<value_nd, 10>(value_nd(50));
+   test_insert_nd<counting_value, 10>(counting_value(50));
+   BOOST_TEST(counting_value::count() == 0);
+   test_insert_nd<shptr_value, 10>(shptr_value(50));
+   test_insert_nd<movable_and_copyable_int, 10>(produce_movable_and_copyable_int());
+
+   test_capacity_0_nd<int>();
+   test_capacity_0_nd<value_nd>();
+   test_capacity_0_nd<counting_value>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_capacity_0_nd<shptr_value>();
+   test_capacity_0_nd<movable_and_copyable_int>();
+
+   test_exceptions_nd<int, 10>();
+   test_exceptions_nd<value_nd, 10>();
+   test_exceptions_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_exceptions_nd<shptr_value, 10>();
+   test_exceptions_nd<movable_and_copyable_int, 10>();
+
+   test_swap_and_move_nd<int, 10>();
+   test_swap_and_move_nd<value_nd, 10>();
+   test_swap_and_move_nd<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+   test_swap_and_move_nd<shptr_value, 10>();
+   test_swap_and_move_nd<movable_and_copyable_int, 10>();
+
+   test_emplace_0p<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+
+   test_emplace_2p<counting_value, 10>();
+   BOOST_TEST(counting_value::count() == 0);
+
+   test_sv_elem<int, 10>(50);
+   test_sv_elem<value_nd, 10>(value_nd(50));
+   test_sv_elem<counting_value, 10>(counting_value(50));
+   BOOST_TEST(counting_value::count() == 0);
+   test_sv_elem<shptr_value, 10>(shptr_value(50));
+   test_sv_elem<movable_and_copyable_int, 10>(movable_and_copyable_int(50));
+
+   BOOST_TEST(default_init_test() == true);
+
+   test_support_for_initializer_list();
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::static_vector<int, 3> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+   }
+
+   return boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/static_vector_test.hpp b/test/static_vector_test.hpp
new file mode 100644
index 0000000..ab931b2
--- /dev/null
+++ b/test/static_vector_test.hpp
@@ -0,0 +1,103 @@
+// Boost.Container static_vector
+// Unit Test
+
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2013 Andrew Hundt.
+
+// Use, modification and distribution is subject to 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)
+
+#ifndef BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
+#define BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
+
+#include <boost/container/static_vector.hpp>
+
+#define BOOST_SP_DISABLE_THREADS
+#include <boost/shared_ptr.hpp>
+#include "movable_int.hpp"
+
+using namespace boost::container;
+
+class value_ndc
+{
+public:
+    explicit value_ndc(int a) : aa(a) {}
+    ~value_ndc() {}
+    bool operator==(value_ndc const& v) const { return aa == v.aa; }
+    bool operator<(value_ndc const& v) const { return aa < v.aa; }
+private:
+    value_ndc(value_ndc const&) {}
+    value_ndc & operator=(value_ndc const&) { return *this; }
+    int aa;
+};
+
+class value_nd
+{
+public:
+    explicit value_nd(int a) : aa(a) {}
+    ~value_nd() {}
+    bool operator==(value_nd const& v) const { return aa == v.aa; }
+    bool operator<(value_nd const& v) const { return aa < v.aa; }
+private:
+    int aa;
+};
+
+class value_nc
+{
+public:
+    explicit value_nc(int a = 0) : aa(a) {}
+    ~value_nc() {}
+    bool operator==(value_nc const& v) const { return aa == v.aa; }
+    bool operator<(value_nc const& v) const { return aa < v.aa; }
+private:
+    value_nc(value_nc const&) {}
+    value_nc & operator=(value_ndc const&) { return *this; }
+    int aa;
+};
+
+class counting_value
+{
+    BOOST_COPYABLE_AND_MOVABLE(counting_value)
+
+public:
+    explicit counting_value(int a = 0, int b = 0) : aa(a), bb(b) { ++c(); }
+    counting_value(counting_value const& v) : aa(v.aa), bb(v.bb) { ++c(); }
+    counting_value(BOOST_RV_REF(counting_value) p) : aa(p.aa), bb(p.bb) { p.aa = 0; p.bb = 0; ++c(); }                      // Move constructor
+    counting_value& operator=(BOOST_RV_REF(counting_value) p) { aa = p.aa; p.aa = 0; bb = p.bb; p.bb = 0; return *this; }   // Move assignment
+    counting_value& operator=(BOOST_COPY_ASSIGN_REF(counting_value) p) { aa = p.aa; bb = p.bb; return *this; }              // Copy assignment
+    ~counting_value() { --c(); }
+    bool operator==(counting_value const& v) const { return aa == v.aa && bb == v.bb; }
+    bool operator<(counting_value const& v) const { return aa < v.aa || ( aa == v.aa && bb < v.bb ); }
+    static size_t count() { return c(); }
+
+private:
+    static size_t & c() { static size_t co = 0; return co; }
+    int aa, bb;
+};
+
+namespace boost {
+
+template <class T>
+struct has_nothrow_move;
+
+template <>
+struct has_nothrow_move<counting_value>
+{
+    static const bool value = true;
+};
+
+}
+
+class shptr_value
+{
+    typedef boost::shared_ptr<int> Ptr;
+public:
+    explicit shptr_value(int a = 0) : m_ptr(new int(a)) {}
+    bool operator==(shptr_value const& v) const { return *m_ptr == *(v.m_ptr); }
+    bool operator<(shptr_value const& v) const { return *m_ptr < *(v.m_ptr); }
+private:
+    boost::shared_ptr<int> m_ptr;
+};
+
+#endif // BOOST_CONTAINER_TEST_STATIC_VECTOR_TEST_HPP
diff --git a/test/string_test.cpp b/test/string_test.cpp
new file mode 100644
index 0000000..16397b0
--- /dev/null
+++ b/test/string_test.cpp
@@ -0,0 +1,590 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/container/string.hpp>
+#include <string>
+#include <vector>
+#include <boost/container/detail/algorithm.hpp> //equal()
+#include <cstring>
+#include <cstdio>
+#include <cstddef>
+#include <new>
+#include "dummy_test_allocator.hpp"
+#include "check_equal_containers.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "propagate_allocator_test.hpp"
+#include "default_init_test.hpp"
+#include "comparison_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+#include <boost/utility/string_view.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+typedef test::simple_allocator<char>           SimpleCharAllocator;
+typedef basic_string<char, std::char_traits<char>, SimpleCharAllocator> SimpleString;
+typedef test::simple_allocator<SimpleString>    SimpleStringAllocator;
+typedef test::simple_allocator<wchar_t>              SimpleWCharAllocator;
+typedef basic_string<wchar_t, std::char_traits<wchar_t>, SimpleWCharAllocator> SimpleWString;
+typedef test::simple_allocator<SimpleWString>         SimpleWStringAllocator;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiations of container::basic_string
+template class basic_string<char,    std::char_traits<char>, SimpleCharAllocator>;
+template class basic_string<wchar_t, std::char_traits<wchar_t>, SimpleWCharAllocator>;
+template class basic_string<char,    std::char_traits<char>, std::allocator<char> >;
+template class basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >;
+
+//Explicit instantiation of container::vectors of container::strings
+template class vector<SimpleString, SimpleStringAllocator>;
+template class vector<SimpleWString, SimpleWStringAllocator>;
+
+}}
+
+struct StringEqual
+{
+   template<class Str1, class Str2>
+   bool operator ()(const Str1 &string1, const Str2 &string2) const
+   {
+      if(string1.size() != string2.size())
+         return false;
+      return std::char_traits<typename Str1::value_type>::compare
+         (string1.c_str(), string2.c_str(), string1.size()) == 0;
+   }
+};
+
+//Function to check if both lists are equal
+template<class StrVector1, class StrVector2>
+bool CheckEqualStringVector(StrVector1 *strvect1, StrVector2 *strvect2)
+{
+   StringEqual comp;
+   return boost::container::algo_equal(strvect1->begin(), strvect1->end(),
+                     strvect2->begin(), comp);
+}
+
+template<class ForwardIt>
+ForwardIt unique(ForwardIt first, ForwardIt const last)
+{
+   if(first == last){
+      ForwardIt i = first;
+      //Find first adjacent pair
+      while(1){
+         if(++i == last){
+            return last;
+         }
+         else if(*first == *i){
+            break;
+         }
+         ++first;
+      }
+      //Now overwrite skipping adjacent elements
+      while (++i != last) {
+         if (!(*first == *i)) {
+            *(++first) = boost::move(*i);
+         }
+      }
+      ++first;
+   }
+   return first;
+}
+
+template<class CharType>
+struct string_literals;
+
+template<>
+struct string_literals<char>
+{
+   static const char *String()
+      {  return "String";  }
+   static const char *Prefix()
+      {  return "Prefix";  }
+   static const char *Suffix()
+      {  return "Suffix";  }
+   static const char *LongString()
+      {  return "LongLongLongLongLongLongLongLongLongLongLongLongLongString";  }
+   static char Char()
+      {  return 'C';  }
+   static void sprintf_number(char *buf, int number)
+   {
+      std::sprintf(buf, "%i", number);
+   }
+};
+
+template<>
+struct string_literals<wchar_t>
+{
+   static const wchar_t *String()
+      {  return L"String";  }
+   static const wchar_t *Prefix()
+      {  return L"Prefix";  }
+   static const wchar_t *Suffix()
+      {  return L"Suffix";  }
+   static const wchar_t *LongString()
+      {  return L"LongLongLongLongLongLongLongLongLongLongLongLongLongString";  }
+   static wchar_t Char()
+      {  return L'C';  }
+   static void sprintf_number(wchar_t *buffer, unsigned int number)
+   {
+      //For compilers without wsprintf, print it backwards
+      const wchar_t *digits = L"0123456789";
+      wchar_t *buf = buffer;
+
+      while(1){
+         int rem = number % 10;
+         number  = number / 10;
+
+         *buf = digits[rem];
+         ++buf;
+         if(!number){
+            *buf = 0;
+            break;
+         }
+      }
+
+   }
+};
+
+template<class CharType>
+int string_test()
+{
+   typedef std::basic_string<CharType> StdString;
+   typedef vector<StdString>  StdStringVector;
+   typedef basic_string<CharType> BoostString;
+   typedef vector<BoostString> BoostStringVector;
+
+   const int MaxSize = 100;
+
+   {
+      BoostStringVector *boostStringVect = new BoostStringVector;
+      StdStringVector *stdStringVect = new StdStringVector;
+      BoostString auxBoostString;
+      StdString auxStdString(StdString(auxBoostString.begin(), auxBoostString.end() ));
+
+      CharType buffer [20];
+
+      //First, push back
+      for(int i = 0; i < MaxSize; ++i){
+         auxBoostString = string_literals<CharType>::String();
+         auxStdString = string_literals<CharType>::String();
+         string_literals<CharType>::sprintf_number(buffer, i);
+         auxBoostString += buffer;
+         auxStdString += buffer;
+         boostStringVect->push_back(auxBoostString);
+         stdStringVect->push_back(auxStdString);
+      }
+
+      if(auxBoostString.data() != const_cast<const BoostString&>(auxBoostString).data() &&
+         auxBoostString.data() != &auxBoostString[0])
+         return 1;
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+         return 1;
+      }
+
+      //Now push back moving
+      for(int i = 0; i < MaxSize; ++i){
+         auxBoostString = string_literals<CharType>::String();
+         auxStdString = string_literals<CharType>::String();
+         string_literals<CharType>::sprintf_number(buffer, i);
+         auxBoostString += buffer;
+         auxStdString += buffer;
+         boostStringVect->push_back(boost::move(auxBoostString));
+         stdStringVect->push_back(auxStdString);
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+         return 1;
+      }
+
+      //push front
+      for(int i = 0; i < MaxSize; ++i){
+         auxBoostString = string_literals<CharType>::String();
+         auxStdString = string_literals<CharType>::String();
+         string_literals<CharType>::sprintf_number(buffer, i);
+         auxBoostString += buffer;
+         auxStdString += buffer;
+         boostStringVect->insert(boostStringVect->begin(), auxBoostString);
+         stdStringVect->insert(stdStringVect->begin(), auxStdString);
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+         return 1;
+      }
+
+      //Now push front moving
+      for(int i = 0; i < MaxSize; ++i){
+         auxBoostString = string_literals<CharType>::String();
+         auxStdString = string_literals<CharType>::String();
+         string_literals<CharType>::sprintf_number(buffer, i);
+         auxBoostString += buffer;
+         auxStdString += buffer;
+         boostStringVect->insert(boostStringVect->begin(), boost::move(auxBoostString));
+         stdStringVect->insert(stdStringVect->begin(), auxStdString);
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)){
+         return 1;
+      }
+
+      //Now test long and short representation swapping
+
+      //Short first
+      auxBoostString = string_literals<CharType>::String();
+      auxStdString = string_literals<CharType>::String();
+      BoostString boost_swapper;
+      StdString std_swapper;
+      boost_swapper.swap(auxBoostString);
+      std_swapper.swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+      if(!StringEqual()(boost_swapper, std_swapper))
+         return 1;
+      boost_swapper.swap(auxBoostString);
+      std_swapper.swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+      if(!StringEqual()(boost_swapper, std_swapper))
+         return 1;
+
+      //Shrink_to_fit
+      auxBoostString.shrink_to_fit();
+      StdString(auxStdString).swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+
+      //Reserve + shrink_to_fit
+      auxBoostString.reserve(boost_swapper.size()*2+1);
+      auxStdString.reserve(std_swapper.size()*2+1);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+
+      auxBoostString.shrink_to_fit();
+      StdString(auxStdString).swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+
+      //Long string
+      auxBoostString = string_literals<CharType>::LongString();
+      auxStdString   = string_literals<CharType>::LongString();
+      boost_swapper = BoostString();
+      std_swapper = StdString();
+      boost_swapper.swap(auxBoostString);
+      std_swapper.swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+      if(!StringEqual()(boost_swapper, std_swapper))
+         return 1;
+      boost_swapper.swap(auxBoostString);
+      std_swapper.swap(auxStdString);
+
+      //Shrink_to_fit
+      auxBoostString.shrink_to_fit();
+      StdString(auxStdString).swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+
+      auxBoostString.clear();
+      auxStdString.clear();
+      auxBoostString.shrink_to_fit();
+      StdString(auxStdString).swap(auxStdString);
+      if(!StringEqual()(auxBoostString, auxStdString))
+         return 1;
+
+      //No sort
+      std::sort(boostStringVect->begin(), boostStringVect->end());
+      std::sort(stdStringVect->begin(), stdStringVect->end());
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      const CharType *prefix    = string_literals<CharType>::Prefix();
+      const int  prefix_size    = std::char_traits<CharType>::length(prefix);
+      const CharType *sufix      = string_literals<CharType>::Suffix();
+
+      for(int i = 0; i < MaxSize; ++i){
+         (*boostStringVect)[i].append(sufix);
+         (*stdStringVect)[i].append(sufix);
+         (*boostStringVect)[i].insert((*boostStringVect)[i].begin(),
+                                    prefix, prefix + prefix_size);
+         (*stdStringVect)[i].insert((*stdStringVect)[i].begin(),
+                                    prefix, prefix + prefix_size);
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      for(int i = 0; i < MaxSize; ++i){
+         std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
+         std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      for(int i = 0; i < MaxSize; ++i){
+         std::reverse((*boostStringVect)[i].begin(), (*boostStringVect)[i].end());
+         std::reverse((*stdStringVect)[i].begin(), (*stdStringVect)[i].end());
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      for(int i = 0; i < MaxSize; ++i){
+         std::sort(boostStringVect->begin(), boostStringVect->end());
+         std::sort(stdStringVect->begin(), stdStringVect->end());
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      for(int i = 0; i < MaxSize; ++i){
+         (*boostStringVect)[i].replace((*boostStringVect)[i].begin(),
+                                    (*boostStringVect)[i].end(),
+                                    string_literals<CharType>::String());
+         (*stdStringVect)[i].replace((*stdStringVect)[i].begin(),
+                                    (*stdStringVect)[i].end(),
+                                    string_literals<CharType>::String());
+      }
+
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      boostStringVect->erase(::unique(boostStringVect->begin(), boostStringVect->end()),
+                           boostStringVect->end());
+      stdStringVect->erase(::unique(stdStringVect->begin(), stdStringVect->end()),
+                           stdStringVect->end());
+      if(!CheckEqualStringVector(boostStringVect, stdStringVect)) return 1;
+
+      //Check addition
+      {
+         BoostString bs2 = string_literals<CharType>::String();
+         StdString   ss2 = string_literals<CharType>::String();
+         BoostString bs3 = string_literals<CharType>::Suffix();
+         StdString   ss3 = string_literals<CharType>::Suffix();
+         BoostString bs4 = bs2 + bs3;
+         StdString   ss4 = ss2 + ss3;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = bs2 + BoostString();
+         ss4 = ss2 + StdString();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = BoostString() + bs2;
+         ss4 = StdString() + ss2;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs4 = BoostString() + boost::move(bs2);
+         ss4 = StdString() + boost::move(ss2);
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = boost::move(bs2) + BoostString();
+         ss4 = boost::move(ss2) + StdString();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = string_literals<CharType>::Prefix() + boost::move(bs2);
+         ss4 = string_literals<CharType>::Prefix() + boost::move(ss2);
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = boost::move(bs2) + string_literals<CharType>::Suffix();
+         ss4 = boost::move(ss2) + string_literals<CharType>::Suffix();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = string_literals<CharType>::Prefix() + bs2;
+         ss4 = string_literals<CharType>::Prefix() + ss2;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = bs2 + string_literals<CharType>::Suffix();
+         ss4 = ss2 + string_literals<CharType>::Suffix();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = string_literals<CharType>::Char() + bs2;
+         ss4 = string_literals<CharType>::Char() + ss2;
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         bs2 = string_literals<CharType>::String();
+         ss2 = string_literals<CharType>::String();
+         bs4 = bs2 + string_literals<CharType>::Char();
+         ss4 = ss2 + string_literals<CharType>::Char();
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         //Check front/back/begin/end
+
+         if(bs4.front() != *ss4.begin())
+            return 1;
+
+         if(bs4.back() != *(ss4.end()-1))
+            return 1;
+
+         bs4.pop_back();
+         ss4.erase(ss4.end()-1);
+         if(!StringEqual()(bs4, ss4)){
+            return 1;
+         }
+
+         if(*bs4.begin() != *ss4.begin())
+            return 1;
+         if(*bs4.cbegin() != *ss4.begin())
+            return 1;
+         if(*bs4.rbegin() != *ss4.rbegin())
+            return 1;
+         if(*bs4.crbegin() != *ss4.rbegin())
+            return 1;
+         if(*(bs4.end()-1) != *(ss4.end()-1))
+            return 1;
+         if(*(bs4.cend()-1) != *(ss4.end()-1))
+            return 1;
+         if(*(bs4.rend()-1) != *(ss4.rend()-1))
+            return 1;
+         if(*(bs4.crend()-1) != *(ss4.rend()-1))
+            return 1;
+      }
+
+#if __cplusplus >= 201703L
+      //Chect Constructor Template Auto Deduction
+      {
+         auto gold = StdString(string_literals<CharType>::String());
+         auto test = basic_string(gold.begin(), gold.end());
+         if(!StringEqual()(gold, test)) {
+            return 1;
+         }
+      }
+#endif
+
+
+      //When done, delete vector
+      delete boostStringVect;
+      delete stdStringVect;
+   }
+   return 0;
+}
+
+bool test_expand_bwd()
+{
+   //Now test all back insertion possibilities
+   typedef test::expand_bwd_test_allocator<char>
+      allocator_type;
+   typedef basic_string<char, std::char_traits<char>, allocator_type>
+      string_type;
+   return  test::test_all_expand_bwd<string_type>();
+}
+
+struct boost_container_string;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_string>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::basic_string<T, std::char_traits<T>, Allocator> type;
+   };
+};
+
+
+}}}   //namespace boost::container::test
+
+
+int main()
+{
+   if(string_test<char>()){
+      return 1;
+   }
+
+   if(string_test<wchar_t>()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Backwards expansion test
+   ////////////////////////////////////
+   if(!test_expand_bwd())
+      return 1;
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_string>())
+      return 1;
+
+   ////////////////////////////////////
+   //    Default init test
+   ////////////////////////////////////
+   if(!test::default_init_test< basic_string<char, std::char_traits<char>, test::default_init_allocator<char> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   if(!test::default_init_test< basic_string<wchar_t, std::char_traits<wchar_t>, test::default_init_allocator<wchar_t> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::basic_string<char> cont_int;
+      cont_int a; a.push_back(char(1)); a.push_back(char(2)); a.push_back(char(3));
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+   }
+   {
+      typedef boost::container::basic_string<wchar_t> cont_int;
+      cont_int a; a.push_back(wchar_t(1)); a.push_back(wchar_t(2)); a.push_back(wchar_t(3));
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+   }
+
+   ////////////////////////////////////
+   //    Comparison testing
+   ////////////////////////////////////
+   {
+      if(!boost::container::test::test_container_comparisons<string>())
+         return 1;
+      if(!boost::container::test::test_container_comparisons<wstring>())
+         return 1;
+   }
+
+   return boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/string_view_compat_test.cpp b/test/string_view_compat_test.cpp
new file mode 100644
index 0000000..f786b96
--- /dev/null
+++ b/test/string_view_compat_test.cpp
@@ -0,0 +1,275 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2007-2017. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/string.hpp>
+#include <boost/utility/string_view.hpp>
+
+#include <boost/core/lightweight_test.hpp>
+
+void conversion_test()
+{
+   #ifndef BOOST_CONTAINER_TEMPLATED_CONVERSION_OPERATOR_BROKEN
+   {
+      const boost::container::string s = "some text";
+      boost::string_view sv(s);
+      BOOST_TEST(s.data() == sv.data() && s.size() == sv.size());
+      boost::string_view sv2;
+      sv2 = s;
+      BOOST_TEST(s.data() == sv2.data() && s.size() == sv2.size());
+      const boost::string_view csv(s);
+      BOOST_TEST(s.data() == sv.data() && s.size() == csv.size());
+   }
+   #endif
+}
+
+void to_view_test()
+{
+   const boost::container::string s = "some text";
+   boost::string_view sv(s.to_view<boost::string_view>());
+   BOOST_TEST(s.data() == sv.data() && s.size() == sv.size());
+   boost::string_view sv2;
+   sv2 = s.to_view<boost::string_view>();
+   BOOST_TEST(s.data() == sv2.data() && s.size() == sv2.size());
+   const boost::string_view csv(s.to_view<boost::string_view>());
+   BOOST_TEST(s.data() == csv.data() && s.size() == csv.size());
+}
+
+void equal_test()
+{
+   const boost::string_view sv = "same text";
+   const boost::string_view svd = "different text";
+   const boost::container::string s = "same text";
+   BOOST_TEST(sv == s);
+   BOOST_TEST(s == sv);
+   BOOST_TEST(!(svd == s));
+   BOOST_TEST(!(s == svd));
+}
+
+void unequal_test()
+{
+   const boost::string_view sv = "same text";
+   const boost::string_view svd = "different text";
+   const boost::container::string s = "same text";
+   BOOST_TEST(!(sv != s));
+   BOOST_TEST(!(s != sv));
+   BOOST_TEST(svd != s);
+   BOOST_TEST(s != svd);
+}
+
+void less_test()
+{
+   boost::string_view sv  = "0123456";
+   boost::container::string s = "0123459";
+   BOOST_TEST(sv < s);
+   BOOST_TEST(!(s < sv));
+
+   sv = "0123459";
+   s  = "0123456";
+   BOOST_TEST(!(sv < s));
+   BOOST_TEST(s < sv);
+
+   sv = "0123456";
+   BOOST_TEST(!(sv < s));
+   BOOST_TEST(!(s < sv));
+}
+
+void greater_test()
+{
+   boost::string_view sv  = "0123459";
+   boost::container::string s = "0123456";
+   BOOST_TEST(sv > s);
+   BOOST_TEST(!(s > sv));
+
+   sv = "0123456";
+   s  = "0123459";
+   BOOST_TEST(!(sv > s));
+   BOOST_TEST(s > sv);
+
+   sv = "0123459";
+   BOOST_TEST(!(sv > s));
+   BOOST_TEST(!(s > sv));
+}
+
+void less_equal_test()
+{
+   boost::string_view sv  = "0123456";
+   boost::container::string s = "0123459";
+   BOOST_TEST(sv <= s);
+   BOOST_TEST(!(s <= sv));
+
+   sv = "0123459";
+   s  = "0123456";
+   BOOST_TEST(!(sv <= s));
+   BOOST_TEST(s <= sv);
+
+   sv = "0123456";
+   BOOST_TEST(sv <= s);
+   BOOST_TEST(s <= sv);
+}
+
+void greater_equal_test()
+{
+   boost::string_view sv  = "0123459";
+   boost::container::string s = "0123456";
+   BOOST_TEST(sv >= s);
+   BOOST_TEST(!(s >= sv));
+
+   sv = "0123456";
+   s  = "0123459";
+   BOOST_TEST(!(sv >= s));
+   BOOST_TEST(s >= sv);
+
+   sv = "0123459";
+   BOOST_TEST(sv >= s);
+   BOOST_TEST(s >= sv);
+}
+
+void constructor_test()
+{
+   boost::string_view sv  = "0123459";
+   boost::container::string s(sv);
+   BOOST_TEST(sv == s);
+   boost::container::string s2(sv, s.get_allocator());
+   BOOST_TEST(sv == s);
+}
+
+void assignment_test()
+{
+   boost::string_view sv  = "0123459";
+   boost::container::string s;
+   s = sv;
+   BOOST_TEST(sv == s);
+}
+
+void assign_test()
+{
+   boost::string_view sv  = "0123459";
+   boost::container::string s;
+   s.assign(sv);
+   BOOST_TEST(sv == s);
+}
+
+void plus_equal_test()
+{
+   boost::string_view sv  = "23459";
+   boost::container::string s("01");
+   s += sv;
+   BOOST_TEST(s == "0123459");
+}
+
+void append_test()
+{
+   boost::string_view sv  = "23459";
+   boost::container::string s("01");
+   s.append(sv);
+   BOOST_TEST(s == "0123459");
+}
+
+void insert_test()
+{
+   boost::string_view sv  = "34";
+   boost::container::string s("01259");
+   s.insert(3u, sv);
+   BOOST_TEST(s == "0123459");
+}
+
+void replace_test()
+{
+   boost::string_view sv  = "5678";
+   boost::container::string s("01259");
+   s.replace(2u, 2u, sv);
+   BOOST_TEST(s == "0156789");
+   s.replace(s.begin()+3, s.begin()+6, sv);
+   BOOST_TEST(s == "01556789");
+   s.replace(5u, 3u, sv, 2u, 2u);
+   BOOST_TEST(s == "0155678");
+}
+
+void find_test()
+{
+   const boost::string_view sv  = "25";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.find(sv,4) == 5);
+}
+
+void rfind_test()
+{
+   const boost::string_view sv  = "25";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.rfind(sv,4) == 2);
+}
+
+void find_first_of_test()
+{
+   const boost::string_view sv  = "52";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.find_first_of(sv,4) == 5);
+}
+
+void find_last_of_test()
+{
+   const boost::string_view sv  = "52";
+   boost::container::string s("520125925123");
+   BOOST_TEST(s.find_last_of(sv,6) == 5);
+}
+
+void find_first_not_of_test()
+{
+   const boost::string_view sv  = "52";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.find_first_not_of(sv,2) == 4);
+}
+
+void find_last_not_of_test()
+{
+   const boost::string_view sv  = "52";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.find_last_not_of(sv,6) == 4);
+}
+
+void compare_test()
+{
+   const boost::string_view sv  = "52";
+   boost::container::string s("0125925123");
+   BOOST_TEST(s.compare(sv) < 0);
+   BOOST_TEST(s.compare(boost::string_view("0125925123")) == 0);
+   BOOST_TEST(s.compare(2u, s.size() - 2u, boost::string_view("25925123")) == 0);
+   boost::string_view sv2("5212592512389");
+   BOOST_TEST(s.compare(2u, s.size() - 2u, sv2, 3, sv2.size()-5u) == 0);
+}
+
+int main()
+{
+   conversion_test();
+   to_view_test();
+   equal_test();
+   unequal_test();
+   less_test();
+   greater_test();
+   less_equal_test();
+   greater_equal_test();
+   constructor_test();
+   assignment_test();
+   assign_test();
+   plus_equal_test();
+   append_test();
+   insert_test();
+   replace_test();
+   find_test();
+   rfind_test();
+   find_first_of_test();
+   find_last_of_test();
+   find_first_not_of_test();
+   find_last_not_of_test();
+   compare_test();
+
+   return boost::report_errors();
+}
+
diff --git a/test/synchronized_pool_resource_test.cpp b/test/synchronized_pool_resource_test.cpp
new file mode 100644
index 0000000..da1589a
--- /dev/null
+++ b/test/synchronized_pool_resource_test.cpp
@@ -0,0 +1,19 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/synchronized_pool_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "pool_resource_test.hpp"
+
+int main()
+{
+   test_pool_resource<boost::container::pmr::synchronized_pool_resource>();
+   return ::boost::report_errors();
+}
diff --git a/test/throw_exception_test.cpp b/test/throw_exception_test.cpp
new file mode 100644
index 0000000..2cbabef
--- /dev/null
+++ b/test/throw_exception_test.cpp
@@ -0,0 +1,62 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2012-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#define BOOST_CONTAINER_USER_DEFINED_THROW_CALLBACKS
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <boost/container/throw_exception.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+static bool bad_alloc_called     = false;
+static bool out_of_range_called  = false;
+static bool length_error_called  = false;
+static bool logic_error_called   = false;
+static bool runtime_error_called = false;
+
+//User defined throw implementations
+namespace boost {
+namespace container {
+
+   void throw_bad_alloc()
+   {  bad_alloc_called = true;   }
+
+   void throw_out_of_range(const char* str)
+   {  (void)str; out_of_range_called = true;   }
+
+   void throw_length_error(const char* str)
+   {  (void)str; length_error_called = true;   }
+
+   void throw_logic_error(const char* str)
+   {  (void)str; logic_error_called = true; }
+
+   void throw_runtime_error(const char* str)
+   {  (void)str; runtime_error_called = true;  }
+
+}} //boost::container
+
+int main()
+{
+   //Check user-defined throw callbacks are called
+   throw_bad_alloc();
+   BOOST_TEST(bad_alloc_called == true);
+   throw_out_of_range("dummy");
+   BOOST_TEST(out_of_range_called == true);
+   throw_length_error("dummy");
+   BOOST_TEST(length_error_called == true);
+   throw_logic_error("dummy");
+   BOOST_TEST(logic_error_called == true);
+   throw_runtime_error("dummy");
+   BOOST_TEST(runtime_error_called == true);
+   return ::boost::report_errors();
+}
+
+#include <boost/container/detail/config_end.hpp>
diff --git a/test/tree_test.cpp b/test/tree_test.cpp
new file mode 100644
index 0000000..c1a1c3d
--- /dev/null
+++ b/test/tree_test.cpp
@@ -0,0 +1,83 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/tree.hpp>
+#include <boost/container/adaptive_pool.hpp>
+
+#include "movable_int.hpp"
+#include "dummy_test_allocator.hpp"
+
+using namespace boost::container;
+
+typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+
+namespace dtl {
+
+//Instantiate base class as previous instantiations don't instantiate inherited members
+template class tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<pair_t>
+   , tree_assoc_defaults
+   >;
+
+template class tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::allocator<pair_t>
+   , tree_assoc_defaults
+   >;
+
+template class tree
+   < pair_t
+   , select1st<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , adaptive_pool<pair_t>
+   , tree_assoc_defaults
+   >;
+
+template class tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , test::simple_allocator<test::movable_and_copyable_int>
+   , tree_assoc_defaults
+   >;
+
+template class tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , std::allocator<test::movable_and_copyable_int>
+   , tree_assoc_defaults
+   >;
+
+template class tree
+   < test::movable_and_copyable_int
+   , identity<test::movable_and_copyable_int>
+   , std::less<test::movable_and_copyable_int>
+   , adaptive_pool<test::movable_and_copyable_int>
+   , tree_assoc_defaults
+   >;
+
+}  //dtl {
+
+}} //boost::container
+
+int main ()
+{
+   return 0;
+}
diff --git a/test/unsynchronized_pool_resource_test.cpp b/test/unsynchronized_pool_resource_test.cpp
new file mode 100644
index 0000000..298607a
--- /dev/null
+++ b/test/unsynchronized_pool_resource_test.cpp
@@ -0,0 +1,19 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2015-2015. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#include <boost/container/pmr/unsynchronized_pool_resource.hpp>
+#include <boost/core/lightweight_test.hpp>
+#include "pool_resource_test.hpp"
+
+int main()
+{
+   test_pool_resource<boost::container::pmr::unsynchronized_pool_resource>();
+   return ::boost::report_errors();
+}
diff --git a/test/uses_allocator_test.cpp b/test/uses_allocator_test.cpp
new file mode 100644
index 0000000..39807f0
--- /dev/null
+++ b/test/uses_allocator_test.cpp
@@ -0,0 +1,84 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2011-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/uses_allocator_fwd.hpp>
+
+#include <boost/container/uses_allocator.hpp>
+#include "propagation_test_allocator.hpp"
+
+struct not_uses_allocator
+{};
+
+struct uses_allocator_and_not_convertible_to_int
+{
+   typedef uses_allocator_and_not_convertible_to_int allocator_type;
+};
+
+struct uses_allocator_and_convertible_to_int
+{
+   typedef char allocator_type;
+};
+
+struct uses_erased_type_allocator
+{
+   typedef boost::container::erased_type allocator_type;
+};
+
+
+int main()
+{
+   using namespace boost::container;
+   //Using dummy classes
+   BOOST_STATIC_ASSERT(( false == uses_allocator
+                           < not_uses_allocator, int>::value ));
+
+   BOOST_STATIC_ASSERT(( false == uses_allocator
+                           < uses_allocator_and_not_convertible_to_int, int>::value ));
+
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < uses_allocator_and_convertible_to_int, int>::value ));
+
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < uses_erased_type_allocator, int>::value ));
+
+   //Using an allocator-like class
+   BOOST_STATIC_ASSERT(( false == uses_allocator
+                           < allocator_argument_tester<NotUsesAllocator, 0>
+                           , propagation_test_allocator<float, 0>
+                           >::value ));
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < allocator_argument_tester<ConstructiblePrefix, 0>
+                           , propagation_test_allocator<float, 0>
+                           >::value ));
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < allocator_argument_tester<ConstructibleSuffix, 0>
+                           , propagation_test_allocator<float, 0>
+                           >::value ));
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < allocator_argument_tester<ErasedTypeSuffix, 0>
+                           , propagation_test_allocator<float, 0>
+                           >::value ));
+   BOOST_STATIC_ASSERT((  true == uses_allocator
+                           < allocator_argument_tester<ErasedTypePrefix, 0>
+                           , propagation_test_allocator<float, 0>
+                           >::value ));
+   BOOST_STATIC_ASSERT((  true == constructible_with_allocator_prefix
+                           < allocator_argument_tester<ConstructiblePrefix, 0> >::value ));
+
+   BOOST_STATIC_ASSERT((  true == constructible_with_allocator_suffix
+                           < allocator_argument_tester<ConstructibleSuffix, 0> >::value ));
+
+   BOOST_STATIC_ASSERT((  true == constructible_with_allocator_prefix
+                           < allocator_argument_tester<ErasedTypePrefix, 0> >::value ));
+
+   BOOST_STATIC_ASSERT((  true == constructible_with_allocator_suffix
+                           < allocator_argument_tester<ErasedTypeSuffix, 0> >::value ));
+   return 0;
+}
diff --git a/test/vector_options_test.cpp b/test/vector_options_test.cpp
new file mode 100644
index 0000000..9b414fb
--- /dev/null
+++ b/test/vector_options_test.cpp
@@ -0,0 +1,121 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator.hpp>
+#include <boost/container/detail/next_capacity.hpp>
+#include <boost/core/lightweight_test.hpp>
+
+using namespace boost::container;
+
+template<class Unsigned, class VectorType>
+void test_stored_size_type_impl()
+{
+   VectorType v;
+   typedef typename VectorType::size_type    size_type;
+   typedef typename VectorType::value_type   value_type;
+   size_type const max = Unsigned(-1);
+   v.resize(5);
+   v.resize(max);
+   BOOST_TEST_THROWS(v.resize(max+1),                    std::exception);
+   BOOST_TEST_THROWS(v.push_back(value_type(1)),         std::exception);
+   BOOST_TEST_THROWS(v.insert(v.begin(), value_type(1)), std::exception);
+   BOOST_TEST_THROWS(v.emplace(v.begin(), value_type(1)),std::exception);
+   BOOST_TEST_THROWS(v.reserve(max+1),                   std::exception);
+   BOOST_TEST_THROWS(VectorType v2(max+1),               std::exception);
+}
+
+template<class Unsigned>
+void test_stored_size_type()
+{
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+   using options_t = vector_options_t< stored_size<Unsigned> >;
+   #else
+   typedef typename vector_options
+      < stored_size<Unsigned> >::type options_t;
+   #endif
+
+   //Test first with a typical allocator
+   {
+      typedef vector<unsigned char, new_allocator<unsigned char>, options_t> vector_t;
+      test_stored_size_type_impl<Unsigned, vector_t>();
+   }
+   //Test with a V2 allocator
+   {
+      typedef vector<unsigned char, allocator<unsigned char>, options_t> vector_t;
+      test_stored_size_type_impl<Unsigned, vector_t>();
+   }
+}
+
+void test_growth_factor_50()
+{
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+   using options_t = vector_options_t< growth_factor<growth_factor_50> >;
+   #else
+   typedef vector_options
+      < growth_factor<growth_factor_50> >::type options_t;
+   #endif
+
+   vector<int, new_allocator<int>, options_t> v;
+
+   v.resize(5);
+   v.resize(v.capacity());
+   std::size_t old_capacity = v.capacity();
+   v.push_back(0);
+   std::size_t new_capacity = v.capacity();
+   BOOST_TEST(new_capacity == old_capacity + old_capacity/2);
+}
+
+void test_growth_factor_60()
+{
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+   using options_t = vector_options_t< growth_factor<growth_factor_60> >;
+   #else
+   typedef vector_options
+      < growth_factor<growth_factor_60> >::type options_t;
+   #endif
+
+   vector<int, new_allocator<int>, options_t> v;
+
+   v.resize(5);
+   v.resize(v.capacity());
+   std::size_t old_capacity = v.capacity();
+   v.push_back(0);
+   std::size_t new_capacity = v.capacity();
+   BOOST_TEST(new_capacity == old_capacity + 3*old_capacity/5);
+}
+
+void test_growth_factor_100()
+{
+   #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
+   using options_t = vector_options_t< growth_factor<growth_factor_100> >;
+   #else
+   typedef vector_options
+      < growth_factor<growth_factor_100> >::type options_t;
+   #endif
+
+   vector<int, new_allocator<int>, options_t> v;
+
+   v.resize(5);
+   v.resize(v.capacity());
+   std::size_t old_capacity = v.capacity();
+   v.push_back(0);
+   std::size_t new_capacity = v.capacity();
+   BOOST_TEST(new_capacity == 2*old_capacity);
+}
+
+int main()
+{
+   test_growth_factor_50();
+   test_growth_factor_60();
+   test_growth_factor_100();
+   test_stored_size_type<unsigned char>();
+   test_stored_size_type<unsigned short>();
+   return ::boost::report_errors();
+}
diff --git a/test/vector_test.cpp b/test/vector_test.cpp
new file mode 100644
index 0000000..201f201
--- /dev/null
+++ b/test/vector_test.cpp
@@ -0,0 +1,280 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+// the tests trigger deprecation warnings when compiled with msvc in C++17 mode
+#if defined(_MSVC_LANG) && _MSVC_LANG > 201402
+// warning STL4009: std::allocator<void> is deprecated in C++17
+# define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING
+#endif
+
+#include <memory>
+#include <iostream>
+
+#include <boost/container/vector.hpp>
+#include <boost/container/allocator.hpp>
+
+#include <boost/move/utility_core.hpp>
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "expand_bwd_test_allocator.hpp"
+#include "expand_bwd_test_template.hpp"
+#include "dummy_test_allocator.hpp"
+#include "propagate_allocator_test.hpp"
+#include "vector_test.hpp"
+#include "default_init_test.hpp"
+#include "../../intrusive/test/iterator_test.hpp"
+
+using namespace boost::container;
+
+namespace boost {
+namespace container {
+
+//Explicit instantiation to detect compilation errors
+template class boost::container::vector
+   < test::movable_and_copyable_int
+   , test::simple_allocator<test::movable_and_copyable_int> >;
+
+template class boost::container::vector
+   < test::movable_and_copyable_int
+   , allocator<test::movable_and_copyable_int> >;
+
+template class vec_iterator<int*, true >;
+template class vec_iterator<int*, false>;
+
+}}
+
+int test_expand_bwd()
+{
+   //Now test all back insertion possibilities
+
+   //First raw ints
+   typedef test::expand_bwd_test_allocator<int>
+      int_allocator_type;
+   typedef vector<int, int_allocator_type>
+      int_vector;
+   if(!test::test_all_expand_bwd<int_vector>())
+      return 1;
+
+   //Now user defined copyable int
+   typedef test::expand_bwd_test_allocator<test::copyable_int>
+      copyable_int_allocator_type;
+   typedef vector<test::copyable_int, copyable_int_allocator_type>
+      copyable_int_vector;
+   if(!test::test_all_expand_bwd<copyable_int_vector>())
+      return 1;
+
+   return 0;
+}
+
+class recursive_vector
+{
+   public:
+   recursive_vector & operator=(const recursive_vector &x)
+   {  this->vector_ = x.vector_;   return *this; }
+
+   int id_;
+   vector<recursive_vector> vector_;
+   vector<recursive_vector>::iterator it_;
+   vector<recursive_vector>::const_iterator cit_;
+   vector<recursive_vector>::reverse_iterator rit_;
+   vector<recursive_vector>::const_reverse_iterator crit_;
+};
+
+void recursive_vector_test()//Test for recursive types
+{
+   vector<recursive_vector> recursive_vector_vector;
+}
+
+enum Test
+{
+   zero, one, two, three, four, five, six
+};
+
+template<class VoidAllocator>
+struct GetAllocatorCont
+{
+   template<class ValueType>
+   struct apply
+   {
+      typedef vector< ValueType
+                    , typename allocator_traits<VoidAllocator>
+                        ::template portable_rebind_alloc<ValueType>::type
+                    > type;
+   };
+};
+
+template<class VoidAllocator>
+int test_cont_variants()
+{
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
+   typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
+
+   if(test::vector_test<MyCont>())
+      return 1;
+   if(test::vector_test<MyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyMoveCont>())
+      return 1;
+   if(test::vector_test<MyCopyCont>())
+      return 1;
+
+   return 0;
+}
+
+struct boost_container_vector;
+
+namespace boost { namespace container {   namespace test {
+
+template<>
+struct alloc_propagate_base<boost_container_vector>
+{
+   template <class T, class Allocator>
+   struct apply
+   {
+      typedef boost::container::vector<T, Allocator> type;
+   };
+};
+
+}}}   //namespace boost::container::test
+
+int main()
+{
+   {
+      const std::size_t positions_length = 10;
+      std::size_t positions[positions_length];
+      vector<int> vector_int;
+      vector<int> vector_int2(positions_length);
+      for(std::size_t i = 0; i != positions_length; ++i){
+         positions[i] = 0u;
+      }
+      for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){
+         vector_int2[i] = (int)i;
+      }
+
+      vector_int.insert(vector_int.begin(), 999);
+
+      vector_int.insert_ordered_at(positions_length, positions + positions_length, vector_int2.end());
+
+      for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){
+         std::cout << vector_int[i] << std::endl;
+      }
+   }
+   recursive_vector_test();
+   {
+      //Now test move semantics
+      vector<recursive_vector> original;
+      vector<recursive_vector> move_ctor(boost::move(original));
+      vector<recursive_vector> move_assign;
+      move_assign = boost::move(move_ctor);
+      move_assign.swap(original);
+   }
+
+   ////////////////////////////////////
+   //    Testing allocator implementations
+   ////////////////////////////////////
+   //       std:allocator
+   if(test_cont_variants< std::allocator<void> >()){
+      std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
+      return 1;
+   }
+   //       boost::container::allocator
+   if(test_cont_variants< allocator<void> >()){
+      std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
+      return 1;
+   }
+
+   {
+      typedef vector<Test, std::allocator<Test> > MyEnumCont;
+      MyEnumCont v;
+      Test t;
+      v.push_back(t);
+      v.push_back(::boost::move(t));
+      v.push_back(Test());
+   }
+
+   ////////////////////////////////////
+   //    Backwards expansion test
+   ////////////////////////////////////
+   if(test_expand_bwd())
+      return 1;
+
+   ////////////////////////////////////
+   //    Default init test
+   ////////////////////////////////////
+   if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){
+      std::cerr << "Default init test failed" << std::endl;
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Emplace testing
+   ////////////////////////////////////
+   const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
+   if(!boost::container::test::test_emplace< vector<test::EmplaceInt>, Options>()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Allocator propagation testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Initializer lists testing
+   ////////////////////////////////////
+   if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for<
+       boost::container::vector<int>
+   >()) {
+      return 1;
+   }
+
+   ////////////////////////////////////
+   //    Iterator testing
+   ////////////////////////////////////
+   {
+      typedef boost::container::vector<int> cont_int;
+      cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
+      boost::intrusive::test::test_iterator_random< cont_int >(a);
+      if(boost::report_errors() != 0) {
+         return 1;
+      }
+   }
+
+#if __cplusplus >= 201703L
+   ////////////////////////////////////
+   //    Constructor Template Auto Deduction testing
+   ////////////////////////////////////
+   {
+      auto gold = std::vector{ 1, 2, 3 };
+      auto test = boost::container::vector(gold.begin(), gold.end());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+         return 1;
+      }
+   }
+   {
+      auto gold = std::vector{ 1, 2, 3 };
+      auto test = boost::container::vector(gold.begin(), gold.end(), boost::container::new_allocator<int>());
+      if (test.size() != 3) {
+         return 1;
+      }
+      if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
+         return 1;
+      }
+   }
+#endif
+   return 0;
+}
diff --git a/test/vector_test.hpp b/test/vector_test.hpp
new file mode 100644
index 0000000..016da1a
--- /dev/null
+++ b/test/vector_test.hpp
@@ -0,0 +1,563 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// (C) Copyright Ion Gaztanaga 2004-2013. 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)
+//
+// See http://www.boost.org/libs/container for documentation.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#ifndef BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
+#define BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER
+
+#include <boost/container/detail/config_begin.hpp>
+
+#include <vector>
+#include <iostream>
+#include <list>
+
+#include <boost/move/utility_core.hpp>
+#include <boost/container/detail/mpl.hpp>
+#include <boost/move/utility_core.hpp>
+#include <boost/move/iterator.hpp>
+#include <boost/move/make_unique.hpp>
+#include <boost/core/no_exceptions_support.hpp>
+#include <boost/static_assert.hpp>
+
+#include "print_container.hpp"
+#include "check_equal_containers.hpp"
+#include "movable_int.hpp"
+#include "emplace_test.hpp"
+#include "input_from_forward_iterator.hpp"
+#include "insert_test.hpp"
+#include "container_common_tests.hpp"
+
+#include <cstddef>
+#include <string>
+#include <vector>
+
+
+namespace boost{
+namespace container {
+namespace test{
+
+template<class Vector>
+struct vector_hash_function_capacity
+{
+   typedef typename Vector::size_type size_type;
+   template <typename U, size_type (U::*)() const> struct Check;
+   template <typename U> static char func(Check<U, &U::capacity> *);
+   template <typename U> static int func(...);
+
+   public:
+   static const bool value = sizeof(func<Vector>(0)) == sizeof(char);
+};
+
+template<class V1, class V2>
+bool vector_vector_hash_function_capacity_only(V1&, V2&, boost::container::dtl::false_type)
+{
+   return true;
+}
+
+template<class MyBoostVector, class MyStdVector>
+bool vector_vector_hash_function_capacity_only(MyBoostVector&boostvector, MyStdVector&stdvector, boost::container::dtl::true_type)
+{
+   //deque has no reserve
+   boostvector.reserve(boostvector.size()*2);
+   stdvector.reserve(stdvector.size()*2);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+   std::size_t cap = boostvector.capacity();
+   boostvector.reserve(cap*2);
+   stdvector.reserve(cap*2);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+   boostvector.resize(0);
+   stdvector.resize(0);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+   boostvector.resize(cap*2);
+   stdvector.resize(cap*2);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+   boostvector.resize(cap*2);
+   stdvector.resize(cap*2);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+   return true;
+}
+
+
+template<class V1, class V2>
+bool vector_copyable_only(V1&, V2&, boost::container::dtl::false_type)
+{
+   return true;
+}
+
+//Function to check if both sets are equal
+template<class MyBoostVector, class MyStdVector>
+bool vector_copyable_only(MyBoostVector &boostvector, MyStdVector &stdvector, boost::container::dtl::true_type)
+{
+   typedef typename MyBoostVector::value_type IntType;
+   std::size_t size = boostvector.size();
+   boostvector.insert(boostvector.end(), 50, IntType(1));
+   stdvector.insert(stdvector.end(), 50, 1);
+   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+   {
+      IntType move_me(1);
+      boostvector.insert(boostvector.begin()+size/2, 50, boost::move(move_me));
+      stdvector.insert(stdvector.begin()+size/2, 50, 1);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+   }
+   {
+      IntType move_me(2);
+      boostvector.assign(boostvector.size()/2, boost::move(move_me));
+      stdvector.assign(stdvector.size()/2, 2);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+   }
+   {
+      IntType move_me(3);
+      boostvector.assign(boostvector.size()*3-1, boost::move(move_me));
+      stdvector.assign(stdvector.size()*3-1, 3);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+   }
+
+   {
+      IntType copy_me(3);
+      const IntType ccopy_me(3);
+      boostvector.push_back(copy_me);
+      stdvector.push_back(int(3));
+      boostvector.push_back(ccopy_me);
+      stdvector.push_back(int(3));
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+   }
+   {  //Vector(const Vector &)
+      ::boost::movelib::unique_ptr<MyBoostVector> const pv1 =
+         ::boost::movelib::make_unique<MyBoostVector>(boostvector);
+      ::boost::movelib::unique_ptr<MyStdVector> const pv2 =
+         ::boost::movelib::make_unique<MyStdVector>(stdvector);
+
+      MyBoostVector &v1 = *pv1;
+      MyStdVector &v2 = *pv2;
+
+      boostvector.clear();
+      stdvector.clear();
+      boostvector.assign(v1.begin(), v1.end());
+      stdvector.assign(v2.begin(), v2.end());
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+   }
+   {  //Vector(const Vector &, alloc)
+      ::boost::movelib::unique_ptr<MyBoostVector> const pv1 =
+         ::boost::movelib::make_unique<MyBoostVector>(boostvector, typename MyBoostVector::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdVector> const pv2 =
+         ::boost::movelib::make_unique<MyStdVector>(stdvector);
+
+      MyBoostVector &v1 = *pv1;
+      MyStdVector &v2 = *pv2;
+
+      boostvector.clear();
+      stdvector.clear();
+      boostvector.assign(v1.begin(), v1.end());
+      stdvector.assign(v2.begin(), v2.end());
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+   }
+   {  //Vector(n, T)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100, int(5));
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100, IntType(5));
+      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+   }
+   {  //Vector(n, T, alloc)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100, int(5));
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100, IntType(5), typename MyBoostVector::allocator_type());
+      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+   }
+   {  //Vector(It, It)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+         ::boost::movelib::make_unique<MyBoostVector>(boostvectorp->begin(), boostvectorp->end());
+      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+   }
+   {  //Vector(It, It, alloc)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+         ::boost::movelib::make_unique<MyBoostVector>(boostvectorp->begin(), boostvectorp->end(), typename MyBoostVector::allocator_type());
+      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+   }
+   {  //resize(n, T)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>();
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>();
+      stdvectorp->resize(100, int(9));
+      boostvectorp->resize(100, IntType(9));
+      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+   }
+   //operator=
+   {
+      //Copy constructor test
+      MyBoostVector bcopy((const MyBoostVector&) boostvector);
+      MyStdVector   scopy((const MyStdVector&)   stdvector);
+      MyBoostVector bcopy2(boostvector);
+      MyStdVector   scopy2(stdvector);
+
+      if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+      if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+
+      //Assignment from a smaller vector
+      bcopy2.erase(bcopy2.begin() + bcopy2.size()/2, bcopy2.end());
+      scopy2.erase(scopy2.begin() + scopy2.size()/2, scopy2.end());
+      bcopy = bcopy2;
+      scopy = scopy2;
+      if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+
+      //Assignment from a bigger vector with capacity
+      bcopy2  = boostvector;
+      scopy2  = stdvector;
+      if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+
+      //Assignment from bigger vector with no capacity
+      bcopy2.erase(bcopy2.begin() + bcopy2.size()/2, bcopy2.end());
+      scopy2.erase(scopy2.begin() + scopy2.size()/2, scopy2.end());
+      bcopy2.shrink_to_fit();
+      MyStdVector(scopy2).swap(scopy2);
+
+      bcopy2 = boostvector;
+      scopy2 = stdvector;
+      if(!test::CheckEqualContainers(bcopy, scopy)) return false;
+
+      //Assignment with equal capacity
+      bcopy2 = boostvector;
+      scopy2 = stdvector;
+      if(!test::CheckEqualContainers(bcopy2, scopy2)) return false;
+   }
+
+   return true;
+}
+
+template<class MyBoostVector>
+int vector_test()
+{
+   typedef std::vector<int>                     MyStdVector;
+   typedef typename MyBoostVector::value_type   IntType;
+   const int max = 100;
+
+   if(!test_range_insertion<MyBoostVector>()){
+      return 1;
+   }
+   {  //Vector(n)
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+   }
+   {  //Vector(n, alloc)
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100, typename MyBoostVector::allocator_type());
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
+   }
+   {  //Vector(Vector &&)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+         ::boost::movelib::make_unique<MyBoostVector>(::boost::move(*boostvectorp));
+      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+   }
+   {  //Vector(Vector &&, alloc)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+         ::boost::movelib::make_unique<MyBoostVector>
+            (::boost::move(*boostvectorp), typename MyBoostVector::allocator_type());
+      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+   }
+   {  //Vector operator=(Vector &&)
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
+         ::boost::movelib::make_unique<MyStdVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
+         ::boost::movelib::make_unique<MyBoostVector>(100);
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
+         ::boost::movelib::make_unique<MyBoostVector>();
+      *boostvectorp2 = ::boost::move(*boostvectorp);
+      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
+   }
+   {
+      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp = ::boost::movelib::make_unique<MyBoostVector>();
+      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp = ::boost::movelib::make_unique<MyStdVector>();
+
+      MyBoostVector & boostvector = *boostvectorp;
+      MyStdVector & stdvector = *stdvectorp;
+
+      boostvector.resize(100);
+      stdvector.resize(100);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      boostvector.resize(200);
+      stdvector.resize(200);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      boostvector.resize(0);
+      stdvector.resize(0);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      for(int i = 0; i < max; ++i){
+         IntType new_int(i);
+         boostvector.insert(boostvector.end(), boost::move(new_int));
+         stdvector.insert(stdvector.end(), i);
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      typename MyBoostVector::iterator boostit(boostvector.begin());
+      typename MyStdVector::iterator stdit(stdvector.begin());
+      typename MyBoostVector::const_iterator cboostit = boostit;
+      (void)cboostit;
+      ++boostit; ++stdit;
+      boostvector.erase(boostit);
+      stdvector.erase(stdit);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      boostvector.erase(boostvector.begin());
+      stdvector.erase(stdvector.begin());
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      {
+         //Initialize values
+         IntType aux_vect[50];
+         for(int i = 0; i < 50; ++i){
+            IntType new_int(-1);
+            BOOST_STATIC_ASSERT((boost::container::test::is_copyable<boost::container::test::movable_int>::value == false));
+            aux_vect[i] = boost::move(new_int);
+         }
+         int aux_vect2[50];
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = -1;
+         }
+         typename MyBoostVector::iterator insert_it =
+            boostvector.insert(boostvector.end()
+                           ,boost::make_move_iterator(&aux_vect[0])
+                           ,boost::make_move_iterator(aux_vect + 50));
+         if(std::size_t(boost::container::iterator_distance(insert_it, boostvector.end())) != 50) return 1;
+         stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+         for(int i = 0, j = static_cast<int>(boostvector.size()); i < j; ++i){
+            boostvector.erase(boostvector.begin());
+            stdvector.erase(stdvector.begin());
+         }
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+      {
+         boostvector.resize(100);
+         stdvector.resize(100);
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+         IntType aux_vect[50];
+         for(int i = 0; i < 50; ++i){
+            IntType new_int(-i);
+            aux_vect[i] = boost::move(new_int);
+         }
+         int aux_vect2[50];
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = -i;
+         }
+         typename MyBoostVector::size_type old_size = boostvector.size();
+         typename MyBoostVector::iterator insert_it =
+            boostvector.insert(boostvector.begin() + old_size/2
+                           ,boost::make_move_iterator(&aux_vect[0])
+                           ,boost::make_move_iterator(aux_vect + 50));
+         if(boostvector.begin() + old_size/2 != insert_it) return 1;
+         stdvector.insert(stdvector.begin() + old_size/2, aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+         for(int i = 0; i < 50; ++i){
+            IntType new_int(-i);
+            aux_vect[i] = boost::move(new_int);
+         }
+
+         for(int i = 0; i < 50; ++i){
+            aux_vect2[i] = -i;
+         }
+         old_size = boostvector.size();
+         //Now try with input iterators instead
+         insert_it = boostvector.insert(boostvector.begin() + old_size/2
+                           ,boost::make_move_iterator(make_input_from_forward_iterator(&aux_vect[0]))
+                           ,boost::make_move_iterator(make_input_from_forward_iterator(aux_vect + 50))
+                        );
+         if(boostvector.begin() + old_size/2 != insert_it) return 1;
+         stdvector.insert(stdvector.begin() + old_size/2, aux_vect2, aux_vect2 + 50);
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+
+      boostvector.shrink_to_fit();
+      MyStdVector(stdvector).swap(stdvector);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      boostvector.shrink_to_fit();
+      MyStdVector(stdvector).swap(stdvector);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      {  //push_back with not enough capacity
+      IntType push_back_this(1);
+      boostvector.push_back(boost::move(push_back_this));
+      stdvector.push_back(int(1));
+      boostvector.push_back(IntType(1));
+      stdvector.push_back(int(1));
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+
+      {  //test back()
+      const IntType test_this(1);
+      if(test_this != boostvector.back())   return 1;
+      }
+      {  //pop_back with enough capacity
+      boostvector.pop_back();
+      boostvector.pop_back();
+      stdvector.pop_back();
+      stdvector.pop_back();
+
+      IntType push_back_this(1);
+      boostvector.push_back(boost::move(push_back_this));
+      stdvector.push_back(int(1));
+      boostvector.push_back(IntType(1));
+      stdvector.push_back(int(1));
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+
+      if(!vector_copyable_only(boostvector, stdvector
+                     ,dtl::bool_<boost::container::test::is_copyable<IntType>::value>())){
+         return 1;
+      }
+
+      boostvector.erase(boostvector.begin());
+      stdvector.erase(stdvector.begin());
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      for(int i = 0; i < max; ++i){
+         IntType insert_this(i);
+         boostvector.insert(boostvector.begin(), boost::move(insert_this));
+         stdvector.insert(stdvector.begin(), i);
+         boostvector.insert(boostvector.begin(), IntType(i));
+         stdvector.insert(stdvector.begin(), int(i));
+      }
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+      //some comparison operators
+      if(!(boostvector == boostvector))
+         return 1;
+      if(boostvector != boostvector)
+         return 1;
+      if(boostvector < boostvector)
+         return 1;
+      if(boostvector > boostvector)
+         return 1;
+      if(!(boostvector <= boostvector))
+         return 1;
+      if(!(boostvector >= boostvector))
+         return 1;
+
+      //Test insertion from list
+      {
+         std::list<int> l(50, int(1));
+         typename MyBoostVector::iterator it_insert =
+            boostvector.insert(boostvector.begin(), l.begin(), l.end());
+         if(boostvector.begin() != it_insert) return 1;
+         stdvector.insert(stdvector.begin(), l.begin(), l.end());
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+         boostvector.assign(l.begin(), l.end());
+         stdvector.assign(l.begin(), l.end());
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+
+         boostvector.clear();
+         stdvector.clear();
+         boostvector.assign(make_input_from_forward_iterator(l.begin()), make_input_from_forward_iterator(l.end()));
+         stdvector.assign(l.begin(), l.end());
+         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
+      }
+   
+      if(!vector_vector_hash_function_capacity_only(boostvector, stdvector, dtl::bool_<vector_hash_function_capacity<MyBoostVector>::value>()))
+         return 1;
+
+      boostvector.clear();
+      stdvector.clear();
+      boostvector.shrink_to_fit();
+      MyStdVector(stdvector).swap(stdvector);
+      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
+
+      boostvector.resize(100);
+      if(!test_nth_index_of(boostvector))
+         return 1;
+
+   }
+   std::cout << std::endl << "Test OK!" << std::endl;
+   return 0;
+}
+
+template<typename VectorContainerType>
+bool test_vector_methods_with_initializer_list_as_argument_for()
+{
+#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
+   typedef typename VectorContainerType::allocator_type allocator_type;
+   {
+      const VectorContainerType testedVector = {1, 2, 3};
+      const std::vector<int> expectedVector = {1, 2, 3};
+      if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+   }
+   {
+      const VectorContainerType testedVector( { 1, 2, 3 }, allocator_type() );
+      const std::vector<int> expectedVector = {1, 2, 3};
+      if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+   }
+   {
+      VectorContainerType testedVector = {1, 2, 3};
+      testedVector = {11, 12, 13};
+
+      const std::vector<int> expectedVector = {11, 12, 13};
+      if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+   }
+
+   {
+      VectorContainerType testedVector = {1, 2, 3};
+      testedVector.assign({5, 6, 7});
+
+      const std::vector<int> expectedVector = {5, 6, 7};
+      if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+   }
+
+   {
+      VectorContainerType testedVector = {1, 2, 3};
+      testedVector.insert(testedVector.cend(), {5, 6, 7});
+
+      const std::vector<int> expectedVector = {1, 2, 3, 5, 6, 7};
+      if(!test::CheckEqualContainers(testedVector, expectedVector)) return false;
+   }
+   return true;
+#else
+   return true;
+#endif
+}
+
+}  //namespace test{
+}  //namespace container {
+}  //namespace boost{
+
+#include <boost/container/detail/config_end.hpp>
+
+#endif //BOOST_CONTAINER_TEST_VECTOR_TEST_HEADER