mirror of
https://github.com/boostorg/multi_index.git
synced 2025-05-09 23:14:04 +00:00
passim: supressed non-ASCII chars in C++ code bidir_node_iterator.hpp: deleted unused template parameter bucket_array.hpp: avoided allocator<void> instantiations hash_index_iterator.hpp: avoided allocator<void> instantiations hash_index_node.hpp: avoided allocator<void> instantiations, renamed var ord_index_node.hpp: avoided allocator<void> instantiations rnd_index_loader.hpp: avoided allocator<void> instantiations rnd_index_node.hpp: avoided allocator<void> instantiations rnd_index_ptr_array.hpp: avoided allocator<void> instantiations rnd_node_iterator.hpp: deleted unused template parameter seq_index_node.hpp: avoided allocator<void> instantiations hashed_index.hpp: rewritten modify_ so that elements with unmodified key do not change position multi_index_container.hpp: added allocator ctor acknowledgements.html: added acknowledgements for Boost 1.36 compiler_specifics.html: typo hash_indices.html: documented updating functions behavior wrt unmodified keys, formatting typos key_extraction.html: formatting typos multi_index_container.html: added allocator ctor, formatting typos ord_indices.html: documented updating functions behavior wrt unmodified keys, formatting typos rnd_indices.html: formatting typos seq_indices.html: formatting typos release_notes.html: added release notes for Boost 1.36 hashed.cpp: blocked Boost inspect tool check for ASCII only chars non_std_allocator.hpp: removed void specialization to verify that no allocator<void> instantiations are generated test_copy_assignment.cpp: added test for multi_index_container allocator ctor test_update.cpp: added test for stability of update functions wrt to unmodified keys [SVN r46770]
484 lines
13 KiB
C++
484 lines
13 KiB
C++
/* Boost.MultiIndex test for safe_mode.
|
|
*
|
|
* Copyright 2003-2008 Joaquin M Lopez Munoz.
|
|
* 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/multi_index for library home page.
|
|
*/
|
|
|
|
#include "test_safe_mode.hpp"
|
|
|
|
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
|
|
#include "pre_multi_index.hpp"
|
|
#include "employee.hpp"
|
|
#include "pair_of_ints.hpp"
|
|
#include <stdexcept>
|
|
#include <boost/test/test_tools.hpp>
|
|
|
|
using namespace boost::multi_index;
|
|
|
|
#define TRY_SAFE_MODE \
|
|
try{
|
|
|
|
#define CATCH_SAFE_MODE(err) \
|
|
throw std::runtime_error("safe mode violation not detected");\
|
|
}catch(const safe_mode_exception& e){\
|
|
if(e.error_code!=(err))throw std::runtime_error(\
|
|
"safe mode violation not expected");\
|
|
}
|
|
|
|
template<typename Policy>
|
|
static void local_test_safe_mode(
|
|
std::forward_iterator_tag
|
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
|
|
{
|
|
typedef typename Policy::container container;
|
|
typedef typename Policy::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
container c,c2;
|
|
index_type& i=Policy::index_from_container(c);
|
|
index_type& i2=Policy::index_from_container(c2);
|
|
Policy::insert(i,Policy::some_value());
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
iterator it2=i.begin();
|
|
it2=it;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
value_type e=*it;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.end();
|
|
value_type e=*it;
|
|
CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.end();
|
|
++it;
|
|
CATCH_SAFE_MODE(safe_mode::not_incrementable_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
iterator it2;
|
|
bool b=(it==it2);
|
|
b=true; /* avoid warning about unused var */
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
iterator it2;
|
|
bool b=(it==it2);
|
|
b=true; /* avoid warning about unused var */
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
iterator it2=i2.begin();
|
|
bool b=(it==it2);
|
|
b=true; /* avoid warning about unused var */
|
|
CATCH_SAFE_MODE(safe_mode::not_same_owner)
|
|
|
|
TRY_SAFE_MODE
|
|
i.erase(i.end(),i.begin());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_range)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
Policy::insert(i,it,Policy::some_value());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
i.erase(i.end());
|
|
CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
Policy::insert(i2,it,Policy::some_value());
|
|
CATCH_SAFE_MODE(safe_mode::not_owner)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
iterator it2=i2.end();
|
|
i2.erase(it,it2);
|
|
CATCH_SAFE_MODE(safe_mode::not_owner)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=Policy::insert(i,Policy::another_value());
|
|
i.erase(it);
|
|
i.erase(it);
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
container c3(c);
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
iterator it=Policy::insert(i3,Policy::another_value());
|
|
i3.clear();
|
|
i3.erase(it);
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
{
|
|
container c3;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
it=i3.end();
|
|
}
|
|
it=it;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
{
|
|
container c3;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
it=Policy::insert(i3,Policy::some_value());
|
|
}
|
|
value_type e=*it;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
{
|
|
container c3;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
it=Policy::insert(i3,Policy::some_value());
|
|
}
|
|
iterator it2;
|
|
it2=it;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
container c3(c);
|
|
container c4;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
index_type& i4=Policy::index_from_container(c4);
|
|
iterator it=i3.begin();
|
|
i3.swap(i4);
|
|
i3.erase(it);
|
|
CATCH_SAFE_MODE(safe_mode::not_owner)
|
|
|
|
/* this, unlike the previous case, is indeed correct, test safe mode
|
|
* gets it right
|
|
*/
|
|
{
|
|
container c3(c);
|
|
container c4;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
index_type& i4=Policy::index_from_container(c4);
|
|
iterator it=i3.begin();
|
|
i3.swap(i4);
|
|
i4.erase(it);
|
|
}
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.end();
|
|
typename container::iterator it2=project<0>(c2,it);
|
|
CATCH_SAFE_MODE(safe_mode::not_owner)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=Policy::insert(i,Policy::another_value());
|
|
typename container::iterator it2=project<0>(c,it);
|
|
i.erase(it);
|
|
value_type e=*it2;
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
/* testcase for bug reported at
|
|
* http://lists.boost.org/boost-users/2006/02/17230.php
|
|
*/
|
|
{
|
|
container c3(c);
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
iterator it=i3.end();
|
|
i3.clear();
|
|
it=i3.end();
|
|
}
|
|
|
|
/* testcase for doppelganger bug of that discovered for STLport at
|
|
* http://lists.boost.org/Archives/boost/2006/04/102740.php
|
|
*/
|
|
{
|
|
container c3;
|
|
index_type& i3=Policy::index_from_container(c3);
|
|
iterator it=i3.end();
|
|
i3.clear();
|
|
it=it;
|
|
BOOST_CHECK(it==i3.end());
|
|
}
|
|
}
|
|
|
|
template<typename Policy>
|
|
static void local_test_safe_mode(
|
|
std::bidirectional_iterator_tag
|
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
|
|
{
|
|
::local_test_safe_mode<Policy>(std::forward_iterator_tag());
|
|
|
|
typedef typename Policy::container container;
|
|
typedef typename Policy::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
container c;
|
|
index_type& i=Policy::index_from_container(c);
|
|
Policy::insert(i,Policy::some_value());
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
--it;
|
|
CATCH_SAFE_MODE(safe_mode::not_decrementable_iterator)
|
|
}
|
|
|
|
template<typename Policy>
|
|
static void local_test_safe_mode(
|
|
std::random_access_iterator_tag
|
|
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
|
|
{
|
|
::local_test_safe_mode<Policy>(std::bidirectional_iterator_tag());
|
|
|
|
typedef typename Policy::container container;
|
|
typedef typename Policy::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
container c;
|
|
index_type& i=Policy::index_from_container(c);
|
|
Policy::insert(i,Policy::some_value());
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
it+=2;
|
|
CATCH_SAFE_MODE(safe_mode::out_of_bounds)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it=i.begin();
|
|
it-=1;
|
|
CATCH_SAFE_MODE(safe_mode::out_of_bounds)
|
|
}
|
|
|
|
template<typename Policy>
|
|
static void local_test_safe_mode(BOOST_EXPLICIT_TEMPLATE_TYPE(Policy))
|
|
{
|
|
typedef typename Policy::index_type::iterator::iterator_category category;
|
|
::local_test_safe_mode<Policy>(category());
|
|
}
|
|
|
|
template<typename Policy>
|
|
static void local_test_safe_mode_with_rearrange(
|
|
BOOST_EXPLICIT_TEMPLATE_TYPE(Policy))
|
|
{
|
|
::local_test_safe_mode<Policy>();
|
|
|
|
typedef typename Policy::container container;
|
|
typedef typename Policy::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
container c;
|
|
index_type& i=Policy::index_from_container(c);
|
|
Policy::insert(i,Policy::some_value());
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
i.splice(it,i,i.begin(),i.end());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
container c2(c);
|
|
index_type& i2=Policy::index_from_container(c2);
|
|
iterator it2=i2.begin();
|
|
iterator it=i.begin();
|
|
i.splice(it2,i2,it);
|
|
CATCH_SAFE_MODE(safe_mode::not_owner)
|
|
|
|
TRY_SAFE_MODE
|
|
i.splice(i.begin(),i,i.begin(),i.end());
|
|
CATCH_SAFE_MODE(safe_mode::inside_range)
|
|
|
|
TRY_SAFE_MODE
|
|
i.splice(i.begin(),i,i.end(),i.begin());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_range)
|
|
|
|
TRY_SAFE_MODE
|
|
i.splice(i.begin(),i);
|
|
CATCH_SAFE_MODE(safe_mode::same_container)
|
|
|
|
TRY_SAFE_MODE
|
|
iterator it;
|
|
i.relocate(it,i.begin(),i.end());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
i.relocate(i.begin(),i.begin(),i.end());
|
|
CATCH_SAFE_MODE(safe_mode::inside_range)
|
|
|
|
TRY_SAFE_MODE
|
|
i.relocate(i.begin(),i.end(),i.begin());
|
|
CATCH_SAFE_MODE(safe_mode::invalid_range)
|
|
}
|
|
|
|
template<typename MultiIndexContainer,int N>
|
|
struct index_policy_base
|
|
{
|
|
typedef MultiIndexContainer container;
|
|
typedef typename
|
|
boost::multi_index::detail::prevent_eti<
|
|
container,
|
|
typename nth_index<container,N>::type>::type index_type;
|
|
|
|
static index_type& index_from_container(container& c){return get<N>(c);}
|
|
};
|
|
|
|
template<typename MultiIndexContainer,int N>
|
|
struct key_based_index_policy_base:
|
|
index_policy_base<MultiIndexContainer,N>
|
|
{
|
|
typedef index_policy_base<MultiIndexContainer,N> super;
|
|
|
|
typedef typename super::container container;
|
|
typedef typename super::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
static iterator insert(index_type& i,const value_type& v)
|
|
{
|
|
return i.insert(v).first;
|
|
}
|
|
|
|
static iterator insert(index_type& i,iterator it,const value_type& v)
|
|
{
|
|
return i.insert(it,v);
|
|
}
|
|
};
|
|
|
|
template<typename MultiIndexContainer,int N>
|
|
struct non_key_based_index_policy_base:
|
|
index_policy_base<MultiIndexContainer,N>
|
|
{
|
|
typedef index_policy_base<MultiIndexContainer,N> super;
|
|
|
|
typedef typename super::container container;
|
|
typedef typename super::index_type index_type;
|
|
typedef typename index_type::value_type value_type;
|
|
typedef typename index_type::iterator iterator;
|
|
|
|
static iterator insert(index_type& i,const value_type& v)
|
|
{
|
|
return i.push_back(v).first;
|
|
}
|
|
|
|
static iterator insert(index_type& i,iterator it,const value_type& v)
|
|
{
|
|
return i.insert(it,v).first;
|
|
}
|
|
};
|
|
|
|
struct employee_set_policy_base
|
|
{
|
|
static employee some_value(){return employee(0,"Joe",31,1123);}
|
|
static employee another_value(){return employee(1,"Robert",27,5601);}
|
|
};
|
|
|
|
struct employee_set_policy:
|
|
employee_set_policy_base,
|
|
key_based_index_policy_base<employee_set,0>
|
|
{};
|
|
|
|
struct employee_set_by_name_policy:
|
|
employee_set_policy_base,
|
|
key_based_index_policy_base<employee_set,1>
|
|
{};
|
|
|
|
struct employee_set_as_inserted_policy:
|
|
employee_set_policy_base,
|
|
non_key_based_index_policy_base<employee_set,3>
|
|
{};
|
|
|
|
struct employee_set_randomly_policy:
|
|
employee_set_policy_base,
|
|
non_key_based_index_policy_base<employee_set,5>
|
|
{};
|
|
|
|
template<typename IntegralBimap>
|
|
static void test_integral_bimap(BOOST_EXPLICIT_TEMPLATE_TYPE(IntegralBimap))
|
|
{
|
|
typedef typename IntegralBimap::value_type value_type;
|
|
typedef typename IntegralBimap::iterator iterator;
|
|
|
|
TRY_SAFE_MODE
|
|
IntegralBimap bm;
|
|
iterator it=bm.insert(value_type(0,0)).first;
|
|
bm.insert(value_type(1,1));
|
|
bm.modify(it,increment_first);
|
|
value_type v=*it;
|
|
v.first=0; /* avoid warning about unused var */
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
|
|
TRY_SAFE_MODE
|
|
IntegralBimap bm;
|
|
iterator it=bm.insert(value_type(0,0)).first;
|
|
bm.insert(value_type(1,1));
|
|
bm.modify(it,increment_second);
|
|
pair_of_ints v=*it;
|
|
v.first=0; /* avoid warning about unused var */
|
|
CATCH_SAFE_MODE(safe_mode::invalid_iterator)
|
|
}
|
|
|
|
void test_safe_mode()
|
|
{
|
|
local_test_safe_mode<employee_set_policy>();
|
|
local_test_safe_mode<employee_set_by_name_policy>();
|
|
local_test_safe_mode_with_rearrange<employee_set_as_inserted_policy>();
|
|
local_test_safe_mode_with_rearrange<employee_set_randomly_policy>();
|
|
|
|
typedef multi_index_container<
|
|
pair_of_ints,
|
|
indexed_by<
|
|
ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
|
|
ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
|
|
> bimap0_type;
|
|
|
|
/* MSVC++ 6.0 chokes on test_integral_bimap without this
|
|
* explicit instantiation
|
|
*/
|
|
bimap0_type bm0;
|
|
test_integral_bimap<bimap0_type>();
|
|
|
|
typedef multi_index_container<
|
|
pair_of_ints,
|
|
indexed_by<
|
|
ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
|
|
hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
|
|
> bimap1_type;
|
|
|
|
bimap1_type bm1;
|
|
test_integral_bimap<bimap1_type>();
|
|
|
|
typedef multi_index_container<
|
|
pair_of_ints,
|
|
indexed_by<
|
|
hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
|
|
ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
|
|
> bimap2_type;
|
|
|
|
bimap2_type bm2;
|
|
test_integral_bimap<bimap2_type>();
|
|
|
|
typedef multi_index_container<
|
|
pair_of_ints,
|
|
indexed_by<
|
|
hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
|
|
hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
|
|
> bimap3_type;
|
|
|
|
bimap3_type bm3;
|
|
test_integral_bimap<bimap3_type>();
|
|
}
|