//////////////////////////////////////////////////////////////////////////////
//
// (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/container/detail/algorithm.hpp>
#include <boost/container/detail/compare_functors.hpp>
#include <boost/move/utility_core.hpp>
#include <boost/move/iterator.hpp>
#include <boost/move/make_unique.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{


#define BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(FUNC) \
 \
template<class T> \
struct vector_has_function_##FUNC \
{ \
   typedef char yes[1]; \
   typedef char no[2]; \
  \
   struct fallback { int FUNC; }; \
   struct derived : T, fallback {}; \
  \
   template <typename U, U> \
   struct check; \
  \
   template <typename U> \
   static no& test(check<int fallback::*, &U::FUNC>*); \
  \
   template <typename U> \
   static yes& test(...); \
  \
   static const bool value = sizeof(test<derived>(0)) == sizeof(yes); \
}; \
//

BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(capacity)
BOOST_VECTOR_TEST_HAS_MEMBER_FUNC(unchecked_push_back)

template<class V1, class V2>
bool vector_unchecked_push_back_test(V1&, V2&, boost::container::dtl::false_type)
{
   return true;
}

template<class MyBoostVector, class MyStdVector>
bool vector_unchecked_push_back_test(MyBoostVector& , MyStdVector& , boost::container::dtl::true_type)
{
   typedef typename MyBoostVector::value_type IntType;

   MyBoostVector bv;
   MyStdVector sv;

   bv.reserve(10);
   sv.reserve(10);

   for (std::size_t i = 0, max = bv.capacity(); i < max; ++i) {
      bv.unchecked_push_back(IntType((int)i));
      sv.push_back((int)i);
   }

   if(!test::CheckEqualContainers(bv, sv)) return false;

   bv.clear();
   sv.clear();

   for (std::size_t i = 0, max = bv.capacity(); i < max; ++i) {
      IntType move_me((int)i);
      bv.unchecked_push_back(boost::move(move_me));
      sv.push_back((int)i);
   }

   if(!test::CheckEqualContainers(bv, sv)) return false;

   return true;
}

template<class V1, class V2>
bool vector_capacity_test(V1&, V2&, boost::container::dtl::false_type)
{
   //deque has no reserve
   return true;
}

template<class MyBoostVector, class MyStdVector>
bool vector_capacity_test(MyBoostVector&boostvector, MyStdVector&stdvector, boost::container::dtl::true_type)
{
   {
      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;
   }

   //test capacity swapping in swap
   {
      MyBoostVector a, b;
      a.resize(1000);

      const std::size_t sz = a.size();
      const std::size_t cap = a.capacity();

      a.resize(sz);
      b.resize(sz/10);
      a.swap(b);
      if( !(b.capacity() >= cap) ) return false;
      if( !(b.size() == sz) ) return false;
      if( !(a.capacity() >= cap/10) ) return false;
      if( !(a.size() == sz/10) ) return false;

      a.swap(b);

      if( !(a.capacity() >= cap) ) return false;
      if( !(a.size() == sz) ) return false;
      if( !(b.capacity() >= cap/10) ) return false;
      if( !(b.size() == sz/10) ) 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;
   typedef typename MyBoostVector::difference_type difference_type;
   std::size_t size = boostvector.size();
   boostvector.insert(boostvector.end(), 50u, IntType(1));
   stdvector.insert(stdvector.end(), 50u, 1);
   if(!test::CheckEqualContainers(boostvector, stdvector)) return false;

   {
      IntType move_me(1);
      boostvector.insert(boostvector.begin()+difference_type(size/2), 50u, boost::move(move_me));
      stdvector.insert(stdvector.begin()+difference_type(size/2), 50u, 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 false;
   }
   {  //Vector(n, T)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u, int(5));
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u, IntType(5));
      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return false;
   }
   {  //Vector(n, T, alloc)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u, int(5));
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u, IntType(5), typename MyBoostVector::allocator_type());
      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return false;
   }
   {  //Vector(It, It)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
         ::boost::movelib::make_unique<MyBoostVector>(boostvectorp->begin(), boostvectorp->end());
      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return false;
   }
   {  //Vector(It, It), input_iterator
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
         ::boost::movelib::make_unique<MyBoostVector>( make_input_from_forward_iterator(boostvectorp->begin())
                                                     , make_input_from_forward_iterator(boostvectorp->end()));
      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return false;
   }
   {  //Vector(It, It, alloc)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::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 false;
   }
   {  //Vector(It, It, alloc), input_iterator
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
         ::boost::movelib::make_unique<MyBoostVector>( make_input_from_forward_iterator(boostvectorp->begin())
                                                     , make_input_from_forward_iterator(boostvectorp->end())
                                                     , typename MyBoostVector::allocator_type());
      if(!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return false;
   }
   {  //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(100u, int(9));
      boostvectorp->resize(100u, IntType(9));
      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return false;
   }
   //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() + difference_type(bcopy2.size()/2), bcopy2.end());
      scopy2.erase(scopy2.begin() + difference_type(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() + difference_type(bcopy2.size()/2), bcopy2.end());
      scopy2.erase(scopy2.begin() + difference_type(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;

      if(!vector_unchecked_push_back_test(boostvector, stdvector, dtl::bool_<vector_has_function_unchecked_push_back<MyBoostVector>::value>()))
         return 1;
   }

   return true;
}



template<class MyBoostVector>
int vector_move_assignable_only(boost::container::dtl::false_type)
{
   return 0;
}

//Function to check if both sets are equal
template<class MyBoostVector>
int vector_move_assignable_only(boost::container::dtl::true_type)
{
   const int max = 100;
   typedef std::vector<int>                     MyStdVector;
   typedef typename MyBoostVector::value_type   IntType;
   typedef typename MyBoostVector::difference_type difference_type;
   if(!test_range_insertion<MyBoostVector>()){
      return 1;
   }

   {  //Vector operator=(Vector &&)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::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(100u);
      stdvector.resize(100u);
      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;

      boostvector.erase(boostvector.end()-1);
      stdvector.erase(stdvector.end()-1);
      if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

      {
         //Initialize values
         IntType aux_vect[50];
         for(int i = 0; i < 50; ++i){
            aux_vect[i] = -1;
         }
         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(boost::container::iterator_udistance(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;
      }
      {
         //Initialize values
         IntType aux_vect[50];
         for(int i = 0; i < 50; ++i){
            aux_vect[i] = -1;
         }
         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(boost::container::iterator_udistance(insert_it, boostvector.end()) != 50) return 1;
         stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         boostvector.erase(boostvector.begin(), boostvector.begin() + 5);
         stdvector.erase(stdvector.begin(), stdvector.begin()+5);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         boostvector.erase(boostvector.end() - 5, boostvector.end());
         stdvector.erase(stdvector.end() - 5, stdvector.end());
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         boostvector.erase(boostvector.begin()+5, boostvector.begin() + 10);
         stdvector.erase(stdvector.begin()+5, stdvector.begin()+10);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         boostvector.erase(boostvector.end() - 10, boostvector.end()-5);
         stdvector.erase(stdvector.end() - 10, stdvector.end()-5);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;
      }
      {
         boostvector.resize(100u);
         stdvector.resize(100u);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         IntType aux_vect[50];
         for(int i = 0; i < 50; ++i){
            aux_vect[i] = -i;
         }
         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() + difference_type(old_size/2)
                           ,boost::make_move_iterator(&aux_vect[0])
                           ,boost::make_move_iterator(aux_vect + 50));
         if(boostvector.begin() + difference_type(old_size/2) != insert_it) return 1;
         stdvector.insert(stdvector.begin() + difference_type(old_size/2), aux_vect2, aux_vect2 + 50);
         if(!test::CheckEqualContainers(boostvector, stdvector)) return 1;

         for(int i = 0; i < 50; ++i){
            aux_vect[i] = -i;
         }

         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() + difference_type(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() + difference_type(old_size/2) != insert_it) return 1;
         stdvector.insert(stdvector.begin() + difference_type(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_capacity_test(boostvector, stdvector, dtl::bool_<vector_has_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(100u);
      if(!test_nth_index_of(boostvector))
         return 1;

      //test erase/erase_if
      IntType aux_vect[50];
      for(int i = 0; i < 50; ++i){
         aux_vect[i] = i;
      }
      int aux_vect2[50];
      for(int i = 0; i < 50; ++i){
         aux_vect2[i] = i;
      }

      boostvector.clear();
      stdvector.clear();
      boostvector.insert(boostvector.end()
                     ,boost::make_move_iterator(&aux_vect[0])
                     ,boost::make_move_iterator(aux_vect + 50));
      stdvector.insert(stdvector.end(), aux_vect2, aux_vect2 + 50);

      //erase
      if (1 != erase(boostvector, 25))
         return 1;
      if (0 != erase(boostvector, 25))
         return 1;
      stdvector.erase(boost::container::find(stdvector.begin(), stdvector.end(), 25));
      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;

      //erase_if
      if (1 != erase_if(boostvector, equal_to_value<int>(24)))
         return 1;
      if (0 != erase_if(boostvector, equal_to_value<int>(24)))
         return 1;
      stdvector.erase(boost::container::find(stdvector.begin(), stdvector.end(), 24));
      if(!test::CheckEqualContainers(boostvector, stdvector)) return false;
   }
   return 0;
}

template<class MyBoostVector>
int vector_test_fully_propagable(dtl::true_ /* fully_propagable */)
{
   typedef std::vector<int>                     MyStdVector;
   {
      //operator=(Vector &&)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp2 =
         ::boost::movelib::make_unique<MyBoostVector>();
      *boostvectorp2 = ::boost::move(*boostvectorp);
      if (!test::CheckEqualContainers(*boostvectorp2, *stdvectorp)) return 1;
   }
   return 0;
}

template<class MyBoostVector>
int vector_test_fully_propagable(dtl::false_ /* fully_propagable */)
{
   return 0;
}

template<class MyBoostVector>
int vector_test()
{
   typedef std::vector<int>                     MyStdVector;
   typedef typename MyBoostVector::value_type   IntType;

   {  //Vector(n)
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
   }
   {  //Vector(n, alloc)
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u, typename MyBoostVector::allocator_type());
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      if(!test::CheckEqualContainers(*boostvectorp, *stdvectorp)) return 1;
   }
   {  //Vector(Vector &&)
      ::boost::movelib::unique_ptr<MyStdVector> const stdvectorp =
         ::boost::movelib::make_unique<MyStdVector>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::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>(100u);
      ::boost::movelib::unique_ptr<MyBoostVector> const boostvectorp =
         ::boost::movelib::make_unique<MyBoostVector>(100u);
      ::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;
   }

   typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT(boost::container::dtl::, MyBoostVector,
      is_partially_propagable, dtl::false_type)
         is_partially_propagable_t;

   if (0 != vector_test_fully_propagable<MyBoostVector>( dtl::bool_< !is_partially_propagable_t::value >() ))   return 1;

   if (0 != vector_move_assignable_only< MyBoostVector>(dtl::bool_<boost::container::test::is_move_assignable<IntType>::value>()))
      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
