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//
4// Teuchos: Common Tools Package
5// Copyright (2004) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ***********************************************************************
40// @HEADER
41
42#ifndef TEUCHOS_TESTING_HELPERS_HPP
43#define TEUCHOS_TESTING_HELPERS_HPP
44
45
54#include "Teuchos_FancyOStream.hpp"
55
56
57namespace Teuchos {
58
59
64inline void updateSuccess(const bool result, bool &success);
65
66
71inline const std::string passfail(const bool result);
72
73
78TEUCHOSCORE_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber);
79
85
86
92
93
98template <bool hasMachineParameters, class Scalar>
100public:
101 static Scalar smallNumber()
102 {
104 }
105};
106
107
112template <class Scalar>
113class RelErrSmallNumber<false,Scalar> {
114public:
115 static Scalar smallNumber()
116 {
117 return Scalar(1e-8);
118 }
119};
120
121
126template <class Scalar>
127class RelErrSmallNumber<true,Scalar> {
128public:
129 static Scalar smallNumber()
130 {
132 }
133};
134
135
140template <class Scalar>
142{
143 const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
145}
146
147
154template <class Scalar1, class Scalar2>
156relErr( const Scalar1 &s1, const Scalar2 &s2 );
157
158
165template <typename T1, typename T2, typename Enabled = void>
167 typedef typename Teuchos::ScalarTraits<T1>::magnitudeType magType1;
168 typedef typename Teuchos::ScalarTraits<T2>::magnitudeType magType2;
169 typedef typename std::common_type<magType1,magType2>::type magnitudeType;
170 static bool eval(
171 const std::string &v1_name,
172 const T1 &v1,
173 const std::string &v2_name,
174 const T2 &v2,
175 const std::string &maxRelErr_error_name,
176 const magnitudeType &maxRelErr_error,
177 const std::string &maxRelErr_warning_name,
178 const magnitudeType &maxRelErr_warning,
179 const Ptr<std::ostream> &out
180 )
181 {
182 using std::endl;
183 typedef ScalarTraits<magnitudeType> SMT;
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 );
187 if (!is_null(out)) {
188 *out
189 << endl
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 ) {
196 *out
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";
202 }
203 }
204 return success;
205 }
206};
207
208template <typename T1, typename T2>
209bool testRelErr(
210 const std::string &v1_name,
211 const T1 &v1,
212 const std::string &v2_name,
213 const T2 &v2,
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,
218 const Ptr<std::ostream> &out) {
219 return TestRelErr<T1,T2>::eval(v1_name, v1, v2_name,v2, maxRelErr_error_name, maxRelErr_error, maxRelErr_warning_name, maxRelErr_warning, out);
220}
221
233template<class Array1, class Array2>
234bool compareArrays(
235 const Array1 &a1, const std::string &a1_name,
236 const Array2 &a2, const std::string &a2_name,
238 );
239
240
253template<class Array1, class Array2, class ScalarMag>
255 const Array1 &a1, const std::string &a1_name,
256 const Array2 &a2, const std::string &a2_name,
257 const ScalarMag &tol,
259 );
260
261
262} // namespace Teuchos
263
264
273#define TEUCHOS_PASS_FAIL(RESULT) \
274 Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
275
276
283#define TEUCHOS_ECHO( statement, out ) \
284 (out) << #statement ";\n"; \
285 statement;
286
293#define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
294 { \
295 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
296 const bool l_result = (v1) == (v2); \
297 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
298 if (!l_result) (success) = false; \
299 }
300
307#define TEUCHOS_TEST_ASSERT( v1, out, success ) \
308 { \
309 const bool l_result = v1; \
310 (out) << #v1" = "<<l_result<<" == true : "; \
311 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
312 if (!l_result) (success) = false; \
313 }
314
321#define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
322 { \
323 (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
324 const bool l_result = (v1) == (v2); \
325 if (!l_result) (success) = false; \
326 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
327 }
328
329
336#define TEUCHOS_TEST_INEQUALITY_CONST( v1, v2, out, success ) \
337 { \
338 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "<<Teuchos::toString(v2)<<" : "; \
339 const bool l_result = (v1) != (v2); \
340 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
341 if (!l_result) (success) = false; \
342 }
343
344
351#define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
352 { \
353 (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
354 const bool l_result = (v1) != (v2); \
355 if (!l_result) (success) = false; \
356 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
357 }
358
359
366#define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
367 { \
368 const bool l_result = Teuchos::testRelErr( \
369 #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
370 if (!l_result) (success) = false; \
371 }
372
373
383#define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
384 { \
385 (out) << #iter1" == "#iter2" = : "; \
386 const bool l_result = (iter1) == (iter2); \
387 if (!l_result) (success) = false; \
388 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
389 }
390
391
401#define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \
402 { \
403 (out) << #iter1" != "#iter2" = : "; \
404 const bool l_result = (iter1) != (iter2); \
405 if (!l_result) (success) = false; \
406 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
407 }
408
409
416#define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
417 { \
418 const bool l_result = ( (a)[i] == (val) ); \
419 if (!l_result) (success) = false; \
420 if (printPass || !(l_result)) { \
421 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
422 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
423 } \
424 }
425
426
433#define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
434 { \
435 const bool l_result = ( (a)[i] != (val) ); \
436 if (!l_result) (success) = false; \
437 if (printPass || !(l_result)) { \
438 out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
439 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
440 } \
441 }
442
443
451#define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
452 { \
453 std::ostringstream a_i_str; \
454 a_i_str <<#a<<"("<<i<<","<<j<<")"; \
455 const bool l_result = Teuchos::testRelErr( \
456 a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
457 (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
458 if (!l_result) (success) = false; \
459 }
460
461
468#define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
469 { \
470 const bool l_result = ( (a)(i,j) == (val) ); \
471 if (!l_result) (success) = false; \
472 if (printPass || !(l_result)) { \
473 out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
474 << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
475 } \
476 }
477
478
488#define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
489 { \
490 out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
491 const bool l_result = (v1) comp (v2); \
492 if (!l_result) (success) = false; \
493 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
494 }
495
496
507#define TEUCHOS_TEST_COMPARE_CONST( v1, comp, v2, out, success ) \
508 { \
509 out << #v1" = "<<(v1)<<" "#comp" "<<(v2)<<" : "; \
510 const bool l_result = (v1) comp (v2); \
511 if (!l_result) (success) = false; \
512 (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
513 }
514
515
530#define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \
531 { \
532 std::ostream& l_out = (out); \
533 try { \
534 l_out << "Test that code {"#code";} throws " \
535 << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \
536 code; \
537 (success) = false; \
538 l_out << "failed (code did not throw an exception at all)\n"; \
539 } \
540 catch (const ExceptType& except) { \
541 l_out << "passed\n"; \
542 l_out << "\nException message for expected exception:\n\n"; \
543 { \
544 Teuchos::OSTab l_tab (out); \
545 l_out << except.what () << "\n\n"; \
546 } \
547 } \
548 catch (std::exception& except) { \
549 l_out << "The code was supposed to throw an exception of type " \
550 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
551 << "instead threw an exception of type " \
552 << typeid (except).name () << ", which is a subclass of " \
553 << "std::exception. The exception's message is:\n\n"; \
554 { \
555 Teuchos::OSTab l_tab (out); \
556 l_out << except.what () << "\n\n"; \
557 } \
558 l_out << "failed\n"; \
559 } \
560 catch (...) { \
561 l_out << "The code was supposed to throw an exception of type " \
562 << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
563 << "instead threw an exception of some unknown type, which is " \
564 << "not a subclass of std::exception. This means we cannot " \
565 << "show you the exception's message, if it even has one.\n\n"; \
566 l_out << "failed\n"; \
567 } \
568 }
569
570
577#define TEUCHOS_TEST_NOTHROW( code, out, success ) \
578 { \
579 std::ostream& l_out = (out); \
580 try { \
581 l_out << "Test that code {"#code";} does not throw : "; \
582 code; \
583 l_out << "passed\n"; \
584 } \
585 catch (std::exception& except) { \
586 (success) = false; \
587 l_out << "The code was not supposed to throw an exception, but " \
588 << "instead threw an exception of type " \
589 << typeid (except).name () << ", which is a subclass of " \
590 << "std::exception. The exception's message is:\n\n"; \
591 { \
592 Teuchos::OSTab l_tab (out); \
593 l_out << except.what () << "\n\n"; \
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
621Teuchos::passfail(const bool result)
622{
623 if (!result)
624 return "FAILED";
625 return "passed";
626}
627
628
629template <class Scalar1, class Scalar2>
631Teuchos::relErr( const Scalar1 &s1, const Scalar2 &s2 )
632{
633 typedef typename std::common_type<Scalar1,Scalar2>::type Scalar;
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 bool success = true;
655
656 out << "Comparing " << a1_name << " == " << a2_name << " ... ";
657
658 const int n = a1.size();
659
660 // Compare sizes
661 if (as<int>(a2.size()) != n) {
662 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
663 << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
664 return false;
665 }
666
667 // Compare elements
668 for( int i = 0; i < n; ++i ) {
669 const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
670 if (!result) {
671 out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
672 << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
673 success = false;
674 }
675 }
676 if (success) {
677 out << "passed\n";
678 }
679
680 return success;
681
682}
683
684
685template<class Array1, class Array2, class ScalarMag>
687 const Array1 &a1, const std::string &a1_name,
688 const Array2 &a2, const std::string &a2_name,
689 const ScalarMag &tol,
691 )
692{
693 using Teuchos::as;
694 bool success = true;
695
696 out << "Comparing " << a1_name << " == " << a2_name << " ... ";
697
698 const int n = a1.size();
699
700 // Compare sizes
701 if (as<int>(a2.size()) != n) {
702 out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
703 << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
704 return false;
705 }
706
707 // Compare elements
708 for( int i = 0; i < n; ++i ) {
709 const ScalarMag err = relErr( a1[i], a2[i] );
710 if ( !(err <= tol) ) {
711 out
712 <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
713 <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
714 <<err<<" <= tol = "<<tol<<": failed!\n";
715 success = false;
716 }
717 }
718 if (success) {
719 out << "passed\n";
720 }
721
722 return success;
723
724}
725
726
727#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.
Simple wrapper class for raw pointers to single objects where no persisting relationship exists.
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.
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.
T magnitudeType
Mandatory typedef for result of magnitude.
static magnitudeType eps()
Returns relative machine precision.
Compute, check and optionally print the relative error in two scalars.