Sequoia
Loading...
Searching...
No Matches
Output.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2020. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
16#include "sequoia/PlatformSpecific/Preprocessor.hpp"
17
18#include <cmath>
19#include <filesystem>
20#include <source_location>
21
22namespace sequoia::testing
23{
25 {
26 public:
27 constexpr line_breaks() = default;
28
29 constexpr explicit line_breaks(std::size_t n) : m_Breaks{n}
30 {}
31
32 [[nodiscard]]
33 constexpr std::size_t value() const noexcept
34 {
35 return m_Breaks;
36 }
37 private:
38 std::size_t m_Breaks{};
39 };
40
41 [[nodiscard]]
42 consteval line_breaks operator ""_linebreaks(unsigned long long int n) noexcept
43 {
44 return line_breaks{static_cast<std::size_t>(n)};
45 }
46
47 [[nodiscard]]
48 std::string emphasise(std::string_view s);
49
50 template<class Char>
51 inline constexpr bool is_character_v{
52 std::is_same_v<std::remove_cvref_t<Char>, char>
53 || std::is_same_v<std::remove_cvref_t<Char>, wchar_t>
54 || std::is_same_v<std::remove_cvref_t<Char>, char8_t>
55 || std::is_same_v<std::remove_cvref_t<Char>, char16_t>
56 || std::is_same_v<std::remove_cvref_t<Char>, char32_t>
57 };
58
59 template<class Char>
60 requires is_character_v<Char>
61 [[nodiscard]]
62 std::string display_character(Char c)
63 {
64 if(c == '\a') return "'\\a'";
65 if(c == '\b') return "'\\b'";
66 if(c == '\f') return "'\\f'";
67 if(c == '\n') return "'\\n'";
68 if(c == '\r') return "'\\r'";
69 if(c == '\t') return "'\\t'";
70 if(c == '\v') return "'\\v'";
71 if(c == '\0') return "'\\0'";
72 if(c == ' ') return "' '";
73
74 return std::string(1, static_cast<char>(c));
75 }
76
77 void end_block(std::string& s, line_breaks newlines, std::string_view footer="");
78
79 [[nodiscard]]
80 std::string end_block(std::string_view s, line_breaks newlines, std::string_view footer="");
81
82 [[nodiscard]]
83 std::string exception_message(std::string_view tag,
84 const std::filesystem::path& filename,
85 const uncaught_exception_info& info,
86 std::string_view exceptionMessage);
87
88 [[nodiscard]]
89 std::string operator_message(std::string_view op, std::string_view retVal);
90
91 [[nodiscard]]
92 std::string nullable_type_message(bool obtainedHoldsValue, bool predictedHoldsValue);
93
94 [[nodiscard]]
95 std::string equality_operator_failure_message();
96
97 [[nodiscard]]
98 std::string pointer_prediction_message();
99
100 [[nodiscard]]
101 std::string default_prediction_message(std::string_view obtained, std::string_view prediction);
102
103 [[nodiscard]]
104 std::string prediction_message(const std::string& obtained, const std::string& prediction);
105
106 template<class Char>
107 requires is_character_v<Char>
108 [[nodiscard]]
109 std::string prediction_message(Char obtained, Char prediction)
110 {
111 return prediction_message(display_character(obtained), display_character(prediction));
112 }
113
114 template<class Ptr>
115 requires std::is_pointer_v<Ptr> || is_const_pointer_v<Ptr>
116 [[nodiscard]]
117 std::string prediction_message(Ptr obtained, Ptr prediction)
118 {
119 return (obtained && prediction) ? pointer_prediction_message() : nullable_type_message(obtained, prediction);
120 }
121
122 template<serializable T>
123 requires (!is_character_v<T> && !std::is_pointer_v<T> && !is_const_pointer_v<T>)
124 [[nodiscard]]
125 std::string prediction_message(const T& obtained, const T& prediction)
126 {
127 return default_prediction_message(to_string(obtained), to_string(prediction));
128 }
129
130 template<bool IsFinalMessage>
131 struct final_message_constant : std::bool_constant<IsFinalMessage> {};
132
135
136 inline constexpr is_final_message_t is_final_message{};
137 inline constexpr is_not_final_message_t is_not_final_message{};
138
139 template<class T>
140 concept reportable = serializable<T> || is_character_v<T>;
141
143 template<reportable T>
144 requires std::is_same_v<T, bool>
145 [[nodiscard]]
147 {
148 return "check failed";
149 }
150
151 template<reportable T>
152 requires (!std::is_same_v<T, bool>)
153 [[nodiscard]]
154 std::string failure_message(is_final_message_t, const T& obtained, const T& prediction)
155 {
156 auto message{equality_operator_failure_message()};
157
158 append_lines(message, prediction_message(obtained, prediction));
159
160 return message;
161 }
162
163 template<class T>
164 [[nodiscard]]
165 std::string failure_message(is_not_final_message_t, const T&, const T&)
166 {
167 return equality_operator_failure_message();
168 }
169
170 [[nodiscard]]
171 std::string footer();
172
173 [[nodiscard]]
174 std::string instability_footer();
175
176 [[nodiscard]]
177 std::string report_line(std::string_view message, const std::filesystem::path& repository, const std::source_location loc);
178
179 [[nodiscard]]
180 std::filesystem::path path_for_reporting(const std::filesystem::path& file, const std::filesystem::path& repository);
181
183 inline constexpr no_source_location_t no_source_location{};
184
186 {
187 public:
188 reporter(const char* message, const std::source_location loc = std::source_location::current())
189 : reporter{std::string{message},loc}
190 {}
191
192 reporter(std::string_view message, const std::source_location loc = std::source_location::current())
193 : reporter{std::string{message},loc}
194 {}
195
196 reporter(std::string message, const std::source_location loc = std::source_location::current())
197 : m_Message{std::move(message)}
198 , m_Loc{loc}
199 {}
200
201 reporter(std::string message, no_source_location_t)
202 : m_Message{std::move(message)}
203 {}
204
205 reporter(std::string_view message, no_source_location_t)
206 : reporter{std::string{message}, no_source_location}
207 {}
208
209 [[nodiscard]]
210 const std::string& message() const noexcept { return m_Message; }
211
212 [[nodiscard]]
213 const std::optional<std::source_location>& location() const noexcept { return m_Loc; }
214 private:
215 std::string m_Message{};
216 std::optional<std::source_location> m_Loc{};
217 };
218
219 [[nodiscard]]
220 std::string tidy_name(std::string name, clang_type);
221
222 [[nodiscard]]
223 std::string tidy_name(std::string name, gcc_type);
224
225 [[nodiscard]]
226 std::string tidy_name(std::string name, msvc_type);
227
228 [[nodiscard]]
229 std::string tidy_name(std::string name, other_compiler_type);
230
231 [[nodiscard]]
232 std::string demangle(std::string mangled);
233
234 template<class T, invocable_r<std::string, std::string> Tidy>
235 [[nodiscard]]
236 std::string demangle(Tidy tidy)
237 {
238 return tidy(demangle({typeid(T).name()}));
239 }
240
241 template<class T>
242 [[nodiscard]]
243 std::string demangle()
244 {
245 return demangle<type_normalizer_t<T>>([](std::string name) -> std::string { return tidy_name(name, compiler_constant{}); });
246 }
247
254 template<class T>
256 {
257 [[nodiscard]]
258 static std::string make()
259 {
260 return demangle<T>();
261 }
262 };
263
264
266 template<class T, class... U>
268 {
269 [[nodiscard]]
270 static std::string make()
271 {
272 auto info{type_demangler<T>::make()};
273 if constexpr(sizeof...(U) > 0)
274 {
275 info += ',';
276 append_lines(info, type_list_demangler<U...>::make());
277 }
278
279 return info;
280 }
281 };
282
283 template<class T, class... U>
284 [[nodiscard]]
285 std::string make_type_info()
286 {
287 return std::string{"["}.append(type_list_demangler<T, U...>::make()).append("]");
288 }
289
290 template<class T, class... U>
291 [[nodiscard]]
292 std::string add_type_info(std::string description)
293 {
294 return append_lines(std::move(description), make_type_info<T, U...>());
295 }
296}
Core declarations / definitions used in the testing framework.
A collection of functions for formatting test output.
std::string failure_message(is_final_message_t, T, T)
To prevent implicit conversions to bool.
Definition: Output.hpp:146
Definition: Output.hpp:25
Definition: Output.hpp:186
Definition: Output.hpp:140
Definition: CoreInfrastructure.hpp:54
Definition: Output.hpp:182
Specialize this struct template to customize the way in which type info is generated for a given clas...
Definition: Output.hpp:256
Demangles T; if U... is not empty, appends each demangled element of U on a new line.
Definition: Output.hpp:268