Chebyshev
Unit testing for scientific software
Loading...
Searching...
No Matches
err.h
Go to the documentation of this file.
1
5
6#ifndef CHEBYSHEV_ERR_H
7#define CHEBYSHEV_ERR_H
8
9#include <vector>
10#include <cstdlib>
11#include <iostream>
12#include <memory>
13#include <iomanip>
14
15#include "./core/common.h"
16#include "./core/random.h"
17#include "./core/output.h"
19
20
21namespace chebyshev {
22
23
24// To err is human; to forgive, divine.
25
26
34namespace err {
35
36
39 struct err_settings {
40
42 std::string moduleName = "unknown";
43
45 bool outputToFile = true;
46
48 std::vector<std::string> outputFiles {};
49
52 std::vector<std::string> assertOutputFiles {};
53
55 std::vector<std::string> assertColumns = {
56 "name", "evaluated", "failed", "description"
57 };
58
61 std::vector<std::string> errnoOutputFiles {};
62
64 std::vector<std::string> errnoColumns = {
65 "name", "evaluated", "expectedFlags", "failed"
66 };
67
70 std::vector<std::string> exceptionOutputFiles {};
71
73 std::vector<std::string> exceptionColumns = {
74 "name", "thrown", "correctType", "failed"
75 };
76
80 std::map<std::string, bool> pickedChecks {};
81
83 bool quiet = false;
84
85 };
86
87
91 private:
92
94 std::map<std::string, std::vector<assert_result>> assertResults {};
95
97 std::map<std::string, std::vector<errno_result>> errnoResults {};
98
100 std::map<std::string, std::vector<exception_result>> exceptionResults {};
101
103 bool wasTerminated {false};
104
105 public:
106
109
112 std::shared_ptr<output::output_context> output;
113
116 std::shared_ptr<random::random_context> random;
117
118
125 inline void setup(
126 const std::string& moduleName,
127 int argc = 0, const char** argv = nullptr) {
128
129 // Initialize other modules
131 output = std::make_shared<output::output_context>();
132 random = std::make_shared<random::random_context>();
133
134 if(argc && argv)
135 for (int i = 1; i < argc; ++i)
136 settings.pickedChecks[argv[i]] = true;
137
138 std::cout << "Starting error checking on ";
139 std::cout << moduleName << " module ..." << std::endl;
140
141 settings.moduleName = moduleName;
142 wasTerminated = false;
143 }
144
145
150 inline void terminate(bool exit = false) {
151
152 unsigned int failedChecks = 0;
153 unsigned int totalChecks = 0;
154
155 for (const auto& pair : assertResults) {
156 for (const auto& testCase : pair.second) {
157 totalChecks++;
158 failedChecks += testCase.failed ? 1 : 0;
159 }
160 }
161
162 for (const auto& pair : errnoResults) {
163 for (const auto& testCase : pair.second) {
164 totalChecks++;
165 failedChecks += testCase.failed ? 1 : 0;
166 }
167 }
168
169 for (const auto& pair : exceptionResults) {
170 for (const auto& testCase : pair.second) {
171 totalChecks++;
172 failedChecks += testCase.failed ? 1 : 0;
173 }
174 }
175
176 // Ensure that an output file is specified
178 !output->settings.outputFiles.size() &&
179 !settings.assertOutputFiles.size() &&
180 !settings.errnoOutputFiles.size() &&
182 !settings.outputFiles.size()) {
183
184 settings.outputFiles = { settings.moduleName + "_results" };
185 }
186
187 std::vector<std::string> outputFiles;
188
189 // Print assert results
190 outputFiles = settings.outputFiles;
191 outputFiles.insert(
192 outputFiles.end(),
195 );
196
197
198 output->print_results(
199 assertResults,
201 outputFiles
202 );
203
204 // Print errno checking results
205 outputFiles = settings.outputFiles;
206 outputFiles.insert(
207 outputFiles.end(),
210 );
211
212
213 output->print_results(
214 errnoResults,
216 outputFiles
217 );
218
219 // Print exception checking results
220 outputFiles = settings.outputFiles;
221 outputFiles.insert(
222 outputFiles.end(),
225 );
226
227
228 output->print_results(
229 exceptionResults,
231 outputFiles
232 );
233
234 // Print overall checks results
235 std::cout << "Finished testing " << settings.moduleName << '\n';
236 std::cout << totalChecks << " total checks, ";
237 std::cout << failedChecks << " failed";
238
239 // Print proportion of failed checks, avoiding division by zero
240 if (totalChecks > 0) {
241
242 const double percent = (failedChecks / (double) totalChecks) * 100;
243 std::cout << " (" << std::setprecision(3) << percent << "%)" << std::endl;
244
245 } else {
246 std::cout << "\nNo checks were run!" << std::endl;
247 }
248
249 if(exit) {
250 output->terminate();
251 std::exit(failedChecks);
252 }
253
254 wasTerminated = true;
255 }
256
257
260 std::string moduleName,
261 int argc = 0,
262 const char** argv = nullptr) {
263
264 setup(moduleName, argc, argv);
265 }
266
267
270 if (!wasTerminated)
271 terminate();
272 }
273
274
280 inline void assert(
281 const std::string& name,
282 bool exp,
283 std::string description = "",
284 bool quiet = false) {
285
287
288 res.name = name;
289 res.evaluated = exp;
290 res.failed = !exp;
291 res.description = description;
292 res.quiet = quiet;
293
294 assertResults[name].push_back(res);
295 }
296
297
304 template<typename Function, typename InputType>
305 inline void errno_value(
306 const std::string& name,
307 Function f,
308 InputType x,
309 int expected_errno,
310 bool quiet = false) {
311
312 errno_result res {};
313 errno = 0;
314
315 try {
316 volatile auto r = f(x);
317 r = *(&r);
318 } catch(...) {}
319
320 res.name = name;
321 res.evaluated = errno;
322 res.expectedFlags = { expected_errno };
323 res.failed = (errno != expected_errno);
324 res.quiet = quiet;
325
326 errnoResults[name].push_back(res);
327 }
328
329
336 template<typename Function, typename InputType>
337 inline void errno_value(
338 const std::string& name, Function f,
339 std::function<InputType()> generator,
340 int expected_errno,
341 bool quiet = false) {
342
343 errno_value(name, f, generator(), expected_errno, quiet);
344 }
345
346
355 template<typename Function, typename InputType>
356 inline void errno_flags(
357 const std::string& name,
358 Function f,
359 InputType x,
360 std::vector<int>& expected_flags,
361 bool quiet = false) {
362
363
364 errno_result res {};
365 errno = 0;
366
367 try {
368 volatile auto r = f(x);
369 r = *(&r);
370 } catch(...) {}
371
372 res.name = name;
373 res.evaluated = errno;
374 res.expectedFlags = expected_flags;
375 res.quiet = quiet;
376
377 res.failed = false;
378 for (int flag : expected_flags)
379 if(!(errno & flag))
380 res.failed = true;
381
382 errnoResults[name].push_back(res);
383 }
384
385
394 template<typename Function, typename InputType>
396 const std::string& name, Function f,
397 std::function<InputType()> generator,
398 std::vector<int>& expected_flags,
399 bool quiet = false) {
400
401 errno_flags(name, f, generator(), expected_flags, quiet);
402 }
403
404
411 template<typename Function, typename InputType>
412 inline void throws(
413 const std::string& name,
414 Function f,
415 InputType x,
416 bool quiet = false) {
417
419 bool thrown = false;
420
421 try {
422 volatile auto r = f(x);
423 r = *(&r);
424 } catch(...) {
425 thrown = true;
426 }
427
428 res.name = name;
429 res.thrown = thrown;
430 res.failed = !thrown;
431 res.correctType = true;
432 res.quiet = quiet;
433
434 exceptionResults[name].push_back(res);
435 }
436
437
444 template<typename Function, typename InputType>
445 inline void throws(
446 const std::string& name, Function f,
447 std::function<InputType()> generator,
448 bool quiet = false) {
449
450 throws(name, f, generator(), quiet);
451 }
452
453
460 template <
461 typename ExceptionType,
462 typename Function,
463 typename InputType
464 >
465 inline void throws(
466 const std::string& name,
467 Function f,
468 InputType x,
469 bool quiet = false) {
470
472 bool thrown = false;
473 bool correctType = false;
474
475 try {
476 volatile auto r = f(x);
477 r = *(&r);
478 } catch(ExceptionType& exc) {
479
480 correctType = true;
481 thrown = true;
482
483 } catch(...) {
484 thrown = true;
485 }
486
487 res.name = name;
488 res.thrown = thrown;
489 res.failed = !(thrown && correctType);
490 res.correctType = correctType;
491 res.quiet = quiet;
492
493 exceptionResults[name].push_back(res);
494 }
495
496
504 template <
505 typename ExceptionType,
506 typename Function,
507 typename InputType
508 >
509 inline void throws(
510 const std::string& name, Function f,
511 std::function<InputType()> generator,
512 bool quiet = false) {
513
514 throws(name, f, generator(), quiet);
515 }
516
517
519 inline std::vector<assert_result> get_assertion(const std::string& name) {
520 return assertResults[name];
521 }
522
523
525 inline assert_result get_assertion(const std::string& name, unsigned int i) {
526 return assertResults[name].at(i);
527 }
528
529
531 inline std::vector<errno_result> get_errno(const std::string& name) {
532 return errnoResults[name];
533 }
534
535
537 inline errno_result get_errno(const std::string& name, unsigned int i) {
538 return errnoResults[name].at(i);
539 }
540
541
543 inline std::vector<exception_result> get_exception(const std::string& name) {
544 return exceptionResults[name];
545 }
546
547
549 inline exception_result get_exception(const std::string& name, unsigned int i) {
550 return exceptionResults[name].at(i);
551 }
552
553 };
554
555
561 err_context make_context(const std::string& moduleName,
562 int argc = 0, const char** argv = nullptr) {
563
564 return err_context(moduleName, argc, argv);
565 }
566
567}}
568
569#endif
Error checking context, for assertions and exception checking.
Definition err.h:90
void errno_value(const std::string &name, Function f, InputType x, int expected_errno, bool quiet=false)
Check errno value after function call.
Definition err.h:305
void errno_flags(const std::string &name, Function f, InputType x, std::vector< int > &expected_flags, bool quiet=false)
Check the value of errno after a function call, comparing to multiple expected flags which should all...
Definition err.h:356
std::vector< errno_result > get_errno(const std::string &name)
Get the results of errno checking by name or label.
Definition err.h:531
err_context(std::string moduleName, int argc=0, const char **argv=nullptr)
Setup the error checking module.
Definition err.h:259
~err_context()
Terminate the error checking module.
Definition err.h:269
void setup(const std::string &moduleName, int argc=0, const char **argv=nullptr)
Setup error checking module.
Definition err.h:125
std::shared_ptr< random::random_context > random
Random module settings for the context, dynamically allocated and possibly shared between multiple co...
Definition err.h:116
std::vector< assert_result > get_assertion(const std::string &name)
Get the results of an assertion by name or label.
Definition err.h:519
errno_result get_errno(const std::string &name, unsigned int i)
Get a single result of errno checking by label and index.
Definition err.h:537
assert_result get_assertion(const std::string &name, unsigned int i)
Get a single result of an assertion by label and index.
Definition err.h:525
std::vector< exception_result > get_exception(const std::string &name)
Get the results of exception checking by name or label.
Definition err.h:543
void errno_flags(const std::string &name, Function f, std::function< InputType()> generator, std::vector< int > &expected_flags, bool quiet=false)
Check the value of errno after a function call, comparing to multiple expected flags which should all...
Definition err.h:395
err_settings settings
Settings for the benchmark context.
Definition err.h:108
std::shared_ptr< output::output_context > output
Output module settings for the context, dynamically allocated and possibly shared between multiple co...
Definition err.h:112
exception_result get_exception(const std::string &name, unsigned int i)
Get a single result of exception checking by label and index.
Definition err.h:549
void errno_value(const std::string &name, Function f, std::function< InputType()> generator, int expected_errno, bool quiet=false)
Check errno value after function call.
Definition err.h:337
void terminate(bool exit=false)
Terminate the error testing environment.
Definition err.h:150
void assert(const std::string &name, bool exp, std::string description="", bool quiet=false)
Assert that an expression is true.
Definition err.h:280
Common definitions for the framework.
Structures for the error checking module.
err_context make_context(const std::string &moduleName, int argc=0, const char **argv=nullptr)
Construct an error checking context with the given parameters.
Definition err.h:561
General namespace of the framework.
Definition benchmark.h:22
constexpr FloatType get_nan()
Get a quiet NaN of the specified floating point type.
Definition common.h:65
The output module, with formatting capabilities.
The pseudorandom number generation and sampling module.
Result of assertion checking of a function.
Definition err_structures.h:21
std::string name
Identifying name of the function or test case.
Definition err_structures.h:24
Settings of the error testing module, used in err_context.
Definition err.h:39
std::vector< std::string > outputFiles
The files to write all error checking results to.
Definition err.h:48
std::vector< std::string > assertOutputFiles
The files to write assertion results results to (if empty, all results are output to a generic file).
Definition err.h:52
std::vector< std::string > exceptionOutputFiles
The files to write exception results results to (if empty, all results are output to a generic file).
Definition err.h:70
std::vector< std::string > assertColumns
Default columns to print for assertions.
Definition err.h:55
std::vector< std::string > exceptionColumns
Default columns to print for exception checks.
Definition err.h:73
std::map< std::string, bool > pickedChecks
Target checks marked for execution, can be picked by passing test case names by command line.
Definition err.h:80
std::string moduleName
Name of the module being tested.
Definition err.h:42
std::vector< std::string > errnoOutputFiles
The files to write errno checking results to (if empty, all results are output to a generic file).
Definition err.h:61
std::vector< std::string > errnoColumns
Default columns to print for errno checks.
Definition err.h:64
bool quiet
Whether to print to standard output.
Definition err.h:83
bool outputToFile
Whether to print to an output file.
Definition err.h:45
Result of errno checking of a function.
Definition err_structures.h:42
Result of exception checking of a function.
Definition err_structures.h:63