Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_TestingHelpers.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Teuchos: Common Tools Package
4//
5// Copyright 2004 NTESS and the Teuchos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TEUCHOS_TESTING_HELPERS_HPP
11#define TEUCHOS_TESTING_HELPERS_HPP
12
13
22#include "Teuchos_FancyOStream.hpp"
23
24
25namespace Teuchos {
26
27
32inline void updateSuccess(const bool result, bool &success);
33
34
39inline const std::string passfail(const bool result);
40
41
46TEUCHOSCORE_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber);
47
53
54
60
61
66template <bool hasMachineParameters, class Scalar>
68public:
69 static Scalar smallNumber()
70 {
72 }
73};
74
75
80template <class Scalar>
81class RelErrSmallNumber<false,Scalar> {
82public:
83 static Scalar smallNumber()
84 {
85 return Scalar(1e-8);
86 }
87};
88
89
94template <class Scalar>
95class RelErrSmallNumber<true,Scalar> {
96public:
97 static Scalar smallNumber()
98 {
100 }
101};
102
103
108template <class Scalar>
114
115
122template <class Scalar1, class Scalar2>
124relErr( const Scalar1 &s1, const Scalar2 &s2 );
125
126
133template <typename T1, typename T2, typename Enabled = void>
137 typedef typename std::common_type<magType1,magType2>::type magnitudeType;
138 static bool eval(
139 const std::string &v1_name,
140 const T1 &v1,
141 const std::string &v2_name,
142 const T2 &v2,
143 const std::string &maxRelErr_error_name,
144 const magnitudeType &maxRelErr_error,
145 const std::string &maxRelErr_warning_name,
146 const magnitudeType &maxRelErr_warning,
147 const Ptr<std::ostream> &out
148 )
149 {
150 using std::endl;
152 const magnitudeType rel_err = relErr( v1, v2 );
153 const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
154 && rel_err <= maxRelErr_error );
155 if (!is_null(out)) {
156 *out
157 << endl
158 << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
159 << " = rel_err(" << v1 << ", " << v2 << ") "
160 << "= " << rel_err << endl
161 << " <= " << maxRelErr_error_name
162 << " = " << maxRelErr_error << " : " << passfail(success) << endl;
163 if( success && rel_err >= maxRelErr_warning ) {
164 *out
165 << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
166 << " = rel_err(" << v1 << ", " << v2 << ") "
167 << "= " << rel_err << endl
168 << " >= " << maxRelErr_warning_name
169 << " = " << maxRelErr_warning << "!\n";
170 }
171 }
172 return success;
173 }
174};
175
176template <typename T1, typename T2>
177bool testRelErr(
178 const std::string &v1_name,
179 const T1 &v1,
180 const std::string &v2_name,
181 const T2 &v2,
182 const std::string &maxRelErr_error_name,
183 const typename TestRelErr<T1,T2>::magnitudeType &maxRelErr_error,
184 const std::string &maxRelErr_warning_name,
185 const typename TestRelErr<T1,T2>::magnitudeType &maxRelErr_warning,
186 const Ptr<std::ostream> &out) {
188}
189
203template<class Array1, class Array2>
204bool compareArrays(
205 const Array1 &a1, const std::string &a1_name,
206 const Array2 &a2, const std::string &a2_name,
208 );
209
210
226template<class Array1, class Array2, class ScalarMag>
228 const Array1 &a1, const std::string &a1_name,
229 const Array2 &a2, const std::string &a2_name,
230 const ScalarMag &tol,
232 );
233
250template<class Array1, class Array2, class ScalarMag>
252 const Array1 &a1, const std::string &a1_name,
253 const Array2 &a2, const std::string &a2_name,
254 const ScalarMag &tol,
256 );
257
258
259} // namespace Teuchos
260
261
270#define TEUCHOS_PASS_FAIL(RESULT) \
271 Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
272
273
280#define TEUCHOS_ECHO( statement, out ) \
281 (out) << #statement ";\n"; \
282 statement;
283
290#define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
291 { \
292 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
293 const bool l_result = (v1) == (v2); \
294 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
295 if (!l_result) (success) = false; \
296 }
297
304#define TEUCHOS_TEST_ASSERT( v1, out, success ) \
305 { \
306 const bool l_result = v1; \
307 (out) << #v1" = "<<l_result<<" == true : "; \
308 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
309 if (!l_result) (success) = false; \
310 }
311
318#define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
319 { \
320 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
321 const bool l_result = (v1) == (v2); \
322 if (!l_result) (success) = false; \
323 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
324 }
325
326
333#define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
334 { \
335 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
336 const bool l_result = (v1) != (v2); \
337 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
338 if (!l_result) (success) = false; \
339 }
340
341
348#define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
349 { \
350 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
351 const bool l_result = (v1) != (v2); \
352 if (!l_result) (success) = false; \
353 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
354 }
355
356
363#define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
364 { \
365 const bool l_result = Teuchos::testRelErr( \
366 #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
367 if (!l_result) (success) = false; \
368 }
369
370
380#define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
381 { \
382 (out) << #iter1" == "#iter2" = : "; \
383 const bool l_result = (iter1) == (iter2); \
384 if (!l_result) (success) = false; \
385 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
386 }
387
388
398#define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \
399 { \
400 (out) << #iter1" != "#iter2" = : "; \
401 const bool l_result = (iter1) != (iter2); \
402 if (!l_result) (success) = false; \
403 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
404 }
405
406
413#define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
414 { \
415 const bool l_result = ( (a)[i] == (val) ); \
416 if (!l_result) (success) = false; \
417 if (printPass || !(l_result)) { \
418 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
419 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
420 } \
421 }
422
423
430#define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
431 { \
432 const bool l_result = ( (a)[i] != (val) ); \
433 if (!l_result) (success) = false; \
434 if (printPass || !(l_result)) { \
435 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
436 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
437 } \
438 }
439
440
448#define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
449 { \
450 std::ostringstream a_i_str; \
451 a_i_str <<#a<<"("<<i<<","<<j<<")"; \
452 const bool l_result = Teuchos::testRelErr( \
453 a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
454 (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
455 if (!l_result) (success) = false; \
456 }
457
458
465#define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
466 { \
467 const bool l_result = ( (a)(i,j) == (val) ); \
468 if (!l_result) (success) = false; \
469 if (printPass || !(l_result)) { \
470 out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
471 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
472 } \
473 }
474
475
485#define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
486 { \
487 out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
488 const bool l_result = (v1) comp (v2); \
489 if (!l_result) (success) = false; \
490 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
491 }
492
493
504#define TEUCHOS_TEST_COMPARE_CONST( v1, comp, v2, out, success ) \
505 { \
506 out << #v1" = "<<(v1)<<" "#comp" "<<(v2)<<" : "; \
507 const bool l_result = (v1) comp (v2); \
508 if (!l_result) (success) = false; \
509 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
510 }
511
512
527#define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \
528 { \
529 std::ostream& l_out = (out); \
530 try { \
531 l_out << "Test that code {"#code";} throws " \
532 << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \
533 code; \
534 (success) = false; \
535 l_out << "failed (code did not throw an exception at all)\n"; \
536 } \
537 catch (const ExceptType& except) { \
538 l_out << "passed\n"; \
539 l_out << "\nException message for expected exception:\n\n"; \
540 { \
541 Teuchos::OSTab l_tab(out); \
542 l_out << except.what () << "\n\n"; \
543 (void)l_tab; \
544 } \
545 } \
546 catch (std::exception& except) { \
547 l_out << "The code was supposed to throw an exception of type " \
548 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
549 << "instead threw an exception of type " \
550 << typeid (except).name () << ", which is a subclass of " \
551 << "std::exception. The exception's message is:\n\n"; \
552 { \
553 Teuchos::OSTab l_tab(out); \
554 l_out << except.what () << "\n\n"; \
555 (void)l_tab; \
556 } \
557 l_out << "failed\n"; \
558 } \
559 catch (...) { \
560 l_out << "The code was supposed to throw an exception of type " \
561 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
562 << "instead threw an exception of some unknown type, which is " \
563 << "not a subclass of std::exception. This means we cannot " \
564 << "show you the exception's message, if it even has one.\n\n"; \
565 l_out << "failed\n"; \
566 } \
567 }
568
569
576#define TEUCHOS_TEST_NOTHROW( code, out, success ) \
577 { \
578 std::ostream& l_out = (out); \
579 try { \
580 l_out << "Test that code {"#code";} does not throw : "; \
581 code; \
582 l_out << "passed\n"; \
583 } \
584 catch (std::exception& except) { \
585 (success) = false; \
586 l_out << "The code was not supposed to throw an exception, but " \
587 << "instead threw an exception of type " \
588 << typeid (except).name () << ", which is a subclass of " \
589 << "std::exception. The exception's message is:\n\n"; \
590 { \
591 Teuchos::OSTab l_tab(out); \
592 l_out << except.what () << "\n\n"; \
593 (void)l_tab; \
594 } \
595 l_out << "failed\n"; \
596 } \
597 catch (...) { \
598 (success) = false; \
599 l_out << "The code was not supposed to throw an exception, but " \
600 << "instead threw an exception of some unknown type, which is " \
601 << "not a subclass of std::exception. This means we cannot " \
602 << "show you the exception's message, if it even has one.\n\n"; \
603 l_out << "failed\n"; \
604 } \
605 }
606
607//
608// Implementations
609//
610
611
612inline
613void Teuchos::updateSuccess(const bool result, bool &success)
614{
615 if (!result) success = false;
616}
617
618
619inline
620const std::string
622{
623 if (!result)
624 return "FAILED";
625 return "passed";
626}
627
628
629template <class Scalar1, class Scalar2>
632{
633 typedef typename std::common_type<Scalar1,Scalar2>::type Scalar3;
635 return
636 ST::magnitude( s1 - s2 )
637 / (
638 ST::magnitude(
640 )
641 + std::max( ST::magnitude(s1), ST::magnitude(s2) )
642 );
643}
644
645
646template<class Array1, class Array2>
648 const Array1 &a1, const std::string &a1_name,
649 const Array2 &a2, const std::string &a2_name,
651 )
652{
653 using Teuchos::as;
654
655 bool success = true;
656
657 out << "Comparing " << a1_name << " == " << a2_name << " ... ";
658
659 const int n = a1.size();
660
661 // Compare sizes
662 if (as<int>(a2.size()) != n) {
663 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
664 << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
665 return false;
666 }
667
668 // Compare elements
669 for( int i = 0; i < n; ++i ) {
670 const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
671 if (!result) {
672 out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
673 << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
674 success = false;
675 }
676 }
677 if (success) {
678 out << "passed\n";
679 }
680
681 return success;
682
683}
684
685
686template<class Array1, class Array2, class ScalarMag>
688 const Array1 &a1, const std::string &a1_name,
689 const Array2 &a2, const std::string &a2_name,
690 const ScalarMag &tol,
692 )
693{
694 using Teuchos::as;
695
696 // Determine the element types of Array1 and Array2
697 using Elem1 = std::decay_t<decltype(std::declval<Array1>()[0])>;
698 using Elem2 = std::decay_t<decltype(std::declval<Array2>()[0])>;
699
700 static_assert(std::is_same_v<Elem1, Elem2>,
701 "Teuchos::compareFloatingArrays: element types of Array1 and Array2 must be the same.");
702
703 bool success = true;
704
705 out << "Comparing " << a1_name << " == " << a2_name << " ... ";
706
707 const int n = a1.size();
708
709 // Compare sizes
710 if (as<int>(a2.size()) != n) {
711 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
712 << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
713 return false;
714 }
715
716 // Compare elements
717 for( int i = 0; i < n; ++i ) {
718 const ScalarMag err = relErr( a1[i], a2[i] );
719 if ( !(err <= tol) ) {
720 out
721 <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
722 <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
723 <<err<<" <= tol = "<<tol<<": failed!\n";
724 success = false;
725 }
726 }
727 if (success) {
728 out << "passed\n";
729 }
730
731 return success;
732
733}
734
735template<class Array1, class Array2, class ScalarMag>
737 const Array1 &a1, const std::string &a1_name,
738 const Array2 &a2, const std::string &a2_name,
739 const ScalarMag &tol,
741 )
742{
743 using Teuchos::as;
745
746 // Determine the element types of Array1 and Array2
747 using Elem1 = std::decay_t<decltype(std::declval<Array1>()[0])>;
748 using Elem2 = std::decay_t<decltype(std::declval<Array2>()[0])>;
749
750 static_assert(std::is_same_v<Elem1, Elem2>,
751 "Teuchos::compareFloatingArraysAbsolute: element types of Array1 and Array2 must be the same.");
752
753 bool success = true;
754
755 out << "Comparing " << a1_name << " == " << a2_name << " ... ";
756
757 const int n = a1.size();
758
759 // Compare sizes
760 if (as<int>(a2.size()) != n) {
761 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
762 << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
763 return false;
764 }
765
766 // Compare elements
767 for( int i = 0; i < n; ++i ) {
769 if ( !(err <= tol) ) {
770 out
771 <<"\nError, ||"<<a1_name<<"["<<i<<"] - " << a2_name<<"["<<i<<"]|| = "
772 <<err<<" <= tol = "<<tol<<": failed!\n";
773 success = false;
774 }
775 }
776 if (success) {
777 out << "passed\n";
778 }
779 return success;
780}
781
782
783#endif // TEUCHOS_TESTING_HELPERS_HPP
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
Defines basic traits for the scalar field type.
Defines basic traits returning the name of a type in a portable and readable way.
Smart reference counting pointer class for automatic garbage collection.
std::ostream subclass that performs the magic of indenting data sent to an std::ostream object among ...
bool is_null(const std::shared_ptr< T > &p)
Returns true if p.get()==NULL.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
Teuchos::ScalarTraits< typenamestd::common_type< Scalar1, Scalar2 >::type >::magnitudeType relErr(const Scalar1 &s1, const Scalar2 &s2)
Return relative error of two scalars.
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(...).
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 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.
bool showTestFailureLocation()
Return if TEUCHOS_PASS_FAIL(...) should print test failure location.
const std::string passfail(const bool result)
Return "passed" or "failed".
void updateSuccess(const bool result, bool &success)
Update the success bool flag.
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...
Scalar defaultSmallNumber()
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
This structure defines some basic traits for a scalar field type.
static magnitudeType eps()
Returns relative machine precision.
Compute, check and optionally print the relative error in two scalars.