Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_TestingHelpers.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_TESTING_HELPERS_HPP
00030 #define TEUCHOS_TESTING_HELPERS_HPP
00031 
00032 
00038 #include "Teuchos_ConfigDefs.hpp"
00039 #include "Teuchos_ScalarTraits.hpp"
00040 #include "Teuchos_TypeNameTraits.hpp"
00041 #include "Teuchos_FancyOStream.hpp"
00042 
00043 
00044 namespace Teuchos {
00045 
00046 
00051 inline void updateSuccess(const bool result, bool &success);
00052 
00053 
00058 inline const std::string passfail(const bool result);
00059 
00060 
00065 TEUCHOS_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber);
00066 
00071 void showTestFailureLocation(bool);
00072 
00073 
00078 bool showTestFailureLocation();
00079 
00080 
00085 template <bool hasMachineParameters, class Scalar>
00086 class RelErrSmallNumber {
00087 public:
00088   static Scalar smallNumber()
00089     {
00090       return ScalarTraits<Scalar>::ThisShouldNotCompile();
00091     }
00092 };
00093 
00094 
00099 template <class Scalar>
00100 class RelErrSmallNumber<false,Scalar> {
00101 public:
00102   static Scalar smallNumber()
00103     {
00104       return Scalar(1e-8);
00105     }
00106 };
00107 
00108 
00113 template <class Scalar>
00114 class RelErrSmallNumber<true,Scalar> {
00115 public:
00116   static Scalar smallNumber()
00117     {
00118       return Teuchos::ScalarTraits<Scalar>::eps();
00119     }
00120 };
00121 
00122 
00127 template <class Scalar>
00128 Scalar defaultSmallNumber()
00129 {
00130   const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
00131   return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber();
00132 }
00133 
00134 
00141 template <class Scalar>
00142 typename ScalarTraits<Scalar>::magnitudeType
00143 relErr( const Scalar &s1, const Scalar &s2 );
00144 
00145 
00152 template<class Scalar>
00153 bool testRelErr(
00154   const std::string &v1_name,
00155   const Scalar &v1,
00156   const std::string &v2_name,
00157   const Scalar &v2,
00158   const std::string &maxRelErr_error_name,
00159   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00160   const std::string &maxRelErr_warning_name,
00161   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00162   const Ptr<std::ostream> &out
00163   );
00164 
00165 
00177 template<class Array1, class Array2>
00178 bool compareArrays(
00179   const Array1 &a1, const std::string &a1_name,
00180   const Array2 &a2, const std::string &a2_name,
00181   Teuchos::FancyOStream &out
00182   );
00183 
00184 
00197 template<class Array1, class Array2, class ScalarMag>
00198 bool compareFloatingArrays(
00199   const Array1 &a1, const std::string &a1_name,
00200   const Array2 &a2, const std::string &a2_name,
00201   const ScalarMag &tol,
00202   Teuchos::FancyOStream &out
00203   );
00204 
00205 
00206 } // namespace Teuchos
00207 
00208 
00217 #define TEUCHOS_PASS_FAIL(RESULT) \
00218   Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
00219 
00220 
00227 #define TEUCHOS_ECHO( statement, out ) \
00228   (out) << #statement ";\n"; \
00229   statement;
00230 
00237 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
00238   { \
00239     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
00240     const bool l_result = (v1) == (v2); \
00241     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00242     if (!l_result) (success) = false; \
00243   }
00244 
00251 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \
00252   { \
00253     const bool l_result = v1; \
00254     (out) << #v1" = "<<l_result<<" == true : "; \
00255     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00256     if (!l_result) (success) = false; \
00257   }
00258 
00265 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
00266   { \
00267     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00268     const bool l_result = (v1) == (v2); \
00269     if (!l_result) (success) = false; \
00270     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00271   }
00272 
00273 
00280 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
00281   { \
00282     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
00283     const bool l_result = (v1) != (v2); \
00284     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00285     if (!l_result) (success) = false; \
00286   }
00287 
00288 
00295 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
00296   { \
00297     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00298     const bool l_result = (v1) != (v2); \
00299     if (!l_result) (success) = false; \
00300     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00301   }
00302 
00303 
00310 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
00311   { \
00312     const bool l_result = Teuchos::testRelErr( \
00313       #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
00314     if (!l_result) (success) = false; \
00315   }
00316 
00317 
00327 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
00328   { \
00329     (out) << #iter1" == "#iter2" =  : "; \
00330     const bool l_result = (iter1) == (iter2); \
00331     if (!l_result) (success) = false; \
00332     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00333   }
00334 
00335 
00342 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
00343   { \
00344     const bool l_result = ( (a)[i] == (val) ); \
00345     if (!l_result) (success) = false; \
00346     if (printPass || !(l_result)) { \
00347       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
00348           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00349     } \
00350   }
00351 
00352 
00359 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
00360   { \
00361     const bool l_result = ( (a)[i] != (val) ); \
00362     if (!l_result) (success) = false; \
00363     if (printPass || !(l_result)) { \
00364       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
00365           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00366     } \
00367   }
00368 
00369 
00377 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
00378   { \
00379     std::ostringstream a_i_str; \
00380     a_i_str <<#a<<"("<<i<<","<<j<<")"; \
00381     const bool l_result = Teuchos::testRelErr( \
00382       a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
00383       (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
00384     if (!l_result) (success) = false; \
00385   }
00386 
00387 
00394 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
00395   { \
00396     const bool l_result = ( (a)(i,j) == (val) ); \
00397     if (!l_result) (success) = false; \
00398     if (printPass || !(l_result)) { \
00399       out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
00400           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00401     } \
00402   }
00403 
00404 
00411 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
00412   { \
00413     out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
00414     const bool l_result = (v1) comp (v2); \
00415     if (!l_result) (success) = false; \
00416     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00417   }
00418 
00419 
00426 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00427   try { \
00428     (out) << "Test that code {"#code";} throws " \
00429           <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \
00430     code; \
00431     (success) = false; \
00432     (out) << "failed\n"; \
00433   } \
00434   catch (const ExceptType& except) { \
00435     out << "passed\n"; \
00436     out << "\nException message for expected exception:\n\n"; \
00437     { \
00438       Teuchos::OSTab l_tab(out); \
00439       out << except.what() << "\n\n"; \
00440     } \
00441   }
00442 
00443 
00450 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00451   try { \
00452     (out) << "Test that code {"#code";} does not throw : "; \
00453     code; \
00454     (out) << "passes\n"; \
00455   } \
00456   catch (...) { \
00457     (success) = false; \
00458     out << "failed\n"; \
00459   }
00460 
00461 
00462 //
00463 // Implementations
00464 //
00465 
00466 
00467 inline
00468 void Teuchos::updateSuccess(const bool result, bool &success)
00469 {
00470   if (!result) success = false;
00471 }
00472 
00473 
00474 inline
00475 const std::string
00476 Teuchos::passfail(const bool result)
00477 {
00478   if (!result)
00479     return "FAILED";
00480   return "passed";
00481 }
00482 
00483 
00484 template <class Scalar>
00485 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00486 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00487 {
00488   typedef Teuchos::ScalarTraits<Scalar> ST;
00489   return
00490     ST::magnitude( s1 - s2 )
00491     / (
00492       ST::magnitude(
00493         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00494         )
00495       + std::max( ST::magnitude(s1), ST::magnitude(s1) )
00496       );
00497 }
00498 
00499 
00500 template<class Scalar>
00501 bool Teuchos::testRelErr(
00502   const std::string &v1_name,
00503   const Scalar &v1,
00504   const std::string &v2_name,
00505   const Scalar &v2,
00506   const std::string &maxRelErr_error_name,
00507   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00508   const std::string &maxRelErr_warning_name,
00509   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00510   const Ptr<std::ostream> &out
00511   )
00512 {
00513   using std::endl;
00514   typedef ScalarTraits<Scalar> ST;
00515   typedef typename ST::magnitudeType ScalarMag;
00516   typedef ScalarTraits<ScalarMag> SMT;
00517   const ScalarMag rel_err = relErr( v1, v2 );
00518   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00519     && rel_err <= maxRelErr_error );
00520   if (!is_null(out)) {
00521     *out
00522       << endl
00523       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00524       << "       = rel_err(" << v1 << ", " << v2 << ") "
00525       << "= " << rel_err << endl
00526       << "         <= " << maxRelErr_error_name
00527       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00528     if( success && rel_err >= maxRelErr_warning ) {
00529       *out
00530         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00531         << "       = rel_err(" << v1 << ", " << v2 << ") "
00532         << "= " << rel_err << endl
00533         << "         >= " << maxRelErr_warning_name
00534         << " = " << maxRelErr_warning << "!\n";
00535     }
00536   }
00537   return success;
00538 }
00539 
00540 
00541 template<class Array1, class Array2>
00542 bool Teuchos::compareArrays(
00543   const Array1 &a1, const std::string &a1_name,
00544   const Array2 &a2, const std::string &a2_name,
00545   Teuchos::FancyOStream &out
00546   )
00547 {
00548   using Teuchos::as;
00549   bool success = true;
00550 
00551   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00552 
00553   const int n = a1.size();
00554 
00555   // Compare sizes
00556   if (as<int>(a2.size()) != n) {
00557     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00558         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00559     return false;
00560   }
00561   
00562   // Compare elements
00563   for( int i = 0; i < n; ++i ) {
00564     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00565     if (!result) {
00566       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00567           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00568       success = false;
00569     }
00570   }
00571   if (success) {
00572     out << "passed\n";
00573   }
00574 
00575   return success;
00576 
00577 }
00578 
00579 
00580 template<class Array1, class Array2, class ScalarMag>
00581 bool Teuchos::compareFloatingArrays(
00582   const Array1 &a1, const std::string &a1_name,
00583   const Array2 &a2, const std::string &a2_name,
00584   const ScalarMag &tol,
00585   Teuchos::FancyOStream &out
00586   )
00587 {
00588   using Teuchos::as;
00589   bool success = true;
00590 
00591   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00592 
00593   const int n = a1.size();
00594 
00595   // Compare sizes
00596   if (as<int>(a2.size()) != n) {
00597     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00598         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00599     return false;
00600   }
00601   
00602   // Compare elements
00603   for( int i = 0; i < n; ++i ) {
00604     const ScalarMag err = relErr( a1[i], a2[i] );
00605     if ( err > tol ) {
00606       out
00607         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00608         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00609         <<err<<" <= tol = "<<tol<<": failed!\n";
00610       success = false;
00611     }
00612   }
00613   if (success) {
00614     out << "passed\n";
00615   }
00616 
00617   return success;
00618 
00619 }
00620 
00621 
00622 #endif  // TEUCHOS_TESTING_HELPERS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines