CppUnit project page CppUnit home page

assertenum.h

Go to the documentation of this file.
00001 #ifndef CPPUT_ASSERTENUM_H_INCLUDED
00002 # define CPPUT_ASSERTENUM_H_INCLUDED
00003 
00004 # include <cpput/assertcommon.h>
00005 # include <cpptl/enumerator.h>
00006 # include <functional>
00007 # include <deque>
00008 
00009 //todo: for sequence, list 'common' sequence part before expected & actual divergence
00010 
00011 namespace CppUT
00012 {
00013    template<class AType
00014            ,class BType>
00015    struct DefaultComparator
00016    {
00017       DefaultComparator() // Declaration needed to avoid bogus suncc warning.
00018       {
00019       }
00020 
00021       bool operator()( const AType &a, const BType &b ) const
00022       {
00023          return equalityTest( a, b );
00024       }
00025    };
00026 
00027    template<class AType
00028             ,class BType>
00029    struct DeRefComparator
00030    {
00031       bool operator()( const AType *a, const BType *b ) const
00032       {
00033          return a == b  ||  
00034                 ( !a  &&  !b  &&  *a == *b );
00035       }
00036    };
00037 
00038    template<class AType
00039             ,class BType>
00040    struct RefComparator
00041    {
00042       bool operator()( AType a, BType b ) const
00043       {
00044          return equalityTest( a, b );
00045       }
00046    };
00047 
00048 # ifndef CPPUT_NO_DEFAULT_ENUM_ITEM_STRINGIZE
00049    template<typename ItemType>
00050    std::string stringizeEnumItem( const ItemType &item )
00051    {
00052       return stringize( item );
00053    }
00054 # endif // CPPUT_NO_DEFAULT_ENUM_ITEM_STRINGIZE
00055 
00056 
00058    namespace Impl {
00059 
00060       enum { noDifference = -1 };
00061 
00062       template<class ExpectedEnumType
00063               ,class ActualEnumType
00064               ,class EqualityPredicate>
00065       unsigned int getSequenceDiffIndex( ExpectedEnumType expected, 
00066                                          ActualEnumType actual,
00067                                          EqualityPredicate comparator )
00068       {
00069          unsigned int diffIndex = 0;
00070          while ( expected.is_open() )
00071          {
00072             if ( !actual.is_open() )
00073                return diffIndex;
00074             if ( !comparator(expected.current(), actual.current() ) )
00075                return diffIndex;
00076             expected.advance();
00077             actual.advance();
00078             ++diffIndex;
00079          }
00080          if ( actual.is_open() )
00081             return diffIndex;
00082          return (unsigned int)noDifference;
00083       }
00084 
00085 
00086       template<class ExpectedSetType
00087                ,class ActualSetType
00088                ,class MissingSeqType
00089                ,class ExtraneousSeqType
00090                ,class EqualityPredicate>
00091       void getSetDifference( ExpectedSetType expectedEnum,
00092                              ActualSetType actualEnum,
00093                              MissingSeqType &missing,
00094                              ExtraneousSeqType &extraneous,
00095                              EqualityPredicate predicate )
00096       {
00097          for ( ; actualEnum.is_open(); actualEnum.advance() )
00098             extraneous.push_back( actualEnum.current() );
00099 
00100          for ( ; expectedEnum.is_open(); expectedEnum.advance() )
00101          {
00102             CPPTL_TYPENAME ExpectedSetType::value_type expectedItem = expectedEnum.current();
00103             bool found = false;
00104             CPPTL_TYPENAME ExtraneousSeqType::iterator it = extraneous.begin();
00105             for ( ; it != extraneous.end(); ++it )
00106             {
00107                const CPPTL_TYPENAME ExtraneousSeqType::value_type &actualItem = *it;
00108                if ( predicate( expectedItem, actualItem ) )
00109                {
00110                   it = extraneous.erase( it );
00111                   found = true;
00112                   break;
00113                }
00114             }
00115 
00116             if ( !found )
00117                missing.push_back( expectedItem );
00118          }
00119       }
00120 
00121    } // namespace Impl
00123 
00124    template<class ExpectedEnumerator
00125            ,class ActualEnumerator
00126            ,class ExpectedStringizer
00127            ,class ActualStringizer
00128            ,class EqualityPredicate>
00129    CheckerResult checkCustomHeterogeneousSequenceEqual( const ExpectedEnumerator &expected,
00130                                                         const ActualEnumerator &actual,
00131                                                         ExpectedStringizer expectedStringizer,
00132                                                         ActualStringizer actualStringizer,
00133                                                         EqualityPredicate comparator,
00134                                                         const Message &message )
00135    {
00136       CheckerResult result;
00137       unsigned int diffIndex = Impl::getSequenceDiffIndex( expected, 
00138                                                            actual, 
00139                                                            comparator );
00140       if ( diffIndex == Impl::noDifference )
00141          return result;
00142 
00143       typedef CppTL::SliceEnumerator<ExpectedEnumerator> ExpectedEnumeratorSlice;
00144       ExpectedEnumeratorSlice common = CppTL::Enum::slice( expected, 0, diffIndex );
00145       ExpectedEnumeratorSlice expectedDiff = CppTL::Enum::slice( expected, diffIndex );
00146       typedef CppTL::SliceEnumerator<ActualEnumerator> ActualEnumeratorSlice;
00147       ActualEnumeratorSlice actualDiff = CppTL::Enum::slice( actual, diffIndex );
00148 
00149       result.setFailed();
00150       result.message_ = message;
00151       result.message_.add( translate( "Sequences are not identical." ) );
00152       result.message_.add( translate( "Divergence position (0 based): " ) + stringize(diffIndex) );
00153       if ( common.is_open() )
00154          result.message_.add( translate( "Common:\n" ) + enumToStringCustom(common,  
00155                                                                             expectedStringizer) );
00156       result.message_.add( translate( "Expected:\n" ) + enumToStringCustom(expectedDiff, 
00157                                                                            expectedStringizer) );
00158       result.message_.add( translate( "Actual:\n" ) + enumToStringCustom(actualDiff, 
00159                                                                          actualStringizer) );
00160       return result;
00161    }
00162 
00163    template<class EnumeratorType
00164            ,class StringizerType
00165            ,class EqualityPredicate>
00166    CheckerResult checkCustomSequenceEqual( const EnumeratorType &expected,
00167                                            const EnumeratorType &actual,
00168                                            StringizerType stringizer,
00169                                            EqualityPredicate comparator,
00170                                            const Message &message )
00171    {
00172       return checkCustomHeterogeneousSequenceEqual( expected, actual,
00173                                                     stringizer, stringizer,
00174                                                     comparator, message );
00175    }
00176 
00177    template<class EnumeratorType
00178            ,class StringizerType
00179            ,class EqualityPredicate>
00180    CheckerResult checkCustomStringSequenceEqual( const EnumeratorType &expected,
00181                                                  const EnumeratorType &actual,
00182                                                  StringizerType stringizer,
00183                                                  const Message &message = Message() )
00184    {
00185       typedef CPPTL_TYPENAME EnumeratorType::value_type ValueType;
00186       DefaultComparator<ValueType,ValueType> comparator;
00187       return checkCustomHeterogeneousSequenceEqual( expected, actual,
00188                                                     stringizer, stringizer,
00189                                                     comparator, message );
00190    }
00191 
00192    template<class ExpectedEnumerator
00193            ,class ActualEnumerator
00194            ,class EqualityPredicate>
00195    CheckerResult checkCustomEqualitySequenceEqual( const ExpectedEnumerator &expected,
00196                                                    const ActualEnumerator &actual,
00197                                                    EqualityPredicate comparator,
00198                                                    const Message &message = Message() )
00199    {
00200       typedef DefaultStringizer<CPPTL_TYPENAME ExpectedEnumerator::value_type> ExpectedStringizer;
00201       typedef DefaultStringizer<CPPTL_TYPENAME ActualEnumerator::value_type> ActualStringizer;
00202       return checkCustomHeterogeneousSequenceEqual( expected, actual,
00203                                                     ExpectedStringizer(), ActualStringizer(),
00204                                                     comparator, message );
00205    }
00206 
00207 
00208    template<class ExpectedEnumeratorType
00209            ,class ActualEnumeratorType>
00210    CheckerResult checkSequenceEqual( const ExpectedEnumeratorType &expected,
00211                                      const ActualEnumeratorType &actual,
00212                                      const Message &message  = Message() )
00213    {
00214       DefaultComparator<CPPTL_TYPENAME ExpectedEnumeratorType::value_type
00215                        ,CPPTL_TYPENAME ActualEnumeratorType::value_type> comparator;
00216       return checkCustomEqualitySequenceEqual( expected, actual, comparator, message );
00217    }
00218 
00219    template<class ExpectedEnumeratorType
00220            ,class ActualEnumeratorType
00221            ,class EqualityPredicate>
00222    CheckerResult checkCustomEqualityStlSequenceEqual( const ExpectedEnumeratorType &expected,
00223                                                       const ActualEnumeratorType &actual,
00224                                                       EqualityPredicate comparator,
00225                                                       const Message &message = Message() )
00226    {
00227       return checkCustomEqualitySequenceEqual( CppTL::Enum::container( expected ), 
00228                                                CppTL::Enum::container( actual ), 
00229                                                comparator, message );
00230    }
00231 
00232    template<class ExpectedEnumeratorType
00233            ,class ActualEnumeratorType>
00234    CheckerResult checkStlSequenceEqual( const ExpectedEnumeratorType &expected,
00235                                         const ActualEnumeratorType &actual,
00236                                         const Message &message  = Message() )
00237    {
00238       return checkSequenceEqual( CppTL::Enum::container( expected ), 
00239                                  CppTL::Enum::container( actual ), 
00240                                  message );
00241    }
00242 
00243    template<class ExpectedEnumerator
00244            ,class ActualEnumerator
00245            ,class ExpectedStringizer
00246            ,class ActualStringizer
00247            ,class EqualityPredicate>
00248    CheckerResult checkCustomHeterogeneousSetEqual( const ExpectedEnumerator &expected,
00249                                                    const ActualEnumerator &actual,
00250                                                    ExpectedStringizer expectedStringizer,
00251                                                    ActualStringizer actualStringizer,
00252                                                    EqualityPredicate predicate,
00253                                                    const Message &message )
00254    {
00255       CheckerResult result;
00256       std::deque<CPPTL_TYPENAME ExpectedEnumerator::value_type> missing;
00257       std::deque<CPPTL_TYPENAME ActualEnumerator::value_type> extraneous;
00258       Impl::getSetDifference( expected, actual,
00259                               missing, extraneous,
00260                               predicate );
00261       if ( missing.empty()  &&  extraneous.empty() )
00262          return result;
00263 
00264       result.setFailed();
00265       result.message_ = message;
00266       result.message_.add( translate( "Sets do not contain the same items." ) );
00267       result.message_.add( translate( "Actual:\n" ) + enumToStringCustom(actual,actualStringizer) );
00268       if ( missing.size() > 0 )
00269          result.message_.add( translate( "Missing:\n" ) + 
00270                               enumToStringCustom( CppTL::Enum::container(missing),
00271                                                   expectedStringizer ) );
00272       if ( extraneous.size() > 0 )
00273          result.message_.add( translate( "Extraneous:\n" ) + 
00274                               enumToStringCustom( CppTL::Enum::container(extraneous), 
00275                                                   actualStringizer ) );
00276       return result;
00277    }
00278 
00279    template<class ExpectedEnumerator
00280            ,class ActualEnumerator
00281            ,class ItemStringizer
00282            ,class EqualityPredicate>
00283    CheckerResult checkCustomSetEqual( const ExpectedEnumerator &expected,
00284                                       const ActualEnumerator &actual,
00285                                       ItemStringizer itemStringizer,
00286                                       EqualityPredicate comparator,
00287                                       const Message &message = Message() )
00288    {
00289       return checkCustomHeterogeneousSetEqual( expected, actual, 
00290                                                itemStringizer, itemStringizer, 
00291                                                comparator, message );
00292    }
00293 
00294    template<class ExpectedEnumerator
00295            ,class ActualEnumerator
00296            ,class ItemStringizer>
00297    CheckerResult checkCustomStringSetEqual( const ExpectedEnumerator &expected,
00298                                             const ActualEnumerator &actual,
00299                                             ItemStringizer itemStringizer,
00300                                             const Message &message = Message() )
00301    {
00302       DefaultComparator<CPPTL_TYPENAME ExpectedEnumerator::value_type
00303                        ,CPPTL_TYPENAME ActualEnumerator::value_type> comparator;
00304       return checkCustomSetEqual( expected, actual, itemStringizer, comparator, message );
00305    }
00306 
00307    template<class ExpectedEnumerator
00308            ,class ActualEnumerator
00309            ,class EqualityPredicate>
00310    CheckerResult checkCustomEqualitySetEqual( const ExpectedEnumerator &expected,
00311                                               const ActualEnumerator &actual,
00312                                               EqualityPredicate comparator,
00313                                               const Message &message = Message() )
00314    {
00315       typedef DefaultStringizer<CPPTL_TYPENAME ExpectedEnumerator::value_type> ExpectedStringizer;
00316       typedef DefaultStringizer<CPPTL_TYPENAME ActualEnumerator::value_type> ActualStringizer;
00317       return checkCustomHeterogeneousSetEqual( expected, actual, 
00318                                                ExpectedStringizer(), ActualStringizer(),
00319                                                comparator, message );
00320    }
00321 
00322    template<class ExpectedEnumerator
00323            ,class ActualEnumerator>
00324    CheckerResult checkSetEqual( const ExpectedEnumerator &expected,
00325                                 const ActualEnumerator &actual,
00326                                 const Message &message = Message() )
00327    {
00328       DefaultComparator<CPPTL_TYPENAME ExpectedEnumerator::value_type
00329                        ,CPPTL_TYPENAME ActualEnumerator::value_type> comparator;
00330       return checkCustomEqualitySetEqual( expected, actual, comparator, message );
00331    }
00332 
00333    template<class ExpectedStlSet
00334            ,class ActualStlSet>
00335    CheckerResult checkStlSetEqual( const ExpectedStlSet &expected,
00336                                    const ActualStlSet &actual,
00337                                    const Message &message = Message() )
00338    {
00339       return checkSetEqual( CppTL::Enum::container( expected ), 
00340                             CppTL::Enum::container( actual ), 
00341                             message );
00342    }
00343 
00344    template<class ExpectedSetType
00345            ,class ActualSetType
00346            ,class EqualityPredicate>
00347    CheckerResult checkCustomEqualityStlSetEqual( const ExpectedSetType &expected,
00348                                                  const ActualSetType &actual,
00349                                                  EqualityPredicate predicate,
00350                                                  const Message &message = Message() )
00351    {
00352       return checkSetEqual( CppTL::Enum::container( expected ), 
00353                             CppTL::Enum::container( actual ), 
00354                             predicate, message );
00355    }
00356 
00357 
00358    template<class EnumeratorType
00359            ,class ItemStringizerType>
00360    std::string enumToStringCustom( EnumeratorType enumerator,
00361                                    ItemStringizerType itemStringizer,
00362                                    const std::string &separator = "; ",
00363                                    const std::string &begin = "{ ",
00364                                    const std::string &end = " }" )
00365    {
00366       std::string str;
00367       for ( ; enumerator.is_open(); enumerator.advance() )
00368       {
00369          std::string item = itemStringizer( enumerator.current() );
00370          if ( !str.empty() )
00371             str += separator;
00372          str += item;
00373       }
00374       return begin + str + end;
00375    }
00376 
00377 
00378    template<class EnumType>
00379    std::string enumToString( const EnumType &enumerator,
00380                              const std::string &separator = "; ",
00381                              const std::string &begin = "{ ",
00382                              const std::string &end = " }" )
00383    {
00384       return enumToStringCustom( enumerator, 
00385                                  DefaultStringizer<CPPTL_TYPENAME EnumType::value_type>(), 
00386                                  separator, 
00387                                  begin, 
00388                                  end );
00389    }
00390 
00391 } // namespace CppUT
00392 
00393 
00397 # define CPPUT_ASSERT_SEQUENCE_EQUAL  \
00398    CPPUT_BEGIN_ASSERTION_MACRO() \
00399    ::CppUT::checkSequenceEqual
00400 
00404 # define CPPUT_ASSERT_SET_EQUAL \
00405    CPPUT_BEGIN_ASSERTION_MACRO() \
00406    ::CppUT::checkSetEqual
00407 
00411 # define CPPUT_ASSERT_STL_SEQUENCE_EQUAL  \
00412    CPPUT_BEGIN_ASSERTION_MACRO() \
00413    ::CppUT::checkStlSequenceEqual
00414 
00418 # define CPPUT_ASSERT_STL_SET_EQUAL \
00419    CPPUT_BEGIN_ASSERTION_MACRO() \
00420    ::CppUT::checkStlSetEqual
00421 
00422 
00426 # define CPPUT_CHECK_SEQUENCE_EQUAL  \
00427    CPPUT_BEGIN_CHECKING_MACRO() \
00428    ::CppUT::checkSequenceEqual
00429 
00433 # define CPPUT_CHECK_SET_EQUAL \
00434    CPPUT_BEGIN_CHECKING_MACRO() \
00435    ::CppUT::checkSetEqual
00436 
00437 
00441 # define CPPUT_CHECK_STL_SEQUENCE_EQUAL  \
00442    CPPUT_BEGIN_CHECKING_MACRO() \
00443    ::CppUT::checkStlSequenceEqual
00444 
00448 # define CPPUT_CHECK_STL_SET_EQUAL \
00449    CPPUT_BEGIN_CHECKING_MACRO() \
00450    ::CppUT::checkStlSetEqual
00451 
00452 #endif // CPPUT_ASSERTENUM_H_INCLUDED
00453 

SourceForge Logo hosts this site. Send comments to:
CppUnit Developers