Teuchos - Trilinos Tools Package 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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #ifndef TEUCHOS_TESTING_HELPERS_HPP
00043 #define TEUCHOS_TESTING_HELPERS_HPP
00044 
00045 
00051 #include "Teuchos_ConfigDefs.hpp"
00052 #include "Teuchos_ScalarTraits.hpp"
00053 #include "Teuchos_TypeNameTraits.hpp"
00054 #include "Teuchos_FancyOStream.hpp"
00055 
00056 
00057 namespace Teuchos {
00058 
00059 
00064 inline void updateSuccess(const bool result, bool &success);
00065 
00066 
00071 inline const std::string passfail(const bool result);
00072 
00073 
00078 TEUCHOS_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber);
00079 
00084 void showTestFailureLocation(bool);
00085 
00086 
00091 bool showTestFailureLocation();
00092 
00093 
00098 template <bool hasMachineParameters, class Scalar>
00099 class RelErrSmallNumber {
00100 public:
00101   static Scalar smallNumber()
00102     {
00103       return ScalarTraits<Scalar>::ThisShouldNotCompile();
00104     }
00105 };
00106 
00107 
00112 template <class Scalar>
00113 class RelErrSmallNumber<false,Scalar> {
00114 public:
00115   static Scalar smallNumber()
00116     {
00117       return Scalar(1e-8);
00118     }
00119 };
00120 
00121 
00126 template <class Scalar>
00127 class RelErrSmallNumber<true,Scalar> {
00128 public:
00129   static Scalar smallNumber()
00130     {
00131       return Teuchos::ScalarTraits<Scalar>::eps();
00132     }
00133 };
00134 
00135 
00140 template <class Scalar>
00141 Scalar defaultSmallNumber()
00142 {
00143   const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
00144   return RelErrSmallNumber<hasMachineParameters,Scalar>::smallNumber();
00145 }
00146 
00147 
00154 template <class Scalar>
00155 typename ScalarTraits<Scalar>::magnitudeType
00156 relErr( const Scalar &s1, const Scalar &s2 );
00157 
00158 
00165 template<class Scalar>
00166 bool testRelErr(
00167   const std::string &v1_name,
00168   const Scalar &v1,
00169   const std::string &v2_name,
00170   const Scalar &v2,
00171   const std::string &maxRelErr_error_name,
00172   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00173   const std::string &maxRelErr_warning_name,
00174   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00175   const Ptr<std::ostream> &out
00176   );
00177 
00178 
00190 template<class Array1, class Array2>
00191 bool compareArrays(
00192   const Array1 &a1, const std::string &a1_name,
00193   const Array2 &a2, const std::string &a2_name,
00194   Teuchos::FancyOStream &out
00195   );
00196 
00197 
00210 template<class Array1, class Array2, class ScalarMag>
00211 bool compareFloatingArrays(
00212   const Array1 &a1, const std::string &a1_name,
00213   const Array2 &a2, const std::string &a2_name,
00214   const ScalarMag &tol,
00215   Teuchos::FancyOStream &out
00216   );
00217 
00218 
00219 } // namespace Teuchos
00220 
00221 
00230 #define TEUCHOS_PASS_FAIL(RESULT) \
00231   Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
00232 
00233 
00240 #define TEUCHOS_ECHO( statement, out ) \
00241   (out) << #statement ";\n"; \
00242   statement;
00243 
00250 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
00251   { \
00252     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
00253     const bool l_result = (v1) == (v2); \
00254     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00255     if (!l_result) (success) = false; \
00256   }
00257 
00264 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \
00265   { \
00266     const bool l_result = v1; \
00267     (out) << #v1" = "<<l_result<<" == true : "; \
00268     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00269     if (!l_result) (success) = false; \
00270   }
00271 
00278 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
00279   { \
00280     (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00281     const bool l_result = (v1) == (v2); \
00282     if (!l_result) (success) = false; \
00283     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00284   }
00285 
00286 
00293 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
00294   { \
00295     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
00296     const bool l_result = (v1) != (v2); \
00297     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00298     if (!l_result) (success) = false; \
00299   }
00300 
00301 
00308 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
00309   { \
00310     (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
00311     const bool l_result = (v1) != (v2); \
00312     if (!l_result) (success) = false; \
00313     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00314   }
00315 
00316 
00323 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
00324   { \
00325     const bool l_result = Teuchos::testRelErr( \
00326       #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
00327     if (!l_result) (success) = false; \
00328   }
00329 
00330 
00340 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
00341   { \
00342     (out) << #iter1" == "#iter2" =  : "; \
00343     const bool l_result = (iter1) == (iter2); \
00344     if (!l_result) (success) = false; \
00345     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00346   }
00347 
00348 
00355 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
00356   { \
00357     const bool l_result = ( (a)[i] == (val) ); \
00358     if (!l_result) (success) = false; \
00359     if (printPass || !(l_result)) { \
00360       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
00361           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00362     } \
00363   }
00364 
00365 
00372 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
00373   { \
00374     const bool l_result = ( (a)[i] != (val) ); \
00375     if (!l_result) (success) = false; \
00376     if (printPass || !(l_result)) { \
00377       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
00378           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00379     } \
00380   }
00381 
00382 
00390 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
00391   { \
00392     std::ostringstream a_i_str; \
00393     a_i_str <<#a<<"("<<i<<","<<j<<")"; \
00394     const bool l_result = Teuchos::testRelErr( \
00395       a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
00396       (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
00397     if (!l_result) (success) = false; \
00398   }
00399 
00400 
00407 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
00408   { \
00409     const bool l_result = ( (a)(i,j) == (val) ); \
00410     if (!l_result) (success) = false; \
00411     if (printPass || !(l_result)) { \
00412       out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
00413           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00414     } \
00415   }
00416 
00417 
00424 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
00425   { \
00426     out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
00427     const bool l_result = (v1) comp (v2); \
00428     if (!l_result) (success) = false; \
00429     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00430   }
00431 
00432 
00439 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00440   try { \
00441     (out) << "Test that code {"#code";} throws " \
00442           <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \
00443     code; \
00444     (success) = false; \
00445     (out) << "failed\n"; \
00446   } \
00447   catch (const ExceptType& except) { \
00448     out << "passed\n"; \
00449     out << "\nException message for expected exception:\n\n"; \
00450     { \
00451       Teuchos::OSTab l_tab(out); \
00452       out << except.what() << "\n\n"; \
00453     } \
00454   }
00455 
00456 
00463 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00464   try { \
00465     (out) << "Test that code {"#code";} does not throw : "; \
00466     code; \
00467     (out) << "passes\n"; \
00468   } \
00469   catch (...) { \
00470     (success) = false; \
00471     out << "failed\n"; \
00472   }
00473 
00474 
00475 //
00476 // Implementations
00477 //
00478 
00479 
00480 inline
00481 void Teuchos::updateSuccess(const bool result, bool &success)
00482 {
00483   if (!result) success = false;
00484 }
00485 
00486 
00487 inline
00488 const std::string
00489 Teuchos::passfail(const bool result)
00490 {
00491   if (!result)
00492     return "FAILED";
00493   return "passed";
00494 }
00495 
00496 
00497 template <class Scalar>
00498 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00499 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00500 {
00501   typedef Teuchos::ScalarTraits<Scalar> ST;
00502   return
00503     ST::magnitude( s1 - s2 )
00504     / (
00505       ST::magnitude(
00506         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00507         )
00508       + std::max( ST::magnitude(s1), ST::magnitude(s2) )
00509       );
00510 }
00511 
00512 
00513 template<class Scalar>
00514 bool Teuchos::testRelErr(
00515   const std::string &v1_name,
00516   const Scalar &v1,
00517   const std::string &v2_name,
00518   const Scalar &v2,
00519   const std::string &maxRelErr_error_name,
00520   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00521   const std::string &maxRelErr_warning_name,
00522   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00523   const Ptr<std::ostream> &out
00524   )
00525 {
00526   using std::endl;
00527   typedef ScalarTraits<Scalar> ST;
00528   typedef typename ST::magnitudeType ScalarMag;
00529   typedef ScalarTraits<ScalarMag> SMT;
00530   const ScalarMag rel_err = relErr( v1, v2 );
00531   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00532     && rel_err <= maxRelErr_error );
00533   if (!is_null(out)) {
00534     *out
00535       << endl
00536       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00537       << "       = rel_err(" << v1 << ", " << v2 << ") "
00538       << "= " << rel_err << endl
00539       << "         <= " << maxRelErr_error_name
00540       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00541     if( success && rel_err >= maxRelErr_warning ) {
00542       *out
00543         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00544         << "       = rel_err(" << v1 << ", " << v2 << ") "
00545         << "= " << rel_err << endl
00546         << "         >= " << maxRelErr_warning_name
00547         << " = " << maxRelErr_warning << "!\n";
00548     }
00549   }
00550   return success;
00551 }
00552 
00553 
00554 template<class Array1, class Array2>
00555 bool Teuchos::compareArrays(
00556   const Array1 &a1, const std::string &a1_name,
00557   const Array2 &a2, const std::string &a2_name,
00558   Teuchos::FancyOStream &out
00559   )
00560 {
00561   using Teuchos::as;
00562   bool success = true;
00563 
00564   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00565 
00566   const int n = a1.size();
00567 
00568   // Compare sizes
00569   if (as<int>(a2.size()) != n) {
00570     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00571         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00572     return false;
00573   }
00574   
00575   // Compare elements
00576   for( int i = 0; i < n; ++i ) {
00577     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00578     if (!result) {
00579       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00580           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00581       success = false;
00582     }
00583   }
00584   if (success) {
00585     out << "passed\n";
00586   }
00587 
00588   return success;
00589 
00590 }
00591 
00592 
00593 template<class Array1, class Array2, class ScalarMag>
00594 bool Teuchos::compareFloatingArrays(
00595   const Array1 &a1, const std::string &a1_name,
00596   const Array2 &a2, const std::string &a2_name,
00597   const ScalarMag &tol,
00598   Teuchos::FancyOStream &out
00599   )
00600 {
00601   using Teuchos::as;
00602   bool success = true;
00603 
00604   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00605 
00606   const int n = a1.size();
00607 
00608   // Compare sizes
00609   if (as<int>(a2.size()) != n) {
00610     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00611         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00612     return false;
00613   }
00614   
00615   // Compare elements
00616   for( int i = 0; i < n; ++i ) {
00617     const ScalarMag err = relErr( a1[i], a2[i] );
00618     if ( err > tol ) {
00619       out
00620         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00621         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00622         <<err<<" <= tol = "<<tol<<": failed!\n";
00623       success = false;
00624     }
00625   }
00626   if (success) {
00627     out << "passed\n";
00628   }
00629 
00630   return success;
00631 
00632 }
00633 
00634 
00635 #endif  // TEUCHOS_TESTING_HELPERS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines