FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
test_system.hpp
Go to the documentation of this file.
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5#pragma once
6
7// includes, FEAT
9#include <kernel/backend.hpp>
10#include <kernel/util/type_traits.hpp>
12#include <kernel/util/math.hpp>
13
14// includes, system
15#include <string>
16#include <exception>
17#include <list>
18#include <typeinfo>
19#include <cstdlib>
20#include <iostream>
21#include <algorithm>
22#include <cmath>
23
24#define CHECK_INTERNAL(was_ok, message)\
25 if(! (was_ok))\
26 throw FEAT::TestSystem::TestFailedException(__func__, __FILE__, __LINE__, message);
27
34namespace FEAT
35{
37 namespace TestSystem
38 {
39 // Forward declaration
40 class UnitTest;
41
44 : public std::exception
45 {
46
47 private:
48
51
52
53 public:
54
71 const char* const function,
72 const char* const file,
73 const long line,
74 const String & message)
75 : _message(stringify(file) + ":" + stringify(line) + ": in " + stringify(function) + ": " + message )
76 {
77 }
78
80 virtual ~TestFailedException() noexcept
81 {
82 }
83
85 virtual const char* what() const noexcept override
86 {
87 return _message.c_str();
88 }
89 }; // class TestFailedException
90
93 {
94 private:
96 {
97 private:
99 TestList * * const _ptr;
100
101 public:
103 explicit DeleteOnDestruction(TestList * * const ptr)
104 : _ptr(ptr)
105 {
106 }
107
110 {
111 TestList::_delete(*_ptr);
112 *_ptr = nullptr;
113 }
114 };
115
118 {
119 // The Microsoft compiler warns that creating a local static object is not thread-safe.
120 // The corresponding warning is enabled by default, so we'll only disable it for the following
121 // code and restore the warning state afterwards.
122#ifdef FEAT_COMPILER_MICROSOFT
123# pragma warning(push)
124# pragma warning(disable: 4640)
125#endif
126
127 static TestList * instance(nullptr);
128 static DeleteOnDestruction delete_instance(&instance);
129
130#ifdef FEAT_COMPILER_MICROSOFT
131# pragma warning(pop)
132#endif
133
134 return &instance;
135 }
136
137 static void _delete(TestList * const ptr)
138 {
139 delete ptr;
140 }
141
143 std::list<UnitTest*> _tests;
144
147 {
148 }
149
150 TestList(const TestList&) = delete;
151 TestList& operator=(const TestList&) = delete;
152
153 public:
161 {
162 TestList * * instance_ptr = _instance_ptr();
163
164 if (nullptr == *instance_ptr)
165 {
167 //static Mutex m;
168 //Lock l(m);
169
170 instance_ptr = _instance_ptr();
171
172 if (nullptr == *instance_ptr)
173 {
174 *instance_ptr = new TestList;
175 }
176 }
177 return *instance_ptr;
178 }
179
181 typedef std::list<UnitTest*>::iterator Iterator;
182
189 void register_test(UnitTest* const test)
190 {
191 _tests.push_back(test);
192 }
193
196 {
197 return _tests.begin();
198 }
199
202 {
203 return _tests.end();
204 }
205
207 size_t size()
208 {
209 return _tests.size();
210 }
211
214 {
215 return _tests.erase(i);
216 }
217 }; // class TestList
218
219
226 {
227 protected:
228
230 const String _id;
237
238
239 public:
240
247 explicit UnitTest(const String& id_in, const String& datatype_name = "none", const String& index_name = "none", PreferredBackend preferred_backend = PreferredBackend::generic)
248 : _id(id_in),
249 _datatype_name(datatype_name),
250 _index_name(index_name),
251 _preferred_backend(preferred_backend)
252 {
254 }
255
257 virtual ~UnitTest() {}
258
260 virtual const String id() const
261 {
262 return _id;
263 }
264
266 virtual void check(const char * const function, const char * const file,
267 const long line, bool was_ok, const String & message) const
268 {
269 if(! was_ok)
270 throw TestFailedException(function, file, line, message);
271 }
272
278 virtual void run() const = 0;
279
282 {
283 return _datatype_name;
284 }
285
288 {
289 return _index_name;
290 }
291
292 virtual PreferredBackend get_preferred_backend() const
293 {
294 return _preferred_backend;
295 }
296
297 virtual String get_preferred_backend_name() const
298 {
300 }
301 }; // class UnitTest
302
303 } // namespace TestSystem
304} // namespace FEAT
306#define TEST_CHECK_EQUAL(a, b) \
307 do { \
308 CHECK_INTERNAL((a)==(b), this->_id + "\n" + "Expected '" #a "' to equal \n'" + FEAT::stringify(b) + "'\nbut got\n'" + FEAT::stringify(a) + "'")\
309 } while (false)
310
312#define TEST_CHECK_NOT_EQUAL(a, b) \
313 do { \
314 CHECK_INTERNAL(!((a)==(b)), this->_id + "\n" + "Expected '" #a "' that is'" + FEAT::stringify(a) + "' to equal not '" + FEAT::stringify(b) + "'")\
315 } while (false)
316
318#define TEST_CHECK_IN_RANGE(x, a, b) \
319 do { \
320 CHECK_INTERNAL(((a) <= (x)) && ((x) <= (b)), this->_id + "\n" + "Expected '" #x "' that is'" + FEAT::stringify(x) + "' to be in range [" + FEAT::stringify(a) + "," + FEAT::stringify(b) + "]")\
321 } while (false)
322
324#define TEST_CHECK_STRINGIFY_EQUAL(a, b) \
325 do { \
326 String s_a(FEAT::stringify(a)); \
327 String s_b(FEAT::stringify(b)); \
328 CHECK_INTERNAL(s_a == s_b, this->_id + "\n" + "Expected '" #a "' to equal '" + s_b + "'\nbut got\n'" + s_a + "'")\
329 } while (false)
330
332#define TEST_CHECK(a) \
333 do { \
334 CHECK_INTERNAL(a, this->_id + "\n" + "Check '" #a "' failed") \
335 } while (false)
336
338#define TEST_CHECK_MSG(a,msg) \
339 do { \
340 CHECK_INTERNAL(a, this->_id + "\n" + (msg))\
341 } while (false)
342
344#define TEST_CHECK_THROWS(a, b) \
345 do { \
346 try { \
347 try { \
348 a; \
349 this->check(__func__, __FILE__, __LINE__, false, \
350 this->_id + "\n" + "Expected exception of type '" #b "' not thrown"); \
351 } catch (b &) { \
352 TEST_CHECK(true); \
353 } \
354 } catch (const FEAT::TestSystem::TestFailedException &) { \
355 throw; \
356 } catch (const std::exception & test_e) { \
357 throw FEAT::TestSystem::TestFailedException(__func__, __FILE__, __LINE__, \
358 "Test threw unexpected exception "+ FEAT::stringify(test_e.what()) + \
359 " inside a TEST_CHECK_THROWS block"); \
360 } catch (...) { \
361 throw FEAT::TestSystem::TestFailedException(__func__, __FILE__, __LINE__, \
362 "Test threw unexpected unknown exception inside a TEST_CHECK_THROWS block"); \
363 } \
364 } while (false)
365
367#define TEST_CHECK_EQUAL_WITHIN_EPS(a, b, eps) \
368 do { \
369 CHECK_INTERNAL(((a) <= ((b) + (eps))) && ((b) <= ((a) + (eps))), \
370 this->_id + "\n" + "Expected '|" #a " - " #b \
371 "|' <= '" + FEAT::stringify(eps) + "' but was '" + \
372 FEAT::stringify((a) < (b) ? (b) - (a) : (a) - (b)) + "'" \
373 + ", with " #a "=" + FEAT::stringify(a) + " and " #b "=" + FEAT::stringify(b))\
374 } while (false)
375
377#define TEST_CHECK_RELATIVE(a, b, eps) \
378 do { \
379 CHECK_INTERNAL(Math::abs((a) - (b)) <= (eps)*Math::abs(b), \
380 this->_id + "\n" + "Expected '|" #a " - " #b \
381 "|' <= '" + FEAT::stringify(eps) + "*|" #b "|' = '" + \
382 FEAT::stringify((eps)*Math::abs(b)) + "' but was '" + \
383 FEAT::stringify(Math::abs((a) - (b))) + "'" \
384 + ", with " #a "=" + FEAT::stringify(a) + " and " #b "=" + FEAT::stringify(b))\
385 } while (false)
386
388#define TEST_CHECK_LESS_THAN(a, b) \
389 do { \
390 CHECK_INTERNAL((a) < (b), this->_id + "\n" + "Expected '" #a "' to be less than \n'" + FEAT::stringify(b) + "'\nbut got\n'" + FEAT::stringify(a) + "'")\
391 } while (false)
392
394#define TEST(pre, test, post) \
395 do { \
396 pre; \
397 try { \
398 test; \
399 } catch (const FEAT::TestSystem::TestFailedException & test_e) { \
400 post; \
401 throw; } \
402 post; \
403 } while (false)
FEAT Kernel base header.
String class implementation.
Definition: string.hpp:46
exception thrown by the check method in UnitTest
Definition: test_system.hpp:45
virtual const char * what() const noexcept override
description
Definition: test_system.hpp:85
const String _message
failure message
Definition: test_system.hpp:50
virtual ~TestFailedException() noexcept
DTOR.
Definition: test_system.hpp:80
TestFailedException(const char *const function, const char *const file, const long line, const String &message)
CTOR.
Definition: test_system.hpp:70
TestList **const _ptr
Pointer to our managed object.
Definition: test_system.hpp:99
DeleteOnDestruction(TestList **const ptr)
Constructor.
list of all instantiated tests
Definition: test_system.hpp:93
static TestList * instance()
Returns the instance.
std::list< UnitTest * > _tests
internal STL list representation of TestList
static TestList ** _instance_ptr()
Returns a pointer to our instance pointer.
Iterator begin_tests()
returns an iterator to the front of the TestList
std::list< UnitTest * >::iterator Iterator
TestList forward iterator.
void register_test(UnitTest *const test)
adds a test to the TestList
size_t size()
returns the size of the TestList
Iterator erase(Iterator i)
removes iterator target from the TestList
Iterator end_tests()
returns an iterator beyond the last element of the TestList
base class for all Tests
virtual const String id() const
returns our id string
String _index_name
index type description String
virtual String get_index_name()
returns our target platform
const String _id
test description String
UnitTest(const String &id_in, const String &datatype_name="none", const String &index_name="none", PreferredBackend preferred_backend=PreferredBackend::generic)
CTOR.
virtual void run() const =0
runs the test case
virtual void check(const char *const function, const char *const file, const long line, bool was_ok, const String &message) const
utility method used bei TEST_CHECK_THROWS
virtual String get_datatype_name()
returns our target platform
String _datatype_name
precision description String
PreferredBackend _preferred_backend
preferred compute intensive backend
FEAT namespace.
Definition: adjactor.hpp:12
PreferredBackend
The backend that shall be used in all compute heavy calculations.
Definition: backend.hpp:124
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944