diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:45:59 +0000 |
commit | 19fcec84d8d7d21e796c7624e521b60d28ee21ed (patch) | |
tree | 42d26aa27d1e3f7c0b8bd3fd14e7d7082f5008dc /src/boost/libs/container/test | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 16.2.11+ds.upstream/16.2.11+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/container/test')
88 files changed, 21805 insertions, 0 deletions
diff --git a/src/boost/libs/container/test/Jamfile.v2 b/src/boost/libs/container/test/Jamfile.v2 new file mode 100644 index 000000000..2b4995bee --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/alloc_basic_test.cpp b/src/boost/libs/container/test/alloc_basic_test.cpp new file mode 100644 index 000000000..4bfdcf48b --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/alloc_full_test.cpp b/src/boost/libs/container/test/alloc_full_test.cpp new file mode 100644 index 000000000..54e1160c9 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/allocator_argument_tester.hpp b/src/boost/libs/container/test/allocator_argument_tester.hpp new file mode 100644 index 000000000..73993285e --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/allocator_traits_test.cpp b/src/boost/libs/container/test/allocator_traits_test.cpp new file mode 100644 index 000000000..401442414 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/check_equal_containers.hpp b/src/boost/libs/container/test/check_equal_containers.hpp new file mode 100644 index 000000000..758780a7f --- /dev/null +++ b/src/boost/libs/container/test/check_equal_containers.hpp @@ -0,0 +1,159 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/move/utility_core.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; + } +}; + +struct equal_transparent +{ + typedef void is_transparent; + + template<class T, class U> + bool operator()(const T &t, const U &u) const + { + return t == u; + } +}; + +struct move_op +{ + template<class T> + typename boost::move_detail::add_rvalue_reference<T>::type operator()(T &t) + { + return boost::move(t); + } +}; + +struct const_ref_op +{ + template<class T> + const T & operator()(const T &t) + { + return t; + } + +}; + +} //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/src/boost/libs/container/test/comparison_test.hpp b/src/boost/libs/container/test/comparison_test.hpp new file mode 100644 index 000000000..7f3f1b3a0 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/container_common_tests.hpp b/src/boost/libs/container/test/container_common_tests.hpp new file mode 100644 index 000000000..63e15477f --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/default_init_test.hpp b/src/boost/libs/container/test/default_init_test.hpp new file mode 100644 index 000000000..2e83a361f --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/deque_options_test.cpp b/src/boost/libs/container/test/deque_options_test.cpp new file mode 100644 index 000000000..9a7a43ae9 --- /dev/null +++ b/src/boost/libs/container/test/deque_options_test.cpp @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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/deque.hpp> +#include <boost/container/allocator.hpp> +#include <boost/core/lightweight_test.hpp> + +using namespace boost::container; + +void test_block_bytes() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = deque_options_t< block_bytes<128u> >; + #else + typedef deque_options< block_bytes<128u> >::type options_t; + #endif + typedef deque<unsigned short, void, options_t> deque_t; + BOOST_TEST(deque_t::get_block_size() == 128u/sizeof(unsigned short)); +} + +void test_block_elements() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = deque_options_t< block_size<64> >; + #else + typedef deque_options< block_size<64 > >::type options_t; + #endif + typedef deque<unsigned char, void, options_t> deque_t; + BOOST_TEST(deque_t::get_block_size() == 64U); +} + +int main() +{ + test_block_bytes(); + test_block_elements(); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/container/test/deque_test.cpp b/src/boost/libs/container/test/deque_test.cpp new file mode 100644 index 000000000..22b87f49b --- /dev/null +++ b/src/boost/libs/container/test/deque_test.cpp @@ -0,0 +1,446 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +//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; + } + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //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; + } + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::deque<int> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::deque<int, std::allocator<int> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/derived_from_memory_resource.hpp b/src/boost/libs/container/test/derived_from_memory_resource.hpp new file mode 100644 index 000000000..a8097a783 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/dummy_test_allocator.hpp b/src/boost/libs/container/test/dummy_test_allocator.hpp new file mode 100644 index 000000000..024ab0e0e --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/emplace_test.hpp b/src/boost/libs/container/test/emplace_test.hpp new file mode 100644 index 000000000..f017d9550 --- /dev/null +++ b/src/boost/libs/container/test/emplace_test.hpp @@ -0,0 +1,686 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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::size_t hash_value(const EmplaceInt &v) + { return std::size_t(v.a_); } + + 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/src/boost/libs/container/test/expand_bwd_test_allocator.hpp b/src/boost/libs/container/test/expand_bwd_test_allocator.hpp new file mode 100644 index 000000000..60b32839e --- /dev/null +++ b/src/boost/libs/container/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> &, + const expand_bwd_test_allocator<T> &) +{ return false; } + +//!Inequality test for same type of expand_bwd_test_allocator +template<class T> inline +bool operator!=(const expand_bwd_test_allocator<T> &, + const expand_bwd_test_allocator<T> &) +{ 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/src/boost/libs/container/test/expand_bwd_test_template.hpp b/src/boost/libs/container/test/expand_bwd_test_template.hpp new file mode 100644 index 000000000..1c193ac66 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/explicit_inst_deque_test.cpp b/src/boost/libs/container/test/explicit_inst_deque_test.cpp new file mode 100644 index 000000000..6fec8116b --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_deque_test.cpp @@ -0,0 +1,46 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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> +#include <boost/container/allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.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>; + +volatile ::boost::container::deque<empty> dummy; + +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> >; + +} //namespace boost { +} //namespace container { + +int main() +{ + return 0; +} + diff --git a/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp b/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp new file mode 100644 index 000000000..3a8ff6fa3 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_flat_map_test.cpp @@ -0,0 +1,94 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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> +#include <boost/container/allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" +#include <boost/container/stable_vector.hpp> +#include <boost/container/small_vector.hpp> +#include <boost/container/deque.hpp> +#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::flat_map<empty, empty>; +template class ::boost::container::flat_multimap<empty, empty>; + +volatile ::boost::container::flat_map<empty, empty> dummy; +volatile ::boost::container::flat_multimap<empty, empty> dummy2; + +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> + , 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 + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp b/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp new file mode 100644 index 000000000..eeb8366ed --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_flat_set_test.cpp @@ -0,0 +1,88 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; + +volatile ::boost::container::flat_set<empty> dummy; +volatile ::boost::container::flat_multiset<empty> dummy2; + +#include <boost/container/allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" +#include <boost/container/stable_vector.hpp> +#include <boost/container/small_vector.hpp> +#include <boost/container/deque.hpp> +#include <boost/container/static_vector.hpp> + +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> + , 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 + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_list_test.cpp b/src/boost/libs/container/test/explicit_inst_list_test.cpp new file mode 100644 index 000000000..4faeaebae --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_list_test.cpp @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_map_test.cpp b/src/boost/libs/container/test/explicit_inst_map_test.cpp new file mode 100644 index 000000000..5a4a2b408 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_map_test.cpp @@ -0,0 +1,56 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; + +volatile ::boost::container::map<empty, empty> dummy; +volatile ::boost::container::multimap<empty, empty> dummy2; + +#include <boost/container/allocator.hpp> +#include <boost/container/adaptive_pool.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +namespace boost { +namespace container { + +typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t; + +//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 > + >; +}} //boost::container + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_set_test.cpp b/src/boost/libs/container/test/explicit_inst_set_test.cpp new file mode 100644 index 000000000..fa0312356 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_set_test.cpp @@ -0,0 +1,54 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; + +volatile ::boost::container::set<empty> dummy; +volatile ::boost::container::multiset<empty> dummy2; + +#include <boost/container/allocator.hpp> +#include <boost/container/adaptive_pool.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +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> + >; + +//multiset +template class multiset + < test::movable_and_copyable_int + , std::less<test::movable_and_copyable_int> + , adaptive_pool<test::movable_and_copyable_int> + >; + +}} //boost::container + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_slist_test.cpp b/src/boost/libs/container/test/explicit_inst_slist_test.cpp new file mode 100644 index 000000000..f825c10c7 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_slist_test.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::slist<empty> dummy; + +#include <boost/container/allocator.hpp> +#include <boost/container/node_allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +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> >; + +}} + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp new file mode 100644 index 000000000..6259aae82 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_small_vector_test.cpp @@ -0,0 +1,56 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::small_vector<empty, 2> dummy; + +#include <boost/container/allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +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> >; + +}} + + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp new file mode 100644 index 000000000..b11b4c65c --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_stable_vector_test.cpp @@ -0,0 +1,45 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::stable_vector<empty> dummy; + +#include <boost/container/node_allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +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 >; + +}} + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp new file mode 100644 index 000000000..081775df8 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_static_vector_test.cpp @@ -0,0 +1,33 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::static_vector<empty, 2> dummy; + +namespace boost { +namespace container { + +//Explicit instantiation to detect compilation errors +template class boost::container::static_vector<int, 10>; + +}} + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_string_test.cpp b/src/boost/libs/container/test/explicit_inst_string_test.cpp new file mode 100644 index 000000000..fd7696921 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_string_test.cpp @@ -0,0 +1,44 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::basic_string<char> dummy; + +#include <boost/container/vector.hpp> +#include "dummy_test_allocator.hpp" + +namespace boost { +namespace 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; + +//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>; + +}} + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/explicit_inst_vector_test.cpp b/src/boost/libs/container/test/explicit_inst_vector_test.cpp new file mode 100644 index 000000000..619dfc956 --- /dev/null +++ b/src/boost/libs/container/test/explicit_inst_vector_test.cpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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>; +volatile ::boost::container::vector<empty> dummy; + +#include <boost/container/allocator.hpp> +#include "movable_int.hpp" +#include "dummy_test_allocator.hpp" + +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>; + +} //namespace boost { +} //namespace container { + +int main() +{ + return 0; +} diff --git a/src/boost/libs/container/test/flat_map_adaptor_test.cpp b/src/boost/libs/container/test/flat_map_adaptor_test.cpp new file mode 100644 index 000000000..520ef3c14 --- /dev/null +++ b/src/boost/libs/container/test/flat_map_adaptor_test.cpp @@ -0,0 +1,104 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2019. 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> +#include <boost/container/small_vector.hpp> +#include <boost/container/static_vector.hpp> +#include <boost/container/stable_vector.hpp> +#include <boost/container/vector.hpp> +#include <boost/container/deque.hpp> + +#include <boost/container/detail/container_or_allocator_rebind.hpp> + +#include "map_test.hpp" +#include <map> + +using namespace boost::container; + +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; + }; +}; + +int main() +{ + using namespace boost::container::test; + + //////////////////////////////////// + // Testing sequence container implementations + //////////////////////////////////// + { + typedef std::map<int, int> MyStdMap; + typedef std::multimap<int, int> MyStdMultiMap; + + if (0 != test::map_test + < GetMapContainer<vector<std::pair<int, int> > >::apply<int>::map_type + , MyStdMap + , GetMapContainer<vector<std::pair<int, int> > >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<vector<std::pair<int, int> > >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<small_vector<std::pair<int, int>, 7> >::apply<int>::map_type + , MyStdMap + , GetMapContainer<small_vector<std::pair<int, int>, 7> >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<small_vector<std::pair<int, int>, 7> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<static_vector<std::pair<int, int>, MaxElem * 10> >::apply<int>::map_type + , MyStdMap + , GetMapContainer<static_vector<std::pair<int, int>, MaxElem * 10> >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<static_vector<std::pair<int, int>, MaxElem * 10> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<stable_vector<std::pair<int, int> > >::apply<int>::map_type + , MyStdMap + , GetMapContainer<stable_vector<std::pair<int, int> > >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<stable_vector<std::pair<int, int> > >" << std::endl; + return 1; + } + + + if (0 != test::map_test + < GetMapContainer<deque<std::pair<int, int> > >::apply<int>::map_type + , MyStdMap + , GetMapContainer<deque<std::pair<int, int> > >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<deque<std::pair<int, int> > >" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/flat_map_test.cpp b/src/boost/libs/container/test/flat_map_test.cpp new file mode 100644 index 000000000..f5caff7ac --- /dev/null +++ b/src/boost/libs/container/test/flat_map_test.cpp @@ -0,0 +1,838 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <vector> + +#include <boost/container/flat_map.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 "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> +#include <utility> + + +using namespace boost::container; + +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() +{ + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + 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))); + } + 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))); + } + + typedef std::less<int> comp_int_t; + typedef std::allocator<std::pair<int, int> > alloc_pair_int_t; + + //range + { + auto fmap = flat_map(int_map.begin(), int_map.end()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = flat_map(int_map.begin(), int_map.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end()); + if(!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end()); + if(!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t()); + 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() +{ + BOOST_STATIC_ASSERT((dtl::is_transparent<less_transparent>::value)); + BOOST_STATIC_ASSERT(!(dtl::is_transparent<std::less<int> >::value)); + 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; + + if(!map1.insert_or_assign(1, 'a').second) + return false; + if( map1.insert_or_assign(1, 'b').second) + return false; + if(!map1.insert_or_assign(2, 'c').second) + return false; + if( map1.insert_or_assign(2, 'd').second) + return false; + if(!map1.insert_or_assign(3, 'e').second) + return false; + + if(map1.insert_or_assign(1, 'a').second) + return false; + if(map1.insert_or_assign(1, 'b').second) + return false; + if(map1.insert_or_assign(2, 'c').second) + return false; + if(map1.insert_or_assign(2, 'd').second) + return false; + if(map1.insert_or_assign(3, 'e').second) + return false; + + 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; + + //contains + if(!map1.contains(find_me)) + return false; + if(!cmap1.contains(find_me)) + return false; + if(!mmap1.contains(find_me)) + return false; + if(!cmmap1.contains(find_me)) + 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; +} + +// An ordered sequence of std:pair is also ordered by std::pair::first. +struct with_lookup_by_first +{ + typedef void is_transparent; + inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const + { + return a < b; + } + inline bool operator()(std::pair<int, int> a, int first) const + { + return a.first < first; + } + inline bool operator()(int first, std::pair<int, int> b) const + { + return first < b.first; + } +}; + +bool test_heterogeneous_lookup_by_partial_key() +{ + typedef flat_map<std::pair<int, int>,int, with_lookup_by_first> map_t; + + map_t map1; + map1[std::pair<int, int>(0, 1)] = 3; + map1[std::pair<int, int>(0, 2)] = 3; + + std::pair<map_t::iterator, map_t::iterator> const first_0_range = map1.equal_range(0); + + if(2 != (first_0_range.second - first_0_range.first)) + return false; + + if(2 != map1.count(0)) + return false; + return true; +} + +}}} //namespace boost::container::test + +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; + + if (!test_heterogeneous_lookup_by_partial_key()) + return 1; + + //////////////////////////////////// + // Testing allocator implementations + //////////////////////////////////// + { + typedef std::map<int, int> MyStdMap; + typedef std::multimap<int, int> MyStdMultiMap; + + if (0 != test::map_test + < GetMapContainer<std::allocator<void> >::apply<int>::map_type + , MyStdMap + , GetMapContainer<std::allocator<void> >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<std::allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<new_allocator<void> >::apply<int>::map_type + , MyStdMap + , GetMapContainer<new_allocator<void> >::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<new_allocator<void> >::apply<test::movable_int>::map_type + , MyStdMap + , GetMapContainer<new_allocator<void> >::apply<test::movable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::map_type + , MyStdMap + , GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::map_type + , MyStdMap + , GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void> >" << 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; + } + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef boost::container::dtl::pair<int, int> value_t; + typedef boost::container::dtl::select1st<int> key_of_value_t; + // flat_map, default + { + typedef boost::container::new_allocator<value_t> alloc_or_cont_t; + typedef boost::container::flat_map<int, int> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, default) test failed" << std::endl; + return 1; + } + } + // flat_map, vector + { + typedef boost::container::vector<value_t> alloc_or_cont_t; + typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, vector) test failed" << std::endl; + return 1; + } + } + // flat_map, std::vector + { + typedef std::vector<value_t> alloc_or_cont_t; + typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_map, std::vector) test failed" << std::endl; + return 1; + } + } + // flat_multimap, default + { + typedef boost::container::new_allocator<value_t> alloc_or_cont_t; + typedef boost::container::flat_multimap<int, int> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, default) test failed" << std::endl; + return 1; + } + } + // flat_multimap, vector + { + typedef boost::container::vector<value_t> alloc_or_cont_t; + typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, vector) test failed" << std::endl; + return 1; + } + } + // flat_multimap, std::vector + { + typedef std::vector<value_t> alloc_or_cont_t; + typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multimap, std::vector) test failed" << std::endl; + return 1; + } + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/flat_set_adaptor_test.cpp b/src/boost/libs/container/test/flat_set_adaptor_test.cpp new file mode 100644 index 000000000..b59ab1794 --- /dev/null +++ b/src/boost/libs/container/test/flat_set_adaptor_test.cpp @@ -0,0 +1,101 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Ion Gaztanaga 2004-2019. 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> +#include <boost/container/small_vector.hpp> +#include <boost/container/static_vector.hpp> +#include <boost/container/stable_vector.hpp> +#include <boost/container/vector.hpp> +#include <boost/container/deque.hpp> + +#include <boost/container/detail/container_or_allocator_rebind.hpp> + +#include "set_test.hpp" +#include <set> + +using namespace boost::container; + +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; + }; +}; + +int main() +{ + using namespace boost::container::test; + + //////////////////////////////////// + // Testing sequence container implementations + //////////////////////////////////// + { + typedef std::set<int> MyStdSet; + typedef std::multiset<int> MyStdMultiSet; + + if (0 != test::set_test + < GetSetContainer<vector<int> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<vector<int> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<vector<int> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<small_vector<int, 7> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<small_vector<int, 7> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<small_vector<int, 7> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<static_vector<int, MaxElem * 10> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<static_vector<int, MaxElem * 10> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<static_vector<int, MaxElem * 10> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<stable_vector<int> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<stable_vector<int> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<stable_vector<int> >" << std::endl; + return 1; + } + + + if (0 != test::set_test + < GetSetContainer<deque<int> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<deque<int> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<deque<int> >" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/flat_set_test.cpp b/src/boost/libs/container/test/flat_set_test.cpp new file mode 100644 index 000000000..7927b99a4 --- /dev/null +++ b/src/boost/libs/container/test/flat_set_test.cpp @@ -0,0 +1,933 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <iostream> +#include <set> +#include <utility> +#include <vector> + +#include <boost/container/flat_set.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; + +//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; +} + +bool constructor_template_auto_deduction_test() +{ + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + std::set<int> int_set; + for (std::size_t i = 0; i != NumElements; ++i) { + int_set.insert(static_cast<int>(i)); + } + std::multiset<int> int_mset; + for (std::size_t i = 0; i != NumElements; ++i) { + int_mset.insert(static_cast<int>(i)); + } + + typedef std::less<int> comp_int_t; + typedef std::allocator<int> alloc_int_t; + + //range + { + auto fset = flat_set(int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = flat_set(int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + 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 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; + + //contains + if(!set1.contains(find_me)) + return false; + if(!cset1.contains(find_me)) + return false; + if(!mset1.contains(find_me)) + return false; + if(!cmset1.contains(find_me)) + 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; +} + +// An ordered sequence of std:pair is also ordered by std::pair::first. +struct with_lookup_by_first +{ + typedef void is_transparent; + inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const + { + return a < b; + } + inline bool operator()(std::pair<int, int> a, int first) const + { + return a.first < first; + } + inline bool operator()(int first, std::pair<int, int> b) const + { + return first < b.first; + } +}; + +bool test_heterogeneous_lookup_by_partial_key() +{ + typedef flat_set<std::pair<int, int>, with_lookup_by_first> set_t; + + set_t set1; + set1.insert(std::pair<int, int>(0, 1)); + set1.insert(std::pair<int, int>(0, 2)); + + std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(0); + if(2 != (first_0_range.second - first_0_range.first)) + return false; + + if(2 != set1.count(0)) + 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<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; + } + + //////////////////////////////////// + // 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_set<int>, flat_multiset<int> >()) + return 1; + + if(!test_heterogeneous_lookups()){ + return 1; + } + + if(!test_heterogeneous_lookup_by_partial_key()){ + return 1; + } + + //////////////////////////////////// + // Testing allocator implementations + //////////////////////////////////// + { + typedef std::set<int> MyStdSet; + typedef std::multiset<int> MyStdMultiSet; + + if (0 != test::set_test + < GetSetContainer<std::allocator<void> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<std::allocator<void> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<std::allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<new_allocator<void> >::apply<int>::set_type + , MyStdSet + , GetSetContainer<new_allocator<void> >::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<new_allocator<void> >::apply<test::movable_int>::set_type + , MyStdSet + , GetSetContainer<new_allocator<void> >::apply<test::movable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::set_type + , MyStdSet + , GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void> >" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::set_type + , MyStdSet + , GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void> >" << 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; + } + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef boost::container::dtl::identity<int> key_of_value_t; + // flat_set, default + { + typedef boost::container::flat_set<int> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, default) test failed" << std::endl; + return 1; + } + } + // flat_set, vector + { + typedef boost::container::vector<int> alloc_or_cont_t; + typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, vector) test failed" << std::endl; + return 1; + } + } + // flat_set, std::vector + { + typedef std::vector<int> alloc_or_cont_t; + typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_set, std::vector) test failed" << std::endl; + return 1; + } + } + // flat_multiset, default + { + typedef boost::container::flat_multiset<int> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, default) test failed" << std::endl; + return 1; + } + } + // flat_multiset, vector + { + typedef boost::container::vector<int> alloc_or_cont_t; + typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, vector) test failed" << std::endl; + return 1; + } + } + // flat_multiset, std::vector + { + typedef std::vector<int> alloc_or_cont_t; + typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont; + typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(flat_multiset, std::vector) test failed" << std::endl; + return 1; + } + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> + diff --git a/src/boost/libs/container/test/flat_tree_test.cpp b/src/boost/libs/container/test/flat_tree_test.cpp new file mode 100644 index 000000000..e94c0892b --- /dev/null +++ b/src/boost/libs/container/test/flat_tree_test.cpp @@ -0,0 +1,156 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <iostream> + +#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 () +{ + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default + { + typedef boost::container::dtl::flat_tree<int, boost::container::dtl::identity<int>, + std::less<int>, void> tree; + typedef tree::container_type container_type; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move<tree>::value != + boost::has_trivial_destructor_after_move<container_type>::value && + boost::has_trivial_destructor_after_move<key_compare>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::dtl::flat_tree<int, boost::container::dtl::identity<int>, + std::less<int>, std::allocator<int> > tree; + typedef tree::container_type container_type; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move<tree>::value != + boost::has_trivial_destructor_after_move<container_type>::value && + boost::has_trivial_destructor_after_move<key_compare>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/global_resource_test.cpp b/src/boost/libs/container/test/global_resource_test.cpp new file mode 100644 index 000000000..bb6e96837 --- /dev/null +++ b/src/boost/libs/container/test/global_resource_test.cpp @@ -0,0 +1,127 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +#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 + +//ASAN does not support operator new overloading +#ifndef BOOST_CONTAINER_ASAN + +std::size_t allocation_count = 0; + +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); +} + +#endif //BOOST_CONTAINER_ASAN + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +#ifndef BOOST_CONTAINER_ASAN + +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); +} + +#endif //BOOST_CONTAINER_ASAN + +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() +{ + #ifndef BOOST_CONTAINER_ASAN + test_new_delete_resource(); + #endif + test_null_memory_resource(); + test_default_resource(); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/container/test/hash_table_test.cppx b/src/boost/libs/container/test/hash_table_test.cppx new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/boost/libs/container/test/hash_table_test.cppx diff --git a/src/boost/libs/container/test/input_from_forward_iterator.hpp b/src/boost/libs/container/test/input_from_forward_iterator.hpp new file mode 100644 index 000000000..9436ceffa --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/insert_test.hpp b/src/boost/libs/container/test/insert_test.hpp new file mode 100644 index 000000000..cb862f3c5 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/insert_vs_emplace_test.cpp b/src/boost/libs/container/test/insert_vs_emplace_test.cpp new file mode 100644 index 000000000..b91a693c5 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/list_test.cpp b/src/boost/libs/container/test/list_test.cpp new file mode 100644 index 000000000..c4f9f41d4 --- /dev/null +++ b/src/boost/libs/container/test/list_test.cpp @@ -0,0 +1,286 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 + //////////////////////////////////// + // int variants + if (test::list_test<list<int, std::allocator<int> >, true>()) + return 1; + if (test::list_test<list<int>, true>()) + return 1; + if (test::list_test<list<int, adaptive_pool<int> >, true>()) + return 1; + if (test::list_test<list<test::movable_int>, true>()) + return 1; + if (test::list_test<list<test::movable_and_copyable_int>, true>()) + return 1; + if (test::list_test<list<test::copyable_int>, true>()) + 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; + } + } + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //////////////////////////////////// + // 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 + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::list<int> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::list<int, std::allocator<int> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/list_test.hpp b/src/boost/libs/container/test/list_test.hpp new file mode 100644 index 000000000..9640ec099 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/map_test.cpp b/src/boost/libs/container/test/map_test.cpp new file mode 100644 index 000000000..74483037d --- /dev/null +++ b/src/boost/libs/container/test/map_test.cpp @@ -0,0 +1,693 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +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; + }; +}; + +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; + + if(!map1.insert_or_assign(1, 'a').second) + return false; + if( map1.insert_or_assign(1, 'b').second) + return false; + if(!map1.insert_or_assign(2, 'c').second) + return false; + if( map1.insert_or_assign(2, 'd').second) + return false; + if(!map1.insert_or_assign(3, 'e').second) + return false; + + if(map1.insert_or_assign(1, 'a').second) + return false; + if(map1.insert_or_assign(1, 'b').second) + return false; + if(map1.insert_or_assign(2, 'c').second) + return false; + if(map1.insert_or_assign(2, 'd').second) + return false; + if(map1.insert_or_assign(3, 'e').second) + return false; + + 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; + + //contains + if(!map1.contains(find_me)) + return false; + if(!cmap1.contains(find_me)) + return false; + if(!mmap1.contains(find_me)) + return false; + if(!cmmap1.contains(find_me)) + 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; +} + +bool constructor_template_auto_deduction_test() +{ + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + 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))); + } + 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))); + } + + typedef std::less<int> comp_int_t; + typedef std::allocator<std::pair<const int, int> > alloc_pair_int_t; + + //range + { + auto fmap = map(int_map.begin(), int_map.end()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = map(int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = map(int_map.begin(), int_map.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end()); + if(!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end()); + if(!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+comp+alloc + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + //range+alloc + { + auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_map, fmap)) + return false; + auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t()); + if (!CheckEqualContainers(int_mmap, fmmap)) + return false; + } + } +#endif + + 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 + //////////////////////////////////// + { + typedef std::map<int, int> MyStdMap; + typedef std::multimap<int, int> MyStdMultiMap; + + if (0 != test::map_test + < GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::map_type + , MyStdMap + , GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<std::allocator<void>, red_black_tree>" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::map_type + , MyStdMap + , GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void>, avl_tree>" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::map_type + , MyStdMap + , GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<adaptive_pool<void>, scapegoat_tree>" << std::endl; + return 1; + } + + /////////// + + if (0 != test::map_test + < GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::map_type + , MyStdMap + , GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void>, splay_tree>" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::map_type + , MyStdMap + , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl; + return 1; + } + + if (0 != test::map_test + < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::map_type + , MyStdMap + , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multimap_type + , MyStdMultiMap>()) { + std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << 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; + } + } + + //////////////////////////////////// + // Node extraction/insertion testing functions + //////////////////////////////////// + if(!node_type_test()) + return 1; + + //////////////////////////////////// + // Constructor Template Auto Deduction test + //////////////////////////////////// + if (!test::constructor_template_auto_deduction_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)); + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + { + typedef std::pair<const int, int> value_type; + // + // map + // + // default allocator + { + typedef boost::container::map<int, int> cont; + typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(map, default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::map<int, int, std::less<int>, std::allocator<value_type> > cont; + typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(map, std::allocator) test failed" << std::endl; + return 1; + } + } + // + // multimap + // + // default allocator + { + // default allocator + typedef boost::container::multimap<int, int> cont; + typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(multimap, default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::multimap<int, int, std::less<int>, std::allocator<value_type> > cont; + typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(multimap, std::allocator) test failed" << std::endl; + return 1; + } + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/map_test.hpp b/src/boost/libs/container/test/map_test.hpp new file mode 100644 index 000000000..160c46ad0 --- /dev/null +++ b/src/boost/libs/container/test/map_test.hpp @@ -0,0 +1,1264 @@ +//////////////////////////////////////// +// +// (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 "movable_int.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) + +}}} + +const int MaxElem = 50; + +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; + + ::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_range() +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + 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; + } + return 0; +} + + +template<class MyBoostMap + ,class MyStdMap + ,class MyBoostMultiMap + ,class MyStdMultiMap> +int map_test_step(MyBoostMap &, MyStdMap &, MyBoostMultiMap &, MyStdMultiMap &) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + + { + //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; + } + return 0; +} + +template<class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_insert(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + { + //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; + } + return 0; +} + +template<class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_erase(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + //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; + } + return 0; +} + +template<class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_insert2(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + //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; + } + } + return 0; +} + + +template<class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_search(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + + //Compare count/contains with std containers + for(int i = 0; i < MaxElem; ++i){ + IntType k(i); + if(boostmap.count(k) != stdmap.count(i)){ + return -1; + } + + if(boostmap.contains(k) != (stdmap.find(i) != stdmap.end())){ + return -1; + } + + if(boostmultimap.count(k) != stdmultimap.count(i)){ + return -1; + } + + if(boostmultimap.contains(k) != (stdmultimap.find(i) != stdmultimap.end())){ + 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; + } + } + + return 0; +} + +template<class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_indexing(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + + { //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; + } + return 0; +} + +template< class MyBoostMap, class StdMap, class MaybeMove> +int map_test_insert_or_assign_impl() +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + typedef typename MyBoostMap::iterator Biterator; + typedef std::pair<Biterator, bool> Bpair; + + MaybeMove maybe_move; + + { //insert_or_assign test + MyBoostMap boostmap; + StdMap stdmap; + IntPairType aux_vect[MaxElem]; + for(int i = 0; i < MaxElem; ++i){ + IntType i1(i); + IntType i2(MaxElem-i); + new(&aux_vect[i])IntPairType(maybe_move(i1), maybe_move(i2)); + } + + IntPairType aux_vect2[MaxElem]; + for(int i = 0; i < MaxElem; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect2[i])IntPairType(maybe_move(i1), maybe_move(i2)); + } + + for(int i = 0; i < MaxElem; ++i){ + Bpair r = boostmap.insert_or_assign(maybe_move(aux_vect[i].first), maybe_move(aux_vect[i].second)); + stdmap[i] = MaxElem-i; + if(!r.second) + return 1; + const IntType key(i); + if(r.first->first != key) + return 1; + const IntType mapped(MaxElem-i); + if(r.first->second != mapped) + return 1; + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + + for(int i = 0; i < MaxElem; ++i){ + Bpair r = boostmap.insert_or_assign(maybe_move(aux_vect2[i].first), maybe_move(aux_vect2[i].second)); + stdmap[i] = i; + if(r.second) + return 1; + const IntType key(i); + if(r.first->first != key) + return 1; + const IntType mapped(i); + if(r.first->second != mapped) + return 1; + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + } + { //insert_or_assign test with hint + MyBoostMap boostmap; + StdMap stdmap; + IntPairType aux_vect[MaxElem]; + for(int i = 0; i < MaxElem; ++i){ + IntType i1(i); + IntType i2(MaxElem-i); + new(&aux_vect[i])IntPairType(maybe_move(i1), maybe_move(i2)); + } + + IntPairType aux_vect2[MaxElem]; + for(int i = 0; i < MaxElem; ++i){ + IntType i1(i); + IntType i2(i); + new(&aux_vect2[i])IntPairType(maybe_move(i1), maybe_move(i2)); + } + + for(int i = 0; i < MaxElem; ++i){ + Biterator r = boostmap.insert_or_assign(boostmap.end(), maybe_move(aux_vect[i].first), maybe_move(aux_vect[i].second)); + stdmap[i] = MaxElem-i; + const IntType key(i); + if(r->first != key) + return 1; + const IntType mapped(MaxElem-i); + if(r->second != mapped) + return 1; + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + + for(int i = 0; i < MaxElem; ++i){ + Biterator r = boostmap.insert_or_assign(boostmap.end(), maybe_move(aux_vect2[i].first), maybe_move(aux_vect2[i].second)); + stdmap[i] = i; + const IntType key(i); + if(r->first != key) + return 1; + const IntType mapped(i); + if(r->second != mapped) + return 1; + } + + if(!CheckEqualPairContainers(boostmap, stdmap)) return 1; + } + return 0; +} + +template< class MyBoostMap, class StdMap> +int map_test_insert_or_assign(dtl::bool_<false> )//noncopyable +{ + return map_test_insert_or_assign_impl<MyBoostMap, StdMap, move_op>(); +} + +template< class MyBoostMap, class StdMap> +int map_test_insert_or_assign(dtl::bool_<true> )//copyable +{ + int r = map_test_insert_or_assign_impl<MyBoostMap, StdMap, const_ref_op>(); + if (r) + r = map_test_insert_or_assign_impl<MyBoostMap, StdMap, move_op>(); + return r; +} + +template< class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_try_emplace(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + + { //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; + } + return 0; +} + + +template< class MyBoostMap + , class MyStdMap + , class MyBoostMultiMap + , class MyStdMultiMap> +int map_test_merge(MyBoostMap &boostmap, MyStdMap &stdmap, MyBoostMultiMap &boostmultimap, MyStdMultiMap &stdmultimap) +{ + typedef typename MyBoostMap::key_type IntType; + typedef dtl::pair<IntType, IntType> IntPairType; + typedef typename MyStdMap::value_type StdPairType; + + { //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; + } + return 0; +} + + +template<class MyBoostMap + ,class MyStdMap + ,class MyBoostMultiMap + ,class MyStdMultiMap> +int map_test() +{ + typedef typename MyBoostMap::key_type IntType; + + if(map_test_range<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>()) + 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; + typedef dtl::bool_<boost::container::test::is_copyable<IntType>::value> copyable_t; + + if (map_test_step(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_insert(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_erase(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_insert2(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_search(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_indexing(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_try_emplace(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_merge(boostmap, stdmap, boostmultimap, stdmultimap)) + return 1; + + if (map_test_insert_or_assign<MyBoostMap, MyStdMap>(copyable_t())) + return 1; + + if(map_test_copyable<MyBoostMap, MyStdMap, MyBoostMultiMap, MyStdMultiMap>(copyable_t())) + 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/src/boost/libs/container/test/memory_resource_logger.hpp b/src/boost/libs/container/test/memory_resource_logger.hpp new file mode 100644 index 000000000..e8bc405b8 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/memory_resource_test.cpp b/src/boost/libs/container/test/memory_resource_test.cpp new file mode 100644 index 000000000..4c4cb511b --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp b/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp new file mode 100644 index 000000000..4923e2460 --- /dev/null +++ b/src/boost/libs/container/test/monotonic_buffer_resource_test.cpp @@ -0,0 +1,483 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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() +{ + //Allocate buffer first to avoid stack-use-after-scope in monotonic_buffer_resource's destructor + const std::size_t BufSz = monotonic_buffer_resource::initial_next_buffer_size; + boost::move_detail::aligned_storage<BufSz+block_slist::header_size>::type buf; + //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); + //Now stub buffer storage it as the return buffer + //for "derived_from_memory_resource": + 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 occurred + 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 occurred + 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/src/boost/libs/container/test/movable_int.hpp b/src/boost/libs/container/test/movable_int.hpp new file mode 100644 index 000000000..c38146ecf --- /dev/null +++ b/src/boost/libs/container/test/movable_int.hpp @@ -0,0 +1,437 @@ +/////////////////////////////////////////////////////////////////////////// +// +// (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(); } + + friend std::size_t hash_value(const movable_int &v) + { return (std::size_t)v.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(); } + + friend std::size_t hash_value(const movable_and_copyable_int &v) + { return (std::size_t)v.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(); } + + friend std::size_t hash_value(const copyable_int &v) + { return (std::size_t)v.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(); } + + friend std::size_t hash_value(const non_copymovable_int &v) + { return (std::size_t)v.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/src/boost/libs/container/test/node_handle_test.cpp b/src/boost/libs/container/test/node_handle_test.cpp new file mode 100644 index 000000000..3c2637946 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/null_iterators_test.cpp b/src/boost/libs/container/test/null_iterators_test.cpp new file mode 100644 index 000000000..f081dbe0e --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pair_test.cpp b/src/boost/libs/container/test/pair_test.cpp new file mode 100644 index 000000000..5ead7a450 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_deque_test.cpp b/src/boost/libs/container/test/pmr_deque_test.cpp new file mode 100644 index 000000000..15c67e2a6 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_flat_map_test.cpp b/src/boost/libs/container/test/pmr_flat_map_test.cpp new file mode 100644 index 000000000..f98e497bf --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_flat_set_test.cpp b/src/boost/libs/container/test/pmr_flat_set_test.cpp new file mode 100644 index 000000000..5c9efe1a7 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_list_test.cpp b/src/boost/libs/container/test/pmr_list_test.cpp new file mode 100644 index 000000000..794ccf524 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_map_test.cpp b/src/boost/libs/container/test/pmr_map_test.cpp new file mode 100644 index 000000000..5db3f1091 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_set_test.cpp b/src/boost/libs/container/test/pmr_set_test.cpp new file mode 100644 index 000000000..3093fd434 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_slist_test.cpp b/src/boost/libs/container/test/pmr_slist_test.cpp new file mode 100644 index 000000000..ed4b5ae9c --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_small_vector_test.cpp b/src/boost/libs/container/test/pmr_small_vector_test.cpp new file mode 100644 index 000000000..334588da3 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_stable_vector_test.cpp b/src/boost/libs/container/test/pmr_stable_vector_test.cpp new file mode 100644 index 000000000..246f071c3 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_static_vector_test.cpp b/src/boost/libs/container/test/pmr_static_vector_test.cpp new file mode 100644 index 000000000..6681f7cd2 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_string_test.cpp b/src/boost/libs/container/test/pmr_string_test.cpp new file mode 100644 index 000000000..c8d81a5ba --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pmr_vector_test.cpp b/src/boost/libs/container/test/pmr_vector_test.cpp new file mode 100644 index 000000000..293291ce0 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/polymorphic_allocator_test.cpp b/src/boost/libs/container/test/polymorphic_allocator_test.cpp new file mode 100644 index 000000000..10899cac1 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/pool_resource_test.hpp b/src/boost/libs/container/test/pool_resource_test.hpp new file mode 100644 index 000000000..110274e32 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/print_container.hpp b/src/boost/libs/container/test/print_container.hpp new file mode 100644 index 000000000..2e49ec60e --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/propagate_allocator_test.hpp b/src/boost/libs/container/test/propagate_allocator_test.hpp new file mode 100644 index 000000000..e3a504818 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/propagation_test_allocator.hpp b/src/boost/libs/container/test/propagation_test_allocator.hpp new file mode 100644 index 000000000..7c8643c55 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/resource_adaptor_test.cpp b/src/boost/libs/container/test/resource_adaptor_test.cpp new file mode 100644 index 000000000..5f8ece297 --- /dev/null +++ b/src/boost/libs/container/test/resource_adaptor_test.cpp @@ -0,0 +1,234 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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" +#include <boost/container/new_allocator.hpp> +#include <memory> + +using namespace boost::container::pmr; + +static const std::size_t max_alignment_value = boost::move_detail::alignment_of<boost::move_detail::max_align_t>::value; + +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_deallocate() +{ + { + derived_from_resource_adaptor_stateful dra; + char dummy = 0; + dra.get_allocator().allocate_return = &dummy; + void *allocate_ret = dra.do_allocate(998, 1); + BOOST_TEST(allocate_ret == &dummy); + BOOST_TEST(dra.get_allocator().allocate_size == 998); + } + { + derived_from_resource_adaptor_stateful dra; + char dummy = 0; + dra.do_deallocate(&dummy, 1234, 1); + BOOST_TEST(dra.get_allocator().deallocate_p == &dummy); + BOOST_TEST(dra.get_allocator().deallocate_size == 1234); + } + { + //Overaligned allocation + derived_from_resource_adaptor_stateful dra; + const std::size_t alignment = max_alignment_value*2u; + const std::size_t bytes = alignment/2; + char dummy[alignment*2u+sizeof(void*)]; + dra.get_allocator().allocate_return = dummy; + + //First allocate + void *allocate_ret = dra.do_allocate(bytes, alignment); + BOOST_TEST( (char*)allocate_ret >= (dummy+sizeof(void*)) && (char*)allocate_ret < (dummy + sizeof(dummy)) ); + BOOST_TEST( (std::size_t(allocate_ret) & (alignment - 1u)) == 0 ); + BOOST_TEST( dra.get_allocator().allocate_size >= (alignment/2+sizeof(void*)) ); + + //Then allocate + dra.do_deallocate(allocate_ret, bytes, alignment); + BOOST_TEST(dra.get_allocator().deallocate_p == dummy); + BOOST_TEST(dra.get_allocator().deallocate_size == dra.get_allocator().allocate_size); + } + { + typedef resource_adaptor< boost::container::new_allocator<int> > new_resource_alloc_t; + new_resource_alloc_t ra; + boost::container::pmr::memory_resource &mr = ra; + + //new_allocator, low alignment + mr.deallocate(mr.allocate(16, 1), 16, 1); + + //new_allocator, high alignment + mr.deallocate(mr.allocate(16, max_alignment_value*4u), 16, max_alignment_value*4u); + } + { + typedef resource_adaptor<std ::allocator<int> > new_resource_alloc_t; + new_resource_alloc_t ra; + boost::container::pmr::memory_resource &mr = ra; + + //std::allocator, low alignment + mr.deallocate(mr.allocate(16, 1), 16, 1); + + //std::allocator, high alignment + mr.deallocate(mr.allocate(16, max_alignment_value*4u), 16, max_alignment_value*4u); + } +} + +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_deallocate(); + test_do_is_equal(); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp b/src/boost/libs/container/test/scoped_allocator_adaptor_test.cpp new file mode 100644 index 000000000..6a051e279 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/scoped_allocator_usage_test.cpp b/src/boost/libs/container/test/scoped_allocator_usage_test.cpp new file mode 100644 index 000000000..6eb143811 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/set_test.cpp b/src/boost/libs/container/test/set_test.cpp new file mode 100644 index 000000000..a7d0b4741 --- /dev/null +++ b/src/boost/libs/container/test/set_test.cpp @@ -0,0 +1,655 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +//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; + }; +}; + +bool constructor_template_auto_deduction_test() +{ +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + using namespace boost::container; + const std::size_t NumElements = 100; + { + std::set<int> int_set; + for (std::size_t i = 0; i != NumElements; ++i) { + int_set.insert(static_cast<int>(i)); + } + std::multiset<int> int_mset; + for (std::size_t i = 0; i != NumElements; ++i) { + int_mset.insert(static_cast<int>(i)); + } + + typedef std::less<int> comp_int_t; + typedef std::allocator<int> alloc_int_t; + + //range + { + auto fset = set(int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = set(int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = set(int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + + //ordered_unique_range / ordered_range + + //range + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+comp+alloc + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + //range+alloc + { + auto fset = set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t()); + if (!CheckEqualContainers(int_set, fset)) + return false; + auto fmset = multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t()); + if (!CheckEqualContainers(int_mset, fmset)) + return false; + } + } +#endif + return true; +} + +}}} //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; + }; +}; + +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; + + //contains + if(!set1.contains(find_me)) + return false; + if(!cset1.contains(find_me)) + return false; + if(!mset1.contains(find_me)) + return false; + if(!cmset1.contains(find_me)) + 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(); + + //////////////////////////////////// + // Constructor Template Auto Deduction test + //////////////////////////////////// + if (!test::constructor_template_auto_deduction_test()) { + return 1; + } + + if(!test_heterogeneous_lookups()) + return 1; + + //////////////////////////////////// + // Testing allocator implementations + //////////////////////////////////// + { + typedef std::set<int> MyStdSet; + typedef std::multiset<int> MyStdMultiSet; + + if (0 != test::set_test + < GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::set_type + , MyStdSet + , GetAllocatorSet<std::allocator<void>, red_black_tree>::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<std::allocator<void>, red_black_tree>" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::set_type + , MyStdSet + , GetAllocatorSet<new_allocator<void>, avl_tree>::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void>, avl_tree>" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::set_type + , MyStdSet + , GetAllocatorSet<adaptive_pool<void>, scapegoat_tree>::apply<int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<adaptive_pool<void>, scapegoat_tree>" << std::endl; + return 1; + } + + /////////// + + if (0 != test::set_test + < GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::set_type + , MyStdSet + , GetAllocatorSet<new_allocator<void>, splay_tree>::apply<test::movable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void>, splay_tree>" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::set_type + , MyStdSet + , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << std::endl; + return 1; + } + + if (0 != test::set_test + < GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::set_type + , MyStdSet + , GetAllocatorSet<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multiset_type + , MyStdMultiSet>()) { + std::cout << "Error in set_test<new_allocator<void>, red_black_tree>" << 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; + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // set, default allocator + { + typedef boost::container::set<int> cont; + typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(set, default allocator) test failed" << std::endl; + return 1; + } + } + // set, std::allocator + { + typedef boost::container::set<int, std::less<int>, std::allocator<int> > cont; + typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(set, std::allocator) test failed" << std::endl; + return 1; + } + } + // multiset, default allocator + { + typedef boost::container::multiset<int> cont; + typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(multiset, default allocator) test failed" << std::endl; + return 1; + } + } + // multiset, std::allocator + { + typedef boost::container::multiset<int, std::less<int>, std::allocator<int> > cont; + typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<tree>::value) { + std::cerr << "has_trivial_destructor_after_move(multiset, std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/set_test.hpp b/src/boost/libs/container/test/set_test.hpp new file mode 100644 index 000000000..7bc3a0933 --- /dev/null +++ b/src/boost/libs/container/test/set_test.hpp @@ -0,0 +1,942 @@ +//////////////////////////////////////// +// +// (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 "movable_int.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 k(i); + if(boostset.count(k) != stdset.count(i)){ + return -1; + } + + if(boostset.contains(k) != (stdset.find(i) != stdset.end())){ + return -1; + } + + if(boostmultiset.count(k) != stdmultiset.count(i)){ + return -1; + } + + if(boostmultiset.contains(k) != (stdmultiset.find(i) != stdmultiset.end())){ + 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/src/boost/libs/container/test/slist_test.cpp b/src/boost/libs/container/test/slist_test.cpp new file mode 100644 index 000000000..08943448a --- /dev/null +++ b/src/boost/libs/container/test/slist_test.cpp @@ -0,0 +1,290 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +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; + }; +}; + +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 + //////////////////////////////////// + if (test::list_test<slist<int, std::allocator<int> >, false>()) + return 1; + if (test::list_test<slist<int>, false>()) + return 1; + if (test::list_test<slist<int, node_allocator<int> >, false>()) + return 1; + if (test::list_test<slist<test::movable_int>, false>()) + return 1; + if (test::list_test<slist<test::movable_and_copyable_int>, false>()) + return 1; + if (test::list_test<slist<test::copyable_int>, false>()) + 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; + } + } +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //////////////////////////////////// + // 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 + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::slist<int> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::slist<int, std::allocator<int> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> + diff --git a/src/boost/libs/container/test/small_vector_options_test.cpp b/src/boost/libs/container/test/small_vector_options_test.cpp new file mode 100644 index 000000000..73e485536 --- /dev/null +++ b/src/boost/libs/container/test/small_vector_options_test.cpp @@ -0,0 +1,110 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/core/lightweight_test.hpp> +#include <boost/assert.hpp> +using namespace boost::container; + +const std::size_t Capacity = 10u; + +void test_alignment() +{ + { //extended alignment + const std::size_t extended_alignment = sizeof(int)*4u; + BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of<int>::value); + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< inplace_alignment<extended_alignment> >; + #else + typedef small_vector_options + < inplace_alignment<extended_alignment> >::type options_t; + #endif + + small_vector<int, Capacity, void, options_t> v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % extended_alignment) == 0); + } + { //default alignment + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< inplace_alignment<0> >; + #else + typedef small_vector_options< inplace_alignment<0> >::type options_t; + #endif + + small_vector<int, Capacity, void, options_t> v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % dtl::alignment_of<int>::value) == 0); + } +} + +void test_growth_factor_50() +{ + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = small_vector_options_t< growth_factor<growth_factor_50> >; + #else + typedef small_vector_options + < growth_factor<growth_factor_50> >::type options_t; + #endif + + small_vector<int, Capacity, 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 = small_vector_options_t< growth_factor<growth_factor_60> >; + #else + typedef small_vector_options + < growth_factor<growth_factor_60> >::type options_t; + #endif + + small_vector<int, Capacity, 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 = small_vector_options_t< growth_factor<growth_factor_100> >; + #else + typedef small_vector_options + < growth_factor<growth_factor_100> >::type options_t; + #endif + + small_vector<int, Capacity, 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_alignment(); + test_growth_factor_50(); + test_growth_factor_60(); + test_growth_factor_100(); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/container/test/small_vector_test.cpp b/src/boost/libs/container/test/small_vector_test.cpp new file mode 100644 index 000000000..315d64ddc --- /dev/null +++ b/src/boost/libs/container/test/small_vector_test.cpp @@ -0,0 +1,236 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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> + +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; + } + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::small_vector<int, 0> cont; + if (boost::has_trivial_destructor_after_move<cont>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::small_vector<int, 0, std::allocator<int> > cont; + if (boost::has_trivial_destructor_after_move<cont>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/stable_vector_test.cpp b/src/boost/libs/container/test/stable_vector_test.cpp new file mode 100644 index 000000000..e0fb5867f --- /dev/null +++ b/src/boost/libs/container/test/stable_vector_test.cpp @@ -0,0 +1,227 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +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; + } + } + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //////////////////////////////////// + // 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 + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::stable_vector<int> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::stable_vector<int, std::allocator<int> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/static_vector_options_test.cpp b/src/boost/libs/container/test/static_vector_options_test.cpp new file mode 100644 index 000000000..e8965d54f --- /dev/null +++ b/src/boost/libs/container/test/static_vector_options_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. +// +////////////////////////////////////////////////////////////////////////////// +#define BOOST_ENABLE_ASSERT_HANDLER +#include <boost/container/static_vector.hpp> +#include <boost/core/lightweight_test.hpp> +#include <new> //for bad_alloc +#include <boost/assert.hpp> +using namespace boost::container; + +//User-defined assertion to test throw_on_overflow +struct throw_on_overflow_off +{}; + +namespace boost { + void assertion_failed(char const *, char const *, char const *, long) + { + throw throw_on_overflow_off(); + } + + void assertion_failed_msg(char const *, char const *, char const *, char const *, long ) + { + throw throw_on_overflow_off(); + } +} + +void test_alignment() +{ + const std::size_t Capacity = 10u; + { //extended alignment + const std::size_t extended_alignment = sizeof(int)*4u; + BOOST_STATIC_ASSERT(extended_alignment > dtl::alignment_of<int>::value); + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< inplace_alignment<extended_alignment> >; + #else + typedef static_vector_options + < inplace_alignment<extended_alignment> >::type options_t; + #endif + + static_vector<int, Capacity, options_t> v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % extended_alignment) == 0); + } + { //default alignment + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< inplace_alignment<0> >; + #else + typedef static_vector_options< inplace_alignment<0> >::type options_t; + #endif + + static_vector<int, Capacity, options_t> v; + v.resize(v.capacity()); + BOOST_ASSERT((reinterpret_cast<std::size_t>(&v[0]) % dtl::alignment_of<int>::value) == 0); + } +} + +void test_throw_on_overflow() +{ + #if !defined(BOOST_NO_EXCEPTIONS) + const std::size_t Capacity = 10u; + { //throw_on_overflow == true, expect bad_alloc + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< throw_on_overflow<true> >; + #else + typedef static_vector_options + < throw_on_overflow<true> >::type options_t; + #endif + + static_vector<int, Capacity, options_t> v; + + v.resize(Capacity); + bool expected_type_thrown = false; + try{ + v.push_back(0); + } + catch(std::bad_alloc&) + { + expected_type_thrown = true; + } + catch(...) + {} + BOOST_TEST(expected_type_thrown == true); + BOOST_TEST(v.capacity() == Capacity); + } + { //throw_on_overflow == false, test it through BOOST_ASSERT + //even in release mode (BOOST_ENABLE_ASSERT_HANDLER), and throwing + //a special type in that assertion. + #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) + using options_t = static_vector_options_t< throw_on_overflow<false> >; + #else + typedef static_vector_options< throw_on_overflow<false> >::type options_t; + #endif + + static_vector<int, Capacity, options_t> v; + + v.resize(Capacity); + bool expected_type_thrown = false; + try{ + v.push_back(0); + } + catch(throw_on_overflow_off) + { + expected_type_thrown = true; + } + catch(...) + {} + BOOST_TEST(expected_type_thrown == true); + BOOST_TEST(v.capacity() == Capacity); + } + #endif +} + +int main() +{ + test_alignment(); + test_throw_on_overflow(); + return ::boost::report_errors(); +} diff --git a/src/boost/libs/container/test/static_vector_test.cpp b/src/boost/libs/container/test/static_vector_test.cpp new file mode 100644 index 000000000..f47df2e0c --- /dev/null +++ b/src/boost/libs/container/test/static_vector_test.cpp @@ -0,0 +1,827 @@ +// 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" + + +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(), 1, 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/2+1, 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/src/boost/libs/container/test/static_vector_test.hpp b/src/boost/libs/container/test/static_vector_test.hpp new file mode 100644 index 000000000..ab931b274 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/string_test.cpp b/src/boost/libs/container/test/string_test.cpp new file mode 100644 index 000000000..b2d17f6aa --- /dev/null +++ b/src/boost/libs/container/test/string_test.cpp @@ -0,0 +1,596 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +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; + } + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //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; + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::basic_string<char> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::basic_string<char, std::char_traits<char>, std::allocator<char> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return boost::report_errors(); +} + +#include <boost/container/detail/config_end.hpp> diff --git a/src/boost/libs/container/test/string_view_compat_test.cpp b/src/boost/libs/container/test/string_view_compat_test.cpp new file mode 100644 index 000000000..f786b96c2 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/synchronized_pool_resource_test.cpp b/src/boost/libs/container/test/synchronized_pool_resource_test.cpp new file mode 100644 index 000000000..da1589a06 --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/throw_exception_test.cpp b/src/boost/libs/container/test/throw_exception_test.cpp new file mode 100644 index 000000000..2cbabefcc --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/tree_test.cpp b/src/boost/libs/container/test/tree_test.cpp new file mode 100644 index 000000000..e07559677 --- /dev/null +++ b/src/boost/libs/container/test/tree_test.cpp @@ -0,0 +1,119 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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 <boost/container/new_allocator.hpp> +#include <boost/move/traits.hpp> + +#include <iostream> + +#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 () +{ + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default + { + typedef boost::container::dtl::tree<int, void, std::less<int>, void, void> tree; + typedef tree::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move<tree>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value && + boost::has_trivial_destructor_after_move<key_compare>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::dtl::tree<int, void, std::less<int>, std::allocator<int>, void> tree; + typedef tree::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + typedef tree::key_compare key_compare; + if (boost::has_trivial_destructor_after_move<tree>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value && + boost::has_trivial_destructor_after_move<key_compare>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp b/src/boost/libs/container/test/unsynchronized_pool_resource_test.cpp new file mode 100644 index 000000000..298607a8b --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/uses_allocator_test.cpp b/src/boost/libs/container/test/uses_allocator_test.cpp new file mode 100644 index 000000000..39807f09e --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/vector_options_test.cpp b/src/boost/libs/container/test/vector_options_test.cpp new file mode 100644 index 000000000..9b414fb8d --- /dev/null +++ b/src/boost/libs/container/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/src/boost/libs/container/test/vector_test.cpp b/src/boost/libs/container/test/vector_test.cpp new file mode 100644 index 000000000..c9b82cc38 --- /dev/null +++ b/src/boost/libs/container/test/vector_test.cpp @@ -0,0 +1,364 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (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; + +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; +} + +struct X; + +template<typename T> +struct XRef +{ + explicit XRef(T* ptr) : ptr(ptr) {} + operator T*() const { return ptr; } + T* ptr; +}; + +struct X +{ + XRef<X const> operator&() const { return XRef<X const>(this); } + XRef<X> operator&() { return XRef<X>(this); } +}; + + +bool test_smart_ref_type() +{ + boost::container::vector<X> x(5); + return x.empty(); +} + +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 + +template<typename T> +class check_dealloc_allocator : public std::allocator<T> +{ + public: + bool allocate_zero_called_; + bool deallocate_called_without_allocate_; + + check_dealloc_allocator() + : std::allocator<T>() + , allocate_zero_called_(false) + , deallocate_called_without_allocate_(false) + {} + + T* allocate(std::size_t n) + { + if (n == 0) { + allocate_zero_called_ = true; + } + return std::allocator<T>::allocate(n); + } + + void deallocate(T* p, std::size_t n) + { + if (n == 0 && !allocate_zero_called_) { + deallocate_called_without_allocate_ = true; + } + return std::allocator<T>::deallocate(p, n); + } +}; + +bool test_merge_empty_free() +{ + vector<int> source; + source.emplace_back(1); + + vector< int, check_dealloc_allocator<int> > empty; + empty.merge(source.begin(), source.end()); + + return empty.get_stored_allocator().deallocate_called_without_allocate_; +} + +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()); + } + + if (test_smart_ref_type()) + return 1; + + //////////////////////////////////// + // 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; + } + } + +#ifndef BOOST_CONTAINER_NO_CXX17_CTAD + //////////////////////////////////// + // 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 + + if (test_merge_empty_free()) { + std::cerr << "Merge into empty vector test failed" << std::endl; + return 1; + } + + //////////////////////////////////// + // has_trivial_destructor_after_move testing + //////////////////////////////////// + // default allocator + { + typedef boost::container::vector<int> cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(default allocator) test failed" << std::endl; + return 1; + } + } + // std::allocator + { + typedef boost::container::vector<int, std::allocator<int> > cont; + typedef cont::allocator_type allocator_type; + typedef boost::container::allocator_traits<allocator_type>::pointer pointer; + if (boost::has_trivial_destructor_after_move<cont>::value != + boost::has_trivial_destructor_after_move<allocator_type>::value && + boost::has_trivial_destructor_after_move<pointer>::value) { + std::cerr << "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl; + return 1; + } + } + + return 0; +} diff --git a/src/boost/libs/container/test/vector_test.hpp b/src/boost/libs/container/test/vector_test.hpp new file mode 100644 index 000000000..016da1a71 --- /dev/null +++ b/src/boost/libs/container/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 |