• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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