GCC Code Coverage Report


Directory: include/tts/
File: include/tts/test/types.hpp
Date: 2026-10-14 16:28:14
Exec Total Coverage
Lines: 15 23 65.2%
Functions: 48 48 100.0%
Branches: 10 18 55.6%

Line Branch Exec Source
1 //======================================================================================================================
2 //! @file
3 /*
4 TTS - Tiny Test System
5 Copyright : TTS Contributors & Maintainers
6 SPDX-License-Identifier: BSL-1.0
7 */
8 //======================================================================================================================
9 #pragma once
10
11 #include <tts/engine/info.hpp>
12 #include <tts/engine/check.hpp>
13 #include <tts/tools/preprocessor.hpp>
14 #include <tts/tools/typename.hpp>
15 #include <tts/tools/types.hpp>
16
17 namespace tts::_
18 {
19 348 template<typename T, typename R> logger check_type(check_site const& site, bool expression)
20 {
21 if constexpr(std::is_same_v<T, R>)
22 {
23
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 173 times.
344 if(check_passed())
24 ✗ check_report(site,
25 expression
26 ✗ ? ::tts::text {"Expression: '%s' is of type '%s'.", site.lhs, site.rhs}
27 ✗ : ::tts::text {"Type: '%s' is '%s'.", site.lhs, site.rhs});
28 344 return logger {false};
29 }
30 else
31 {
32 4 char const* format = expression
33
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
4 ? "Expression: '%s' is not of type '%s' because '%.*s' is not '%.*s'."
34 : "Type: '%s' is not the same as '%s' because '%.*s' is not '%.*s'.";
35 8 return check_failed(site,
36 ::tts::text {format,
37 4 site.lhs,
38 4 site.rhs,
39 ::tts::typename_<T>.size(),
40 ::tts::typename_<T>.data(),
41 ::tts::typename_<R>.size(),
42
1/1
✓ Branch 1 taken 2 times.
8 ::tts::typename_<R>.data()});
43 }
44 ✗ }
45
46 11 inline logger check_compiles(bool compiles, bool expected, check_site const& site)
47 {
48
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 2 times.
11 if(compiles == expected)
49 {
50
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if(check_passed())
51 ✗ check_report(site,
52 ✗ ::tts::text {compiles ? "Expression: '%s' compiles as expected."
53 : "Expression: '%s' does not compile as expected.",
54 ✗ site.lhs});
55 9 return logger {false};
56 }
57
58 return check_failed(site,
59 2 ::tts::text {compiles ? "Expression: '%s' compiles unexpectedly."
60 : "Expression: '%s' does not compile as expected.",
61
3/3
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 4 taken 2 times.
2 site.lhs});
62 ✗ }
63 }
64
65 //======================================================================================================================
66 /**
67 @defgroup test-types Type Tests Macros
68 @brief Macros for performing checks on types and their properties.
69 @{
70 **/
71 //======================================================================================================================
72
73 //======================================================================================================================
74 /**
75 @def TTS_TYPE_IS
76 @brief Checks if two types satisfy `std::is_same_v<Type,Target> == true`.
77
78 @param TYPE Type to compare.
79 @param REF Expected type.
80 @param ... Optional tag. If equals to `REQUIRED`, this test will stop the program if it fails.
81
82 @groupheader{Example}
83 @snippet doc/type_is.cpp snippet
84
85 **/
86 //======================================================================================================================
87 #if defined(TTS_DOXYGEN_INVOKED)
88 #define TTS_TYPE_IS(TYPE, REF, ...)
89 #else
90 #define TTS_TYPE_IS(TYPE, REF, ...) TTS_TYPE_IS_##__VA_ARGS__(TYPE, REF)
91 #endif
92
93 #define TTS_TYPE_IS_(TYPE, REF) TTS_TYPE_IS_IMPL(TYPE, REF, TTS_FAIL)
94 #define TTS_TYPE_IS_REQUIRED(TYPE, REF) TTS_TYPE_IS_IMPL(TYPE, REF, TTS_FATAL)
95
96 #define TTS_TYPE_IS_IMPL(TYPE, REF, FAILURE) \
97 ::tts::_::check_type<TTS_REMOVE_PARENS(TYPE), TTS_REMOVE_PARENS(REF)>( \
98 TTS_CHECK_SITE( \
99 FAILURE, TTS_STRING(TTS_REMOVE_PARENS(TYPE)), "", TTS_STRING(TTS_REMOVE_PARENS(REF)), ""), \
100 false) /**/
101
102 //======================================================================================================================
103 /**
104 @def TTS_EXPR_IS
105 @brief Checks if an Expression evaluates to a value of a given Type.
106
107 @param EXPR Expression to evaluate.
108 @param TYPE Expected type.
109 @param ... Optional tag. If equals to `REQUIRED`, this test will stop the program if it fails.
110
111 @groupheader{Example}
112 @snippet doc/expr_is.cpp snippet
113 **/
114 //======================================================================================================================
115 #if defined(TTS_DOXYGEN_INVOKED)
116 #define TTS_EXPR_IS(EXPR, TYPE, ...)
117 #else
118 #define TTS_EXPR_IS(EXPR, TYPE, ...) TTS_EXPR_IS_##__VA_ARGS__(EXPR, TYPE)
119 #endif
120
121 #define TTS_EXPR_IS_(EXPR, TYPE) TTS_EXPR_IS_IMPL(EXPR, TYPE, TTS_FAIL)
122 #define TTS_EXPR_IS_REQUIRED(EXPR, TYPE) TTS_EXPR_IS_IMPL(EXPR, TYPE, TTS_FATAL)
123
124 #define TTS_EXPR_IS_IMPL(EXPR, TYPE, FAILURE) \
125 ::tts::_::check_type<decltype(TTS_REMOVE_PARENS(EXPR)), TTS_REMOVE_PARENS(TYPE)>( \
126 TTS_CHECK_SITE( \
127 FAILURE, TTS_STRING(TTS_REMOVE_PARENS(EXPR)), "", TTS_STRING(TTS_REMOVE_PARENS(TYPE)), ""), \
128 true) /**/
129
130 #define TTS_EXPECT_COMPILES_IMPL(EXPR, ...) \
131 TTS_DISABLE_WARNING_PUSH \
132 TTS_DISABLE_WARNING_SHADOW \
133 [ & ](TTS_ARG(__VA_ARGS__)) \
134 { \
135 return ::tts::_::check_compiles( \
136 requires TTS_REMOVE_PARENS(EXPR), \
137 true, \
138 TTS_CHECK_SITE(TTS_FAIL, TTS_STRING(TTS_REMOVE_PARENS(EXPR)), "", "", "")); \
139 TTS_DISABLE_WARNING_POP \
140 }(__VA_ARGS__) /**/
141
142 //======================================================================================================================
143 /**
144 @def TTS_EXPECT_COMPILES
145 @brief Checks if an `Expression` based on a list of `Symbols` will compile properly in a SFINAE
146 context.
147
148 @param Symbols Variadic lists of symbols used in the tests
149 @param Expression Brace-enclosed expression to validate.
150
151 @groupheader{Example}
152 @snippet doc/expect_compiles.cpp snippet
153 **/
154 //======================================================================================================================
155 #if defined(TTS_DOXYGEN_INVOKED)
156 #define TTS_EXPECT_COMPILES(Symbols, Expression, ...)
157 #else
158 #define TTS_EXPECT_COMPILES(...) TTS_VAL(TTS_EXPECT_COMPILES_IMPL TTS_REVERSE(__VA_ARGS__))
159 #endif
160
161 #define TTS_EXPECT_NOT_COMPILES_IMPL(EXPR, ...) \
162 TTS_DISABLE_WARNING_PUSH \
163 TTS_DISABLE_WARNING_SHADOW \
164 [ & ](TTS_ARG(__VA_ARGS__)) \
165 { \
166 return ::tts::_::check_compiles( \
167 requires TTS_REMOVE_PARENS(EXPR), \
168 false, \
169 TTS_CHECK_SITE(TTS_FAIL, TTS_STRING(TTS_REMOVE_PARENS(EXPR)), "", "", "")); \
170 TTS_DISABLE_WARNING_POP \
171 }(__VA_ARGS__) /**/
172
173 //======================================================================================================================
174 /**
175 @def TTS_EXPECT_NOT_COMPILES
176 @brief Checks if an `Expression` based on a list of `Symbols` will not compile properly in a
177 SFINAE context.
178
179 @param Symbols Variadic lists of symbols used in the tests
180 @param Expression Brace-enclosed expression to validate.
181
182 @groupheader{Example}
183 @snippet doc/expect_not_compiles.cpp snippet
184 **/
185 //======================================================================================================================
186 #if defined(TTS_DOXYGEN_INVOKED)
187 #define TTS_EXPECT_NOT_COMPILES(Symbols..., Expression, ...)
188 #else
189 #define TTS_EXPECT_NOT_COMPILES(...) TTS_VAL(TTS_EXPECT_NOT_COMPILES_IMPL TTS_REVERSE(__VA_ARGS__))
190 #endif
191
192 //======================================================================================================================
193 /// @}
194 //======================================================================================================================
195