blob: 5b2123e203097986faa026d98e0363f3f1df5318 [file] [log] [blame]
//
// unit_test.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef UNIT_TEST_HPP
#define UNIT_TEST_HPP
#include "asio/detail/config.hpp"
#include <iostream>
#include "asio/detail/atomic_count.hpp"
#if defined(__sun)
# include <stdlib.h> // Needed for lrand48.
#endif // defined(__sun)
#if defined(__BORLANDC__) && !defined(__clang__)
// Prevent use of intrinsic for strcmp.
# include <cstring>
# undef strcmp
// Suppress error about condition always being true.
# pragma option -w-ccc
#endif // defined(__BORLANDC__) && !defined(__clang__)
#if defined(ASIO_MSVC)
# pragma warning (disable:4127)
# pragma warning (push)
# pragma warning (disable:4244)
# pragma warning (disable:4702)
#endif // defined(ASIO_MSVC)
#if !defined(ASIO_TEST_IOSTREAM)
# define ASIO_TEST_IOSTREAM std::cerr
#endif // !defined(ASIO_TEST_IOSTREAM)
namespace asio {
namespace detail {
inline const char*& test_name()
{
static const char* name = 0;
return name;
}
inline atomic_count& test_errors()
{
static atomic_count errors(0);
return errors;
}
inline void begin_test_suite(const char* name)
{
asio::detail::test_name();
asio::detail::test_errors();
ASIO_TEST_IOSTREAM << name << " test suite begins" << std::endl;
}
inline int end_test_suite(const char* name)
{
ASIO_TEST_IOSTREAM << name << " test suite ends" << std::endl;
ASIO_TEST_IOSTREAM << "\n*** ";
long errors = asio::detail::test_errors();
if (errors == 0)
ASIO_TEST_IOSTREAM << "No errors detected.";
else if (errors == 1)
ASIO_TEST_IOSTREAM << "1 error detected.";
else
ASIO_TEST_IOSTREAM << errors << " errors detected." << std::endl;
ASIO_TEST_IOSTREAM << std::endl;
return errors == 0 ? 0 : 1;
}
template <void (*Test)()>
inline void run_test(const char* name)
{
test_name() = name;
long errors_before = asio::detail::test_errors();
Test();
if (test_errors() == errors_before)
ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
else
ASIO_TEST_IOSTREAM << name << " failed" << std::endl;
}
template <void (*)()>
inline void compile_test(const char* name)
{
ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
}
#if defined(ASIO_NO_EXCEPTIONS)
template <typename T>
void throw_exception(const T& t)
{
ASIO_TEST_IOSTREAM << "Exception: " << t.what() << std::endl;
std::abort();
}
#endif // defined(ASIO_NO_EXCEPTIONS)
} // namespace detail
} // namespace asio
#define ASIO_CHECK(expr) \
do { if (!(expr)) { \
ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
<< asio::detail::test_name() << ": " \
<< "check '" << #expr << "' failed" << std::endl; \
++asio::detail::test_errors(); \
} } while (0)
#define ASIO_CHECK_MESSAGE(expr, msg) \
do { if (!(expr)) { \
ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
<< asio::detail::test_name() << ": " \
<< msg << std::endl; \
++asio::detail::test_errors(); \
} } while (0)
#define ASIO_WARN_MESSAGE(expr, msg) \
do { if (!(expr)) { \
ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
<< asio::detail::test_name() << ": " \
<< msg << std::endl; \
} } while (0)
#define ASIO_ERROR(msg) \
do { \
ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
<< asio::detail::test_name() << ": " \
<< msg << std::endl; \
++asio::detail::test_errors(); \
} while (0)
#define ASIO_TEST_SUITE(name, tests) \
int main() \
{ \
asio::detail::begin_test_suite(name); \
tests \
return asio::detail::end_test_suite(name); \
}
#define ASIO_TEST_CASE(test) \
asio::detail::run_test<&test>(#test);
#define ASIO_TEST_CASE2(test1, test2) \
asio::detail::run_test<&test1, test2>(#test1 "," #test2);
#define ASIO_TEST_CASE3(test1, test2, test3) \
asio::detail::run_test<&test1, test2, test3>( \
#test1 "," #test2 "," #test3);
#define ASIO_TEST_CASE4(test1, test2, test3, test4) \
asio::detail::run_test<&test1, test2, test3, test4>( \
#test1 "," #test2 "," #test3 "," #test4);
#define ASIO_TEST_CASE5(test1, test2, test3, test4, test5) \
asio::detail::run_test<&test1, test2, test3, test4, test5>( \
#test1 "," #test2 "," #test3 "," #test4 "," #test5);
#define ASIO_COMPILE_TEST_CASE(test) \
asio::detail::compile_test<&test>(#test);
inline void null_test()
{
}
#if defined(__GNUC__) && defined(_AIX)
// AIX needs this symbol defined in asio, even if it doesn't do anything.
int test_main(int, char**)
{
}
#endif // defined(__GNUC__) && defined(_AIX)
#if defined(ASIO_MSVC)
# pragma warning (pop)
#endif // defined(ASIO_MSVC)
#endif // UNIT_TEST_HPP