stdcpp/tsrc/Boost_test/multi_index/src/test_safe_mode.cpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 /* Boost.MultiIndex test for safe_mode.
       
     2  *
       
     3  * Copyright 2003-2006 Joaquín M López Muñoz.
       
     4  * Distributed under the Boost Software License, Version 1.0.
       
     5  * (See accompanying file LICENSE_1_0.txt or copy at
       
     6  * http://www.boost.org/LICENSE_1_0.txt)
       
     7  *
       
     8  * See http://www.boost.org/libs/multi_index for library home page.
       
     9  */
       
    10 
       
    11 #include "test_safe_mode.hpp"
       
    12 
       
    13 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
       
    14 #include "pre_multi_index.hpp"
       
    15 #include "employee.hpp"
       
    16 #include "pair_of_ints.hpp"
       
    17 #include <stdexcept>
       
    18 #include <boost/test/test_tools.hpp>
       
    19 
       
    20 using namespace boost::multi_index;
       
    21 
       
    22 #define TRY_SAFE_MODE \
       
    23 try{
       
    24 
       
    25 #define CATCH_SAFE_MODE(err) \
       
    26   throw std::runtime_error("safe mode violation not detected");\
       
    27 }catch(const safe_mode_exception& e){\
       
    28   if(e.error_code!=(err))throw std::runtime_error(\
       
    29     "safe mode violation not expected");\
       
    30 }
       
    31 
       
    32 template<typename Policy>
       
    33 static void local_test_safe_mode(
       
    34   std::forward_iterator_tag
       
    35   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
       
    36 {
       
    37   typedef typename Policy::container      container;
       
    38   typedef typename Policy::index_type     index_type;
       
    39   typedef typename index_type::value_type value_type;
       
    40   typedef typename index_type::iterator   iterator;
       
    41 
       
    42   container   c,c2;
       
    43   index_type& i=Policy::index_from_container(c);
       
    44   index_type& i2=Policy::index_from_container(c2);
       
    45   Policy::insert(i,Policy::some_value());
       
    46 
       
    47   TRY_SAFE_MODE
       
    48     iterator it;
       
    49     iterator it2=i.begin();
       
    50     it2=it;
       
    51   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
    52 
       
    53   TRY_SAFE_MODE
       
    54     iterator it;
       
    55     value_type e=*it;
       
    56   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
    57   
       
    58   TRY_SAFE_MODE
       
    59     iterator it=i.end();
       
    60     value_type e=*it;
       
    61   CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
       
    62 
       
    63   TRY_SAFE_MODE
       
    64     iterator it=i.end();
       
    65     ++it;
       
    66   CATCH_SAFE_MODE(safe_mode::not_incrementable_iterator)
       
    67 
       
    68   TRY_SAFE_MODE
       
    69     iterator it;
       
    70     iterator it2;
       
    71     bool b=(it==it2);
       
    72     b=true; /* avoid warning about unused var */
       
    73   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
    74 
       
    75   TRY_SAFE_MODE
       
    76     iterator it=i.begin();
       
    77     iterator it2;
       
    78     bool b=(it==it2);
       
    79     b=true; /* avoid warning about unused var */
       
    80   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
    81 
       
    82   TRY_SAFE_MODE
       
    83     iterator it=i.begin();
       
    84     iterator it2=i2.begin();
       
    85     bool b=(it==it2);
       
    86     b=true; /* avoid warning about unused var */
       
    87   CATCH_SAFE_MODE(safe_mode::not_same_owner)
       
    88 
       
    89   TRY_SAFE_MODE
       
    90     i.erase(i.end(),i.begin());
       
    91   CATCH_SAFE_MODE(safe_mode::invalid_range)
       
    92 
       
    93   TRY_SAFE_MODE
       
    94     iterator it;
       
    95     Policy::insert(i,it,Policy::some_value());
       
    96   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
    97 
       
    98   TRY_SAFE_MODE
       
    99     i.erase(i.end());
       
   100   CATCH_SAFE_MODE(safe_mode::not_dereferenceable_iterator)
       
   101 
       
   102   TRY_SAFE_MODE
       
   103     iterator it=i.begin();
       
   104     Policy::insert(i2,it,Policy::some_value());
       
   105   CATCH_SAFE_MODE(safe_mode::not_owner)
       
   106 
       
   107   TRY_SAFE_MODE
       
   108     iterator it=i.begin();
       
   109     iterator it2=i2.end();
       
   110     i2.erase(it,it2);
       
   111   CATCH_SAFE_MODE(safe_mode::not_owner)
       
   112 
       
   113   TRY_SAFE_MODE
       
   114     iterator it=Policy::insert(i,Policy::another_value());
       
   115     i.erase(it);
       
   116     i.erase(it);
       
   117   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   118 
       
   119   TRY_SAFE_MODE
       
   120     container   c3(c);
       
   121     index_type& i3=Policy::index_from_container(c3);
       
   122     iterator it=Policy::insert(i3,Policy::another_value());
       
   123     i3.clear();
       
   124     i3.erase(it);
       
   125   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   126 
       
   127   TRY_SAFE_MODE
       
   128     iterator it;
       
   129     {
       
   130       container   c3;
       
   131       index_type& i3=Policy::index_from_container(c3);
       
   132       it=i3.end();
       
   133     }
       
   134     it=it;
       
   135   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   136 
       
   137   TRY_SAFE_MODE
       
   138     iterator it;
       
   139     {
       
   140       container   c3;
       
   141       index_type& i3=Policy::index_from_container(c3);
       
   142       it=Policy::insert(i3,Policy::some_value());
       
   143     }
       
   144     value_type e=*it;
       
   145   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   146 
       
   147   TRY_SAFE_MODE
       
   148     iterator it;
       
   149     {
       
   150       container   c3;
       
   151       index_type& i3=Policy::index_from_container(c3);
       
   152       it=Policy::insert(i3,Policy::some_value());
       
   153     }
       
   154     iterator it2;
       
   155     it2=it;
       
   156   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   157 
       
   158   TRY_SAFE_MODE
       
   159     container   c3(c);
       
   160     container   c4;
       
   161     index_type& i3=Policy::index_from_container(c3);
       
   162     index_type& i4=Policy::index_from_container(c4);
       
   163     iterator  it=i3.begin();
       
   164     i3.swap(i4);
       
   165     i3.erase(it);
       
   166   CATCH_SAFE_MODE(safe_mode::not_owner)
       
   167 
       
   168   /* this, unlike the previous case, is indeed correct, test safe mode
       
   169    * gets it right
       
   170    */
       
   171   { 
       
   172     container   c3(c);
       
   173     container   c4;
       
   174     index_type& i3=Policy::index_from_container(c3);
       
   175     index_type& i4=Policy::index_from_container(c4);
       
   176     iterator  it=i3.begin();
       
   177     i3.swap(i4);
       
   178     i4.erase(it);
       
   179   }
       
   180 
       
   181   TRY_SAFE_MODE
       
   182     iterator it=i.end();
       
   183     typename container::iterator it2=project<0>(c2,it);
       
   184   CATCH_SAFE_MODE(safe_mode::not_owner)
       
   185 
       
   186   TRY_SAFE_MODE
       
   187     iterator it=Policy::insert(i,Policy::another_value());
       
   188     typename container::iterator it2=project<0>(c,it);
       
   189     i.erase(it);
       
   190     value_type e=*it2;
       
   191   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   192 
       
   193   /* testcase for bug reported at
       
   194    * http://lists.boost.org/boost-users/2006/02/17230.php
       
   195    */
       
   196   {
       
   197     container c3(c);
       
   198     index_type& i3=Policy::index_from_container(c3);
       
   199     iterator it=i3.end();
       
   200     i3.clear();
       
   201     it=i3.end();
       
   202   }
       
   203 
       
   204   /* testcase for doppelganger bug of that discovered for STLport at
       
   205    * http://lists.boost.org/Archives/boost/2006/04/102740.php
       
   206    */
       
   207   {
       
   208     container c3;
       
   209     index_type& i3=Policy::index_from_container(c3);
       
   210     iterator it=i3.end();
       
   211     i3.clear();
       
   212     it=it;
       
   213     BOOST_CHECK(it==i3.end());
       
   214   }
       
   215 }
       
   216 
       
   217 template<typename Policy>
       
   218 static void local_test_safe_mode(
       
   219   std::bidirectional_iterator_tag
       
   220   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
       
   221 {
       
   222   ::local_test_safe_mode<Policy>(std::forward_iterator_tag());
       
   223 
       
   224   typedef typename Policy::container      container;
       
   225   typedef typename Policy::index_type     index_type;
       
   226   typedef typename index_type::value_type value_type;
       
   227   typedef typename index_type::iterator   iterator;
       
   228 
       
   229   container   c;
       
   230   index_type& i=Policy::index_from_container(c);
       
   231   Policy::insert(i,Policy::some_value());
       
   232 
       
   233   TRY_SAFE_MODE
       
   234     iterator it=i.begin();
       
   235     --it;
       
   236   CATCH_SAFE_MODE(safe_mode::not_decrementable_iterator)
       
   237 }
       
   238 
       
   239 template<typename Policy>
       
   240 static void local_test_safe_mode(
       
   241   std::random_access_iterator_tag
       
   242   BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(Policy))
       
   243 {
       
   244   ::local_test_safe_mode<Policy>(std::bidirectional_iterator_tag());
       
   245 
       
   246   typedef typename Policy::container      container;
       
   247   typedef typename Policy::index_type     index_type;
       
   248   typedef typename index_type::value_type value_type;
       
   249   typedef typename index_type::iterator   iterator;
       
   250 
       
   251   container   c;
       
   252   index_type& i=Policy::index_from_container(c);
       
   253   Policy::insert(i,Policy::some_value());
       
   254 
       
   255   TRY_SAFE_MODE
       
   256     iterator it=i.begin();
       
   257     it+=2;
       
   258   CATCH_SAFE_MODE(safe_mode::out_of_bounds)
       
   259 
       
   260   TRY_SAFE_MODE
       
   261     iterator it=i.begin();
       
   262     it-=1;
       
   263   CATCH_SAFE_MODE(safe_mode::out_of_bounds)
       
   264 }
       
   265 
       
   266 template<typename Policy>
       
   267 static void local_test_safe_mode(BOOST_EXPLICIT_TEMPLATE_TYPE(Policy))
       
   268 {
       
   269   typedef typename Policy::index_type::iterator::iterator_category category;
       
   270   ::local_test_safe_mode<Policy>(category());
       
   271 }
       
   272 
       
   273 template<typename Policy>
       
   274 static void local_test_safe_mode_with_rearrange(
       
   275   BOOST_EXPLICIT_TEMPLATE_TYPE(Policy))
       
   276 {
       
   277   ::local_test_safe_mode<Policy>();
       
   278 
       
   279   typedef typename Policy::container      container;
       
   280   typedef typename Policy::index_type     index_type;
       
   281   typedef typename index_type::value_type value_type;
       
   282   typedef typename index_type::iterator   iterator;
       
   283 
       
   284   container   c;
       
   285   index_type& i=Policy::index_from_container(c);
       
   286   Policy::insert(i,Policy::some_value());
       
   287 
       
   288   TRY_SAFE_MODE
       
   289     iterator it;
       
   290     i.splice(it,i,i.begin(),i.end());
       
   291   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   292 
       
   293   TRY_SAFE_MODE
       
   294     container   c2(c);
       
   295     index_type& i2=Policy::index_from_container(c2);
       
   296     iterator    it2=i2.begin();
       
   297     iterator    it=i.begin();
       
   298     i.splice(it2,i2,it);
       
   299   CATCH_SAFE_MODE(safe_mode::not_owner)
       
   300 
       
   301   TRY_SAFE_MODE
       
   302     i.splice(i.begin(),i,i.begin(),i.end());
       
   303   CATCH_SAFE_MODE(safe_mode::inside_range)
       
   304 
       
   305   TRY_SAFE_MODE
       
   306     i.splice(i.begin(),i,i.end(),i.begin());
       
   307   CATCH_SAFE_MODE(safe_mode::invalid_range)
       
   308 
       
   309   TRY_SAFE_MODE
       
   310     i.splice(i.begin(),i);
       
   311   CATCH_SAFE_MODE(safe_mode::same_container)
       
   312 
       
   313   TRY_SAFE_MODE
       
   314     iterator it;
       
   315     i.relocate(it,i.begin(),i.end());
       
   316   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   317 
       
   318   TRY_SAFE_MODE
       
   319     i.relocate(i.begin(),i.begin(),i.end());
       
   320   CATCH_SAFE_MODE(safe_mode::inside_range)
       
   321 
       
   322   TRY_SAFE_MODE
       
   323     i.relocate(i.begin(),i.end(),i.begin());
       
   324   CATCH_SAFE_MODE(safe_mode::invalid_range)
       
   325 }
       
   326 
       
   327 template<typename MultiIndexContainer,int N>
       
   328 struct index_policy_base
       
   329 {
       
   330   typedef MultiIndexContainer                    container;
       
   331   typedef typename 
       
   332     boost::multi_index::detail::prevent_eti<
       
   333       container,
       
   334     typename nth_index<container,N>::type>::type index_type;
       
   335 
       
   336   static index_type& index_from_container(container& c){return get<N>(c);}
       
   337 };
       
   338 
       
   339 template<typename MultiIndexContainer,int N>
       
   340 struct key_based_index_policy_base:
       
   341   index_policy_base<MultiIndexContainer,N>
       
   342 {
       
   343   typedef index_policy_base<MultiIndexContainer,N> super;
       
   344 
       
   345   typedef typename super::container       container;
       
   346   typedef typename super::index_type      index_type;
       
   347   typedef typename index_type::value_type value_type;
       
   348   typedef typename index_type::iterator   iterator;
       
   349 
       
   350   static iterator insert(index_type& i,const value_type& v)
       
   351   {
       
   352     return i.insert(v).first;
       
   353   }
       
   354 
       
   355   static iterator insert(index_type& i,iterator it,const value_type& v)
       
   356   {
       
   357     return i.insert(it,v);
       
   358   }
       
   359 };
       
   360 
       
   361 template<typename MultiIndexContainer,int N>
       
   362 struct non_key_based_index_policy_base:
       
   363   index_policy_base<MultiIndexContainer,N>
       
   364 {
       
   365   typedef index_policy_base<MultiIndexContainer,N> super;
       
   366 
       
   367   typedef typename super::container       container;
       
   368   typedef typename super::index_type      index_type;
       
   369   typedef typename index_type::value_type value_type;
       
   370   typedef typename index_type::iterator   iterator;
       
   371 
       
   372   static iterator insert(index_type& i,const value_type& v)
       
   373   {
       
   374     return i.push_back(v).first;
       
   375   }
       
   376 
       
   377   static iterator insert(index_type& i,iterator it,const value_type& v)
       
   378   {
       
   379     return i.insert(it,v).first;
       
   380   }
       
   381 };
       
   382 
       
   383 struct employee_set_policy_base
       
   384 {
       
   385   static employee    some_value(){return employee(0,"Joe",31,1123);}
       
   386   static employee    another_value(){return employee(1,"Robert",27,5601);}
       
   387 };
       
   388 
       
   389 struct employee_set_policy:
       
   390   employee_set_policy_base,
       
   391   key_based_index_policy_base<employee_set,0>
       
   392 {};
       
   393 
       
   394 struct employee_set_by_name_policy:
       
   395   employee_set_policy_base,
       
   396   key_based_index_policy_base<employee_set,1>
       
   397 {};
       
   398 
       
   399 struct employee_set_as_inserted_policy:
       
   400   employee_set_policy_base,
       
   401   non_key_based_index_policy_base<employee_set,3>
       
   402 {};
       
   403 
       
   404 struct employee_set_randomly_policy:
       
   405   employee_set_policy_base,
       
   406   non_key_based_index_policy_base<employee_set,5>
       
   407 {};
       
   408 
       
   409 template<typename IntegralBimap>
       
   410 static void test_integral_bimap(BOOST_EXPLICIT_TEMPLATE_TYPE(IntegralBimap))
       
   411 {
       
   412   typedef typename IntegralBimap::value_type value_type;
       
   413   typedef typename IntegralBimap::iterator   iterator;
       
   414 
       
   415   TRY_SAFE_MODE
       
   416     IntegralBimap bm;
       
   417     iterator it=bm.insert(value_type(0,0)).first;
       
   418     bm.insert(value_type(1,1));
       
   419     bm.modify(it,increment_first);
       
   420     value_type v=*it;
       
   421     v.first=0; /* avoid warning about unused var */
       
   422   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   423 
       
   424   TRY_SAFE_MODE
       
   425     IntegralBimap bm;
       
   426     iterator it=bm.insert(value_type(0,0)).first;
       
   427     bm.insert(value_type(1,1));
       
   428     bm.modify(it,increment_second);
       
   429     pair_of_ints v=*it;
       
   430     v.first=0; /* avoid warning about unused var */
       
   431   CATCH_SAFE_MODE(safe_mode::invalid_iterator)
       
   432 }
       
   433 
       
   434 void test_safe_mode()
       
   435 {
       
   436   local_test_safe_mode<employee_set_policy>();
       
   437   local_test_safe_mode<employee_set_by_name_policy>();
       
   438   local_test_safe_mode_with_rearrange<employee_set_as_inserted_policy>();
       
   439   local_test_safe_mode_with_rearrange<employee_set_randomly_policy>();
       
   440 
       
   441   typedef multi_index_container<
       
   442     pair_of_ints,
       
   443     indexed_by<
       
   444       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
       
   445       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
       
   446   > bimap0_type;
       
   447 
       
   448   /* MSVC++ 6.0 chokes on test_integral_bimap without this
       
   449    * explicit instantiation
       
   450    */
       
   451   bimap0_type bm0;
       
   452   test_integral_bimap<bimap0_type>();
       
   453 
       
   454   typedef multi_index_container<
       
   455     pair_of_ints,
       
   456     indexed_by<
       
   457       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
       
   458       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
       
   459   > bimap1_type;
       
   460 
       
   461   bimap1_type bm1;
       
   462   test_integral_bimap<bimap1_type>();
       
   463 
       
   464   typedef multi_index_container<
       
   465     pair_of_ints,
       
   466     indexed_by<
       
   467       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
       
   468       ordered_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
       
   469   > bimap2_type;
       
   470 
       
   471   bimap2_type bm2;
       
   472   test_integral_bimap<bimap2_type>();
       
   473 
       
   474   typedef multi_index_container<
       
   475     pair_of_ints,
       
   476     indexed_by<
       
   477       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,first)>,
       
   478       hashed_unique<BOOST_MULTI_INDEX_MEMBER(pair_of_ints,int,second)> >
       
   479   > bimap3_type;
       
   480 
       
   481   bimap3_type bm3;
       
   482   test_integral_bimap<bimap3_type>();
       
   483 }