42 #ifndef TEUCHOS_TESTING_HELPERS_HPP
43 #define TEUCHOS_TESTING_HELPERS_HPP
54 #include "Teuchos_FancyOStream.hpp"
71 inline const std::string
passfail(
const bool result);
78 TEUCHOSCORE_LIB_DLL_EXPORT
const std::string
passfail_with_location(
const bool result,
const std::string &file,
const int lineNumber);
98 template <
bool hasMachineParameters,
class Scalar>
101 static Scalar smallNumber()
112 template <
class Scalar>
115 static Scalar smallNumber()
126 template <
class Scalar>
129 static Scalar smallNumber()
140 template <
class Scalar>
154 template <
class Scalar1,
class Scalar2>
156 relErr(
const Scalar1 &s1,
const Scalar2 &s2 );
165 template <
typename T1,
typename T2,
typename Enabled =
void>
169 typedef typename std::common_type<magType1,magType2>::type magnitudeType;
171 const std::string &v1_name,
173 const std::string &v2_name,
175 const std::string &maxRelErr_error_name,
176 const magnitudeType &maxRelErr_error,
177 const std::string &maxRelErr_warning_name,
178 const magnitudeType &maxRelErr_warning,
184 const magnitudeType rel_err =
relErr( v1, v2 );
185 const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
186 && rel_err <= maxRelErr_error );
190 <<
"Check: rel_err(" << v1_name <<
", " << v2_name <<
")\n"
191 <<
" = rel_err(" << v1 <<
", " << v2 <<
") "
192 <<
"= " << rel_err << endl
193 <<
" <= " << maxRelErr_error_name
194 <<
" = " << maxRelErr_error <<
" : " <<
passfail(success) << endl;
195 if( success && rel_err >= maxRelErr_warning ) {
197 <<
"Warning! rel_err(" << v1_name <<
", " << v2_name <<
")\n"
198 <<
" = rel_err(" << v1 <<
", " << v2 <<
") "
199 <<
"= " << rel_err << endl
200 <<
" >= " << maxRelErr_warning_name
201 <<
" = " << maxRelErr_warning <<
"!\n";
208 template <
typename T1,
typename T2>
210 const std::string &v1_name,
212 const std::string &v2_name,
214 const std::string &maxRelErr_error_name,
215 const typename TestRelErr<T1,T2>::magnitudeType &maxRelErr_error,
216 const std::string &maxRelErr_warning_name,
217 const typename TestRelErr<T1,T2>::magnitudeType &maxRelErr_warning,
219 return TestRelErr<T1,T2>::eval(v1_name, v1, v2_name,v2, maxRelErr_error_name, maxRelErr_error, maxRelErr_warning_name, maxRelErr_warning, out);
235 template<
class Array1,
class Array2>
237 const Array1 &a1,
const std::string &a1_name,
238 const Array2 &a2,
const std::string &a2_name,
258 template<
class Array1,
class Array2,
class ScalarMag>
260 const Array1 &a1,
const std::string &a1_name,
261 const Array2 &a2,
const std::string &a2_name,
262 const ScalarMag &tol,
282 template<
class Array1,
class Array2,
class ScalarMag>
284 const Array1 &a1,
const std::string &a1_name,
285 const Array2 &a2,
const std::string &a2_name,
286 const ScalarMag &tol,
302 #define TEUCHOS_PASS_FAIL(RESULT) \
303 Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
312 #define TEUCHOS_ECHO( statement, out ) \
313 (out) << #statement ";\n"; \
322 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
324 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
325 const bool l_result = (v1) == (v2); \
326 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
327 if (!l_result) (success) = false; \
336 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \
338 const bool l_result = v1; \
339 (out) << #v1" = "<<l_result<<" == true : "; \
340 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
341 if (!l_result) (success) = false; \
350 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
352 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
353 const bool l_result = (v1) == (v2); \
354 if (!l_result) (success) = false; \
355 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
365 #define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
367 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
368 const bool l_result = (v1) != (v2); \
369 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
370 if (!l_result) (success) = false; \
380 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
382 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
383 const bool l_result = (v1) != (v2); \
384 if (!l_result) (success) = false; \
385 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
395 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
397 const bool l_result = Teuchos::testRelErr( \
398 #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
399 if (!l_result) (success) = false; \
412 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
414 (out) << #iter1" == "#iter2" = : "; \
415 const bool l_result = (iter1) == (iter2); \
416 if (!l_result) (success) = false; \
417 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
430 #define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \
432 (out) << #iter1" != "#iter2" = : "; \
433 const bool l_result = (iter1) != (iter2); \
434 if (!l_result) (success) = false; \
435 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
445 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
447 const bool l_result = ( (a)[i] == (val) ); \
448 if (!l_result) (success) = false; \
449 if (printPass || !(l_result)) { \
450 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
451 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
462 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
464 const bool l_result = ( (a)[i] != (val) ); \
465 if (!l_result) (success) = false; \
466 if (printPass || !(l_result)) { \
467 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
468 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
480 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
482 std::ostringstream a_i_str; \
483 a_i_str <<#a<<"("<<i<<","<<j<<")"; \
484 const bool l_result = Teuchos::testRelErr( \
485 a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
486 (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
487 if (!l_result) (success) = false; \
497 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
499 const bool l_result = ( (a)(i,j) == (val) ); \
500 if (!l_result) (success) = false; \
501 if (printPass || !(l_result)) { \
502 out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
503 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
517 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
519 out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
520 const bool l_result = (v1) comp (v2); \
521 if (!l_result) (success) = false; \
522 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
536 #define TEUCHOS_TEST_COMPARE_CONST( v1, comp, v2, out, success ) \
538 out << #v1" = "<<(v1)<<" "#comp" "<<(v2)<<" : "; \
539 const bool l_result = (v1) comp (v2); \
540 if (!l_result) (success) = false; \
541 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
559 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \
561 std::ostream& l_out = (out); \
563 l_out << "Test that code {"#code";} throws " \
564 << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \
567 l_out << "failed (code did not throw an exception at all)\n"; \
569 catch (const ExceptType& except) { \
570 l_out << "passed\n"; \
571 l_out << "\nException message for expected exception:\n\n"; \
573 Teuchos::OSTab l_tab(out); \
574 l_out << except.what () << "\n\n"; \
578 catch (std::exception& except) { \
579 l_out << "The code was supposed to throw an exception of type " \
580 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
581 << "instead threw an exception of type " \
582 << typeid (except).name () << ", which is a subclass of " \
583 << "std::exception. The exception's message is:\n\n"; \
585 Teuchos::OSTab l_tab(out); \
586 l_out << except.what () << "\n\n"; \
589 l_out << "failed\n"; \
592 l_out << "The code was supposed to throw an exception of type " \
593 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
594 << "instead threw an exception of some unknown type, which is " \
595 << "not a subclass of std::exception. This means we cannot " \
596 << "show you the exception's message, if it even has one.\n\n"; \
597 l_out << "failed\n"; \
608 #define TEUCHOS_TEST_NOTHROW( code, out, success ) \
610 std::ostream& l_out = (out); \
612 l_out << "Test that code {"#code";} does not throw : "; \
614 l_out << "passed\n"; \
616 catch (std::exception& except) { \
618 l_out << "The code was not supposed to throw an exception, but " \
619 << "instead threw an exception of type " \
620 << typeid (except).name () << ", which is a subclass of " \
621 << "std::exception. The exception's message is:\n\n"; \
623 Teuchos::OSTab l_tab(out); \
624 l_out << except.what () << "\n\n"; \
627 l_out << "failed\n"; \
631 l_out << "The code was not supposed to throw an exception, but " \
632 << "instead threw an exception of some unknown type, which is " \
633 << "not a subclass of std::exception. This means we cannot " \
634 << "show you the exception's message, if it even has one.\n\n"; \
635 l_out << "failed\n"; \
647 if (!result) success =
false;
661 template <
class Scalar1,
class Scalar2>
665 typedef typename std::common_type<Scalar1,Scalar2>::type Scalar;
668 ST::magnitude( s1 - s2 )
673 + std::max( ST::magnitude(s1), ST::magnitude(s2) )
678 template<
class Array1,
class Array2>
680 const Array1 &a1,
const std::string &a1_name,
681 const Array2 &a2,
const std::string &a2_name,
689 out <<
"Comparing " << a1_name <<
" == " << a2_name <<
" ... ";
691 const int n = a1.size();
694 if (as<int>(a2.size()) != n) {
695 out <<
"\nError, "<<a1_name<<
".size() = "<<a1.size()<<
" == "
696 << a2_name<<
".size() = "<<a2.size()<<
" : failed!\n";
701 for(
int i = 0; i < n; ++i ) {
702 const bool result = ( a1[i] == a2[i] );
704 out <<
"\nError, "<<a1_name<<
"["<<i<<
"] = "<<a1[i]<<
" == "
705 << a2_name<<
"["<<i<<
"] = "<<a2[i]<<
": failed!\n";
718 template<
class Array1,
class Array2,
class ScalarMag>
720 const Array1 &a1,
const std::string &a1_name,
721 const Array2 &a2,
const std::string &a2_name,
722 const ScalarMag &tol,
729 using Elem1 = std::decay_t<decltype(std::declval<Array1>()[0])>;
730 using Elem2 = std::decay_t<decltype(std::declval<Array2>()[0])>;
732 static_assert(std::is_same_v<Elem1, Elem2>,
733 "Teuchos::compareFloatingArrays: element types of Array1 and Array2 must be the same.");
737 out <<
"Comparing " << a1_name <<
" == " << a2_name <<
" ... ";
739 const int n = a1.size();
742 if (as<int>(a2.size()) != n) {
743 out <<
"\nError, "<<a1_name<<
".size() = "<<a1.size()<<
" == "
744 << a2_name<<
".size() = "<<a2.size()<<
" : failed!\n";
749 for(
int i = 0; i < n; ++i ) {
750 const ScalarMag err =
relErr( a1[i], a2[i] );
751 if ( !(err <= tol) ) {
753 <<
"\nError, relErr("<<a1_name<<
"["<<i<<
"],"
754 <<a2_name<<
"["<<i<<
"]) = relErr("<<a1[i]<<
","<<a2[i]<<
") = "
755 <<err<<
" <= tol = "<<tol<<
": failed!\n";
767 template<
class Array1,
class Array2,
class ScalarMag>
769 const Array1 &a1,
const std::string &a1_name,
770 const Array2 &a2,
const std::string &a2_name,
771 const ScalarMag &tol,
779 using Elem1 = std::decay_t<decltype(std::declval<Array1>()[0])>;
780 using Elem2 = std::decay_t<decltype(std::declval<Array2>()[0])>;
782 static_assert(std::is_same_v<Elem1, Elem2>,
783 "Teuchos::compareFloatingArraysAbsolute: element types of Array1 and Array2 must be the same.");
787 out <<
"Comparing " << a1_name <<
" == " << a2_name <<
" ... ";
789 const int n = a1.size();
792 if (as<int>(a2.size()) != n) {
793 out <<
"\nError, "<<a1_name<<
".size() = "<<a1.size()<<
" == "
794 << a2_name<<
".size() = "<<a2.size()<<
" : failed!\n";
799 for(
int i = 0; i < n; ++i ) {
801 if ( !(err <= tol) ) {
803 <<
"\nError, ||"<<a1_name<<
"["<<i<<
"] - " << a2_name<<
"["<<i<<
"]|| = "
804 <<err<<
" <= tol = "<<tol<<
": failed!\n";
815 #endif // TEUCHOS_TESTING_HELPERS_HPP
bool compareFloatingArrays(const Array1 &a1, const std::string &a1_name, const Array2 &a2, const std::string &a2_name, const ScalarMag &tol, Teuchos::FancyOStream &out)
Compare if two array objects are the same or not up to a relative floating point precision.
T magnitudeType
Mandatory typedef for result of magnitude.
static magnitudeType eps()
Returns relative machine precision.
bool compareFloatingArraysAbsolute(const Array1 &a1, const std::string &a1_name, const Array2 &a2, const std::string &a2_name, const ScalarMag &tol, Teuchos::FancyOStream &out)
Compare if two array objects are the same up to an absolute tolerance: elements a1[i] and a2[i] are c...
bool compareArrays(const Array1 &a1, const std::string &a1_name, const Array2 &a2, const std::string &a2_name, Teuchos::FancyOStream &out)
Compare if two array objects are the same or not.
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
TEUCHOSCORE_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber)
Helper function for TEUCHOS_PASS_FAIL(...).
const std::string passfail(const bool result)
Return "passed" or "failed".
Teuchos header file which uses auto-configuration information to include necessary C++ headers...
This structure defines some basic traits for a scalar field type.
Scalar defaultSmallNumber()
void showTestFailureLocation(bool)
Set if TEUCHOS_PASS_FAIL(...) should print test failure location.
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
Compute, check and optionally print the relative error in two scalars.
void updateSuccess(const bool result, bool &success)
Update the success bool flag.
Teuchos::ScalarTraits< typename std::common_type< Scalar1, Scalar2 >::type >::magnitudeType relErr(const Scalar1 &s1, const Scalar2 &s2)
Return relative error of two scalars.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
Defines basic traits for the scalar field type.
Defines basic traits returning the name of a type in a portable and readable way. ...
Simple wrapper class for raw pointers to single objects where no persisting relationship exists...