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