1 //
2 // unit_test.hpp
3 // ~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #ifndef UNIT_TEST_HPP
12 #define UNIT_TEST_HPP
13
14 #include <boost/asio/detail/config.hpp>
15 #include <iostream>
16 #include <boost/asio/detail/atomic_count.hpp>
17
18 #if defined(__sun)
19 # include <stdlib.h> // Needed for lrand48.
20 #endif // defined(__sun)
21
22 #if defined(__BORLANDC__) && !defined(__clang__)
23
24 // Prevent use of intrinsic for strcmp.
25 # include <cstring>
26 # undef strcmp
27
28 // Suppress error about condition always being true.
29 # pragma option -w-ccc
30
31 #endif // defined(__BORLANDC__) && !defined(__clang__)
32
33 #if defined(BOOST_ASIO_MSVC)
34 # pragma warning (disable:4127)
35 # pragma warning (push)
36 # pragma warning (disable:4244)
37 # pragma warning (disable:4702)
38 #endif // defined(BOOST_ASIO_MSVC)
39
40 #if !defined(BOOST_ASIO_TEST_IOSTREAM)
41 # define BOOST_ASIO_TEST_IOSTREAM std::cerr
42 #endif // !defined(BOOST_ASIO_TEST_IOSTREAM)
43
44 namespace boost {
45 namespace asio {
46 namespace detail {
47
test_name()48 inline const char*& test_name()
49 {
50 static const char* name = 0;
51 return name;
52 }
53
test_errors()54 inline atomic_count& test_errors()
55 {
56 static atomic_count errors(0);
57 return errors;
58 }
59
begin_test_suite(const char * name)60 inline void begin_test_suite(const char* name)
61 {
62 boost::asio::detail::test_name();
63 boost::asio::detail::test_errors();
64 BOOST_ASIO_TEST_IOSTREAM << name << " test suite begins" << std::endl;
65 }
66
end_test_suite(const char * name)67 inline int end_test_suite(const char* name)
68 {
69 BOOST_ASIO_TEST_IOSTREAM << name << " test suite ends" << std::endl;
70 BOOST_ASIO_TEST_IOSTREAM << "\n*** ";
71 long errors = boost::asio::detail::test_errors();
72 if (errors == 0)
73 BOOST_ASIO_TEST_IOSTREAM << "No errors detected.";
74 else if (errors == 1)
75 BOOST_ASIO_TEST_IOSTREAM << "1 error detected.";
76 else
77 BOOST_ASIO_TEST_IOSTREAM << errors << " errors detected." << std::endl;
78 BOOST_ASIO_TEST_IOSTREAM << std::endl;
79 return errors == 0 ? 0 : 1;
80 }
81
82 template <void (*Test)()>
run_test(const char * name)83 inline void run_test(const char* name)
84 {
85 test_name() = name;
86 long errors_before = boost::asio::detail::test_errors();
87 Test();
88 if (test_errors() == errors_before)
89 BOOST_ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
90 else
91 BOOST_ASIO_TEST_IOSTREAM << name << " failed" << std::endl;
92 }
93
94 template <void (*)()>
compile_test(const char * name)95 inline void compile_test(const char* name)
96 {
97 BOOST_ASIO_TEST_IOSTREAM << name << " passed" << std::endl;
98 }
99
100 #if defined(BOOST_ASIO_NO_EXCEPTIONS)
101
102 template <typename T>
throw_exception(const T & t)103 void throw_exception(const T& t)
104 {
105 BOOST_ASIO_TEST_IOSTREAM << "Exception: " << t.what() << std::endl;
106 std::abort();
107 }
108
109 #endif // defined(BOOST_ASIO_NO_EXCEPTIONS)
110
111 } // namespace detail
112 } // namespace asio
113 } // namespace boost
114
115 #define BOOST_ASIO_CHECK(expr) \
116 do { if (!(expr)) { \
117 BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
118 << boost::asio::detail::test_name() << ": " \
119 << "check '" << #expr << "' failed" << std::endl; \
120 ++boost::asio::detail::test_errors(); \
121 } } while (0)
122
123 #define BOOST_ASIO_CHECK_MESSAGE(expr, msg) \
124 do { if (!(expr)) { \
125 BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
126 << boost::asio::detail::test_name() << ": " \
127 << msg << std::endl; \
128 ++boost::asio::detail::test_errors(); \
129 } } while (0)
130
131 #define BOOST_ASIO_WARN_MESSAGE(expr, msg) \
132 do { if (!(expr)) { \
133 BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
134 << boost::asio::detail::test_name() << ": " \
135 << msg << std::endl; \
136 } } while (0)
137
138 #define BOOST_ASIO_ERROR(msg) \
139 do { \
140 BOOST_ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \
141 << boost::asio::detail::test_name() << ": " \
142 << msg << std::endl; \
143 ++boost::asio::detail::test_errors(); \
144 } while (0)
145
146 #define BOOST_ASIO_TEST_SUITE(name, tests) \
147 int main() \
148 { \
149 boost::asio::detail::begin_test_suite(name); \
150 tests \
151 return boost::asio::detail::end_test_suite(name); \
152 }
153
154 #define BOOST_ASIO_TEST_CASE(test) \
155 boost::asio::detail::run_test<&test>(#test);
156
157 #define BOOST_ASIO_TEST_CASE2(test1, test2) \
158 boost::asio::detail::run_test<&test1, test2>(#test1 "," #test2);
159
160 #define BOOST_ASIO_TEST_CASE3(test1, test2, test3) \
161 boost::asio::detail::run_test<&test1, test2, test3>( \
162 #test1 "," #test2 "," #test3);
163
164 #define BOOST_ASIO_TEST_CASE4(test1, test2, test3, test4) \
165 boost::asio::detail::run_test<&test1, test2, test3, test4>( \
166 #test1 "," #test2 "," #test3 "," #test4);
167
168 #define BOOST_ASIO_TEST_CASE5(test1, test2, test3, test4, test5) \
169 boost::asio::detail::run_test<&test1, test2, test3, test4, test5>( \
170 #test1 "," #test2 "," #test3 "," #test4 "," #test5);
171
172 #define BOOST_ASIO_COMPILE_TEST_CASE(test) \
173 boost::asio::detail::compile_test<&test>(#test);
174
null_test()175 inline void null_test()
176 {
177 }
178
179 #if defined(__GNUC__) && defined(_AIX)
180
181 // AIX needs this symbol defined in asio, even if it doesn't do anything.
test_main(int,char **)182 int test_main(int, char**)
183 {
184 }
185
186 #endif // defined(__GNUC__) && defined(_AIX)
187
188 #if defined(BOOST_ASIO_MSVC)
189 # pragma warning (pop)
190 #endif // defined(BOOST_ASIO_MSVC)
191
192 #endif // UNIT_TEST_HPP
193