Spinning Topp Logo BlackTopp Studios
inc
testdatatools.h
Go to the documentation of this file.
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _testdatatools_h
41 #define _testdatatools_h
42 
43 /// @file
44 /// @brief TestData, TestDataStorage and UnitTestGroup class definitions.
45 
46 #include "datatypes.h"
47 
48 #include "testdata.h"
49 
50 #include <limits>
51 
52 namespace Mezzanine
53 {
54  namespace Testing
55  {
56  #ifndef TEST
57  /// @def TEST
58  /// @brief The easiest way to add a test to the currently running UnitTestGroup.
59  /// This captures test location meta data and should be considered the default way to record tests
60  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
61  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
62  /// @param Cond A boolean operand of some kind
63  /// @param Name The name of the current test
64  #ifdef __FUNCTION__
65  #define TEST(Cond, Name) Test( (Cond), (Name), Testing::Failed, Testing::Success, __FUNCTION__, __FILE__, __LINE__ );
66  #else
67  #define TEST(Cond, Name) Test( (Cond), (Name), Testing::Failed, Testing::Success, __func__, __FILE__, __LINE__ );
68  #endif
69  #endif
70 
71  /// @brief Calculate if an assumption is close enough to be considered equal
72  /// @details this uses std::numeric_limits<T>::epsilon() to get the amount of round that is acceptable.
73  /// This all the Epsilon to be included multiple times if required generally once is the right amount
74  /// to include. However, sometimes an operation can cause rounding multiple times, if this is case, then
75  /// an EpsilonFactor can be passed and set to the number of times rounding can be expected.
76  /// @param Left One value to check for equality.
77  /// @param Right The other value to check.
78  /// @param EpsilonFactor How many times should the epsilon be included.
79  template <typename T>
80  bool CompareEqualityWithEpsilon(const T& Left, const T& Right, size_t EpsilonFactor = 1)
81  {
82  T Epsilon(std::numeric_limits<T>::epsilon());
83  return Right-Epsilon*PreciseReal(EpsilonFactor) <= Left
84  &&
85  Left <= Right+Epsilon*PreciseReal(EpsilonFactor);
86  }
87 
88  #ifndef TEST_EQUAL_EPSILON
89  /// @def TEST_EQUAL_EPSILON
90  /// @brief Compare types that might
91  /// @param LeftValue One value to compare
92  /// @param RightValue One value to compare
93  /// @param Name The name of the current test
94  #ifdef __FUNCTION__
95  #define TEST_EQUAL_EPSILON(LeftValue, RightValue, Name) Test( CompareEqualityWithEpsilon(LeftValue, RightValue), (Name), Testing::Failed, Testing::Success, __FUNCTION__, __FILE__, __LINE__ );
96  #else
97  #define TEST_EQUAL_EPSILON(LeftValue, RightValue, Name) Test( CompareEqualityWithEpsilon(LeftValue, RightValue), (Name), Testing::Failed, Testing::Success, __func__, __FILE__, __LINE__ );
98  #endif
99  #endif
100 
101  #ifndef TEST_EQUAL_MULTI_EPSILON
102  /// @def TEST_EQUAL_MULTI_EPSILON
103  /// @details This is only rarely required. TEST_EQUAL_EPSILON should be prefferred as this can spuriously pass.
104  /// @param LeftValue One value to compare
105  /// @param RightValue One value to compare
106  /// @param EpsilonFactor How many times rounding could occur that could round to the epsilon, so that it can be accounted for?
107  /// @param Name The name of the current test
108  #ifdef __FUNCTION__
109  #define TEST_EQUAL_MULTI_EPSILON(LeftValue, RightValue, Name, EpsilonFactor) Test( CompareEqualityWithEpsilon(LeftValue, RightValue, EpsilonFactor), (Name), Testing::Failed, Testing::Success, __FUNCTION__, __FILE__, __LINE__ );
110  #else
111  #define TEST_EQUAL_MULTI_EPSILON(LeftValue, RightValue, Name, EpsilonFactor) Test( CompareEqualityWithEpsilon(LeftValue, RightValue, EpsilonFactor), (Name), Testing::Failed, Testing::Success, __func__, __FILE__, __LINE__ );
112  #endif
113  #endif
114 
115  #ifndef TEST_WARN
116  /// @def TEST_WARN
117  /// @brief Just like TEST but if the test fails only a warning is added.
118  /// This captures test location meta data and should be considered the default way to record tests that warn instead of fail
119  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
120  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
121  /// @param Cond A boolean operand of some kind
122  /// @param Name The name of the current test
123  #ifdef __FUNCTION__
124  #define TEST_WARN(Cond, Name) Test( (Cond), (Name), Testing::Warning, Testing::Success, __FUNCTION__, __FILE__, __LINE__ );
125  #else
126  #define TEST_WARN(Cond, Name) Test( (Cond), (Name), Testing::Warning, Testing::Success, __func__, __FILE__, __LINE__ );
127  #endif
128  #endif
129 
130  #ifndef TEST_RESULT
131  /// @def TEST_RESULT
132  /// @brief An easy way to add a test and associated data to the currently running UnitTestGroup
133  /// This captures test location meta data and should be considered a good way to record tests that do not easily break down to a single conditional.
134  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
135  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
136  /// @param ExistingResult A TestResult To be added directy
137  /// @param Name The name of the current test
138  #ifdef __FUNCTION__
139  #define TEST_RESULT(ExistingResult, Name) AddTestResult( TestData( (Name), (ExistingResult), __FUNCTION__, __FILE__, __LINE__)) ;
140  #else
141  #define TEST_RESULT(ExistingResult, Name) AddTestResult( TestData( (Name), (ExistingResult), __func__, __FILE__, __LINE__)) ;
142  #endif
143 
144  #endif
145 
146  #ifndef TEST_THROW
147  /// @def TEST_THROW
148  /// @brief An easy way to add a test whether or not a function/code snippet throws exceptions (or whatever) the way planned.
149  /// @details This captures test location meta data and should be considered the default way to capture exception tests.
150  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
151  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
152  /// @param ExpectThrown The type of the thing that should be thrown
153  /// @param CodeThatThrows A snippet of code that throws an exception
154  /// @param Name The name of the current test
155  #ifdef __FUNCTION__
156  #define TEST_THROW(ExpectThrown, CodeThatThrows, Name) \
157  try { \
158  CodeThatThrows; \
159  AddTestResult( TestData( (Name), Testing::Failed, __FUNCTION__, __FILE__, __LINE__)) ; \
160  } catch (ExpectThrown) { \
161  AddTestResult( TestData( (Name), Testing::Success, __FUNCTION__, __FILE__, __LINE__)) ; \
162  } catch (...) { \
163  AddTestResult( TestData( (Name), Testing::Failed, __FUNCTION__, __FILE__, __LINE__)) ; \
164  }
165  #else
166  #define TEST_THROW(ExpectThrown, CodeThatThrows, Name) \
167  try { \
168  CodeThatThrows; \
169  AddTestResult( TestData( (Name), Testing::Failed, __func__, __FILE__, __LINE__)) ; \
170  } catch (ExpectThrown) { \
171  AddTestResult( TestData( (Name), Testing::Success, __func__, __FILE__, __LINE__)) ; \
172  } catch (...) { \
173  AddTestResult( TestData( (Name), Testing::Failed, __func__, __FILE__, __LINE__)) ; \
174  }
175  #endif
176  #endif
177 
178  #ifndef TEST_NO_THROW
179  /// @def TEST_THROW
180  /// @brief An easy way to add a test whether or not a function/code snippet throws exceptions (or whatever) the way planned.
181  /// @details This captures test location meta data and should be considered the default way to capture exception tests
182  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
183  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
184  /// @param CodeThatMightThrow The type of the thing that should be thrown
185  /// @param Name The name of the current test
186  #ifdef __FUNCTION__
187  #define TEST_NO_THROW(CodeThatMightThrow, Name) \
188  try { \
189  CodeThatMightThrow; \
190  AddTestResult( TestData( (Name), Testing::Success, __FUNCTION__, __FILE__, __LINE__)) ; \
191  } catch (...) { \
192  AddTestResult( TestData( (Name), Testing::Failed, __FUNCTION__, __FILE__, __LINE__)) ; \
193  }
194  #else
195  #define TEST_NO_THROW(CodeThatMightThrow, Name) \
196  try { \
197  CodeThatMightThrow; \
198  AddTestResult( TestData( (Name), Testing::Success, __func__, __FILE__, __LINE__)) ; \
199  } catch (...) { \
200  AddTestResult( TestData( (Name), Testing::Failed, __func__, __FILE__, __LINE__)) ; \
201  }
202  #endif
203  #endif
204 
205  /// @brief Get a timestamp, in microseconds. This will generally be some multiple of the GetTimeStampResolution return value.
206  /// @warning On some platforms this requires a static initialization, an can cause undefined behavior if called before static initializations are complete
207  /// @return The largest size integer containing a timestamp that can be compared to other timestamps, but hads no guarantees for external value.
208  MaxInt Now();
209 
210  /// @brief Get the resolution of the timestamp in microseconds. This is the smallest amount of time that the GetTimeStamp can accurately track.
211  /// @return A Whole which returns in millionths of a second the smallest unit of time that GetTimeStamp can measure.
213 
214  /// @brief An easy way to get the time something took to execute.
215  class TimedTest
216  {
217  /// @brief The time this was constructed.
218  MaxInt BeginTimer;
219  public:
220  /// @brief Simply Creating this starts the timer
222  : BeginTimer(Mezzanine::Testing::Now())
223  {}
224 
225  /// @brief How long since this started.
226  /// @return A MaxInt containing the Now - BeginTimer.
228  { return Mezzanine::Testing::Now() - BeginTimer; }
229  };
230 
231  #ifndef TEST_TIMED
232  /// @def TEST_TIMED
233  /// @brief An easy way to add a test whether or not a function/code snippet takes the expected amount of time
234  /// @details This starts a timer just before the CodeToTime is execute and stops that time right after it finishes
235  /// @note This calls a member function on the UnitTestGroup class, so it can only be used in UnitTestGroup Functions
236  /// like UnitTestGroup::RunInteractiveTests or UnitTestGroup::RunAutomaticTests
237  /// @param CodeToTime The code to time
238  /// @param ExpectedTime The Expected amount if time in microseconds.
239  /// @param Variance A fraction 0.00 of how far off, long or short, the execution time can be and still pass. For example .02 is 2%
240  /// @param Name The name of the current test
241  #ifdef __FUNCTION__
242  #define TEST_TIMED(CodeToTime, ExpectedTime, Variance, Name) \
243  { \
244  TimedTest TESTDuration; \
245  CodeToTime; \
246  MaxInt TESTLength = TESTDuration.GetLength(); \
247  MaxInt TESTTargetTime = ExpectedTime; \
248  MaxInt TESTVariance = Variance * double(ExpectedTime); \
249  if( MaxInt(TESTTargetTime-TESTVariance) < TESTLength && \
250  TESTLength < MaxInt(TESTTargetTime+TESTVariance)) \
251  { AddTestResult( TestData( (Name), Testing::Success, __FUNCTION__, __FILE__, __LINE__) ); } \
252  else \
253  { AddTestResult( TestData( (Name), Testing::Failed, __FUNCTION__, __FILE__, __LINE__) ); } \
254  }
255  #else
256  #define TEST_TIMED(CodeToTime, ExpectedTime, Variance, Name) \
257  { \
258  TimedTest TESTDuration; \
259  CodeToTime; \
260  MaxInt TESTLength = TESTDuration.GetLength(); \
261  MaxInt TESTTargetTime = ExpectedTime; \
262  MaxInt TESTVariance = Variance * double(ExpectedTime); \
263  if( MaxInt(TESTTargetTime-TESTVariance) < TESTLength && \
264  TESTLength < MaxInt(TESTTargetTime+TESTVariance)) \
265  { AddTestResult( TestData( (Name), Testing::Success, __func__, __FILE__, __LINE__) ); } \
266  else \
267  { AddTestResult( TestData( (Name), Testing::Failed, __func__, __FILE__, __LINE__) ); } \
268  }
269  #endif
270  #endif
271  }// Testing
272 }// Mezzanine
273 
274 #endif
TestData, TestDataStorage and UnitTestGroup class definitions.
All the definitions for datatypes as well as some basic conversion functions are defined here...
Whole NowResolution()
Get the resolution of the timestamp in microseconds. This is the smallest amount of time that the Get...
TimedTest()
Simply Creating this starts the timer.
An easy way to get the time something took to execute.
MaxInt Now()
Get a timestamp, in microseconds. This will generally be some multiple of the GetTimeStampResolution ...
MaxInt GetLength()
How long since this started.
bool CompareEqualityWithEpsilon(const T &Left, const T &Right, size_t EpsilonFactor=1)
Calculate if an assumption is close enough to be considered equal.
Definition: testdatatools.h:80
long long MaxInt
A large integer type suitable for compile time math and long term microsecond time keeping...
Definition: datatypes.h:190
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
double PreciseReal
A Real number that is at least as precise as the Real and could be considerably moreso, perhaps Doubly precise. This type might be poorly aligned but very precise.
Definition: datatypes.h:146
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151