genericopenlibs/cppstdlib/stl/test/eh/test_insert.h
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /***********************************************************************************
       
     2   test_insert.h
       
     3 
       
     4  * Copyright (c) 1997
       
     5  * Mark of the Unicorn, Inc.
       
     6  *
       
     7  * Permission to use, copy, modify, distribute and sell this software
       
     8  * and its documentation for any purpose is hereby granted without fee,
       
     9  * provided that the above copyright notice appear in all copies and
       
    10  * that both that copyright notice and this permission notice appear
       
    11  * in supporting documentation.  Mark of the Unicorn makes no
       
    12  * representations about the suitability of this software for any
       
    13  * purpose.  It is provided "as is" without express or implied warranty.
       
    14 
       
    15 ***********************************************************************************/
       
    16 #ifndef test_insert_H_
       
    17 #define test_insert_H_
       
    18 
       
    19 # include "Prefix.h"
       
    20 # if defined (EH_NEW_HEADERS)
       
    21 #  include <utility>
       
    22 #  include <vector>
       
    23 #  include <cassert>
       
    24 #  include <climits>
       
    25 # else
       
    26 #  include <vector.h>
       
    27 #  include <assert.h>
       
    28 #  include <limits.h>
       
    29 # endif
       
    30 #include "random_number.h"
       
    31 #include "nc_alloc.h"
       
    32 #include "ThrowCompare.h"
       
    33 
       
    34 // A classification system for containers, for verification
       
    35 struct container_tag {};
       
    36 struct sequence_container_tag  {};
       
    37 struct associative_container_tag  {};
       
    38 
       
    39 struct set_tag  {};
       
    40 struct multiset_tag  {};
       
    41 struct map_tag {};
       
    42 struct multimap_tag {};
       
    43 
       
    44 template <class C, class Iter>
       
    45 size_t CountNewItems( const C&, const Iter& firstNew,
       
    46                       const Iter& lastNew, sequence_container_tag )
       
    47 {
       
    48     size_t dist = 0;
       
    49 #if 0 //def __SUNPRO_CC
       
    50     EH_DISTANCE( firstNew, lastNew, dist );
       
    51 #else
       
    52     EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
       
    53 #endif
       
    54     return dist;
       
    55 }
       
    56 
       
    57 template <class C, class Iter>
       
    58 size_t CountNewItems( const C& c, const Iter& firstNew,
       
    59                       const Iter& lastNew, multimap_tag )
       
    60 {
       
    61     return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
       
    62 }
       
    63 
       
    64 template <class C, class Iter>
       
    65 size_t CountNewItems( const C& c, const Iter& firstNew,
       
    66                       const Iter& lastNew, multiset_tag )
       
    67 {
       
    68     return CountNewItems( c, firstNew, lastNew, sequence_container_tag() );
       
    69 }
       
    70 
       
    71 
       
    72 template <class C, class Iter, class KeyOfValue>
       
    73 #ifdef __BORLANDC__
       
    74 size_t CountUniqueItems_Aux( const C& original, const Iter& firstNew,
       
    75 #else
       
    76 size_t CountUniqueItems_Aux( const C& original, Iter firstNew,
       
    77 #endif
       
    78                              Iter lastNew, const KeyOfValue& keyOfValue )
       
    79 {
       
    80   typedef typename C::key_type key;
       
    81   typedef typename C::const_iterator const_iter;
       
    82   typedef EH_STD::vector<key> key_list;
       
    83   typedef typename key_list::iterator key_iterator;
       
    84   key_list keys;
       
    85   size_t dist = 0;
       
    86 #ifdef __SUNPRO_CC
       
    87   EH_DISTANCE( firstNew, lastNew, dist );
       
    88 #else
       
    89   EH_DISTANCE( Iter(firstNew), Iter(lastNew), dist );
       
    90 #endif
       
    91   keys.reserve( dist );
       
    92   for ( Iter x = firstNew; x != lastNew; ++x )
       
    93     keys.push_back( keyOfValue(*x) );
       
    94 
       
    95   EH_STD::sort( keys.begin(), keys.end() );
       
    96   key_iterator last = EH_STD::unique( keys.begin(), keys.end() );
       
    97 
       
    98     size_t cnt = 0;
       
    99     for ( key_iterator tmp = keys.begin(); tmp != last; ++tmp )
       
   100     {
       
   101         if ( const_iter(original.find( *tmp )) == const_iter(original.end()) )
       
   102             ++cnt;
       
   103     }
       
   104     return cnt;
       
   105 }
       
   106 
       
   107 #if ! defined (__SGI_STL)
       
   108 EH_BEGIN_NAMESPACE
       
   109 template <class T>
       
   110 struct identity
       
   111 {
       
   112   const T& operator()( const T& x ) const { return x; }
       
   113 };
       
   114 # if ! defined (__KCC)
       
   115 template <class _Pair>
       
   116 struct select1st : public unary_function<_Pair, typename _Pair::first_type> {
       
   117   const typename _Pair::first_type& operator()(const _Pair& __x) const {
       
   118     return __x.first;
       
   119   }
       
   120 };
       
   121 # endif
       
   122 EH_END_NAMESPACE
       
   123 #endif
       
   124 
       
   125 template <class C, class Iter>
       
   126 size_t CountUniqueItems( const C& original, const Iter& firstNew,
       
   127                          const Iter& lastNew, set_tag )
       
   128 {
       
   129     typedef typename C::value_type value_type;
       
   130     return CountUniqueItems_Aux( original, firstNew, lastNew,
       
   131                                  EH_STD::identity<value_type>() );
       
   132 }
       
   133 
       
   134 template <class C, class Iter>
       
   135 size_t CountUniqueItems( const C& original, const Iter& firstNew,
       
   136                          const Iter& lastNew, map_tag )
       
   137 {
       
   138 #ifdef EH_MULTI_CONST_TEMPLATE_ARG_BUG
       
   139     return CountUniqueItems_Aux( original, firstNew, lastNew,
       
   140                                  EH_SELECT1ST_HINT<C::value_type, C::key_type>() );
       
   141 #else
       
   142     typedef typename C::value_type value_type;
       
   143     return CountUniqueItems_Aux( original, firstNew, lastNew,
       
   144                                  EH_STD::select1st<value_type>() );
       
   145 #endif
       
   146 }
       
   147 
       
   148 template <class C, class Iter>
       
   149 size_t CountNewItems( const C& original, const Iter& firstNew,
       
   150                       const Iter& lastNew, map_tag )
       
   151 {
       
   152     return CountUniqueItems( original, firstNew, lastNew,
       
   153                              container_category( original ) );
       
   154 }
       
   155 
       
   156 template <class C, class Iter>
       
   157 size_t CountNewItems( const C& original, const Iter& firstNew,
       
   158                       const Iter& lastNew, set_tag )
       
   159 {
       
   160     return CountUniqueItems( original, firstNew, lastNew,
       
   161                              container_category( original ) );
       
   162 }
       
   163 
       
   164 template <class C, class SrcIter>
       
   165 inline void VerifyInsertion( const C& original, const C& result,
       
   166                              const SrcIter& firstNew, const SrcIter& lastNew,
       
   167                              size_t, associative_container_tag )
       
   168 {
       
   169     typedef typename C::const_iterator DstIter;
       
   170     DstIter first1 = original.begin();
       
   171     DstIter first2 = result.begin();
       
   172 
       
   173     DstIter* from_orig = new DstIter[original.size()];
       
   174     DstIter* last_from_orig = from_orig;
       
   175 
       
   176     // fbp : for hashed containers, the following is needed :
       
   177     while ( first2 != result.end() )
       
   178     {
       
   179         EH_STD::pair<DstIter, DstIter> p = EH_STD::mismatch( first1, original.end(), first2 );
       
   180         if ( p.second != result.end() )
       
   181         {
       
   182             SrcIter srcItem = EH_STD::find( SrcIter(firstNew), SrcIter(lastNew), *p.second );
       
   183 
       
   184             if (srcItem == lastNew)
       
   185             {
       
   186                 // not found in input range, probably re-ordered from the orig
       
   187                 DstIter* tmp;
       
   188                 tmp = EH_STD::find( from_orig, last_from_orig, p.first );
       
   189 
       
   190                 // if already here, exclude
       
   191                 if (tmp != last_from_orig)
       
   192                 {
       
   193                     EH_STD::copy(tmp+1, last_from_orig, tmp);
       
   194                     last_from_orig--;
       
   195                 }
       
   196                 else
       
   197                 {
       
   198                     // register re-ordered element
       
   199                     DstIter dstItem;
       
   200                     dstItem = EH_STD::find( first1, original.end(), *p.first );
       
   201                     EH_ASSERT( dstItem != original.end() );
       
   202                     *last_from_orig = dstItem;
       
   203                     last_from_orig++;
       
   204                     ++p.first;
       
   205                 }
       
   206             }
       
   207             ++p.second;
       
   208         }
       
   209         first1 = p.first;
       
   210         first2 = p.second;
       
   211     }
       
   212 
       
   213     delete [] from_orig;
       
   214 }
       
   215 
       
   216 // VC++
       
   217 template <class C, class SrcIter>
       
   218 inline void VerifyInsertion(
       
   219     const C& original, const C& result, const SrcIter& firstNew,
       
   220     const SrcIter& lastNew, size_t, set_tag )
       
   221 {
       
   222     VerifyInsertion( original, result, firstNew, lastNew,
       
   223                      size_t(0), associative_container_tag() );
       
   224 }
       
   225 
       
   226 template <class C, class SrcIter>
       
   227 inline void VerifyInsertion(const C& original, const C& result,
       
   228                             const SrcIter& firstNew, const SrcIter& lastNew,
       
   229                             size_t, multiset_tag )
       
   230 {
       
   231     VerifyInsertion( original, result, firstNew, lastNew,
       
   232                      size_t(0), associative_container_tag() );
       
   233 }
       
   234 
       
   235 template <class C, class SrcIter>
       
   236 inline void VerifyInsertion(
       
   237     const C& original, const C& result, const SrcIter& firstNew,
       
   238     const SrcIter& lastNew, size_t, map_tag )
       
   239 {
       
   240     VerifyInsertion( original, result, firstNew, lastNew,
       
   241                      size_t(0), associative_container_tag() );
       
   242 }
       
   243 
       
   244 template <class C, class SrcIter>
       
   245 inline void VerifyInsertion(
       
   246     const C& original, const C& result, const SrcIter& firstNew,
       
   247     const SrcIter& lastNew, size_t, multimap_tag )
       
   248 {
       
   249     VerifyInsertion( original, result, firstNew, lastNew,
       
   250                      size_t(0), associative_container_tag() );
       
   251 }
       
   252 
       
   253 template <class C, class SrcIter>
       
   254 void VerifyInsertion(
       
   255 # ifdef _MSC_VER
       
   256     const C& original, const C& result, SrcIter firstNew,
       
   257     SrcIter lastNew, size_t insPos, sequence_container_tag )
       
   258 # else
       
   259     const C& original, const C& result, const SrcIter& firstNew,
       
   260     const SrcIter& lastNew, size_t insPos, sequence_container_tag )
       
   261 # endif
       
   262 {
       
   263     typename C::const_iterator p1 = original.begin();
       
   264     typename C::const_iterator p2 = result.begin();
       
   265     SrcIter tmp(firstNew);
       
   266 
       
   267     for ( size_t n = 0; n < insPos; n++, ++p1, ++p2)
       
   268         EH_ASSERT( *p1 == *p2 );
       
   269 
       
   270     for (; tmp != lastNew; ++p2, ++tmp ) {
       
   271         EH_ASSERT(p2 != result.end());
       
   272         EH_ASSERT(*p2 == *tmp);
       
   273     }
       
   274 
       
   275     for (;  p2 != result.end(); ++p1, ++p2 )
       
   276         EH_ASSERT( *p1 == *p2 );
       
   277     EH_ASSERT( p1 == original.end() );
       
   278 }
       
   279 
       
   280 template <class C, class SrcIter>
       
   281 inline void VerifyInsertion( const C& original, const C& result,
       
   282                              const SrcIter& firstNew,
       
   283                              const SrcIter& lastNew, size_t insPos )
       
   284 {
       
   285     EH_ASSERT( result.size() == original.size() +
       
   286             CountNewItems( original, firstNew, lastNew,
       
   287                            container_category(original) ) );
       
   288     VerifyInsertion( original, result, firstNew, lastNew, insPos,
       
   289                      container_category(original) );
       
   290 }
       
   291 
       
   292 template <class C, class Value>
       
   293 void VerifyInsertN( const C& original, const C& result, size_t insCnt,
       
   294                     const Value& val, size_t insPos )
       
   295 {
       
   296     typename C::const_iterator p1 = original.begin();
       
   297     typename C::const_iterator p2 = result.begin();
       
   298   (void)val;    //*TY 02/06/2000 - to suppress unused variable warning under nondebug build
       
   299 
       
   300     for ( size_t n = 0; n < insPos; n++ )
       
   301         EH_ASSERT( *p1++ == *p2++ );
       
   302 
       
   303     while ( insCnt-- > 0 )
       
   304     {
       
   305         EH_ASSERT(p2 != result.end());
       
   306         EH_ASSERT(*p2 == val );
       
   307         ++p2;
       
   308     }
       
   309 
       
   310     while ( p2 != result.end() ) {
       
   311         EH_ASSERT( *p1 == *p2 );
       
   312         ++p1; ++p2;
       
   313     }
       
   314     EH_ASSERT( p1 == original.end() );
       
   315 }
       
   316 
       
   317 template <class C>
       
   318 void prepare_insert_n( C&, size_t ) {}
       
   319 
       
   320 // Metrowerks 1.8 compiler requires that specializations appear first (!!)
       
   321 // or it won't call them. Fixed in 1.9, though.
       
   322 inline void MakeRandomValue(bool& b) { b = bool(random_number(2) != 0); }
       
   323 
       
   324 template<class T>
       
   325 inline void MakeRandomValue(T&) {}
       
   326 
       
   327 template <class C>
       
   328 struct test_insert_one
       
   329 {
       
   330     test_insert_one( const C& orig, int pos =-1 )
       
   331         : original( orig ), fPos( random_number( orig.size() ))
       
   332     {
       
   333         MakeRandomValue( fInsVal );
       
   334         if ( pos != -1 )
       
   335         {
       
   336             fPos = size_t(pos);
       
   337             if ( pos == 0 )
       
   338                 gTestController.SetCurrentTestName("single insertion at begin()");
       
   339             else
       
   340                 gTestController.SetCurrentTestName("single insertion at end()");
       
   341         }
       
   342         else
       
   343             gTestController.SetCurrentTestName("single insertion at random position");
       
   344     }
       
   345 
       
   346     void operator()( C& c ) const
       
   347     {
       
   348         prepare_insert_n( c, (size_t)1 );
       
   349         typename C::iterator pos = c.begin();
       
   350         EH_STD::advance( pos, size_t(fPos) );
       
   351         c.insert( pos, fInsVal );
       
   352 
       
   353         // Prevent simulated failures during verification
       
   354         gTestController.CancelFailureCountdown();
       
   355         // Success. Check results.
       
   356         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, fPos );
       
   357     }
       
   358 private:
       
   359     typename C::value_type fInsVal;
       
   360     const C& original;
       
   361     size_t fPos;
       
   362 };
       
   363 
       
   364 template <class C>
       
   365 struct test_insert_n
       
   366 {
       
   367     test_insert_n( const C& orig, size_t insCnt, int pos =-1 )
       
   368         : original( orig ), fPos( random_number( orig.size() )), fInsCnt(insCnt)
       
   369     {
       
   370         MakeRandomValue( fInsVal );
       
   371         if (pos!=-1)
       
   372         {
       
   373             fPos=size_t(pos);
       
   374             if (pos==0)
       
   375                 gTestController.SetCurrentTestName("n-ary insertion at begin()");
       
   376             else
       
   377                 gTestController.SetCurrentTestName("n-ary insertion at end()");
       
   378         }
       
   379         else
       
   380             gTestController.SetCurrentTestName("n-ary insertion at random position");
       
   381     }
       
   382 
       
   383     void operator()( C& c ) const
       
   384     {
       
   385         prepare_insert_n( c, fInsCnt );
       
   386         typename C::iterator pos = c.begin();
       
   387         EH_STD::advance( pos, fPos );
       
   388         c.insert( pos, fInsCnt, fInsVal );
       
   389 
       
   390         // Prevent simulated failures during verification
       
   391         gTestController.CancelFailureCountdown();
       
   392         // Success. Check results.
       
   393         VerifyInsertN( original, c, fInsCnt, fInsVal, fPos );
       
   394     }
       
   395 private:
       
   396     typename C::value_type fInsVal;
       
   397     const C& original;
       
   398     size_t fPos;
       
   399     size_t fInsCnt;
       
   400 };
       
   401 
       
   402 template <class C>
       
   403 struct test_insert_value
       
   404 {
       
   405     test_insert_value( const C& orig )
       
   406         : original( orig )
       
   407     {
       
   408         MakeRandomValue( fInsVal );
       
   409         gTestController.SetCurrentTestName("insertion of random value");
       
   410     }
       
   411 
       
   412     void operator()( C& c ) const
       
   413     {
       
   414         c.insert( fInsVal );
       
   415 
       
   416         // Prevent simulated failures during verification
       
   417         gTestController.CancelFailureCountdown();
       
   418         // Success. Check results.
       
   419         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
       
   420     }
       
   421 private:
       
   422     typename C::value_type fInsVal;
       
   423     const C& original;
       
   424 };
       
   425 
       
   426 template <class C>
       
   427 struct test_insert_noresize
       
   428 {
       
   429     test_insert_noresize( const C& orig )
       
   430         : original( orig )
       
   431     {
       
   432         MakeRandomValue( fInsVal );
       
   433         gTestController.SetCurrentTestName("insertion of random value without resize");
       
   434     }
       
   435 
       
   436     void operator()( C& c ) const
       
   437     {
       
   438         c.insert_noresize( fInsVal );
       
   439 
       
   440         // Prevent simulated failures during verification
       
   441         gTestController.CancelFailureCountdown();
       
   442         // Success. Check results.
       
   443         VerifyInsertion( original, c, &fInsVal, 1+&fInsVal, size_t(0) );
       
   444     }
       
   445 private:
       
   446     typename C::value_type fInsVal;
       
   447     const C& original;
       
   448 };
       
   449 
       
   450 template <class C, class Position, class Iter>
       
   451 void do_insert_range( C& c_inst, Position offset,
       
   452                       Iter first, Iter last, sequence_container_tag )
       
   453 {
       
   454     typedef typename C::iterator CIter;
       
   455     CIter pos = c_inst.begin();
       
   456     EH_STD::advance( pos, offset );
       
   457     c_inst.insert( pos, first, last );
       
   458 }
       
   459 
       
   460 template <class C, class Position, class Iter>
       
   461 void do_insert_range( C& c, Position,
       
   462                       Iter first, Iter last, associative_container_tag )
       
   463 {
       
   464     c.insert( first, last );
       
   465 }
       
   466 
       
   467 template <class C, class Position, class Iter>
       
   468 void do_insert_range( C& c, Position, Iter first, Iter last, multiset_tag )
       
   469 {
       
   470     c.insert( first, last );
       
   471 }
       
   472 
       
   473 template <class C, class Position, class Iter>
       
   474 void do_insert_range( C& c, Position, Iter first, Iter last, multimap_tag )
       
   475 {
       
   476     c.insert( first, last );
       
   477 }
       
   478 
       
   479 template <class C, class Position, class Iter>
       
   480 void do_insert_range( C& c, Position, Iter first, Iter last, set_tag )
       
   481 {
       
   482     c.insert( first, last );
       
   483 }
       
   484 
       
   485 template <class C, class Position, class Iter>
       
   486 void do_insert_range( C& c, Position, Iter first, Iter last, map_tag )
       
   487 {
       
   488     c.insert( first, last );
       
   489 }
       
   490 
       
   491 /*
       
   492 template <class C, class Iter>
       
   493 void prepare_insert_range( C&, size_t, Iter, Iter) {}
       
   494 */
       
   495 
       
   496 template <class C, class Iter>
       
   497 struct test_insert_range
       
   498 {
       
   499     test_insert_range( const C& orig, Iter first, Iter last, int pos=-1 )
       
   500         : fFirst( first ),
       
   501           fLast( last ),
       
   502           original( orig ),
       
   503           fPos( random_number( orig.size() ))
       
   504     {
       
   505         gTestController.SetCurrentTestName("range insertion");
       
   506         if ( pos != -1 )
       
   507         {
       
   508             fPos = size_t(pos);
       
   509             if ( pos == 0 )
       
   510                 gTestController.SetCurrentTestName("range insertion at begin()");
       
   511             else
       
   512                 gTestController.SetCurrentTestName("range insertion at end()");
       
   513         }
       
   514         else
       
   515             gTestController.SetCurrentTestName("range insertion at random position");
       
   516     }
       
   517 
       
   518     void operator()( C& c ) const
       
   519     {
       
   520 //        prepare_insert_range( c, fPos, fFirst, fLast );
       
   521         do_insert_range( c, fPos, fFirst, fLast, container_category(c) );
       
   522 
       
   523         // Prevent simulated failures during verification
       
   524         gTestController.CancelFailureCountdown();
       
   525         // Success. Check results.
       
   526         VerifyInsertion( original, c, fFirst, fLast, fPos );
       
   527     }
       
   528 private:
       
   529     Iter fFirst, fLast;
       
   530     const C& original;
       
   531     size_t fPos;
       
   532 };
       
   533 
       
   534 template <class C, class Iter>
       
   535 test_insert_range<C, Iter> insert_range_tester( const C& orig, const Iter& first, const Iter& last )
       
   536 {
       
   537     return test_insert_range<C, Iter>( orig, first, last );
       
   538 }
       
   539 
       
   540 template <class C, class Iter>
       
   541 test_insert_range<C, Iter> insert_range_at_begin_tester( const C& orig, const Iter& first, const Iter& last )
       
   542 {
       
   543   return test_insert_range<C, Iter>( orig, first, last , 0);
       
   544 }
       
   545 
       
   546 template <class C, class Iter>
       
   547 test_insert_range<C, Iter> insert_range_at_end_tester( const C& orig, const Iter& first, const Iter& last )
       
   548 {
       
   549   return test_insert_range<C, Iter>( orig, first, last , (int)orig.size());
       
   550 }
       
   551 
       
   552 #endif // test_insert_H_