os/ossrv/genericopenlibs/cppstdlib/stl/test/eh/test_algo.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 }