micro-test-plus 3.2.2
The µTest++ Testing Framework
Loading...
Searching...
No Matches
detail.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2021 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 *
11 * Major parts of the code are inspired from v1.1.8 of the Boost UT project,
12 * released under the terms of the Boost Version 1.0 Software License,
13 * which can be obtained from https://www.boost.org/LICENSE_1_0.txt.
14 */
15
16#ifndef MICRO_TEST_PLUS_DETAIL_H_
17#define MICRO_TEST_PLUS_DETAIL_H_
18
19// ----------------------------------------------------------------------------
20
21#ifdef __cplusplus
22
23// ----------------------------------------------------------------------------
24
25#include <stdio.h>
26
27// ----------------------------------------------------------------------------
28
29#if defined(__GNUC__)
30#pragma GCC diagnostic push
31#pragma GCC diagnostic ignored "-Wpadded"
32#pragma GCC diagnostic ignored "-Waggregate-return"
33#if defined(__clang__)
34#pragma clang diagnostic ignored "-Wc++98-compat"
35#endif
36#endif
37
39{
40 // --------------------------------------------------------------------------
41
45 namespace detail
46 {
51 template <class Expr_T>
57
58 // ------------------------------------------------------------------------
59
65 template <class T>
66 [[nodiscard]] constexpr auto
67 get_impl (const T& t, int) -> decltype (t.get ())
68 {
69 return t.get ();
70 }
71
76 template <class T>
77 [[nodiscard]] constexpr auto
78 get_impl (const T& t, ...) -> decltype (auto)
79 {
80 return t;
81 }
82
86 template <class T>
87 [[nodiscard]] constexpr auto
88 get (const T& t)
89 {
90 // Call the variadic function, basically to force it return `t`.
91 return get_impl (t, 0);
92 }
93
94 // ------------------------------------------------------------------------
95
100 template <class Lhs_T, class Rhs_T>
102 {
103 constexpr eq_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
104 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
105 // This lambda is called in the constructor to
106 // evaluate the comparison.
107 using std::operator==;
108 using std::operator<;
109
110#if defined(__GNUC__)
111#pragma GCC diagnostic push
112#pragma GCC diagnostic ignored "-Wfloat-equal"
113#pragma GCC diagnostic ignored "-Wconversion"
114#pragma GCC diagnostic ignored "-Wdouble-promotion"
115#pragma GCC diagnostic ignored "-Wsign-compare"
116#if defined(__clang__)
117#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
118#pragma clang diagnostic ignored "-Wpedantic"
119#endif
120#endif
123 {
124 // If both types have values (like numeric constants),
125 // compare them directly.
126 return Lhs_T::value == Rhs_T::value;
127 }
128 else if constexpr (type_traits::has_epsilon_v<Lhs_T>
130 {
131 // If both values have precision, compare them using
132 // the smalles precision.
133 return math::abs (get (lhs) - get (rhs))
134 < math::min_value (Lhs_T::epsilon, Rhs_T::epsilon);
135 }
136 else if constexpr (type_traits::has_epsilon_v<Lhs_T>)
137 {
138 // If only the left operand has precision, use it.
139 return math::abs (get (lhs) - get (rhs)) < Lhs_T::epsilon;
140 }
141 else if constexpr (type_traits::has_epsilon_v<Rhs_T>)
142 {
143 // If only the right operand has precision, use it.
144 return math::abs (get (lhs) - get (rhs)) < Rhs_T::epsilon;
145 }
146 else
147 {
148 // Call the generic getters, which might
149 // either call the type get() or return the value.
150 return get (lhs) == get (rhs);
151 }
152#if defined(__GNUC__)
153#pragma GCC diagnostic pop
154#endif
155 }() }
156 {
157 }
158
159 [[nodiscard]] constexpr
160 operator bool () const
161 {
162 return value_;
163 }
164
165 [[nodiscard]] constexpr auto
166 lhs () const
167 {
168 return get (lhs_);
169 }
170
171 [[nodiscard]] constexpr auto
172 rhs () const
173 {
174 return get (rhs_);
175 }
176
177 const Lhs_T lhs_{};
178 const Rhs_T rhs_{};
179 const bool value_{};
180 };
181
186 template <class Lhs_T, class Rhs_T>
188 {
189 constexpr ne_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
190 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
191 using std::operator==;
192 using std::operator!=;
193 using std::operator>;
194
195#if defined(__GNUC__)
196#pragma GCC diagnostic push
197#pragma GCC diagnostic ignored "-Wfloat-equal"
198#pragma GCC diagnostic ignored "-Wconversion"
199#pragma GCC diagnostic ignored "-Wdouble-promotion"
200#pragma GCC diagnostic ignored "-Wsign-compare"
201#if defined(__clang__)
202#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
203#pragma clang diagnostic ignored "-Wpedantic"
204#endif
205#endif
208 {
209 return Lhs_T::value != Rhs_T::value;
210 }
211 else if constexpr (type_traits::has_epsilon_v<Lhs_T>
212 and type_traits::has_epsilon_v<Rhs_T>)
213 {
214 return math::abs (get (lhs_) - get (rhs_))
215 > math::min_value (Lhs_T::epsilon, Rhs_T::epsilon);
216 }
217 else if constexpr (type_traits::has_epsilon_v<Lhs_T>)
218 {
219 return math::abs (get (lhs_) - get (rhs_)) > Lhs_T::epsilon;
220 }
221 else if constexpr (type_traits::has_epsilon_v<Rhs_T>)
222 {
223 return math::abs (get (lhs_) - get (rhs_)) > Rhs_T::epsilon;
224 }
225 else
226 {
227 return get (lhs_) != get (rhs_);
228 }
229#if defined(__GNUC__)
230#pragma GCC diagnostic pop
231#endif
232 }() }
233 {
234 }
235
236 [[nodiscard]] constexpr
237 operator bool () const
238 {
239 return value_;
240 }
241 [[nodiscard]] constexpr auto
242 lhs () const
243 {
244 return get (lhs_);
245 }
246 [[nodiscard]] constexpr auto
247 rhs () const
248 {
249 return get (rhs_);
250 }
251
252 const Lhs_T lhs_{};
253 const Rhs_T rhs_{};
254 const bool value_{};
255 };
256
261 template <class Lhs_T, class Rhs_T>
263 {
264 constexpr gt_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
265 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
266 using std::operator>;
267
268#if defined(__GNUC__)
269#pragma GCC diagnostic push
270#pragma GCC diagnostic ignored "-Wconversion"
271#pragma GCC diagnostic ignored "-Wdouble-promotion"
272#pragma GCC diagnostic ignored "-Wsign-compare"
273#if defined(__clang__)
274#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
275#pragma clang diagnostic ignored "-Wpedantic"
276#endif
277#endif
280 {
281 return Lhs_T::value > Rhs_T::value;
282 }
283 else
284 {
285 return get (lhs_) > get (rhs_);
286 }
287#if defined(__GNUC__)
288#pragma GCC diagnostic pop
289#endif
290 }() }
291 {
292 }
293
294 [[nodiscard]] constexpr
295 operator bool () const
296 {
297 return value_;
298 }
299 [[nodiscard]] constexpr auto
300 lhs () const
301 {
302 return get (lhs_);
303 }
304 [[nodiscard]] constexpr auto
305 rhs () const
306 {
307 return get (rhs_);
308 }
309
310 const Lhs_T lhs_{};
311 const Rhs_T rhs_{};
312 const bool value_{};
313 };
314
319 template <class Lhs_T, class Rhs_T>
321 {
322 constexpr ge_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
323 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
324 using std::operator>=;
325
326#if defined(__GNUC__)
327#pragma GCC diagnostic push
328#pragma GCC diagnostic ignored "-Wconversion"
329#pragma GCC diagnostic ignored "-Wdouble-promotion"
330#pragma GCC diagnostic ignored "-Wsign-compare"
331#if defined(__clang__)
332#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
333#pragma clang diagnostic ignored "-Wpedantic"
334#endif
335#endif
338 {
339 return Lhs_T::value >= Rhs_T::value;
340 }
341 else
342 {
343 return get (lhs_) >= get (rhs_);
344 }
345#if defined(__GNUC__)
346#pragma GCC diagnostic pop
347#endif
348 }() }
349 {
350 }
351
352 [[nodiscard]] constexpr
353 operator bool () const
354 {
355 return value_;
356 }
357 [[nodiscard]] constexpr auto
358 lhs () const
359 {
360 return get (lhs_);
361 }
362 [[nodiscard]] constexpr auto
363 rhs () const
364 {
365 return get (rhs_);
366 }
367
368 const Lhs_T lhs_{};
369 const Rhs_T rhs_{};
370 const bool value_{};
371 };
372
377 template <class Lhs_T, class Rhs_T>
379 {
380 constexpr lt_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
381 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
382 using std::operator<;
383
384#if defined(__GNUC__)
385#pragma GCC diagnostic push
386#pragma GCC diagnostic ignored "-Wconversion"
387#pragma GCC diagnostic ignored "-Wdouble-promotion"
388#pragma GCC diagnostic ignored "-Wsign-compare"
389#if defined(__clang__)
390#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
391#pragma clang diagnostic ignored "-Wpedantic"
392#endif
393#endif
396 {
397 return Lhs_T::value < Rhs_T::value;
398 }
399 else
400 {
401 return get (lhs_) < get (rhs_);
402 }
403#if defined(__GNUC__)
404#pragma GCC diagnostic pop
405#endif
406 }() }
407 {
408 }
409
410 [[nodiscard]] constexpr
411 operator bool () const
412 {
413 return value_;
414 }
415 [[nodiscard]] constexpr auto
416 lhs () const
417 {
418 return get (lhs_);
419 }
420 [[nodiscard]] constexpr auto
421 rhs () const
422 {
423 return get (rhs_);
424 }
425
426 private:
427 const Lhs_T lhs_{};
428 const Rhs_T rhs_{};
429 const bool value_{};
430 };
431
436 template <class Lhs_T, class Rhs_T>
438 {
439 constexpr le_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
440 : lhs_{ lhs }, rhs_{ rhs }, value_{ [&] {
441 using std::operator<=;
442
443#if defined(__GNUC__)
444#pragma GCC diagnostic push
445#pragma GCC diagnostic ignored "-Wconversion"
446#pragma GCC diagnostic ignored "-Wdouble-promotion"
447#pragma GCC diagnostic ignored "-Wsign-compare"
448#if defined(__clang__)
449#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"
450#pragma clang diagnostic ignored "-Wpedantic"
451#endif
452#endif
455 {
456 return Lhs_T::value <= Rhs_T::value;
457 }
458 else
459 {
460 return get (lhs_) <= get (rhs_);
461 }
462#if defined(__GNUC__)
463#pragma GCC diagnostic pop
464#endif
465 }() }
466 {
467 }
468
469 [[nodiscard]] constexpr
470 operator bool () const
471 {
472 return value_;
473 }
474
475 [[nodiscard]] constexpr auto
476 lhs () const
477 {
478 return get (lhs_);
479 }
480
481 [[nodiscard]] constexpr auto
482 rhs () const
483 {
484 return get (rhs_);
485 }
486
487 const Lhs_T lhs_{};
488 const Rhs_T rhs_{};
489 const bool value_{};
490 };
491
496 template <class Lhs_T, class Rhs_T>
498 {
499 constexpr and_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
500 : lhs_{ lhs }, rhs_{ rhs },
501 value_{ static_cast<bool> (lhs) and static_cast<bool> (rhs) }
502 {
503 }
504
505 [[nodiscard]] constexpr
506 operator bool () const
507 {
508 return value_;
509 }
510
511 [[nodiscard]] constexpr auto
512 lhs () const
513 {
514 return get (lhs_);
515 }
516
517 [[nodiscard]] constexpr auto
518 rhs () const
519 {
520 return get (rhs_);
521 }
522
523 const Lhs_T lhs_{};
524 const Rhs_T rhs_{};
525 const bool value_{};
526 };
527
532 template <class Lhs_T, class Rhs_T>
534 {
535 constexpr or_ (const Lhs_T& lhs = {}, const Rhs_T& rhs = {})
536 : lhs_{ lhs }, rhs_{ rhs },
537 value_{ static_cast<bool> (lhs) or static_cast<bool> (rhs) }
538 {
539 }
540
541 [[nodiscard]] constexpr
542 operator bool () const
543 {
544 return value_;
545 }
546
547 [[nodiscard]] constexpr auto
548 lhs () const
549 {
550 return get (lhs_);
551 }
552
553 [[nodiscard]] constexpr auto
554 rhs () const
555 {
556 return get (rhs_);
557 }
558
559 const Lhs_T lhs_{};
560 const Rhs_T rhs_{};
561 const bool value_{};
562 };
563
568 template <class T>
570 {
571 explicit constexpr not_ (const T& t = {})
572 : t_{ t }, value_{ not static_cast<bool> (t) }
573 {
574 }
575
576 [[nodiscard]] constexpr
577 operator bool () const
578 {
579 return value_;
580 }
581
582 [[nodiscard]] constexpr auto
583 value () const
584 {
585 return get (t_);
586 }
587
588 const T t_{};
589 const bool value_{};
590 };
591
592#if defined(__cpp_exceptions)
597 template <class Callable_T, class Exception_T = void>
599 {
600 constexpr explicit throws_ (const Callable_T& func)
601 : value_{ [&func] {
602 try
603 {
604 func ();
605 }
606 catch (const Exception_T&)
607 {
608 return true;
609 }
610 catch (...)
611 {
612 return false;
613 }
614 return false;
615 }() }
616 {
617 }
618
619 [[nodiscard]] constexpr
620 operator bool () const
621 {
622 return value_;
623 }
624
625 const bool value_{};
626 };
627
632 template <class Callable_T>
633 struct throws_<Callable_T, void> : type_traits::op
634 {
635 constexpr explicit throws_ (const Callable_T& func)
636 : value_{ [&func] {
637 try
638 {
639 func ();
640 }
641 catch (...)
642 {
643 return true;
644 }
645 return false;
646 }() }
647 {
648 }
649
650 [[nodiscard]] constexpr
651 operator bool () const
652 {
653 return value_;
654 }
655
656 const bool value_{};
657 };
658
663 template <class Callable_T>
665 {
666 constexpr explicit nothrow_ (const Callable_T& func)
667 : value_{ [&func] {
668 try
669 {
670 func ();
671 }
672 catch (...)
673 {
674 return false;
675 }
676 return true;
677 }() }
678 {
679 }
680
681 [[nodiscard]] constexpr
682 operator bool () const
683 {
684 return value_;
685 }
686
687 const bool value_{};
688 };
689#endif
690
691 // ------------------------------------------------------------------------
692
699 {
700 public:
702 const reflection::source_location location);
703
705
706 template <class T>
707 auto&
708 operator<< (const T& msg);
709
710 [[nodiscard]] constexpr bool
711 value () const
712 {
713 return value_;
714 }
715
716 protected:
717 bool value_{};
718 bool abort_ = false;
720
725 std::string message_{};
726 };
727
733 template <class Expr_T>
735 {
736 public:
737 constexpr explicit deferred_reporter (
738 const Expr_T& expr, bool abort,
739 const reflection::source_location& location);
740
742
743 protected:
744 const Expr_T expr_{};
745 };
746
747 // ----------------------------------------------------------------------
748 } // namespace detail
749
750 // --------------------------------------------------------------------------
751} // namespace micro_os_plus::micro_test_plus
752
753#if defined(__GNUC__)
754#pragma GCC diagnostic pop
755#endif
756
757// ----------------------------------------------------------------------------
758
759#endif // __cplusplus
760
761// ----------------------------------------------------------------------------
762
763#endif // MICRO_TEST_PLUS_DETAIL_H_
764
765// ----------------------------------------------------------------------------
std::string message_
String to collect the expectation message passed via operator<<().
Definition detail.h:725
deferred_reporter_base(bool value, const reflection::source_location location)
constexpr deferred_reporter(const Expr_T &expr, bool abort, const reflection::source_location &location)
Definition inlines.h:127
Local implementation of the std::source_location.
Definition reflection.h:57
Namespace with implementation details, not part of the public API.
Definition detail.h:46
constexpr auto get_impl(const T &t, int) -> decltype(t.get())
Generic getter implementation. If the type has a get() method, call it. It is recommended for custom ...
Definition detail.h:67
constexpr auto get(const T &t)
Generic getter, calling the getter implementation.
Definition detail.h:88
constexpr auto abs(const T t) -> T
Generic absolute of any value.
Definition math.h:55
constexpr auto min_value(const T &lhs, const T &rhs) -> const T &
Generic minimum of two values.
Definition math.h:65
constexpr and_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:499
An object used to pass assertion parameters to the evaluator.
Definition detail.h:53
reflection::source_location location
Definition detail.h:55
constexpr eq_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:103
constexpr ge_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:322
constexpr gt_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:264
constexpr le_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:439
constexpr lt_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:380
constexpr ne_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:189
constexpr nothrow_(const Callable_T &func)
Definition detail.h:666
constexpr or_(const Lhs_T &lhs={}, const Rhs_T &rhs={})
Definition detail.h:535
constexpr throws_(const Callable_T &func)
Definition detail.h:600
Empty base class of all operators.