File: unit_test.hpp

package info (click to toggle)
actor-framework 0.17.6-3.2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 9,008 kB
  • sloc: cpp: 77,684; sh: 674; python: 309; makefile: 13
file content (717 lines) | stat: -rw-r--r-- 26,205 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <cmath>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include "caf/deep_to_string.hpp"
#include "caf/fwd.hpp"
#include "caf/logger.hpp"
#include "caf/optional.hpp"
#include "caf/term.hpp"
#include "caf/variant.hpp"

#include "caf/detail/arg_wrapper.hpp"
#include "caf/detail/type_traits.hpp"

namespace caf {
namespace test {

// -- Function objects for implementing CAF_CHECK_* macros ---------------------

template <class F>
struct negated {
  template <class T, class U>
  bool operator()(const T& x, const U& y) {
    F f;
    return !f(x, y);
  }
};

template <class T, class Comparator>
struct compare_visitor {
  const T& rhs;

  template <class U>
  bool operator()(const U& lhs) const {
    Comparator f;
    return f(lhs, rhs);
  }
};

struct equality_operator {
  static constexpr bool default_value = false;

  template <class T, class U,
            detail::enable_if_t<((std::is_floating_point<T>::value
                                  && std::is_convertible<U, double>::value)
                                 || (std::is_floating_point<U>::value
                                     && std::is_convertible<T, double>::value))
                                  && detail::is_comparable<T, U>::value,
                                int> = 0>
  bool operator()(const T& t, const U& u) const {
    auto x = static_cast<long double>(t);
    auto y = static_cast<long double>(u);
    auto max = std::max(std::abs(x), std::abs(y));
    auto dif = std::abs(x - y);
    return dif <= max * 1e-5l;
  }

  template <class T, class U,
            detail::enable_if_t<!((std::is_floating_point<T>::value
                                   && std::is_convertible<U, double>::value)
                                  || (std::is_floating_point<U>::value
                                      && std::is_convertible<T, double>::value))
                                  && detail::is_comparable<T, U>::value,
                                int> = 0>
  bool operator()(const T& x, const U& y) const {
    return x == y;
  }

  template <class T, class U,
            typename std::enable_if<!detail::is_comparable<T, U>::value,
                                    int>::type = 0>
  bool operator()(const T&, const U&) const {
    return default_value;
  }
};

struct inequality_operator {
  static constexpr bool default_value = true;

  template <class T, class U,
            typename std::enable_if<(std::is_floating_point<T>::value
                                     || std::is_floating_point<U>::value)
                                    && detail::is_comparable<T, U>::value,
                                    int>::type = 0>
  bool operator()(const T& x, const U& y) const {
    equality_operator f;
    return !f(x, y);
  }

  template <class T, class U,
            typename std::enable_if<!std::is_floating_point<T>::value
                                    && !std::is_floating_point<U>::value
                                    && detail::is_comparable<T, U>::value,
                                    int>::type = 0>
  bool operator()(const T& x, const U& y) const {
    return x != y;
  }

  template <class T, class U,
            typename std::enable_if<!detail::is_comparable<T, U>::value,
                                    int>::type = 0>
  bool operator()(const T&, const U&) const {
    return default_value;
  }
};

template <class F, class T>
struct comparison_unbox_helper {
  const F& f;
  const T& rhs;

  template <class U>
  bool operator()(const U& lhs) const {
    return f(lhs, rhs);
  }
};

template <class Operator>
class comparison {
public:
  // -- default case -----------------------------------------------------------

  template <class T, class U>
  bool operator()(const T& x, const U& y) const {
    std::integral_constant<bool, SumType<T>()> lhs_is_sum_type;
    std::integral_constant<bool, SumType<U>()> rhs_is_sum_type;
    return cmp(x, y, lhs_is_sum_type, rhs_is_sum_type);
  }

private:
  // -- automagic unboxing of sum types ----------------------------------------

  template <class T, class U>
  bool cmp(const T& x, const U& y, std::false_type, std::false_type) const {
    Operator f;
    return f(x, y);
  }

  template <class T, class U>
  bool cmp(const T& x, const U& y, std::true_type, std::false_type) const {
    Operator f;
    auto inner_x = caf::get_if<U>(&x);
    return inner_x ? f(*inner_x, y) : Operator::default_value;
  }

  template <class T, class U>
  bool cmp(const T& x, const U& y, std::false_type, std::true_type) const {
    Operator f;
    auto inner_y = caf::get_if<T>(&y);
    return inner_y ? f(x, *inner_y) : Operator::default_value;
  }

  template <class T, class U>
  bool cmp(const T& x, const U& y, std::true_type, std::true_type) const {
    comparison_unbox_helper<comparison, U> f{*this, y};
    return visit(f, x);
  }
};

using equal_to = comparison<equality_operator>;

using not_equal_to = comparison<inequality_operator>;

struct less_than {
  template <class T, class U>
  bool operator()(const T& x, const U& y) {
    return x < y;
  }
};

struct less_than_or_equal {
  template <class T, class U>
  bool operator()(const T& x, const U& y) {
    return x <= y;
  }
};

struct greater_than {
  template <class T, class U>
  bool operator()(const T& x, const U& y) {
    return x > y;
  }
};

struct greater_than_or_equal {
  template <class T, class U>
  bool operator()(const T& x, const U& y) {
    return x >= y;
  }
};

// -- Core components of the unit testing abstraction --------------------------

/// Default test-running function.
/// This function will be called automatically unless you define
/// `CAF_TEST_NO_MAIN` before including `caf/test/unit_test.hpp`. In
/// the latter case you will have to provide you own `main` function,
/// where you may want to call `caf::test::main` from.
int main(int argc, char** argv);

/// A sequence of *checks*.
class test {
public:
  test(std::string test_name, bool disabled_by_default);

  virtual ~test();

  size_t expected_failures() const;

  void pass();

  void fail(bool expected);

  const std::string& name() const;

  inline size_t good() {
    return good_;
  }

  inline size_t bad() {
    return bad_;
  }

  inline bool disabled() const noexcept {
    return disabled_;
  }

  virtual void run_test_impl() = 0;

private:
  size_t expected_failures_;
  std::string name_;
  size_t good_;
  size_t bad_;
  bool disabled_;
};

struct dummy_fixture { };

template <class T>
class test_impl : public test {
public:
  test_impl(std::string test_name, bool disabled_by_default)
      : test(std::move(test_name), disabled_by_default) {
    // nop
  }

  void run_test_impl() override {
    T impl;
    impl.run_test_impl();
  }
};

namespace detail {

[[noreturn]] void requirement_failed(const std::string& msg);

// constructs spacing given a line number.
const char* fill(size_t line);

void remove_trailing_spaces(std::string& x);

} // namespace detail

/// Logs messages for the test framework.
class logger {
public:
  enum class level : int {
    quiet   = 0,
    error   = 1,
    info    = 2,
    verbose = 3,
    massive = 4
  };

  static bool init(int lvl_cons, int lvl_file, const std::string& logfile);

  static logger& instance();

  template <class T>
  void log(level lvl, const T& x) {
    struct simple_fwd_t {
      const T& operator()(const T& y) const {
        return y;
      }
    };
    using fwd =
      typename std::conditional<
        std::is_same<char, T>::value
        || std::is_convertible<T, std::string>::value
        || std::is_same<caf::term, T>::value,
        simple_fwd_t,
        deep_to_string_t
      >::type;
    fwd f;
    auto y = f(x);
    if (lvl <= level_console_)
      *console_ << y;
    if (lvl <= level_file_)
      file_ << y;
  }

  inline void log(level lvl, const std::nullptr_t&) {
    log(lvl, "null");
  }

  /// Output stream for logging purposes.
  class stream {
  public:
    stream(logger& parent, level lvl);

    stream(const stream&) = default;

    struct reset_flags_t {};

    stream& operator<<(reset_flags_t) {
      return *this;
    }

    template <class T>
    stream& operator<<(const T& x) {
      parent_.log(lvl_, x);
      return *this;
    }

  private:
    logger& parent_;
    level lvl_;
  };

  stream error();
  stream info();
  stream verbose();
  stream massive();

  void disable_colors();

private:
  logger();

  level level_console_;
  level level_file_;
  std::ostream* console_;
  std::ofstream file_;
  std::ostringstream dummy_;
};

/// Drives unit test execution.
class engine {
public:
  /// Sets external command line arguments.
  /// @param argc The argument counter.
  /// @param argv The argument vectors.
  static void args(int argc, char** argv);

  /// Retrieves the argument counter.
  /// @returns The number of arguments set via ::args or 0.
  static int argc();

  /// Retrieves the argument vector.
  /// @returns The argument vector set via ::args or `nullptr`.
  static char** argv();

  /// Sets path of current executable.
  /// @param argv The path of current executable.
  static void path(char* argv);

  /// Retrieves the path of current executable
  /// @returns The path to executable set via ::path(char*) or `nullptr`.
  static char* path();

  /// Returns the maximum number of seconds a test case is allowed to run.
  static int max_runtime();

  /// Sets the maximum number of seconds a test case is
  /// allowed to run to `value`.
  static void max_runtime(int value);

  /// Adds a test to the engine.
  /// @param cstr_name The name of the suite.
  /// @param ptr The test to register.
  static void add(const char* cstr_name, std::unique_ptr<test> ptr);

  /// Invokes tests in all suites.
  /// @param colorize Whether to colorize the output.
  /// @param log_file The filename of the log output. The empty string means
  ///                 that no log file will be written.
  /// @param verbosity_console The log verbosity level on the console.
  /// @param verbosity_file The log verbosity level in the log file.
  /// @param suites_str Regular expression for including test suites.
  /// @param not_suites_str Regular expression for excluding test suites.
  /// @param tests_str Regular expression for individually selecting tests.
  /// @param not_tests_str Regular expression for individually disabling tests.
  /// @returns `true` iff all tests succeeded.
  static bool run(bool colorize,
                  const std::string& log_file,
                  int verbosity_console,
                  int verbosity_file,
                  const std::string& suites_str,
                  const std::string& not_suites_str,
                  const std::string& tests_str,
                  const std::string& not_tests_str);

  static const char* last_check_file();
  static void last_check_file(const char* file);

  static size_t last_check_line();
  static void last_check_line(size_t line);

  static test* current_test();

  static std::vector<std::string> available_suites();

  static std::vector<std::string> available_tests(const std::string& suite);

private:
  engine() = default;

  static engine& instance();

  static std::string render(std::chrono::microseconds t);

  int argc_ = 0;
  char** argv_ = nullptr;
  char*  path_ = nullptr;
  bool colorize_ = false;
  const char* check_file_ = "<none>";
  size_t check_line_ = 0;
  test* current_test_ = nullptr;
  std::map<std::string, std::vector<std::unique_ptr<test>>> suites_;
  int max_runtime_ = 30; // 30s per default
};

namespace detail {

template <class T>
struct adder {
  adder(const char* suite_name, const char* test_name, bool disabled) {
    engine::add(suite_name, std::unique_ptr<T>{new T(test_name, disabled)});
  }
};

bool check(test* parent, const char *file, size_t line,
           const char *expr, bool should_fail, bool result);

template <class T, class U>
bool check(test* parent, const char *file, size_t line,
           const char *expr, bool should_fail, bool result,
           const T& x, const U& y) {
  auto out = logger::instance().massive();
  if (result) {
    out << term::green << "** "
        << term::blue << file << term::yellow << ":"
        << term::blue << line << fill(line) << term::reset
        << expr << '\n';
    parent->pass();
  } else {
    out << term::red << "!! "
        << term::blue << file << term::yellow << ":"
        << term::blue << line << fill(line) << term::reset
        << expr << term::magenta << " ("
        << term::red << x << term::magenta
        << " !! " << term::red << y << term::magenta
        << ')' << term::reset_endl;
    parent->fail(should_fail);
  }
  return result;
}

} // namespace detail
} // namespace test
} // namespace caf

// on the global namespace so that it can hidden via namespace-scoping
using caf_test_case_auto_fixture = caf::test::dummy_fixture;

#define CAF_TEST_PRINT(level, msg, colorcode)                                  \
  (::caf::test::logger::instance().level()                                     \
   << ::caf::term::colorcode << "  -> " << ::caf::term::reset                  \
   << ::caf::test::logger::stream::reset_flags_t{} << msg << " [line "         \
   << __LINE__ << "]\n")

#define CAF_TEST_PRINT_ERROR(msg)   CAF_TEST_PRINT(info, msg, red)
#define CAF_TEST_PRINT_INFO(msg)    CAF_TEST_PRINT(info, msg, yellow)
#define CAF_TEST_PRINT_VERBOSE(msg) CAF_TEST_PRINT(verbose, msg, yellow)

#define CAF_PASTE_CONCAT(lhs, rhs) lhs ## rhs

#define CAF_PASTE(lhs, rhs) CAF_PASTE_CONCAT(lhs, rhs)

#define CAF_UNIQUE(name) CAF_PASTE(name, __LINE__)

#ifndef CAF_SUITE
#define CAF_SUITE unnamed
#endif

#define CAF_STR(s) #s

#define CAF_XSTR(s) CAF_STR(s)

#define CAF_FUNC_EXPR(func, x_expr, y_expr) #func "(" #x_expr ", " #y_expr ")"

#define CAF_ERROR(msg)                                                         \
  do {                                                                         \
    CAF_TEST_PRINT_ERROR(msg);                                                 \
    ::caf::test::engine::current_test()->fail(false);                          \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_CHECK_PASSED(msg)                                                  \
  do {                                                                         \
    auto out = ::caf::test::logger::instance().massive();                      \
    out << term::green << "** " << term::blue << __FILE__ << term::yellow      \
        << ":" << term::blue << __LINE__                                       \
        << ::caf::test::detail::fill(__LINE__) << term::reset << msg << '\n';  \
    ::caf::test::engine::current_test()->pass();                               \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_CHECK_FAILED(msg)                                                  \
  do {                                                                         \
    auto out = ::caf::test::logger::instance().massive();                      \
    out << term::red << "!! " << term::blue << __FILE__ << term::yellow << ":" \
        << term::blue << __LINE__ << ::caf::test::detail::fill(__LINE__)       \
        << term::reset << msg << '\n';                                         \
    ::caf::test::engine::current_test()->fail(false);                          \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_CHECK(...)                                                         \
  do {                                                                         \
    static_cast<void>(::caf::test::detail::check(                              \
      ::caf::test::engine::current_test(), __FILE__, __LINE__,                 \
      #__VA_ARGS__, false, static_cast<bool>(__VA_ARGS__)));                   \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while(false)

#define CAF_CHECK_FUNC(func, x_expr, y_expr)                                   \
  do {                                                                         \
    func comparator;                                                           \
    auto&& x_val___ = x_expr;                                                  \
    auto&& y_val___ = y_expr;                                                  \
    static_cast<void>(::caf::test::detail::check(                              \
      ::caf::test::engine::current_test(), __FILE__, __LINE__,                 \
      CAF_FUNC_EXPR(func, x_expr, y_expr), false,                              \
      comparator(x_val___, y_val___), x_val___, y_val___));                    \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_CHECK_FAIL(...)                                                    \
  do {                                                                         \
    static_cast<void>(::caf::test::detail::check(                              \
      ::caf::test::engine::current_test(), __FILE__, __LINE__,                 \
      #__VA_ARGS__, true, static_cast<bool>(__VA_ARGS__)));                    \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while(false)

#define CAF_FAIL(msg)                                                          \
  do {                                                                         \
    CAF_TEST_PRINT_ERROR(msg);                                                 \
    ::caf::test::engine::current_test()->fail(false);                          \
    ::caf::test::detail::requirement_failed("test failure");                   \
  } while (false)

#define CAF_REQUIRE(...)                                                       \
  do {                                                                         \
    auto CAF_UNIQUE(__result) = ::caf::test::detail::check(                    \
      ::caf::test::engine::current_test(), __FILE__, __LINE__, #__VA_ARGS__,   \
      false, static_cast<bool>(__VA_ARGS__));                                  \
    if (!CAF_UNIQUE(__result))                                                 \
      ::caf::test::detail::requirement_failed(#__VA_ARGS__);                   \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_REQUIRE_FUNC(func, x_expr, y_expr)                                 \
  do {                                                                         \
    func comparator;                                                           \
    auto&& x_val___ = x_expr;                                                  \
    auto&& y_val___ = y_expr;                                                  \
    auto CAF_UNIQUE(__result) = ::caf::test::detail::check(                    \
      ::caf::test::engine::current_test(), __FILE__, __LINE__,                 \
      CAF_FUNC_EXPR(func, x_expr, y_expr), false,                              \
      comparator(x_val___, y_val___), x_val___, y_val___);                     \
    if (!CAF_UNIQUE(__result))                                                 \
      ::caf::test::detail::requirement_failed(                                 \
        CAF_FUNC_EXPR(func, x_expr, y_expr));                                  \
    ::caf::test::engine::last_check_file(__FILE__);                            \
    ::caf::test::engine::last_check_line(__LINE__);                            \
  } while (false)

#define CAF_TEST_IMPL(name, disabled_by_default)                               \
  namespace {                                                                  \
  struct CAF_UNIQUE(test) : caf_test_case_auto_fixture {                       \
    void run_test_impl();                                                      \
  };                                                                           \
  ::caf::test::detail::adder<::caf::test::test_impl<CAF_UNIQUE(test)>>         \
    CAF_UNIQUE(a){CAF_XSTR(CAF_SUITE), CAF_XSTR(name), disabled_by_default};   \
  }                                                                            \
  void CAF_UNIQUE(test)::run_test_impl()

#define CAF_TEST(name) CAF_TEST_IMPL(name, false)

#define CAF_TEST_DISABLED(name) CAF_TEST_IMPL(name, true)

#define CAF_TEST_FIXTURE_SCOPE(scope_name, fixture_name)                       \
  namespace scope_name { using caf_test_case_auto_fixture = fixture_name ;

#define CAF_TEST_FIXTURE_SCOPE_END()                                           \
  } // namespace <scope_name>

// -- Convenience macros -------------------------------------------------------

#define CAF_MESSAGE(msg)                                                       \
  do {                                                                         \
    CAF_LOG_INFO(msg);                                                         \
    CAF_TEST_PRINT_VERBOSE(msg);                                               \
  } while (false)

// -- CAF_CHECK* predicate family ----------------------------------------------

#define CAF_CHECK_EQUAL(x, y)                                                  \
  CAF_CHECK_FUNC(::caf::test::equal_to, x, y)

#define CAF_CHECK_NOT_EQUAL(x, y)                                              \
  CAF_CHECK_FUNC(::caf::test::not_equal_to, x, y)

#define CAF_CHECK_LESS(x, y)                                                   \
  CAF_CHECK_FUNC(::caf::test::less_than, x, y)

#define CAF_CHECK_NOT_LESS(x, y)                                               \
  CAF_CHECK_FUNC(::caf::test::negated<::caf::test::less_than>, x, y)

#define CAF_CHECK_LESS_OR_EQUAL(x, y)                                          \
  CAF_CHECK_FUNC(::caf::test::less_than_or_equal, x, y)

#define CAF_CHECK_NOT_LESS_OR_EQUAL(x, y)                                      \
  CAF_CHECK_FUNC(::caf::test::negated<::caf::test::less_than_or_equal>, x, y)

#define CAF_CHECK_GREATER(x, y)                                                \
  CAF_CHECK_FUNC(::caf::test::greater_than, x, y)

#define CAF_CHECK_NOT_GREATER(x, y)                                            \
  CAF_CHECK_FUNC(::caf::test::negated<::caf::test::greater_than>, x, y)

#define CAF_CHECK_GREATER_OR_EQUAL(x, y)                                       \
  CAF_CHECK_FUNC(::caf::test::greater_than_or_equal, x, y)

#define CAF_CHECK_NOT_GREATER_OR_EQUAL(x, y)                                   \
  CAF_CHECK_FUNC(::caf::test::negated<::caf::test::greater_than_or_equal>, x, y)

// -- CAF_CHECK* predicate family ----------------------------------------------

#define CAF_REQUIRE_EQUAL(x, y)                                                \
  CAF_REQUIRE_FUNC(::caf::test::equal_to, x, y)

#define CAF_REQUIRE_NOT_EQUAL(x, y)                                            \
  CAF_REQUIRE_FUNC(::caf::test::not_equal_to, x, y)

#define CAF_REQUIRE_LESS(x, y)                                                 \
  CAF_REQUIRE_FUNC(::caf::test::less_than, x, y)

#define CAF_REQUIRE_NOT_LESS(x, y)                                             \
  CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::less_than>, x, y)

#define CAF_REQUIRE_LESS_OR_EQUAL(x, y)                                        \
  CAF_REQUIRE_FUNC(::caf::test::less_than_or_equal, x, y)

#define CAF_REQUIRE_NOT_LESS_OR_EQUAL(x, y)                                    \
  CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::less_than_or_equal>, x, y)

#define CAF_REQUIRE_GREATER(x, y)                                              \
  CAF_REQUIRE_FUNC(::caf::test::greater_than, x, y)

#define CAF_REQUIRE_NOT_GREATER(x, y)                                          \
  CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::greater_than>, x, y)

#define CAF_REQUIRE_GREATER_OR_EQUAL(x, y)                                     \
  CAF_REQUIRE_FUNC(::caf::test::greater_than_or_equal, x, y)

#define CAF_REQUIRE_NOT_GREATER_OR_EQUAL(x, y)                                 \
  CAF_REQUIRE_FUNC(::caf::test::negated<::caf::test::greater_than_or_equal>,   \
                   x, y)