From e9c0ed3f5f171d7282e2daecea64141717fa8edb Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 13 Apr 2015 16:43:49 +1000 Subject: [PATCH] tap: use an object for logging --- Makefile.am | 2 ++ tap.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++ tap.hpp | 56 +++++++++++++++++++----------- tap.ipp | 83 +++++++++++++++++++++++++++++++++++++++++++++ test/polynomial.cpp | 4 +-- 5 files changed, 206 insertions(+), 21 deletions(-) create mode 100644 tap.cpp create mode 100644 tap.ipp diff --git a/Makefile.am b/Makefile.am index 416c7170..e46671a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -169,7 +169,9 @@ UTIL_FILES = \ string.hpp \ stringid.cpp \ stringid.hpp \ + tap.cpp \ tap.hpp \ + tap.ipp \ time.cpp \ time.hpp \ types.hpp \ diff --git a/tap.cpp b/tap.cpp new file mode 100644 index 00000000..6a4d5ed3 --- /dev/null +++ b/tap.cpp @@ -0,0 +1,82 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2015 Danny Robson + */ + +#include "tap.hpp" + +#include "debug.hpp" + +#include + +using util::TAP::logger; + +//----------------------------------------------------------------------------- +logger::logger (): + m_status (EXIT_SUCCESS), + m_size (0) +{ ; } + + +//----------------------------------------------------------------------------- +logger::~logger () +{ + std::cout << "1.." << m_size << '\n'; +} + + +////////////0////////////////////////////////////////////////////////////////// +void +util::TAP::logger::expect (bool test, const std::string &msg) +{ + std::cout << (test ? "ok " : "not ok ") << ++m_size << " - " << msg << '\n'; + + if (!test) + m_status = EXIT_FAILURE; +} + + +/////////////////////////////////////////////////////////////////////////////// +void +logger::skip (const std::string &msg) +{ + std::cout << "ok " << ++m_size << " - # SKIP " << msg << '\n'; +} + + +//----------------------------------------------------------------------------- +void +logger::todo (const std::string &msg) +{ + std::cout << "not ok " << ++m_size << " - # TODO " << msg << '\n'; +} + + +//----------------------------------------------------------------------------- +void +logger::noop (void) +{ + skip ("noop"); +} + + +//----------------------------------------------------------------------------- +int +logger::status (void) const +{ + return m_status; +} diff --git a/tap.hpp b/tap.hpp index e2622a84..169e8d4f 100644 --- a/tap.hpp +++ b/tap.hpp @@ -20,33 +20,51 @@ #ifndef __UTIL_TAP_HPP #define __UTIL_TAP_HPP -#include +#include +#include +#include -#define TAP_PLAN(N) do { \ - std::cout << "1.." << (N) << '\n'; \ -} while (0) +namespace util { namespace TAP { + /// A simple TAP (Test Anything Protocol) test case output + class logger { + public: + enum { + PASS, + FAIL, + SKIP, + TODO + }; + logger (); + ~logger (); -#define TAP(OK, MSG) do { \ - std::cout << ((OK) ? "ok - " : "not ok - ") << (MSG) << '\n'; \ -} while (0) + void expect (bool, const std::string &msg); + template + void expect (std::function test, const T&, const U&, const std::string &msg); -#define TAP_EQ(A,B,MSG) do { \ - const auto &&__tap_eq_a = (A); \ - const auto &&__tap_eq_b = (B); \ - \ - TAP (almost_equal (__tap_eq_a, __tap_eq_b), (MSG)); \ -} while (0) + template + void expect_eq (const T&, const U&, const std::string &msg = "equality"); + template + void expect_neq (const T&, const U&, const std::string &msg = "inequality"); + template void expect_gt (const T&, const U&, const std::string &msg = "gt"); + template void expect_ge (const T&, const U&, const std::string &msg = "ge"); + template void expect_lt (const T&, const U&, const std::string &msg = "lt"); + template void expect_le (const T&, const U&, const std::string &msg = "le"); -#define TAP_SKIP(MSG) do { \ - std::cout << "ok # skip " << (MSG) << '\n'; \ -} while (0) + void skip (const std::string &msg); + void todo (const std::string &msg); + void noop (void); + int status (void) const; -#define TAP_BAIL(MSG) do { \ - std::cout << "Bail out! " << (MSG) << '\n'; \ -} while (0) + private: + int m_status; + size_t m_size; + }; +} } + +#include "tap.ipp" #endif diff --git a/tap.ipp b/tap.ipp new file mode 100644 index 00000000..6025d98b --- /dev/null +++ b/tap.ipp @@ -0,0 +1,83 @@ +/* + * This file is part of libgim. + * + * libgim is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * libgim is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with libgim. If not, see . + * + * Copyright 2015 Danny Robson + */ + +#ifdef __UTIL_TAP_IPP +#error +#endif +#define __UTIL_TAP_IPP + +#include "maths.hpp" + +#include +#include + +//----------------------------------------------------------------------------- +template +void +util::TAP::logger::expect (std::function test, + const T &a, + const U &b, + const std::string &msg) +{ + bool success = test (a, b); + std::cout << (success ? "ok " : "not ok ") << ++m_size << " - " << msg << '\n'; + + if (!success) + m_status = EXIT_FAILURE; +} + +//----------------------------------------------------------------------------- +template +void +util::TAP::logger::expect_eq (const T&a, const U &b, const std::string &msg) +{ + expect (almost_equal, a, b, msg); +} + + +//----------------------------------------------------------------------------- +template +void +util::TAP::logger::expect_neq (const T&a, const U &b, const std::string &msg) +{ + static const std::function TEST = [] (const T &t, const U &u) -> bool { + return !almost_equal (t, u); + }; + + expect (TEST, a, b, msg); +} + + +//----------------------------------------------------------------------------- +#define TAP_TEST(SUFFIX,OP) \ +template \ +void \ +util::TAP::logger::expect_ ## SUFFIX (const T &a, \ + const U &b, \ + const std::string &msg) \ +{ \ + std::cout << ((a OP b) ? "ok " : "not ok ") << ++m_size << " - " << msg << '\n'; \ +} + +TAP_TEST(gt, > ) +TAP_TEST(ge, >=) +TAP_TEST(lt, < ) +TAP_TEST(le, <=) + +#undef TAP_TEST diff --git a/test/polynomial.cpp b/test/polynomial.cpp index 0401c4a1..576a3d97 100644 --- a/test/polynomial.cpp +++ b/test/polynomial.cpp @@ -31,7 +31,7 @@ main (int, char**) { "cubic 1 uniq", { 1, -3, 3, -1 }, { 1, nan, nan } }, }; - TAP_PLAN(elems (CUBICS)); + util::TAP::logger test; for (auto &i: CUBICS) { std::array s = util::polynomial::solve<3> (i.coeffs); @@ -52,7 +52,7 @@ main (int, char**) ok = false; } - TAP (ok, i.name); + test.expect (ok, i.name); } return 0;