00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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 }
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
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
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
00563 for( int i = 0; i < n; ++i ) {
00564 const bool result = ( a1[i] == a2[i] );
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
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
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