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 Scalar>
155 typename ScalarTraits<Scalar>::magnitudeType
156 relErr( const Scalar &s1, const Scalar &s2 );
157 
158 
165 template<class Scalar>
166 bool testRelErr(
167  const std::string &v1_name,
168  const Scalar &v1,
169  const std::string &v2_name,
170  const Scalar &v2,
171  const std::string &maxRelErr_error_name,
172  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
173  const std::string &maxRelErr_warning_name,
174  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
175  const Ptr<std::ostream> &out
176  );
177 
178 
190 template<class Array1, class Array2>
191 bool compareArrays(
192  const Array1 &a1, const std::string &a1_name,
193  const Array2 &a2, const std::string &a2_name,
195  );
196 
197 
210 template<class Array1, class Array2, class ScalarMag>
212  const Array1 &a1, const std::string &a1_name,
213  const Array2 &a2, const std::string &a2_name,
214  const ScalarMag &tol,
216  );
217 
218 
219 } // namespace Teuchos
220 
221 
230 #define TEUCHOS_PASS_FAIL(RESULT) \
231  Teuchos::passfail_with_location((RESULT), __FILE__, __LINE__)
232 
233 
240 #define TEUCHOS_ECHO( statement, out ) \
241  (out) << #statement ";\n"; \
242  statement;
243 
250 #define TEUCHOS_TEST_EQUALITY_CONST( v1, v2, out, success ) \
251  { \
252  (out) << #v1" = "<<Teuchos::toString(v1)<<" == "<<Teuchos::toString(v2)<<" : "; \
253  const bool l_result = (v1) == (v2); \
254  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
255  if (!l_result) (success) = false; \
256  }
257 
264 #define TEUCHOS_TEST_ASSERT( v1, out, success ) \
265  { \
266  const bool l_result = v1; \
267  (out) << #v1" = "<<l_result<<" == true : "; \
268  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
269  if (!l_result) (success) = false; \
270  }
271 
278 #define TEUCHOS_TEST_EQUALITY( v1, v2, out, success ) \
279  { \
280  (out) << #v1" = "<<Teuchos::toString(v1)<<" == "#v2" = "<<Teuchos::toString(v2)<<" : "; \
281  const bool l_result = (v1) == (v2); \
282  if (!l_result) (success) = false; \
283  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
284  }
285 
286 
293 #define TEUCHOS_TEST_INEQUALITY_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 
301 
308 #define TEUCHOS_TEST_INEQUALITY( v1, v2, out, success ) \
309  { \
310  (out) << #v1" = "<<Teuchos::toString(v1)<<" != "#v2" = "<<Teuchos::toString(v2)<<" : "; \
311  const bool l_result = (v1) != (v2); \
312  if (!l_result) (success) = false; \
313  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
314  }
315 
316 
323 #define TEUCHOS_TEST_FLOATING_EQUALITY( v1, v2, tol, out, success ) \
324  { \
325  const bool l_result = Teuchos::testRelErr( \
326  #v1, v1, #v2, v2, "tol", tol, "tol", tol, Teuchos::outArg(out) ); \
327  if (!l_result) (success) = false; \
328  }
329 
330 
340 #define TEUCHOS_TEST_ITER_EQUALITY( iter1, iter2, out, success ) \
341  { \
342  (out) << #iter1" == "#iter2" = : "; \
343  const bool l_result = (iter1) == (iter2); \
344  if (!l_result) (success) = false; \
345  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
346  }
347 
348 
358 #define TEUCHOS_TEST_ITER_INEQUALITY( iter1, iter2, out, success ) \
359  { \
360  (out) << #iter1" != "#iter2" = : "; \
361  const bool l_result = (iter1) != (iter2); \
362  if (!l_result) (success) = false; \
363  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
364  }
365 
366 
373 #define TEUCHOS_TEST_ARRAY_ELE_EQUALITY( a, i, val, printPass, out, success ) \
374  { \
375  const bool l_result = ( (a)[i] == (val) ); \
376  if (!l_result) (success) = false; \
377  if (printPass || !(l_result)) { \
378  out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " == "#val" = " << Teuchos::toString(val) \
379  << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
380  } \
381  }
382 
383 
390 #define TEUCHOS_TEST_ARRAY_ELE_INEQUALITY( a, i, val, printPass, out, success ) \
391  { \
392  const bool l_result = ( (a)[i] != (val) ); \
393  if (!l_result) (success) = false; \
394  if (printPass || !(l_result)) { \
395  out << #a"["<<i<<"] = " << Teuchos::toString((a)[i]) << " != "#val" = " << Teuchos::toString(val) \
396  << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
397  } \
398  }
399 
400 
408 #define TEUCHOS_TEST_MATRIX_ELE_FLOATING_EQUALITY( a, i, j, val, tol, printPass, out, success ) \
409  { \
410  std::ostringstream a_i_str; \
411  a_i_str <<#a<<"("<<i<<","<<j<<")"; \
412  const bool l_result = Teuchos::testRelErr( \
413  a_i_str.str(), (a)(i,j), #val, val, "tol", tol, "tol", tol, \
414  (printPass) ? Teuchos::outArg(out) : Teuchos::null ); \
415  if (!l_result) (success) = false; \
416  }
417 
418 
425 #define TEUCHOS_TEST_MATRIX_ELE_EQUALITY( a, i, j, val, printPass, out, success ) \
426  { \
427  const bool l_result = ( (a)(i,j) == (val) ); \
428  if (!l_result) (success) = false; \
429  if (printPass || !(l_result)) { \
430  out << #a"("<<i<<","<<j<<") = " << (a)(i,j) << " == "#val" = " << (val) \
431  << " : " << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
432  } \
433  }
434 
435 
445 #define TEUCHOS_TEST_COMPARE( v1, comp, v2, out, success ) \
446  { \
447  out << #v1" = "<<(v1)<<" "#comp" "#v2" = "<<(v2)<<" : "; \
448  const bool l_result = (v1) comp (v2); \
449  if (!l_result) (success) = false; \
450  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
451  }
452 
453 
464 #define TEUCHOS_TEST_COMPARE_CONST( v1, comp, v2, out, success ) \
465  { \
466  out << #v1" = "<<(v1)<<" "#comp" "<<(v2)<<" : "; \
467  const bool l_result = (v1) comp (v2); \
468  if (!l_result) (success) = false; \
469  (out) << TEUCHOS_PASS_FAIL(l_result) << "\n"; \
470  }
471 
472 
487 #define TEUCHOS_TEST_THROW( code, ExceptType, out, success ) \
488  { \
489  std::ostream& l_out = (out); \
490  try { \
491  l_out << "Test that code {"#code";} throws " \
492  << Teuchos::TypeNameTraits<ExceptType>::name () << ": "; \
493  code; \
494  (success) = false; \
495  l_out << "failed (code did not throw an exception at all)\n"; \
496  } \
497  catch (const ExceptType& except) { \
498  l_out << "passed\n"; \
499  l_out << "\nException message for expected exception:\n\n"; \
500  { \
501  Teuchos::OSTab l_tab (out); \
502  l_out << except.what () << "\n\n"; \
503  } \
504  } \
505  catch (std::exception& except) { \
506  l_out << "The code was supposed to throw an exception of type " \
507  << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
508  << "instead threw an exception of type " \
509  << typeid (except).name () << ", which is a subclass of " \
510  << "std::exception. The exception's message is:\n\n"; \
511  { \
512  Teuchos::OSTab l_tab (out); \
513  l_out << except.what () << "\n\n"; \
514  } \
515  l_out << "failed\n"; \
516  } \
517  catch (...) { \
518  l_out << "The code was supposed to throw an exception of type " \
519  << Teuchos::TypeNameTraits<ExceptType>::name () << ", but " \
520  << "instead threw an exception of some unknown type, which is " \
521  << "not a subclass of std::exception. This means we cannot " \
522  << "show you the exception's message, if it even has one.\n\n"; \
523  l_out << "failed\n"; \
524  } \
525  }
526 
527 
534 #define TEUCHOS_TEST_NOTHROW( code, out, success ) \
535  { \
536  std::ostream& l_out = (out); \
537  try { \
538  l_out << "Test that code {"#code";} does not throw : "; \
539  code; \
540  l_out << "passed\n"; \
541  } \
542  catch (std::exception& except) { \
543  (success) = false; \
544  l_out << "The code was not supposed to throw an exception, but " \
545  << "instead threw an exception of type " \
546  << typeid (except).name () << ", which is a subclass of " \
547  << "std::exception. The exception's message is:\n\n"; \
548  { \
549  Teuchos::OSTab l_tab (out); \
550  l_out << except.what () << "\n\n"; \
551  } \
552  l_out << "failed\n"; \
553  } \
554  catch (...) { \
555  (success) = false; \
556  l_out << "The code was not supposed to throw an exception, but " \
557  << "instead threw an exception of some unknown type, which is " \
558  << "not a subclass of std::exception. This means we cannot " \
559  << "show you the exception's message, if it even has one.\n\n"; \
560  l_out << "failed\n"; \
561  } \
562  }
563 
564 //
565 // Implementations
566 //
567 
568 
569 inline
570 void Teuchos::updateSuccess(const bool result, bool &success)
571 {
572  if (!result) success = false;
573 }
574 
575 
576 inline
577 const std::string
578 Teuchos::passfail(const bool result)
579 {
580  if (!result)
581  return "FAILED";
582  return "passed";
583 }
584 
585 
586 template <class Scalar>
588 Teuchos::relErr( const Scalar &s1, const Scalar &s2 )
589 {
591  return
592  ST::magnitude( s1 - s2 )
593  / (
594  ST::magnitude(
595  RelErrSmallNumber<ST::hasMachineParameters,Scalar>::smallNumber()
596  )
597  + std::max( ST::magnitude(s1), ST::magnitude(s2) )
598  );
599 }
600 
601 
602 template<class Scalar>
604  const std::string &v1_name,
605  const Scalar &v1,
606  const std::string &v2_name,
607  const Scalar &v2,
608  const std::string &maxRelErr_error_name,
609  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_error,
610  const std::string &maxRelErr_warning_name,
611  const typename Teuchos::ScalarTraits<Scalar>::magnitudeType &maxRelErr_warning,
612  const Ptr<std::ostream> &out
613  )
614 {
615  using std::endl;
616  typedef ScalarTraits<Scalar> ST;
617  typedef typename ST::magnitudeType ScalarMag;
618  typedef ScalarTraits<ScalarMag> SMT;
619  const ScalarMag rel_err = relErr( v1, v2 );
620  const bool success = ( !SMT::isnaninf(rel_err) && !SMT::isnaninf(maxRelErr_error)
621  && rel_err <= maxRelErr_error );
622  if (!is_null(out)) {
623  *out
624  << endl
625  << "Check: rel_err(" << v1_name << ", " << v2_name << ")\n"
626  << " = rel_err(" << v1 << ", " << v2 << ") "
627  << "= " << rel_err << endl
628  << " <= " << maxRelErr_error_name
629  << " = " << maxRelErr_error << " : " << passfail(success) << endl;
630  if( success && rel_err >= maxRelErr_warning ) {
631  *out
632  << "Warning! rel_err(" << v1_name << ", " << v2_name << ")\n"
633  << " = rel_err(" << v1 << ", " << v2 << ") "
634  << "= " << rel_err << endl
635  << " >= " << maxRelErr_warning_name
636  << " = " << maxRelErr_warning << "!\n";
637  }
638  }
639  return success;
640 }
641 
642 
643 template<class Array1, class Array2>
645  const Array1 &a1, const std::string &a1_name,
646  const Array2 &a2, const std::string &a2_name,
648  )
649 {
650  using Teuchos::as;
651  bool success = true;
652 
653  out << "Comparing " << a1_name << " == " << a2_name << " ... ";
654 
655  const int n = a1.size();
656 
657  // Compare sizes
658  if (as<int>(a2.size()) != n) {
659  out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
660  << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
661  return false;
662  }
663 
664  // Compare elements
665  for( int i = 0; i < n; ++i ) {
666  const bool result = ( a1[i] == a2[i] ); // Tests C::operator[](i) const
667  if (!result) {
668  out << "\nError, "<<a1_name<<"["<<i<<"] = "<<a1[i]<<" == "
669  << a2_name<<"["<<i<<"] = "<<a2[i]<<": failed!\n";
670  success = false;
671  }
672  }
673  if (success) {
674  out << "passed\n";
675  }
676 
677  return success;
678 
679 }
680 
681 
682 template<class Array1, class Array2, class ScalarMag>
684  const Array1 &a1, const std::string &a1_name,
685  const Array2 &a2, const std::string &a2_name,
686  const ScalarMag &tol,
688  )
689 {
690  using Teuchos::as;
691  bool success = true;
692 
693  out << "Comparing " << a1_name << " == " << a2_name << " ... ";
694 
695  const int n = a1.size();
696 
697  // Compare sizes
698  if (as<int>(a2.size()) != n) {
699  out << "\nError, "<<a1_name<<".size() = "<<a1.size()<<" == "
700  << a2_name<<".size() = "<<a2.size()<<" : failed!\n";
701  return false;
702  }
703 
704  // Compare elements
705  for( int i = 0; i < n; ++i ) {
706  const ScalarMag err = relErr( a1[i], a2[i] );
707  if ( !(err <= tol) ) {
708  out
709  <<"\nError, relErr("<<a1_name<<"["<<i<<"],"
710  <<a2_name<<"["<<i<<"]) = relErr("<<a1[i]<<","<<a2[i]<<") = "
711  <<err<<" <= tol = "<<tol<<": failed!\n";
712  success = false;
713  }
714  }
715  if (success) {
716  out << "passed\n";
717  }
718 
719  return success;
720 
721 }
722 
723 
724 #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.
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...
bool is_null(const ArrayRCP< T > &p)
Returns true if p.get()==NULL.
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 ...
ScalarTraits< Scalar >::magnitudeType relErr(const Scalar &s1, const Scalar &s2)
Return relative error of two scalars.
void updateSuccess(const bool result, bool &success)
Update the success bool flag.
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
Defines basic traits for the scalar field type.
bool testRelErr(const std::string &v1_name, const Scalar &v1, const std::string &v2_name, const Scalar &v2, const std::string &maxRelErr_error_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_error, const std::string &maxRelErr_warning_name, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType &maxRelErr_warning, const Ptr< std::ostream > &out)
Compute, check and optionally print the relative error in two scalars.
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...