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 TEUCHOSCORE_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 
00358 #define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \
00359   { \
00360     (out) << #iter1" != "#iter2" =  : "; \
00361     const bool l_result = (iter1) != (iter2); \
00362     if (!l_result) (success) = false; \
00363     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00364   }
00365 
00366 
00373 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
00374   { \
00375     const bool l_result = ( (a)[i] == (val) ); \
00376     if (!l_result) (success) = false; \
00377     if (printPass || !(l_result)) { \
00378       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
00379           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00380     } \
00381   }
00382 
00383 
00390 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
00391   { \
00392     const bool l_result = ( (a)[i] != (val) ); \
00393     if (!l_result) (success) = false; \
00394     if (printPass || !(l_result)) { \
00395       out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
00396           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00397     } \
00398   }
00399 
00400 
00408 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
00409   { \
00410     std::ostringstream a_i_str; \
00411     a_i_str <<#a<<"("<<i<<","<<j<<")"; \
00412     const bool l_result = Teuchos::testRelErr( \
00413       a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
00414       (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
00415     if (!l_result) (success) = false; \
00416   }
00417 
00418 
00425 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
00426   { \
00427     const bool l_result = ( (a)(i,j) == (val) ); \
00428     if (!l_result) (success) = false; \
00429     if (printPass || !(l_result)) { \
00430       out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
00431           << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00432     } \
00433   }
00434 
00435 
00442 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
00443   { \
00444     out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
00445     const bool l_result = (v1) comp (v2); \
00446     if (!l_result) (success) = false; \
00447     (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
00448   }
00449 
00450 
00457 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00458   try { \
00459     (out) << "Test that code {"#code";} throws " \
00460           <<Teuchos::TypeNameTraits<ExceptType>::name()<<": "; \
00461     code; \
00462     (success) = false; \
00463     (out) << "failed\n"; \
00464   } \
00465   catch (const ExceptType& except) { \
00466     out << "passed\n"; \
00467     out << "\nException message for expected exception:\n\n"; \
00468     { \
00469       Teuchos::OSTab l_tab(out); \
00470       out << except.what() << "\n\n"; \
00471     } \
00472   }
00473 
00474 
00481 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00482   try { \
00483     (out) << "Test that code {"#code";} does not throw : "; \
00484     code; \
00485     (out) << "passes\n"; \
00486   } \
00487   catch (...) { \
00488     (success) = false; \
00489     out << "failed\n"; \
00490   }
00491 
00492 
00493 //
00494 // Implementations
00495 //
00496 
00497 
00498 inline
00499 void Teuchos::updateSuccess(const bool result, bool &success)
00500 {
00501   if (!result) success = false;
00502 }
00503 
00504 
00505 inline
00506 const std::string
00507 Teuchos::passfail(const bool result)
00508 {
00509   if (!result)
00510     return "FAILED";
00511   return "passed";
00512 }
00513 
00514 
00515 template <class Scalar>
00516 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00517 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00518 {
00519   typedef Teuchos::ScalarTraits<Scalar> ST;
00520   return
00521     ST::magnitude( s1 - s2 )
00522     / (
00523       ST::magnitude(
00524         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00525         )
00526       + std::max( ST::magnitude(s1), ST::magnitude(s2) )
00527       );
00528 }
00529 
00530 
00531 template<class Scalar>
00532 bool Teuchos::testRelErr(
00533   const std::string &v1_name,
00534   const Scalar &v1,
00535   const std::string &v2_name,
00536   const Scalar &v2,
00537   const std::string &maxRelErr_error_name,
00538   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00539   const std::string &maxRelErr_warning_name,
00540   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00541   const Ptr<std::ostream> &out
00542   )
00543 {
00544   using std::endl;
00545   typedef ScalarTraits<Scalar> ST;
00546   typedef typename ST::magnitudeType ScalarMag;
00547   typedef ScalarTraits<ScalarMag> SMT;
00548   const ScalarMag rel_err = relErr( v1, v2 );
00549   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00550     && rel_err <= maxRelErr_error );
00551   if (!is_null(out)) {
00552     *out
00553       << endl
00554       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00555       << "       = rel_err(" << v1 << ", " << v2 << ") "
00556       << "= " << rel_err << endl
00557       << "         <= " << maxRelErr_error_name
00558       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00559     if( success && rel_err >= maxRelErr_warning ) {
00560       *out
00561         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00562         << "       = rel_err(" << v1 << ", " << v2 << ") "
00563         << "= " << rel_err << endl
00564         << "         >= " << maxRelErr_warning_name
00565         << " = " << maxRelErr_warning << "!\n";
00566     }
00567   }
00568   return success;
00569 }
00570 
00571 
00572 template<class Array1, class Array2>
00573 bool Teuchos::compareArrays(
00574   const Array1 &a1, const std::string &a1_name,
00575   const Array2 &a2, const std::string &a2_name,
00576   Teuchos::FancyOStream &out
00577   )
00578 {
00579   using Teuchos::as;
00580   bool success = true;
00581 
00582   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00583 
00584   const int n = a1.size();
00585 
00586   // Compare sizes
00587   if (as<int>(a2.size()) != n) {
00588     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00589         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00590     return false;
00591   }
00592   
00593   // Compare elements
00594   for( int i = 0; i < n; ++i ) {
00595     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00596     if (!result) {
00597       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00598           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00599       success = false;
00600     }
00601   }
00602   if (success) {
00603     out << "passed\n";
00604   }
00605 
00606   return success;
00607 
00608 }
00609 
00610 
00611 template<class Array1, class Array2, class ScalarMag>
00612 bool Teuchos::compareFloatingArrays(
00613   const Array1 &a1, const std::string &a1_name,
00614   const Array2 &a2, const std::string &a2_name,
00615   const ScalarMag &tol,
00616   Teuchos::FancyOStream &out
00617   )
00618 {
00619   using Teuchos::as;
00620   bool success = true;
00621 
00622   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00623 
00624   const int n = a1.size();
00625 
00626   // Compare sizes
00627   if (as<int>(a2.size()) != n) {
00628     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == " 
00629         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00630     return false;
00631   }
00632   
00633   // Compare elements
00634   for( int i = 0; i < n; ++i ) {
00635     const ScalarMag err = relErr( a1[i], a2[i] );
00636     if ( !(err <= tol) ) {
00637       out
00638         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00639         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00640         <<err<<" <= tol = "<<tol<<": failed!\n";
00641       success = false;
00642     }
00643   }
00644   if (success) {
00645     out << "passed\n";
00646   }
00647 
00648   return success;
00649 
00650 }
00651 
00652 
00653 #endif  // TEUCHOS_TESTING_HELPERS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines