GCC Code Coverage Report


Directory: src/gate/
File: src/gate/cxx_tests.cpp
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 112 144 77.8%
Functions: 20 24 83.3%
Branches: 66 130 50.8%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/tests.hpp"
30 #include "gate/memalloc.hpp"
31 #include "gate/tests.h"
32 #include "gate/console.hpp"
33 #include "gate/files.hpp"
34 #include "gate/environments.hpp"
35
36 namespace gate
37 {
38 265 UnitTestBase::UnitTestBase(char const* name)
39 265 : unitName(String::createStatic(name))
40 {
41 265 }
42 530 UnitTestBase::~UnitTestBase() noexcept
43 {
44 530 }
45 167 void UnitTestBase::run()
46 {
47 try
48 {
49
1/2
✓ Branch 1 taken 167 times.
✗ Branch 2 not taken.
167 this->test();
50 }
51 catch (...)
52 {
53 }
54 167 }
55 599 char const* UnitTestBase::getUnitTestName() const
56 {
57 599 return this->unitName.c_str();
58 }
59
60
61
62
63 struct GATE_API_LOCAL UnitTestRegistry
64 {
65 public:
66 IRunnable* runnables[512];
67 char const* names[512];
68 size_t runnablesCount;
69 };
70
71 static UnitTestRegistry global_unit_test_registry = GATE_INIT_EMPTY;
72
73 12 int UnitTest::runMainHandler(char const* const* arguments, size_t argcount)
74 {
75
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 static StaticString const argHelp = "--help";
76
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 static StaticString const argList = "--list";
77
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 static StaticString const argTrace = "--trace";
78
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
12 static StaticString const argJunit = "--junit";
79
80 12 bool_t showHelp = false;
81 12 bool_t listTests = false;
82 12 bool_t enableTrace = false;
83 12 bool_t enableHistory = true;
84
85 char const* patterns[512];
86 12 size_t patternsCount = 0;
87 12 const size_t patternsMax = sizeof(patterns) / sizeof(patterns[0]);
88
89
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
14 for (size_t ndx = 0; ndx != argcount; ++ndx)
90 {
91 4 const StaticString arg(arguments[ndx], String::length(arguments[ndx]));
92
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (arg == argHelp)
93 {
94 1 showHelp = true;
95 }
96
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 else if (arg == argList)
97 {
98 1 listTests = true;
99 }
100 else if (arg == argTrace)
101 {
102 enableTrace = true;
103 }
104 else if (arg == argJunit)
105 {
106 enableHistory = true;
107 }
108 else
109 {
110 if (patternsCount < patternsMax)
111 {
112 patterns[patternsCount] = arguments[ndx];
113 ++patternsCount;
114 }
115 }
116 }
117
118
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 11 times.
12 if (showHelp)
119 {
120 gate::Console
121
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "Usage:" << strings::NewLine
122
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "testapp --help" << strings::NewLine
123
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "\tPrint test program usage description" << strings::NewLine
124
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "testapp --list" << strings::NewLine
125
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "\tLists all registered test cases by their anmes" << strings::NewLine
126
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "testapp" << strings::NewLine
127
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "\tExecutes all registered test cases" << strings::NewLine
128
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "testapp test_case_name1 test_case_name2" << strings::NewLine
129
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "\tExecutes only test cases named by arguments" << strings::NewLine
130
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "testapp --trace test_case_name1 test_case_name2" << strings::NewLine
131
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 << "\tExecutes given test cases with trace-mode enabled" << strings::NewLine
132 ;
133 1 return 0;
134 }
135
136
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (listTests)
137 {
138 1 Stream& strm = Console;
139
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 UnitTest::printRegisteredTests(strm);
140 1 return 0;
141 }
142
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (enableTrace)
144 {
145 UnitTest::setTrace(true);
146 }
147
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (enableHistory)
148 {
149
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 UnitTest::setHistory(true);
150 }
151
152
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 UnitTest::init();
153
154
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 int exitCode = UnitTest::runRegisteredTests(patterns, patternsCount);
155
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 UnitTest::printTestReports();
156
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (enableHistory)
157 {
158
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
20 String filename = Environment::getAppExecutableName();
159
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
20 FileStream junitstream(filename + ".junit.xml", File::Open_Write);
160
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 UnitTest::printTestHistory(junitstream, GATE_TEST_HISTORY_FORMAT_JUNIT);
161 }
162
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 UnitTest::uninit();
163 10 return exitCode;
164 }
165
166 10 void UnitTest::init()
167 {
168 10 gate_test_init(NULL);
169 10 }
170
171 10 void UnitTest::uninit()
172 {
173 10 gate_test_uninit();
174 10 }
175
176 265 void UnitTest::registerTest(UnitTestBase& test)
177 {
178 265 size_t const maxRunnables = sizeof(global_unit_test_registry.runnables) / sizeof(global_unit_test_registry.runnables[0]);
179
180
1/2
✓ Branch 0 taken 265 times.
✗ Branch 1 not taken.
265 if (global_unit_test_registry.runnablesCount < maxRunnables)
181 {
182
2/2
✓ Branch 0 taken 4725 times.
✓ Branch 1 taken 265 times.
4990 for (size_t ndx = 0; ndx != global_unit_test_registry.runnablesCount; ++ndx)
183 {
184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4725 times.
4725 if (global_unit_test_registry.runnables[ndx] == &test)
185 {
186 return;
187 }
188 }
189 265 global_unit_test_registry.runnables[global_unit_test_registry.runnablesCount] = &test;
190 265 global_unit_test_registry.names[global_unit_test_registry.runnablesCount] = test.getUnitTestName();
191 265 ++global_unit_test_registry.runnablesCount;
192 }
193 }
194
195 167 static bool_t isSelectedTest(char const* name, char const* const* filterPatterns, size_t filterPatternsCount)
196 {
197
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (filterPatternsCount == 0)
198 {
199 // no filter -> all tests are selected
200 167 return true;
201 }
202
203 StaticString const tcName(name);
204
205 for (size_t ndx = 0; ndx != filterPatternsCount; ++ndx)
206 {
207 StaticString const pattern(filterPatterns[ndx]);
208 if (tcName.like(pattern))
209 {
210 // matching pattern found
211 return true;
212 }
213 }
214 return false;
215 }
216
217 10 int UnitTest::runRegisteredTests(char const* const* filterPatterns, size_t filterPatternsCount)
218 {
219
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 10 times.
177 for (size_t ndx = 0; ndx != global_unit_test_registry.runnablesCount; ++ndx)
220 {
221 167 char const* name = global_unit_test_registry.names[ndx];
222
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 167 times.
167 if (!isSelectedTest(name, filterPatterns, filterPatternsCount))
223 {
224 continue;
225 }
226 167 IRunnable* ptrRunnable = global_unit_test_registry.runnables[ndx];
227
1/2
✓ Branch 0 taken 167 times.
✗ Branch 1 not taken.
167 if (ptrRunnable)
228 {
229 try
230 {
231
1/2
✓ Branch 1 taken 167 times.
✗ Branch 2 not taken.
167 ptrRunnable->run();
232 }
233 catch (UnitTestException const& /*xcpt*/)
234 {
235 }
236 catch (...)
237 {
238 }
239 }
240 }
241
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (UnitTest::haveTestsFailed())
242 {
243 return 1;
244 }
245 else
246 {
247 10 return 0;
248 }
249 }
250 1 void UnitTest::printRegisteredTests(Stream& strm)
251 {
252
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 times.
50 for (size_t ndx = 0; ndx != global_unit_test_registry.runnablesCount; ++ndx)
253 {
254 49 char const* name = global_unit_test_registry.names[ndx];
255 49 strm << name << strings::NewLine;
256 }
257 1 }
258
259 void UnitTest::setTrace(bool_t enabled)
260 {
261 gate_test_trace_enable(enabled);
262 }
263 10 void UnitTest::setHistory(bool_t enabled)
264 {
265 10 gate_test_history_enable(enabled);
266 10 }
267
268 167 void UnitTest::beginTest(char const* unitname, char const* filepath, unsigned codeline)
269 {
270 167 gate_test_unit_begin(unitname, filepath, codeline);
271 167 }
272 167 void UnitTest::endTest(char const* unitname, char const* filepath, unsigned codeline)
273 {
274 167 }
275 129547 void UnitTest::countTest()
276 {
277 129547 gate_test_count_test();
278 129547 }
279 void UnitTest::countTestFailure()
280 {
281 gate_test_count_error();
282 }
283 129548 void UnitTest::printTrace(char const* message, char const* filepath, unsigned codeline)
284 {
285 129548 gate_test_trace_message(message, filepath, codeline);
286 129548 }
287 void printSuccess(char const* message, char const* filepath, unsigned codeline)
288 {
289 gate_test_success_message(message, filepath, codeline);
290 }
291 129547 void UnitTest::printSuccess(char const* message, char const* filepath, unsigned codeline)
292 {
293 129547 gate_test_success_message(message, filepath, codeline);
294 129547 }
295 void UnitTest::printError(char const* message, char const* filepath, unsigned codeline)
296 {
297 gate_test_error_message(message, filepath, codeline);
298 }
299 10 void UnitTest::printTestReports()
300 {
301 10 gate_test_print_reports();
302 10 }
303 10 void UnitTest::printTestHistory(Stream& stream, enumint_t flags)
304 {
305 10 gate_test_print_history(stream.c_impl(), flags);
306 10 }
307
308 10 bool_t UnitTest::haveTestsFailed()
309 {
310 10 return gate_test_failed();
311 }
312
313
314 } // end of namespace test
315
316
317
318