StormByte 2.0.0
C++26 foundation of the StormByte suite
 
Loading...
Searching...
No Matches
test_handlers.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2024-2026 David C. Manuelda (StormBytePP)
3 *
4 * This file is part of StormByte.
5 *
6 * StormByte original source is dual-licensed:
7 *
8 * 1. GNU Lesser General Public License v3.0 (or later)
9 * You may redistribute and/or modify this file under the terms of the
10 * GNU Lesser General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * 2. Commercial license
15 * Alternatively, this file may be used under the terms of a commercial
16 * license agreement with the copyright holder
17 * (David C. Manuelda <StormByte@gmail.com>).
18 *
19 * Both licenses apply only to original StormByte source in this repository.
20 * They do not cover other StormByte modules or any third-party material
21 * shipped with this repository (including everything under thirdparty/),
22 * which remains under its own license.
23 *
24 * Neither license grants any patent rights. Any patent licenses required
25 * to use this software or third-party components must be obtained separately
26 * from the patent holders.
27 *
28 * StormByte is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU Lesser General Public License for more details.
32 *
33 * You should have received a copy of the GNU Lesser General Public License
34 * version 3 along with StormByte. If not, see
35 * <https://www.gnu.org/licenses/lgpl-3.0.html>.
36 *
37 * SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-StormByte-Commercial
38 */
39
40#pragma once
41
42#include <exception>
43#include <filesystem>
44#include <iostream>
45#include <ostream>
46#include <string_view>
47
49 template<typename T>
50 void PrintValue(std::ostream& stream, const T& value) {
51 if constexpr (requires { stream << value; }) {
52 stream << value;
53 } else {
54 stream << "<unprintable>";
55 }
56 }
57}
58
65#define RETURN_TEST(fn_name, fn_result) do { \
66 const int stormbyte_test_result = (fn_result); \
67 if (stormbyte_test_result != 0) { \
68 std::cerr << "Test " << fn_name << " FAILED!" << std::endl; \
69 } \
70 return stormbyte_test_result; \
71} while (false)
72
77#define CurrentFileDirectory std::filesystem::path(__FILE__).parent_path()
78
86#define ASSERT_EQUAL(fn_name, expected, actual) do { \
87 const auto& stormbyte_expected = (expected); \
88 const auto& stormbyte_actual = (actual); \
89 if (!(stormbyte_expected == stormbyte_actual)) { \
90 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": expected \""; \
91 ::StormByte::Test::Detail::PrintValue(std::cerr, stormbyte_expected); \
92 std::cerr << "\", got \""; \
93 ::StormByte::Test::Detail::PrintValue(std::cerr, stormbyte_actual); \
94 std::cerr << "\"" << std::endl; \
95 return 1; \
96 } \
97} while (false)
98
106#define ASSERT_NOT_EQUAL(fn_name, expected, actual) do { \
107 const auto& stormbyte_expected = (expected); \
108 const auto& stormbyte_actual = (actual); \
109 if (stormbyte_expected == stormbyte_actual) { \
110 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": values should differ; both were \""; \
111 ::StormByte::Test::Detail::PrintValue(std::cerr, stormbyte_actual); \
112 std::cerr << "\"" << std::endl; \
113 return 1; \
114 } \
115} while (false)
116
123#define ASSERT_FALSE(fn_name, condition) do { \
124 if ((condition)) { \
125 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": condition is true, expected false" << std::endl; \
126 return 1; \
127 } \
128} while (false)
129
136#define ASSERT_TRUE(fn_name, condition) do { \
137 if (!(condition)) { \
138 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": condition is false, expected true" << std::endl; \
139 return 1; \
140 } \
141} while (false)
142
147#define ASSERT_THROWS(fn_name, expression, exception_type) do { \
148 bool stormbyte_threw = false; \
149 try { \
150 (void)(expression); \
151 } catch (const exception_type&) { \
152 stormbyte_threw = true; \
153 } catch (...) { \
154 } \
155 if (!stormbyte_threw) { \
156 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": expected " << #exception_type << " to be thrown" << std::endl; \
157 return 1; \
158 } \
159} while (false)
160
165#define ASSERT_NO_THROW(fn_name, expression) do { \
166 try { \
167 (void)(expression); \
168 } catch (const std::exception& stormbyte_exception) { \
169 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": unexpected exception: " << stormbyte_exception.what() << std::endl; \
170 return 1; \
171 } catch (...) { \
172 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": unexpected non-standard exception" << std::endl; \
173 return 1; \
174 } \
175} while (false)
176
181#define ASSERT_NEAR(fn_name, expected, actual, tolerance) do { \
182 const auto stormbyte_expected = (expected); \
183 const auto stormbyte_actual = (actual); \
184 const auto stormbyte_tolerance = (tolerance); \
185 const auto stormbyte_difference = stormbyte_expected > stormbyte_actual ? \
186 stormbyte_expected - stormbyte_actual : stormbyte_actual - stormbyte_expected; \
187 if (stormbyte_difference > stormbyte_tolerance) { \
188 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": values differ beyond tolerance" << std::endl; \
189 return 1; \
190 } \
191} while (false)
192
197#define ASSERT_CONTAINS(fn_name, haystack, needle) do { \
198 const auto& stormbyte_haystack = (haystack); \
199 const auto& stormbyte_needle = (needle); \
200 if (stormbyte_haystack.find(stormbyte_needle) == std::string_view::npos) { \
201 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": expected text to contain \"" << stormbyte_needle << "\"" << std::endl; \
202 return 1; \
203 } \
204} while (false)
205
210#define ASSERT_NOT_NULL(fn_name, pointer) do { \
211 if ((pointer) == nullptr) { \
212 std::cerr << fn_name << ": Assertion failed at " << __FILE__ << ":" << __LINE__ << ": pointer is null" << std::endl; \
213 return 1; \
214 } \
215} while (false)
Definition test_handlers.h:48
void PrintValue(std::ostream &stream, const T &value)
Definition test_handlers.h:50