/*! * \file * \brief UnitTest++ checks specialized for IT++ matrices. * \author Vaclav Barta. * * ----------------------------------- * BDM++ - C++ library for Bayesian Decision Making under Uncertainty * * Using IT++ for numerical operations * ----------------------------------- */ #ifndef MAT_CHECKS_H #define MAT_CHECKS_H #include "../bdm/itpp_ext.h" #include "UnitTest++.h" namespace UnitTest { bool AreClose(const itpp::vec &expected, const itpp::vec &actual, double tolerance); bool AreClose(const itpp::vec &expected, const itpp::vec &actual, const itpp::vec &tolerance); bool AreClose(const itpp::mat &expected, const itpp::mat &actual, double tolerance); inline void CheckClose(TestResults &results, const itpp::vec &expected, const itpp::vec &actual, double tolerance, TestDetails const &details) { if (!AreClose(expected, actual, tolerance)) { MemoryOutStream stream; stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } inline void CheckClose(TestResults &results, const itpp::mat &expected, const itpp::mat &actual, double tolerance, TestDetails const &details) { if (!AreClose(expected, actual, tolerance)) { MemoryOutStream stream; stream << "Expected " << expected << " +/- " << tolerance << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } } /*! CHECK_EQUAL_EX and CHECK_CLOSE_EX macros should be used only in blocks having an instance of this class (which sets the globals for error reporting). */ class CurrentContext { private: static const char *config_name; static int index; public: // the pointer must stay valid for the lifetime of the object CurrentContext(const char *name, int idx); ~CurrentContext(); template static void CheckEqualEx(UnitTest::TestResults& results, Expected const& expected, Actual const& actual, UnitTest::TestDetails const& details) { if (!(expected == actual)) { UnitTest::MemoryOutStream stream; stream << "error at " << config_name << '[' << index << "]: expected " << expected << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } template static void CheckCloseEx(UnitTest::TestResults& results, Expected const& expected, Actual const& actual, Tolerance const& tolerance, UnitTest::TestDetails const& details) { if (!UnitTest::AreClose(expected, actual, tolerance)) { UnitTest::MemoryOutStream stream; stream << "error at " << config_name << '[' << index << "]: expected " << expected << " +/- " << tolerance << " but was " << actual; results.OnTestFailure(details, stream.GetText()); } } }; #define CHECK_EQUAL_EX(expected, actual) \ do \ { \ try { \ CurrentContext::CheckEqualEx(*UnitTest::CurrentTest::Results(), expected, actual, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), 0, false)); \ } \ catch (...) { \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_EQUAL_EX(" #expected ", " #actual ")"); \ } \ } while (0) #define CHECK_CLOSE_EX(expected, actual, tolerance) \ do \ { \ try { \ CurrentContext::CheckCloseEx(*UnitTest::CurrentTest::Results(), expected, actual, tolerance, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), 0, false)); \ } \ catch (...) { \ UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ "Unhandled exception in CHECK_CLOSE_EX(" #expected ", " #actual ")"); \ } \ } while (0) #endif