1 // This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
2 // the main distribution directory for license terms and copyright or visit
3 // https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
4
5 #pragma once
6
7 #include <cmath>
8 #include <fstream>
9 #include <iostream>
10 #include <map>
11 #include <memory>
12 #include <mutex>
13 #include <sstream>
14 #include <string>
15 #include <thread>
16 #include <vector>
17
18 #include "caf/deep_to_string.hpp"
19 #include "caf/fwd.hpp"
20 #include "caf/logger.hpp"
21 #include "caf/optional.hpp"
22 #include "caf/term.hpp"
23 #include "caf/variant.hpp"
24
25 #include "caf/detail/arg_wrapper.hpp"
26 #include "caf/detail/type_traits.hpp"
27
28 namespace caf::test {
29
30 // -- Function objects for implementing CAF_CHECK_* macros ---------------------
31
32 template <class F>
33 struct negated {
34 template <class T, class U>
operator ()caf::test::negated35 bool operator()(const T& x, const U& y) {
36 F f;
37 return !f(x, y);
38 }
39 };
40
41 template <class T, class Comparator>
42 struct compare_visitor {
43 const T& rhs;
44
45 template <class U>
operator ()caf::test::compare_visitor46 bool operator()(const U& lhs) const {
47 Comparator f;
48 return f(lhs, rhs);
49 }
50 };
51
52 struct equality_operator {
53 static constexpr bool default_value = false;
54
55 template <class T, class U,
56 detail::enable_if_t<((std::is_floating_point<T>::value
57 && std::is_convertible<U, double>::value)
58 || (std::is_floating_point<U>::value
59 && std::is_convertible<T, double>::value))
60 && detail::is_comparable<T, U>::value,
61 int> = 0>
operator ()caf::test::equality_operator62 bool operator()(const T& t, const U& u) const {
63 auto x = static_cast<long double>(t);
64 auto y = static_cast<long double>(u);
65 auto max = std::max(std::abs(x), std::abs(y));
66 auto dif = std::abs(x - y);
67 return dif <= max * 1e-5l;
68 }
69
70 template <class T, class U,
71 detail::enable_if_t<!((std::is_floating_point<T>::value
72 && std::is_convertible<U, double>::value)
73 || (std::is_floating_point<U>::value
74 && std::is_convertible<T, double>::value))
75 && detail::is_comparable<T, U>::value,
76 int> = 0>
operator ()caf::test::equality_operator77 bool operator()(const T& x, const U& y) const {
78 return x == y;
79 }
80
81 template <
82 class T, class U,
83 typename std::enable_if<!detail::is_comparable<T, U>::value, int>::type = 0>
operator ()caf::test::equality_operator84 bool operator()(const T&, const U&) const {
85 return default_value;
86 }
87 };
88
89 struct inequality_operator {
90 static constexpr bool default_value = true;
91
92 template <class T, class U,
93 typename std::enable_if<(std::is_floating_point<T>::value
94 || std::is_floating_point<U>::value)
95 && detail::is_comparable<T, U>::value,
96 int>::type
97 = 0>
operator ()caf::test::inequality_operator98 bool operator()(const T& x, const U& y) const {
99 equality_operator f;
100 return !f(x, y);
101 }
102
103 template <class T, class U,
104 typename std::enable_if<!std::is_floating_point<T>::value
105 && !std::is_floating_point<U>::value
106 && detail::is_comparable<T, U>::value,
107 int>::type
108 = 0>
operator ()caf::test::inequality_operator109 bool operator()(const T& x, const U& y) const {
110 return x != y;
111 }
112
113 template <
114 class T, class U,
115 typename std::enable_if<!detail::is_comparable<T, U>::value, int>::type = 0>
operator ()caf::test::inequality_operator116 bool operator()(const T&, const U&) const {
117 return default_value;
118 }
119 };
120
121 template <class F, class T>
122 struct comparison_unbox_helper {
123 const F& f;
124 const T& rhs;
125
126 template <class U>
operator ()caf::test::comparison_unbox_helper127 bool operator()(const U& lhs) const {
128 return f(lhs, rhs);
129 }
130 };
131
132 template <class Operator>
133 class comparison {
134 public:
135 // -- default case -----------------------------------------------------------
136
137 template <class T, class U>
operator ()(const T & x,const U & y) const138 bool operator()(const T& x, const U& y) const {
139 std::integral_constant<bool, SumType<T>()> lhs_is_sum_type;
140 std::integral_constant<bool, SumType<U>()> rhs_is_sum_type;
141 return cmp(x, y, lhs_is_sum_type, rhs_is_sum_type);
142 }
143
144 private:
145 // -- automagic unboxing of sum types ----------------------------------------
146
147 template <class T, class U>
cmp(const T & x,const U & y,std::false_type,std::false_type) const148 bool cmp(const T& x, const U& y, std::false_type, std::false_type) const {
149 Operator f;
150 return f(x, y);
151 }
152
153 template <class T, class U>
cmp(const T & x,const U & y,std::true_type,std::false_type) const154 bool cmp(const T& x, const U& y, std::true_type, std::false_type) const {
155 Operator f;
156 auto inner_x = caf::get_if<U>(&x);
157 return inner_x ? f(*inner_x, y) : Operator::default_value;
158 }
159
160 template <class T, class U>
cmp(const T & x,const U & y,std::false_type,std::true_type) const161 bool cmp(const T& x, const U& y, std::false_type, std::true_type) const {
162 Operator f;
163 auto inner_y = caf::get_if<T>(&y);
164 return inner_y ? f(x, *inner_y) : Operator::default_value;
165 }
166
167 template <class T, class U>
cmp(const T & x,const U & y,std::true_type,std::true_type) const168 bool cmp(const T& x, const U& y, std::true_type, std::true_type) const {
169 comparison_unbox_helper<comparison, U> f{*this, y};
170 return visit(f, x);
171 }
172 };
173
174 using equal_to = comparison<equality_operator>;
175
176 using not_equal_to = comparison<inequality_operator>;
177
178 struct less_than {
179 template <class T, class U>
operator ()caf::test::less_than180 bool operator()(const T& x, const U& y) {
181 return x < y;
182 }
183 };
184
185 struct less_than_or_equal {
186 template <class T, class U>
operator ()caf::test::less_than_or_equal187 bool operator()(const T& x, const U& y) {
188 return x <= y;
189 }
190 };
191
192 struct greater_than {
193 template <class T, class U>
operator ()caf::test::greater_than194 bool operator()(const T& x, const U& y) {
195 return x > y;
196 }
197 };
198
199 struct greater_than_or_equal {
200 template <class T, class U>
operator ()caf::test::greater_than_or_equal201 bool operator()(const T& x, const U& y) {
202 return x >= y;
203 }
204 };
205
206 // -- Core components of the unit testing abstraction --------------------------
207
208 /// Default test-running function.
209 /// This function will be called automatically unless you define
210 /// `CAF_TEST_NO_MAIN` before including `caf/test/unit_test.hpp`. In
211 /// the latter case you will have to provide you own `main` function,
212 /// where you may want to call `caf::test::main` from.
213 int main(int argc, char** argv);
214
215 /// A sequence of *checks*.
216 class test {
217 public:
218 test(std::string test_name, bool disabled_by_default);
219
220 virtual ~test();
221
222 size_t expected_failures() const;
223
224 void pass();
225
226 void fail(bool expected);
227
228 const std::string& name() const;
229
good()230 size_t good() {
231 return good_;
232 }
233
bad()234 size_t bad() {
235 return bad_;
236 }
237
disabled() const238 bool disabled() const noexcept {
239 return disabled_;
240 }
241
242 virtual void run_test_impl() = 0;
243
244 private:
245 size_t expected_failures_;
246 std::string name_;
247 size_t good_;
248 size_t bad_;
249 bool disabled_;
250 };
251
252 struct dummy_fixture {};
253
254 template <class T>
255 class test_impl : public test {
256 public:
test_impl(std::string test_name,bool disabled_by_default)257 test_impl(std::string test_name, bool disabled_by_default)
258 : test(std::move(test_name), disabled_by_default) {
259 // nop
260 }
261
run_test_impl()262 void run_test_impl() override {
263 T impl;
264 impl.run_test_impl();
265 }
266 };
267
268 namespace detail {
269
270 [[noreturn]] void requirement_failed(const std::string& msg);
271
272 // constructs spacing given a line number.
273 const char* fill(size_t line);
274
275 void remove_trailing_spaces(std::string& x);
276
277 } // namespace detail
278
279 /// Logs messages for the test framework.
280 class logger {
281 public:
282 enum class level : int {
283 quiet = 0,
284 error = 1,
285 info = 2,
286 verbose = 3,
287 massive = 4
288 };
289
290 static bool init(int lvl_cons, int lvl_file, const std::string& logfile);
291
292 static logger& instance();
293
294 template <class T>
log(level lvl,const T & x)295 void log(level lvl, const T& x) {
296 struct simple_fwd_t {
297 const T& operator()(const T& y) const {
298 return y;
299 }
300 };
301 using fwd =
302 typename std::conditional<std::is_same<char, T>::value
303 || std::is_convertible<T, std::string>::value
304 || std::is_same<caf::term, T>::value,
305 simple_fwd_t, deep_to_string_t>::type;
306 fwd f;
307 auto y = f(x);
308 if (lvl <= level_console_)
309 *console_ << y;
310 if (lvl <= level_file_)
311 file_ << y;
312 }
313
log(level lvl,const std::nullptr_t &)314 void log(level lvl, const std::nullptr_t&) {
315 log(lvl, "null");
316 }
317
318 /// Output stream for logging purposes.
319 class stream {
320 public:
321 stream(logger& parent, level lvl);
322
323 stream(const stream&) = default;
324
325 struct reset_flags_t {};
326
operator <<(reset_flags_t)327 stream& operator<<(reset_flags_t) {
328 return *this;
329 }
330
331 template <class T>
operator <<(const T & x)332 stream& operator<<(const T& x) {
333 parent_.log(lvl_, x);
334 return *this;
335 }
336
337 private:
338 logger& parent_;
339 level lvl_;
340 };
341
342 stream error();
343 stream info();
344 stream verbose();
345 stream massive();
346
347 void disable_colors();
348
349 private:
350 logger();
351
352 level level_console_;
353 level level_file_;
354 std::ostream* console_;
355 std::ofstream file_;
356 std::ostringstream dummy_;
357 };
358
359 /// Drives unit test execution.
360 class engine {
361 public:
362 /// Sets external command line arguments.
363 /// @param argc The argument counter.
364 /// @param argv The argument vectors.
365 static void args(int argc, char** argv);
366
367 /// Retrieves the argument counter.
368 /// @returns The number of arguments set via ::args or 0.
369 static int argc();
370
371 /// Retrieves the argument vector.
372 /// @returns The argument vector set via ::args or `nullptr`.
373 static char** argv();
374
375 /// Sets path of current executable.
376 /// @param argv The path of current executable.
377 static void path(char* argv);
378
379 /// Retrieves the path of current executable
380 /// @returns The path to executable set via ::path(char*) or `nullptr`.
381 static char* path();
382
383 /// Returns the maximum number of seconds a test case is allowed to run.
384 static int max_runtime();
385
386 /// Sets the maximum number of seconds a test case is
387 /// allowed to run to `value`.
388 static void max_runtime(int value);
389
390 /// Adds a test to the engine.
391 /// @param cstr_name The name of the suite.
392 /// @param ptr The test to register.
393 static void add(const char* cstr_name, std::unique_ptr<test> ptr);
394
395 /// Invokes tests in all suites.
396 /// @param colorize Whether to colorize the output.
397 /// @param log_file The filename of the log output. The empty string means
398 /// that no log file will be written.
399 /// @param verbosity_console The log verbosity level on the console.
400 /// @param verbosity_file The log verbosity level in the log file.
401 /// @param suites_str Regular expression for including test suites.
402 /// @param not_suites_str Regular expression for excluding test suites.
403 /// @param tests_str Regular expression for individually selecting tests.
404 /// @param not_tests_str Regular expression for individually disabling tests.
405 /// @returns `true` if all tests succeeded.
406 static bool
407 run(bool colorize, const std::string& log_file, int verbosity_console,
408 int verbosity_file, const std::string& suites_str,
409 const std::string& not_suites_str, const std::string& tests_str,
410 const std::string& not_tests_str);
411
412 static const char* last_check_file();
413 static void last_check_file(const char* file);
414
415 static size_t last_check_line();
416 static void last_check_line(size_t line);
417
418 static test* current_test();
419
420 static std::vector<std::string> available_suites();
421
422 static std::vector<std::string> available_tests(const std::string& suite);
423
424 private:
425 engine() = default;
426
427 static engine& instance();
428
429 static std::string render(std::chrono::microseconds t);
430
431 int argc_ = 0;
432 char** argv_ = nullptr;
433 char* path_ = nullptr;
434 bool colorize_ = false;
435 const char* check_file_ = "<none>";
436 size_t check_line_ = 0;
437 test* current_test_ = nullptr;
438 std::map<std::string, std::vector<std::unique_ptr<test>>> suites_;
439 int max_runtime_ = 30; // 30s per default
440 };
441
442 namespace detail {
443
444 template <class T>
445 struct adder {
addercaf::test::detail::adder446 adder(const char* suite_name, const char* test_name, bool disabled) {
447 engine::add(suite_name, std::unique_ptr<T>{new T(test_name, disabled)});
448 }
449 };
450
451 bool check(test* parent, const char* file, size_t line, const char* expr,
452 bool should_fail, bool result);
453
454 template <class T, class U>
check(test * parent,const char * file,size_t line,const char * expr,bool should_fail,bool result,const T & x,const U & y)455 bool check(test* parent, const char* file, size_t line, const char* expr,
456 bool should_fail, bool result, const T& x, const U& y) {
457 auto out = logger::instance().massive();
458 if (result) {
459 out << term::green << "** " << term::blue << file << term::yellow << ":"
460 << term::blue << line << fill(line) << term::reset << expr << '\n';
461 parent->pass();
462 } else {
463 out << term::red << "!! " << term::blue << file << term::yellow << ":"
464 << term::blue << line << fill(line) << term::reset << expr
465 << term::magenta << " (" << term::red << x << term::magenta << " !! "
466 << term::red << y << term::magenta << ')' << term::reset_endl;
467 parent->fail(should_fail);
468 }
469 return result;
470 }
471
472 bool check_un(bool result, const char* file, size_t line, const char* expr);
473
474 bool check_bin(bool result, const char* file, size_t line, const char* expr,
475 const std::string& lhs, const std::string& rhs);
476
477 } // namespace detail
478 } // namespace caf::test
479
480 // on the global namespace so that it can hidden via namespace-scoping
481 using caf_test_case_auto_fixture = caf::test::dummy_fixture;
482
483 #define CAF_TEST_PRINT(level, msg, colorcode) \
484 (::caf::test::logger::instance().level() \
485 << ::caf::term::colorcode << " -> " << ::caf::term::reset \
486 << ::caf::test::logger::stream::reset_flags_t{} << msg << " [line " \
487 << __LINE__ << "]\n")
488
489 #define CAF_TEST_PRINT_ERROR(msg) CAF_TEST_PRINT(info, msg, red)
490 #define CAF_TEST_PRINT_INFO(msg) CAF_TEST_PRINT(info, msg, yellow)
491 #define CAF_TEST_PRINT_VERBOSE(msg) CAF_TEST_PRINT(verbose, msg, yellow)
492
493 #define CAF_PASTE_CONCAT(lhs, rhs) lhs##rhs
494
495 #define CAF_PASTE(lhs, rhs) CAF_PASTE_CONCAT(lhs, rhs)
496
497 #define CAF_UNIQUE(name) CAF_PASTE(name, __LINE__)
498
499 #ifndef CAF_SUITE
500 # define CAF_SUITE unnamed
501 #endif
502
503 #define CAF_STR(s) #s
504
505 #define CAF_XSTR(s) CAF_STR(s)
506
507 #define CAF_FUNC_EXPR(func, x_expr, y_expr) #func "(" #x_expr ", " #y_expr ")"
508
509 #define CAF_ERROR(msg) \
510 do { \
511 CAF_TEST_PRINT_ERROR(msg); \
512 ::caf::test::engine::current_test()->fail(false); \
513 ::caf::test::engine::last_check_file(__FILE__); \
514 ::caf::test::engine::last_check_line(__LINE__); \
515 } while (false)
516
517 #define CAF_CHECK(...) \
518 [](bool expr_result) { \
519 return ::caf::test::detail::check_un(expr_result, __FILE__, __LINE__, \
520 #__VA_ARGS__); \
521 }(static_cast<bool>(__VA_ARGS__))
522
523 #define CAF_CHECK_FUNC(func, x_expr, y_expr) \
524 [](auto&& x_val, auto&& y_val) { \
525 func comparator; \
526 auto caf_check_res \
527 = ::caf::test::detail::check(::caf::test::engine::current_test(), \
528 __FILE__, __LINE__, \
529 CAF_FUNC_EXPR(func, x_expr, y_expr), false, \
530 comparator(x_val, y_val), x_val, y_val); \
531 return caf_check_res; \
532 }(x_expr, y_expr)
533
534 #define CAF_FAIL(msg) \
535 do { \
536 CAF_TEST_PRINT_ERROR(msg); \
537 ::caf::test::engine::current_test()->fail(false); \
538 ::caf::test::detail::requirement_failed("test failure"); \
539 } while (false)
540
541 #define CAF_REQUIRE(...) \
542 do { \
543 auto CAF_UNIQUE(__result) \
544 = ::caf::test::detail::check(::caf::test::engine::current_test(), \
545 __FILE__, __LINE__, #__VA_ARGS__, false, \
546 static_cast<bool>(__VA_ARGS__)); \
547 if (!CAF_UNIQUE(__result)) \
548 ::caf::test::detail::requirement_failed(#__VA_ARGS__); \
549 } while (false)
550
551 #define CAF_REQUIRE_FUNC(func, x_expr, y_expr) \
552 do { \
553 func comparator; \
554 auto&& x_val___ = x_expr; \
555 auto&& y_val___ = y_expr; \
556 auto CAF_UNIQUE(__result) = ::caf::test::detail::check( \
557 ::caf::test::engine::current_test(), __FILE__, __LINE__, \
558 CAF_FUNC_EXPR(func, x_expr, y_expr), false, \
559 comparator(x_val___, y_val___), x_val___, y_val___); \
560 if (!CAF_UNIQUE(__result)) \
561 ::caf::test::detail::requirement_failed( \
562 CAF_FUNC_EXPR(func, x_expr, y_expr)); \
563 } while (false)
564
565 #define CAF_TEST_IMPL(name, disabled_by_default) \
566 namespace { \
567 struct CAF_UNIQUE(test) : caf_test_case_auto_fixture { \
568 void run_test_impl(); \
569 }; \
570 ::caf::test::detail::adder<::caf::test::test_impl<CAF_UNIQUE(test)>> \
571 CAF_UNIQUE(a){CAF_XSTR(CAF_SUITE), CAF_XSTR(name), disabled_by_default}; \
572 } \
573 void CAF_UNIQUE(test)::run_test_impl()
574
575 #define CAF_TEST(name) CAF_TEST_IMPL(name, false)
576
577 #define CAF_TEST_DISABLED(name) CAF_TEST_IMPL(name, true)
578
579 #define CAF_TEST_FIXTURE_SCOPE(scope_name, fixture_name) \
580 namespace scope_name { \
581 using caf_test_case_auto_fixture = fixture_name;
582
583 #define CAF_TEST_FIXTURE_SCOPE_END() } // namespace <scope_name>
584
585 // -- Convenience macros -------------------------------------------------------
586
587 #define CAF_MESSAGE(msg) \
588 do { \
589 CAF_LOG_INFO(msg); \
590 CAF_TEST_PRINT_VERBOSE(msg); \
591 } while (false)
592
593 // -- CAF_CHECK* predicate family ----------------------------------------------
594
595 #define CAF_CHECK_EQUAL(x_expr, y_expr) \
596 [](const auto& x_val, const auto& y_val) { \
597 return ::caf::test::detail::check_bin( \
598 x_val == y_val, __FILE__, __LINE__, #x_expr " == " #y_expr, \
599 caf::detail::stringification_inspector::render(x_val), \
600 caf::detail::stringification_inspector::render(y_val)); \
601 }(x_expr, y_expr)
602
603 #define CAF_CHECK_NOT_EQUAL(x_expr, y_expr) \
604 [](const auto& x_val, const auto& y_val) { \
605 return ::caf::test::detail::check_bin( \
606 x_val != y_val, __FILE__, __LINE__, #x_expr " != " #y_expr, \
607 caf::detail::stringification_inspector::render(x_val), \
608 caf::detail::stringification_inspector::render(y_val)); \
609 }(x_expr, y_expr)
610
611 #define CAF_CHECK_LESS(x_expr, y_expr) \
612 [](const auto& x_val, const auto& y_val) { \
613 return ::caf::test::detail::check_bin( \
614 x_val < y_val, __FILE__, __LINE__, #x_expr " < " #y_expr, \
615 caf::detail::stringification_inspector::render(x_val), \
616 caf::detail::stringification_inspector::render(y_val)); \
617 }(x_expr, y_expr)
618
619 #define CAF_CHECK_NOT_LESS(x_expr, y_expr) \
620 [](const auto& x_val, const auto& y_val) { \
621 return ::caf::test::detail::check_bin( \
622 !(x_val < y_val), __FILE__, __LINE__, "not " #x_expr " < " #y_expr, \
623 caf::detail::stringification_inspector::render(x_val), \
624 caf::detail::stringification_inspector::render(y_val)); \
625 }(x_expr, y_expr)
626
627 #define CAF_CHECK_LESS_OR_EQUAL(x_expr, y_expr) \
628 [](const auto& x_val, const auto& y_val) { \
629 return ::caf::test::detail::check_bin( \
630 x_val <= y_val, __FILE__, __LINE__, #x_expr " <= " #y_expr, \
631 caf::detail::stringification_inspector::render(x_val), \
632 caf::detail::stringification_inspector::render(y_val)); \
633 }(x_expr, y_expr)
634
635 #define CAF_CHECK_NOT_LESS_OR_EQUAL(x_expr, y_expr) \
636 [](const auto& x_val, const auto& y_val) { \
637 return ::caf::test::detail::check_bin( \
638 !(x_val <= y_val), __FILE__, __LINE__, "not " #x_expr " <= " #y_expr, \
639 caf::detail::stringification_inspector::render(x_val), \
640 caf::detail::stringification_inspector::render(y_val)); \
641 }(x_expr, y_expr)
642
643 #define CAF_CHECK_GREATER(x_expr, y_expr) \
644 [](const auto& x_val, const auto& y_val) { \
645 return ::caf::test::detail::check_bin( \
646 x_val > y_val, __FILE__, __LINE__, #x_expr " > " #y_expr, \
647 caf::detail::stringification_inspector::render(x_val), \
648 caf::detail::stringification_inspector::render(y_val)); \
649 }(x_expr, y_expr)
650
651 #define CAF_CHECK_NOT_GREATER(x_expr, y_expr) \
652 [](const auto& x_val, const auto& y_val) { \
653 return ::caf::test::detail::check_bin( \
654 !(x_val > y_val), __FILE__, __LINE__, "not " #x_expr " > " #y_expr, \
655 caf::detail::stringification_inspector::render(x_val), \
656 caf::detail::stringification_inspector::render(y_val)); \
657 }(x_expr, y_expr)
658
659 #define CAF_CHECK_GREATER_OR_EQUAL(x_expr, y_expr) \
660 [](const auto& x_val, const auto& y_val) { \
661 return ::caf::test::detail::check_bin( \
662 x_val >= y_val, __FILE__, __LINE__, #x_expr " >= " #y_expr, \
663 caf::detail::stringification_inspector::render(x_val), \
664 caf::detail::stringification_inspector::render(y_val)); \
665 }(x_expr, y_expr)
666
667 #define CAF_CHECK_NOT_GREATER_OR_EQUAL(x_expr, y_expr) \
668 [](const auto& x_val, const auto& y_val) { \
669 return ::caf::test::detail::check_bin( \
670 !(x_val >= y_val), __FILE__, __LINE__, "not " #x_expr " >= " #y_expr, \
671 caf::detail::stringification_inspector::render(x_val), \
672 caf::detail::stringification_inspector::render(y_val)); \
673 }(x_expr, y_expr)
674
675 // -- CAF_CHECK* predicate family ----------------------------------------------
676
677 #define CAF_REQUIRE_EQUAL(x, y) CAF_REQUIRE_FUNC(::caf::test::equal_to, x, y)
678
679 #define CAF_REQUIRE_NOT_EQUAL(x, y) \
680 CAF_REQUIRE_FUNC(::caf::test::not_equal_to, x, y)
681
682 #define CAF_REQUIRE_LESS(x, y) CAF_REQUIRE_FUNC(::caf::test::less_than, x, y)
683
684 #define CAF_REQUIRE_NOT_LESS(x, y) \
685 CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::less_than>, x, y)
686
687 #define CAF_REQUIRE_LESS_OR_EQUAL(x, y) \
688 CAF_REQUIRE_FUNC(::caf::test::less_than_or_equal, x, y)
689
690 #define CAF_REQUIRE_NOT_LESS_OR_EQUAL(x, y) \
691 CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::less_than_or_equal>, x, y)
692
693 #define CAF_REQUIRE_GREATER(x, y) \
694 CAF_REQUIRE_FUNC(::caf::test::greater_than, x, y)
695
696 #define CAF_REQUIRE_NOT_GREATER(x, y) \
697 CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::greater_than>, x, y)
698
699 #define CAF_REQUIRE_GREATER_OR_EQUAL(x, y) \
700 CAF_REQUIRE_FUNC(::caf::test::greater_than_or_equal, x, y)
701
702 #define CAF_REQUIRE_NOT_GREATER_OR_EQUAL(x, y) \
703 CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::greater_than_or_equal>, \
704 x, y)
705