/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2017 Danny Robson */ #ifndef CRUFT_UTIL_TAP_HPP #define CRUFT_UTIL_TAP_HPP #include "format.hpp" #include "maths.hpp" #include #include #include namespace cruft::TAP { /// A simple TAP (Test Anything Protocol) test case output class logger { public: enum { PASS, FAIL, SKIP, TODO }; //--------------------------------------------------------------------- logger (); logger (std::ostream&); ~logger (); //--------------------------------------------------------------------- template void expect (const bool test, const char (&fmt)[N], Args&&... args) { m_output << (test ? "ok " : "not ok ") << ++m_size << " - " << format::printf (fmt) (std::forward (args)...) << '\n'; if (!test) m_status = EXIT_FAILURE; } //--------------------------------------------------------------------- template void expect (const std::function &test, Args&&...args, const char (&fmt)[N]) { try { expect (test (std::forward (args)...), fmt); } catch (...) { expect (false, fmt); } } /////////////////////////////////////////////////////////////////////// template void expect_mod (ValueA &&a, ValueB &&b, const char (&fmt)[N], Args &&...args) { return expect (a % b == 0, fmt, std::forward (args)...); } /////////////////////////////////////////////////////////////////////// template void expect_eq (const T &a, const U &b, const char (&fmt)[N], Args&&...args) { #if 1 expect (almost_equal (a, b), fmt, std::forward (args)...); #else if (almost_equal (a, b)) return expect (true, fmt, std::forward (args)...); else return expect (false, "%! # %! != %!", format::printf (fmt)(std::forward (args)...), a, b); #endif } //--------------------------------------------------------------------- template void expect_neq (const T &a, const U &b, const char (&fmt)[N], Args&&...args) { expect (!almost_equal (a, b), fmt, std::forward (args)...); } /////////////////////////////////////////////////////////////////////// template void expect_gt (const ValueA &a, const ValueB &b, const char (&fmt)[N], Args&&...args) { expect (a > b, fmt, std::forward (args)...); } //--------------------------------------------------------------------- template void expect_ge (const T &a, const U &b, const char (&fmt)[N], Args&&...args) { expect (a >= b, fmt, std::forward (args)...); } //--------------------------------------------------------------------- template void expect_lt (const T &a, const U &b, const char (&fmt)[N], Args&&...args) { expect (a < b, fmt, std::forward (args)...); } //--------------------------------------------------------------------- template void expect_le (const T &a, const U &b, const char (&fmt)[N], Args&&...args) { expect (a <= b, fmt, std::forward (args)...); } /////////////////////////////////////////////////////////////////////// template void expect_nan (const T &t, const char (&fmt)[N], Args&&...args) { expect (std::isnan (t), fmt, std::forward (args)...); } /////////////////////////////////////////////////////////////////////// template void expect_nothrow (T &&t, const char (&fmt)[N], Args&&...args) { bool success = true; try { t (); } catch (...) { success = false; } expect (success, fmt, std::forward (args)...); } //--------------------------------------------------------------------- template void expect_throw (T &&t, const char (&fmt)[N], Args&&...args) { bool success = false; try { t (); } catch (const E&) { success = true; } catch (...) { success = false; } expect (success, fmt, std::forward (args)...); } /////////////////////////////////////////////////////////////////////// template void fail (const char (&fmt)[N], Args &&...args) { expect (false, fmt, std::forward (args)...); } //--------------------------------------------------------------------- void skip (const std::string &msg); void todo (const std::string &msg); void noop (void); /////////////////////////////////////////////////////////////////////// int status [[nodiscard]] (void) const; private: #if !defined(NDEBUG) mutable int m_reported = -1; #endif std::ostream &m_output; int m_status; size_t m_size; }; } #endif