genericopenlibs/cppstdlib/stl/test/eh/test_algo.cpp
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /***********************************************************************************
       
     2   test_algo.cpp
       
     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 #include "Tests.h"
       
    17 #include "LeakCheck.h"
       
    18 #include "SortClass.h"
       
    19 
       
    20 #if defined (EH_NEW_HEADERS)
       
    21 # include <algorithm>
       
    22 # include <cassert>
       
    23 #else
       
    24 # include <algo.h>
       
    25 # include <assert.h>
       
    26 #endif
       
    27 
       
    28 #if defined (EH_NEW_IOSTREAMS)
       
    29 # include <iostream>
       
    30 #else
       
    31 # include <iostream.h>
       
    32 #endif
       
    33 
       
    34 //
       
    35 // SortBuffer -- a buffer of SortClass objects that can be used to test sorting.
       
    36 //
       
    37 struct SortBuffer
       
    38 {
       
    39     enum { kBufferSize = 100 };
       
    40 
       
    41     SortClass* begin() { return items; }
       
    42     const SortClass* begin() const { return items; }
       
    43     SortClass* end() { return items + kBufferSize; }
       
    44     const SortClass* end() const { return items + kBufferSize; }
       
    45 
       
    46   // Sort each half of the buffer and reset the address of each element
       
    47   // so that merge() can be tested for stability.
       
    48     void PrepareMerge()
       
    49     {
       
    50         EH_STD::sort( begin(), begin() + ( end() - begin() )/2 );
       
    51         EH_STD::sort( begin() + ( end() - begin() )/2, end() );
       
    52         for ( SortClass* p = begin(); p != end(); p++ )
       
    53             p->ResetAddress();
       
    54     }
       
    55 
       
    56   SortBuffer()
       
    57   {
       
    58     PrepareMerge();
       
    59   }
       
    60 
       
    61   SortBuffer( const SortBuffer& rhs )
       
    62   {
       
    63     SortClass* q = begin();
       
    64     for ( const SortClass* p = rhs.begin() ; p != rhs.end(); p++,q++ )
       
    65       *q = *p;
       
    66   }
       
    67 
       
    68 private:
       
    69     SortClass items[kBufferSize];
       
    70 };
       
    71 
       
    72 //
       
    73 // less_by_reference -- a functor for comparing objects against a
       
    74 //   constant value.
       
    75 //
       
    76 template <class T>
       
    77 struct less_by_reference
       
    78 {
       
    79     less_by_reference( const T& arg ) : fArg(arg) {}
       
    80     bool operator()( const T& x ) const { return x < fArg; }
       
    81 private:
       
    82     const T& fArg;
       
    83 };
       
    84 
       
    85 struct test_stable_partition
       
    86 {
       
    87     test_stable_partition( const SortBuffer& buf )
       
    88         : orig( buf ), partitionPoint(SortClass::kRange / 2) {
       
    89         gTestController.SetCurrentTestName("stable_partition()");
       
    90         }
       
    91 
       
    92     void operator()( SortBuffer& buf ) const
       
    93     {
       
    94         less_by_reference<SortClass> throw_cmp( partitionPoint );
       
    95 
       
    96         SortClass* d = EH_STD::stable_partition( buf.begin(), buf.end(), throw_cmp );
       
    97 
       
    98     // If we get here no exception occurred during the operation.
       
    99     // Stop any potential failures that might occur during verification.
       
   100         gTestController.CancelFailureCountdown();
       
   101 
       
   102         // Prepare an array of counts of the occurrence of each value in
       
   103         // the legal range.
       
   104         unsigned counts[SortClass::kRange];
       
   105         EH_STD::fill_n( counts, (int)SortClass::kRange, 0 );
       
   106         for ( const SortClass *q = orig.begin(); q != orig.end(); q++ )
       
   107             counts[ q->value() ]++;
       
   108 
       
   109         less_by_reference<TestClass> cmp( partitionPoint );
       
   110         for ( const SortClass* p = buf.begin(); p != buf.end(); p++ )
       
   111         {
       
   112           // Check that adjacent items with the same value haven't been
       
   113           // reordered. This could be a more thorough test.
       
   114             if ( p != buf.begin() && p->value() == p[-1].value() )
       
   115                 EH_ASSERT( p->GetAddress() > p[-1].GetAddress() );
       
   116 
       
   117             // Check that the partitioning worked.
       
   118             EH_ASSERT( (p < d) == cmp( *p ) );
       
   119 
       
   120             // Decrement the appropriate count for each value.
       
   121             counts[ p->value() ]--;
       
   122         }
       
   123 
       
   124         // Check that the values were only rearranged, and none were lost.
       
   125         for ( unsigned j = 0; j < SortClass::kRange; j++ )
       
   126             EH_ASSERT( counts[j] == 0 );
       
   127     }
       
   128 
       
   129 private:
       
   130     const SortBuffer& orig;
       
   131     SortClass partitionPoint;
       
   132 };
       
   133 
       
   134 void assert_sorted_version( const SortBuffer& orig, const SortBuffer& buf );
       
   135 
       
   136 /*===================================================================================
       
   137   assert_sorted_version
       
   138 
       
   139   EFFECTS: Asserts that buf is a stable-sorted version of orig.
       
   140 ====================================================================================*/
       
   141 void assert_sorted_version( const SortBuffer& orig, const SortBuffer& buf )
       
   142 {
       
   143   // Stop any potential failures that might occur during verification.
       
   144     gTestController.CancelFailureCountdown();
       
   145 
       
   146     // Prepare an array of counts of the occurrence of each value in
       
   147     // the legal range.
       
   148     unsigned counts[SortClass::kRange];
       
   149     EH_STD::fill_n( counts, (int)SortClass::kRange, 0 );
       
   150     for ( const SortClass *q = orig.begin(); q != orig.end(); q++ )
       
   151         counts[ q->value() ]++;
       
   152 
       
   153   // Check that each element is greater than the previous one, or if they are
       
   154   // equal, that their order has been preserved.
       
   155     for ( const SortClass* p = buf.begin(); p != buf.end(); p++ )
       
   156     {
       
   157         if ( p != buf.begin() )
       
   158             EH_ASSERT( p->value() > p[-1].value()
       
   159                     || p->value() == p[-1].value() && p->GetAddress() > p[-1].GetAddress() );
       
   160     // Decrement the appropriate count for each value.
       
   161         counts[ p->value() ]--;
       
   162     }
       
   163 
       
   164   // Check that the values were only rearranged, and none were lost.
       
   165     for ( unsigned j = 0; j < SortClass::kRange; j++ )
       
   166         EH_ASSERT( counts[j] == 0 );
       
   167 }
       
   168 
       
   169 //
       
   170 // The test operators
       
   171 //
       
   172 struct test_stable_sort_1
       
   173 {
       
   174     test_stable_sort_1( const SortBuffer& buf )
       
   175         : orig( buf ) {
       
   176         gTestController.SetCurrentTestName("stable_sort() #1");
       
   177         }
       
   178 
       
   179     void operator()( SortBuffer& buf ) const
       
   180     {
       
   181         EH_STD::stable_sort( buf.begin(), buf.end() );
       
   182         assert_sorted_version( orig, buf );
       
   183     }
       
   184 
       
   185 private:
       
   186     const SortBuffer& orig;
       
   187 };
       
   188 
       
   189 struct test_stable_sort_2
       
   190 {
       
   191     test_stable_sort_2( const SortBuffer& buf )
       
   192         : orig( buf ) {
       
   193             gTestController.SetCurrentTestName("stable_sort() #2");
       
   194         }
       
   195 
       
   196     void operator()( SortBuffer& buf ) const
       
   197     {
       
   198       EH_STD::stable_sort( buf.begin(), buf.end(), EH_STD::less<SortClass>() );
       
   199       assert_sorted_version( orig, buf );
       
   200     }
       
   201 
       
   202 private:
       
   203     const SortBuffer& orig;
       
   204 };
       
   205 
       
   206 struct test_inplace_merge_1
       
   207 {
       
   208     test_inplace_merge_1( SortBuffer& buf )
       
   209         : orig( buf ) {
       
   210         gTestController.SetCurrentTestName("inplace_merge #1()");
       
   211         }
       
   212 
       
   213     void operator()( SortBuffer& buf ) const
       
   214     {
       
   215         EH_STD::inplace_merge( buf.begin(), buf.begin() + ( buf.end() - buf.begin() )/2, buf.end() );
       
   216         assert_sorted_version( orig, buf );
       
   217     }
       
   218 
       
   219 private:
       
   220     const SortBuffer& orig;
       
   221 };
       
   222 
       
   223 struct test_inplace_merge_2
       
   224 {
       
   225     test_inplace_merge_2( SortBuffer& buf )
       
   226         : orig( buf ) {
       
   227         gTestController.SetCurrentTestName("inplace_merge() #2");
       
   228         }
       
   229 
       
   230     void operator()( SortBuffer& buf ) const
       
   231     {
       
   232         EH_STD::inplace_merge( buf.begin(), buf.begin() + ( buf.end() - buf.begin() )/2, buf.end(),
       
   233                        EH_STD::less<SortClass>() );
       
   234         assert_sorted_version( orig, buf );
       
   235     }
       
   236 
       
   237 private:
       
   238     const SortBuffer& orig;
       
   239 };
       
   240 
       
   241 void test_algo()
       
   242 {
       
   243     SortBuffer mergeBuf;
       
   244     mergeBuf.PrepareMerge();
       
   245 
       
   246     EH_STD::cerr<<"EH test : testing algo.h"<<EH_STD::endl;
       
   247     WeakCheck( mergeBuf, test_inplace_merge_1( mergeBuf ) );
       
   248     WeakCheck( mergeBuf, test_inplace_merge_2( mergeBuf ) );
       
   249 
       
   250     SortBuffer buf;
       
   251     WeakCheck( buf, test_stable_sort_1( buf ) );
       
   252     WeakCheck( buf, test_stable_sort_2( buf ) );
       
   253     WeakCheck( buf, test_stable_partition( buf ) );
       
   254 }