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 // 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 
00465 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success  ) \
00466   { \
00467     std::ostream& l_out = (out); \
00468     try { \
00469       l_out << "Test that code {"#code";} throws " \
00470             << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \
00471       code; \
00472       (success) = false; \
00473       l_out << "failed (code did not throw an exception at all)\n"; \
00474     } \
00475     catch (const ExceptType& except) { \
00476       l_out << "passed\n";                                        \
00477       l_out << "\nException message for expected exception:\n\n";   \
00478       { \
00479         Teuchos::OSTab l_tab (out); \
00480         l_out << except.what () << "\n\n"; \
00481       } \
00482     } \
00483     catch (std::exception& except) { \
00484       l_out << "The code was supposed to throw an exception of type "   \
00485             << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
00486             << "instead threw an exception of type " \
00487             << typeid (except).name () << ", which is a subclass of " \
00488             << "std::exception.  The exception's message is:\n\n"; \
00489       { \
00490         Teuchos::OSTab l_tab (out); \
00491         l_out << except.what () << "\n\n"; \
00492       } \
00493       l_out << "failed\n"; \
00494     } \
00495     catch (...) { \
00496       l_out << "The code was supposed to throw an exception of type "   \
00497             << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
00498             << "instead threw an exception of some unknown type, which is " \
00499             << "not a subclass of std::exception.  This means we cannot " \
00500             << "show you the exception's message, if it even has one.\n\n"; \
00501       l_out << "failed\n"; \
00502     } \
00503   }
00504 
00505 
00512 #define TEUCHOS_TEST_NOTHROW( code, out, success  ) \
00513   { \
00514     std::ostream& l_out = (out); \
00515     try { \
00516       l_out << "Test that code {"#code";} does not throw : "; \
00517       code; \
00518       l_out << "passed\n"; \
00519     } \
00520     catch (std::exception& except) { \
00521       (success) = false; \
00522       l_out << "The code was not supposed to throw an exception, but " \
00523             << "instead threw an exception of type " \
00524             << typeid (except).name () << ", which is a subclass of " \
00525             << "std::exception.  The exception's message is:\n\n"; \
00526       { \
00527         Teuchos::OSTab l_tab (out); \
00528         l_out << except.what () << "\n\n"; \
00529       } \
00530       l_out << "failed\n"; \
00531     } \
00532     catch (...) { \
00533       (success) = false; \
00534       l_out << "The code was not supposed to throw an exception, but " \
00535             << "instead threw an exception of some unknown type, which is " \
00536             << "not a subclass of std::exception.  This means we cannot " \
00537             << "show you the exception's message, if it even has one.\n\n"; \
00538       l_out << "failed\n"; \
00539     } \
00540   }
00541 
00542 //
00543 // Implementations
00544 //
00545 
00546 
00547 inline
00548 void Teuchos::updateSuccess(const bool result, bool &success)
00549 {
00550   if (!result) success = false;
00551 }
00552 
00553 
00554 inline
00555 const std::string
00556 Teuchos::passfail(const bool result)
00557 {
00558   if (!result)
00559     return "FAILED";
00560   return "passed";
00561 }
00562 
00563 
00564 template <class Scalar>
00565 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
00566 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
00567 {
00568   typedef Teuchos::ScalarTraits<Scalar> ST;
00569   return
00570     ST::magnitude( s1 - s2 )
00571     / (
00572       ST::magnitude(
00573         RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
00574         )
00575       + std::max( ST::magnitude(s1), ST::magnitude(s2) )
00576       );
00577 }
00578 
00579 
00580 template<class Scalar>
00581 bool Teuchos::testRelErr(
00582   const std::string &v1_name,
00583   const Scalar &v1,
00584   const std::string &v2_name,
00585   const Scalar &v2,
00586   const std::string &maxRelErr_error_name,
00587   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
00588   const std::string &maxRelErr_warning_name,
00589   const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
00590   const Ptr<std::ostream> &out
00591   )
00592 {
00593   using std::endl;
00594   typedef ScalarTraits<Scalar> ST;
00595   typedef typename ST::magnitudeType ScalarMag;
00596   typedef ScalarTraits<ScalarMag> SMT;
00597   const ScalarMag rel_err = relErr( v1, v2 );
00598   const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
00599     && rel_err <= maxRelErr_error );
00600   if (!is_null(out)) {
00601     *out
00602       << endl
00603       << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
00604       << "       = rel_err(" << v1 << ", " << v2 << ") "
00605       << "= " << rel_err << endl
00606       << "         <= " << maxRelErr_error_name
00607       << " = " << maxRelErr_error << " : " << passfail(success) << endl;
00608     if( success && rel_err >= maxRelErr_warning ) {
00609       *out
00610         << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
00611         << "       = rel_err(" << v1 << ", " << v2 << ") "
00612         << "= " << rel_err << endl
00613         << "         >= " << maxRelErr_warning_name
00614         << " = " << maxRelErr_warning << "!\n";
00615     }
00616   }
00617   return success;
00618 }
00619 
00620 
00621 template<class Array1, class Array2>
00622 bool Teuchos::compareArrays(
00623   const Array1 &a1, const std::string &a1_name,
00624   const Array2 &a2, const std::string &a2_name,
00625   Teuchos::FancyOStream &out
00626   )
00627 {
00628   using Teuchos::as;
00629   bool success = true;
00630 
00631   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00632 
00633   const int n = a1.size();
00634 
00635   // Compare sizes
00636   if (as<int>(a2.size()) != n) {
00637     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
00638         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00639     return false;
00640   }
00641 
00642   // Compare elements
00643   for( int i = 0; i < n; ++i ) {
00644     const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
00645     if (!result) {
00646       out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
00647           << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
00648       success = false;
00649     }
00650   }
00651   if (success) {
00652     out << "passed\n";
00653   }
00654 
00655   return success;
00656 
00657 }
00658 
00659 
00660 template<class Array1, class Array2, class ScalarMag>
00661 bool Teuchos::compareFloatingArrays(
00662   const Array1 &a1, const std::string &a1_name,
00663   const Array2 &a2, const std::string &a2_name,
00664   const ScalarMag &tol,
00665   Teuchos::FancyOStream &out
00666   )
00667 {
00668   using Teuchos::as;
00669   bool success = true;
00670 
00671   out << "Comparing " << a1_name << " == " << a2_name << " ... ";
00672 
00673   const int n = a1.size();
00674 
00675   // Compare sizes
00676   if (as<int>(a2.size()) != n) {
00677     out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
00678         << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
00679     return false;
00680   }
00681 
00682   // Compare elements
00683   for( int i = 0; i < n; ++i ) {
00684     const ScalarMag err = relErr( a1[i], a2[i] );
00685     if ( !(err <= tol) ) {
00686       out
00687         <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
00688         <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
00689         <<err<<" <= tol = "<<tol<<": failed!\n";
00690       success = false;
00691     }
00692   }
00693   if (success) {
00694     out << "passed\n";
00695   }
00696 
00697   return success;
00698 
00699 }
00700 
00701 
00702 #endif  // TEUCHOS_TESTING_HELPERS_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines