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
142 template<reportable T>
143 [[nodiscard]]
144 std::string failure_message(is_final_message_t, const T& obtained, const T& prediction)
145 {
146 auto message{equality_operator_failure_message()};
147
148 append_lines(message, prediction_message(obtained, prediction));
149
150 return message;
151 }
152
153 template<class T>
154 [[nodiscard]]
155 std::string failure_message(is_not_final_message_t, const T&, const T&)
156 {
157 return equality_operator_failure_message();
158 }
159
160 [[nodiscard]]
161 std::string footer();
162
163 [[nodiscard]]
164 std::string instability_footer();
165
166 [[nodiscard]]
167 std::string report_line(std::string_view message, const std::filesystem::path& repository, const std::source_location loc);
168
169 [[nodiscard]]
170 std::filesystem::path path_for_reporting(const std::filesystem::path& file, const std::filesystem::path& repository);
171
173 inline constexpr no_source_location_t no_source_location{};
174
176 {
177 public:
178 reporter(const char* message, const std::source_location loc = std::source_location::current())
179 : reporter{std::string{message},loc}
180 {}
181
182 reporter(std::string_view message, const std::source_location loc = std::source_location::current())
183 : reporter{std::string{message},loc}
184 {}
185
186 reporter(std::string message, const std::source_location loc = std::source_location::current())
187 : m_Message{std::move(message)}
188 , m_Loc{loc}
189 {}
190
191 reporter(std::string message, no_source_location_t)
192 : m_Message{std::move(message)}
193 {}
194
195 reporter(std::string_view message, no_source_location_t)
196 : reporter{std::string{message}, no_source_location}
197 {}
198
199 [[nodiscard]]
200 const std::string& message() const noexcept { return m_Message; }
201
202 [[nodiscard]]
203 const std::optional<std::source_location>& location() const noexcept { return m_Loc; }
204 private:
205 std::string m_Message{};
206 std::optional<std::source_location> m_Loc{};
207 };
208
209 [[nodiscard]]
210 std::string tidy_name(std::string name, clang_type);
211
212 [[nodiscard]]
213 std::string tidy_name(std::string name, gcc_type);
214
215 [[nodiscard]]
216 std::string tidy_name(std::string name, msvc_type);
217
218 [[nodiscard]]
219 std::string tidy_name(std::string name, other_compiler_type);
220
221 [[nodiscard]]
222 std::string demangle(std::string mangled);
223
224 template<class T, invocable_r<std::string, std::string> Tidy>
225 [[nodiscard]]
226 std::string demangle(Tidy tidy)
227 {
228 return tidy(demangle({typeid(T).name()}));
229 }
230
231 template<class T>
232 [[nodiscard]]
233 std::string demangle()
234 {
235 return demangle<type_normalizer_t<T>>([](std::string name) -> std::string { return tidy_name(name, compiler_constant{}); });
236 }
237
244 template<class T>
246 {
247 [[nodiscard]]
248 static std::string make()
249 {
250 return demangle<T>();
251 }
252 };
253
254
256 template<class T, class... U>
258 {
259 [[nodiscard]]
260 static std::string make()
261 {
262 auto info{type_demangler<T>::make()};
263 if constexpr(sizeof...(U) > 0)
264 {
265 info += ',';
266 append_lines(info, type_list_demangler<U...>::make());
267 }
268
269 return info;
270 }
271 };
272
273 template<class T, class... U>
274 [[nodiscard]]
275 std::string make_type_info()
276 {
277 return std::string{"["}.append(type_list_demangler<T, U...>::make()).append("]");
278 }
279
280 template<class T, class... U>
281 [[nodiscard]]
282 std::string add_type_info(std::string description)
283 {
284 return append_lines(std::move(description), make_type_info<T, U...>());
285 }
286}
Core declarations / definitions used in the testing framework.
A collection of functions for formatting test output.
Definition: Output.hpp:25
Definition: Output.hpp:176
Definition: Output.hpp:140
Definition: CoreInfrastructure.hpp:54
Definition: Output.hpp:172
Specialize this struct template to customize the way in which type info is generated for a given clas...
Definition: Output.hpp:246
Demangles T; if U... is not empty, appends each demangled element of U on a new line.
Definition: Output.hpp:258