Teuchos - Trilinos Tools Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
51 #include "Teuchos_ConfigDefs.hpp"
52 #include "Teuchos_ScalarTraits.hpp"
54 #include "Teuchos_FancyOStream.hpp"
55 
56 
57 namespace Teuchos {
58 
59 
64 inline void updateSuccess(const bool result, bool &success);
65 
66 
71 inline const std::string passfail(const bool result);
72 
73 
78 TEUCHOSCORE_LIB_DLL_EXPORT const std::string passfail_with_location(const bool result, const std::string &file, const int lineNumber);
79 
84 void showTestFailureLocation(bool);
85 
86 
92 
93 
98 template <bool hasMachineParameters, class Scalar>
100 public:
101  static Scalar smallNumber()
102  {
104  }
105 };
106 
107 
112 template <class Scalar>
113 class RelErrSmallNumber<false,Scalar> {
114 public:
115  static Scalar smallNumber()
116  {
117  return Scalar(1e-8);
118  }
119 };
120 
121 
126 template <class Scalar>
127 class RelErrSmallNumber<true,Scalar> {
128 public:
129  static Scalar smallNumber()
130  {
132  }
133 };
134 
135 
140 template <class Scalar>
142 {
143  const bool hasMachineParameters = ScalarTraits<Scalar>::hasMachineParameters;
145 }
146 
147 
154 template <class Scalar1, class Scalar2>
156 relErr( const Scalar1 &s1, const Scalar2 &s2 );
157 
158 
165 template <typename T1, typename T2, typename Enabled = void>
166 struct TestRelErr {
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 
208 template <typename T1, typename T2>
209 bool 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 
233 template<class Array1, class Array2>
234 bool compareArrays(
235  const Array1 &a1, const std::string &a1_name,
236  const Array2 &a2, const std::string &a2_name,
238  );
239 
240 
253 template<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 
612 inline
613 void Teuchos::updateSuccess(const bool result, bool &success)
614 {
615  if (!result) success = false;
616 }
617 
618 
619 inline
620 const std::string
621 Teuchos::passfail(const bool result)
622 {
623  if (!result)
624  return "FAILED";
625  return "passed";
626 }
627 
628 
629 template <class Scalar1, class Scalar2>
631 Teuchos::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 
646 template<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 
685 template<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
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 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 &quot;passed&quot; or &quot;failed&quot;.
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...