Spinning Topp Logo BlackTopp Studios
inc
testdata.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 _testdata_h
41 #define _testdata_h
42 
43 /// @file
44 /// @brief TestData, TestDataStorage and UnitTestGroup class definitions.
45 
46 #include "datatypes.h"
47 
48 #include "testenumerations.h"
49 #include "pugixml.h"
50 
51 #include <set>
52 #include <map>
53 #include <iostream>
54 #include <sstream>
55 
56 namespace Mezzanine
57 {
58  /// @namespace Mezzanine::Testing
59  /// @brief This contains all the items (except the tests themselves) that make the unit tests work.
60  namespace Testing
61  {
62  ///////////////////////////////////////////////////////////////////////////////////////////
63  /// @brief The information about a test and how to easily find it in the filesystem
64  struct TestData
65  {
66  /// @brief The name of a given test
68  /// @brief How did the test turn out
70  /// @brief The function the test was called from
72  /// @brief The File The test happened in
74  /// @brief What line in the file this test occurred when the test was compiled
76 
77  /// @brief Create a TestData
78  /// @param Name the name of the test, defaults to "".
79  /// @param Result A TestResult, defaults to Testing::Success.
80  /// @param FuncName The name of the function this test was called from, Defaults to "".
81  /// @param File The name of the file in which the test exists, Defaults to "".
82  /// @param Line The line in the file in which the test exists, Defaults to 0.
83  TestData(const String& Name = "",
85  const String& FuncName = "",
86  const String& File = "",
87  Mezzanine::Whole Line = 0);
88 
89  /// @brief Create Test data from xml.
90  /// @param Node The XMl node to create this from
91  TestData(pugi::xml_node Node);
92 
93  /// @brief Used to sort TestData in std::std and other sorted containers, by TestName.
94  /// @param Rhs the right hand operand when using the less than comparison operator.
95  /// @return A bool with the same value as this->TestName < Rhs.TestName.
96  bool operator<(const TestData& Rhs) const;
97 
98  /// @brief Return a snippet of xml describing this TestData
99  /// @return A String with a single XML element with an attribute for each of the TestName, Results, FunctionName, FileName, LineNumber
100  String GetAsXML() const;
101  };
102 
103  /// @brief Just a map to store the content of TestData, incidentally it will lexographically sort the list of tests.
104  typedef std::set<TestData> TestDataStorage;
105 
106  // Forward declarations.
107  class UnitTestGroup;
109 
110  /// @brief A group of testnames and the Actual test that implement those test(s).
111  typedef std::map<Mezzanine::String, UnitTestGroup*> CoreTestGroup;
112 
113  /// @brief Print all the groups that exist in a given CoreTestGroup
114  /// @param TestGroups The group whose constents names with be printed
115  /// @return ExitSuccess on success.
116  int PrintList(CoreTestGroup &TestGroups);
117 
118  /// @brief Trim the whitespace from a line of text and try to interpret the remains as TestResults and a testname
119  /// @param Line A line of Test that starts with whitespace, then a TestResult String, then has a whitesapce delimiter and a ends with the name of test.
120  /// @return A parsed TestData.
122 
123  ///////////////////////////////////////////////////////////////////////////////////////////
124  /// @brief A single group of tests, suitable for being all the tests of a small subsystem or single class.
125  class UnitTestGroup : public TestDataStorage
126  {
127  friend class OutputCaptureManager;
128 
129  protected:
130  /// @brief A destination for all normal ouput in the tests.
131  std::stringstream TestOutput;
132  /// @brief A destination for errors
133  std::stringstream TestError;
134 
135  /// @brief Used to store the buffer connected to the stdout while it is being redirected.
136  std::streambuf* CoutStreamBuf;
137  /// @brief Used to store the buffer connected to the stderr while it is being redirected.
138  std::streambuf* CerrStreamBuf;
139 
140  /// @brief This will direct any output that would have gone to an external process via cout to TestOutput Instead
141  void CaptureOutputBuffers();
142  /// @brief This will direct any error messages that would have gone to an external process via cerr to TestOutput Instead
143  void RestoreOutputBuffers();
144 
145  /// @brief Some basic variable for tracking simple statistics
146  unsigned int LongestNameLength;
147 
148  /// @brief Set to false if subprocess tests should not be executed. True if they should
150  /// @brief Set the flag to run automatic tests
152  /// @brief Sets the flag to run interactive tests
154 
155  /// @brief Used while running a test to see if
157 
158  public:
159  /// @brief Default constructor
160  UnitTestGroup();
161 
162  /// @brief Copy constructor
163  /// @param OtherGroup A UnitTestGroup to copy into this one. The contents of any log streams are copied and the streams themselves.
164  UnitTestGroup(const UnitTestGroup& OtherGroup);
165 
166  /// @brief This will call RunAutomaticTests based on the values passed.
167  /// @details All test results should be inserted using AddTestResult to allow the returning of results.
168  /// @n @n This can be overloaded to enable better detection of skipped tests. This niavely reports only
169  /// "TestName::Interactive" and "TestName::Automatic" as skipped, and even then only if HasAutomaticTests
170  /// or HasInteractiveTests return true.
171  virtual void RunTests();
172 
173  protected:
174  /// @brief This launches all the automated tests on the derived class if the flag is
175  /// set to run them otherwise it checks if tests exist via HasAutomaticTests() and
176  /// marks them as skipped if they do.
177  void LaunchAutomaticTest();
178  /// @brief This launches all the interactice tests on the derived class if the flag
179  /// is set to run them otherwise it checks if tests exist via HasAutomaticTests()
180  /// and marksthem as skipped if they do.
181  void LaunchInteractiveTest();
182 
183  /// @brief Tests should use this to launch things that need sheltering from
184  /// segfaults and similar faults
185  /// @param Argument A string combined with the command to be run, this must be
186  /// sanitized before being called, do not pass untrusted data.
187  /// @return The output to stdout from the subprocess.
188  String LaunchSubProcessTest(const String& Argument = String(""));
189 
190  public:
191  /// @brief This should be overloaded to run all tests that do require not user interaction
192  virtual void RunAutomaticTests();
193  /// @brief Used only to report skipped tests.
194  /// @return Defaults to returning false, but should be overloaded to return true if RunAutomaticTests() implements any tests.
195  virtual bool HasAutomaticTests() const;
196  /// @brief Sets a flag that indicatesz that is the process that should run this subprocess.
197  virtual void ShouldRunAutomaticTests();
198 
199  /// @brief This should be overloaded to run all tests require user interaction
200  virtual void RunInteractiveTests();
201  /// @brief Used only to report skipped tests.
202  /// @return Defaults to returning false, but should be overloaded to return true if RunInteractiveTests() implements any tests.
203  virtual bool HasInteractiveTests() const;
204  /// @brief Sets a flag that indicatesz that is the process that should run this subprocess.
205  virtual void ShouldRunInteractiveTests();
206 
207  /// @brief Does nothing by default, tests which need to run code in a subprocess should override this.
208  /// @details This will be executed in a subprocess before HasAutomaticTests() and RunInteractiveTests();
209  /// @param Arg An argument from the calling test.
210  /// @return Whatever was sent to stdout via C++ streams will be captured and sent here instead.
211  virtual void RunSubprocessTest(const Mezzanine::String& Arg);
212  /// @brief If this returns false then the test suite treats it like any other test, if true then it enables some features for launching subprocess tests
213  /// @details This will cause an extra command line option to be created (as "debug" + testname). The function SubprocessTest() will be executed in the
214  /// process that the new option is passed into. This allows for subprocess debugging. This will automatically be passed to the test process that will
215  /// executed the sub-process tests.
216  /// @return This returns false by default, any test which wants to execute a subtest will need to implement this to return true.
217  virtual bool HasSubprocessTest() const;
218  /// @brief Sets a flag that indicatesz that is the process that should run this subprocess.
219  virtual void ShouldRunSubProcessTests();
220 
221 
222  /// @brief Get Name of this UnitTestGroup
223  /// @return The string that must be type at the command line to run this testgroup, should be all lowercase.
224  /// @note One of two methods that must be implmented on a UnitTestGroup
225  virtual Mezzanine::String Name();
226 
227  /// @brief Its expected that tests will be inserted using this
228  /// @details This will automate tracking of the most and least successful tests
229  /// @param CurrentTest The New test results and name
230  /// @param Behavior An OverWriteResults that defines the overwrite behavior of this function, defaults to OverWriteIfLessSuccessful
231  void AddTestResult( TestData CurrentTest,
233 
234  /// @brief Add a test results without having to to construct a TestData first
235  /// @details This prepends the name of this UnitTestGroup and "::" to the
236  /// @warning The name of the test can have no spaces in it. An exception will be thrown if found.
237  /// @param TestName The name of the Test
238  /// @param TResult The actual TestResult
239  /// @param Behavior An OverWriteResults that defines the overwirte behavior of this function, defaults to OverWriteIfLessSuccessful
241 
242  /// @brief Add all the items in another UnitTestGroup to this one
243  /// @param rhs The item on the right hand side of the +=.
244  /// @return A reference to this is returned allowiong operator chaining.
245  const UnitTestGroup& operator+=(const UnitTestGroup& rhs);
246 
247  /// @brief Create and add all the tests in a given piece of parsed xml
248  /// @param Node A pugi::xml_node referencing a UnitTestGroup
249  void AddTestsFromXML(pugi::xml_node Node);
250 
251  /// @brief Get the Whole UnitTestGroup as a valid XML document
252  /// @details The root element of the XMl document is named UnitTestGroup
253  /// and it will contain the XML from each TestData this contains
254  /// @return A String containing some XML
255  String GetAsXML() const;
256 
257  /// @brief Print the results or save them to a file.
258  /// @param Output the stream to send the results to.
259  /// @param Error A stream to send errors to.
260  /// @param Summary Print Statistics at the end, not needed when sending results between processes. Defaults to true/enabled.
261  /// @param FullOutput Sometimes the user does not want to see each test results and just wants a little blurb. Defaults to true/enabled.
262  /// @param HeaderOutput Makes the output a little more understandable it is short or needs to be copied into a spreadsheet. Defaults to true/enabled.
263  virtual void DisplayResults(std::ostream& Output=std::cout, std::ostream& Error=std::cerr, bool Summary = true, bool FullOutput = true, bool HeaderOutput = true);
264 
265  /// @brief Interpret Boolean value as a test result. Also Prepends the name of the current test, as returned by Name() + "::", to ease test scoping.
266  /// @warning IfFalse comes first in the argument list, This is because the common test cases have IfTrue = Testing::Success while IfFalse makes sense as other things
267  /// @param TestCondition The test itself or the results of it.
268  /// @param TestName The comple name of the test, used to track results.
269  /// @param IfFalse Defaults to Testing::Failed but can be whatever Testing::TestResult you want if a false passed as the TestCondition.
270  /// @param IfTrue Defaults to Testing::Success but can be whatever Testing::TestResult you want if a true passed as the TestCondition.
271  /// @param FuncName The function the test was called from, if blank
272  /// @param File To make tracking down failures easier the file name of the test can
273  /// be passed in, if not set an empty string is used
274  /// @param Line To make tracking down failures easier the line number of the test
275  /// can be passed in, if not set an empty string is used
276  virtual void Test( bool TestCondition,
277  const String& TestName,
278  TestResult IfFalse = Testing::Failed,
279  TestResult IfTrue = Testing::Success,
280  const String& FuncName = "",
281  const String& File = "",
282  Mezzanine::Whole Line = 0);
283  };
284 
285  /// @internal
286  /// @brief Used to aplly RAII to Stdout and STDERR buffers/streams
288  {
289  private:
290  /// @brief The Target to work with
291  UnitTestGroup* Target;
292  public:
293  /// @brief Captures Output buffers and configures test outputs on creation
294  OutputCaptureManager(UnitTestGroup* RAIITarget) : Target(RAIITarget)
295  { Target->CaptureOutputBuffers(); }
296  /// @brief Restores original output buffers on creation
298  { Target->RestoreOutputBuffers(); }
299 
300  };
301 
302 
303 
304  }// Testing
305 }// Mezzanine
306 
307 #endif
String LaunchSubProcessTest(const String &Argument=String(""))
Tests should use this to launch things that need sheltering from segfaults and similar faults...
Definition: testdata.cpp:198
int32_t Int32
An 32-bit integer.
Definition: datatypes.h:124
void LaunchAutomaticTest()
This launches all the automated tests on the derived class if the flag is set to run them otherwise i...
Definition: testdata.cpp:160
virtual void Test(bool TestCondition, const String &TestName, TestResult IfFalse=Testing::Failed, TestResult IfTrue=Testing::Success, const String &FuncName="", const String &File="", Mezzanine::Whole Line=0)
Interpret Boolean value as a test result. Also Prepends the name of the current test, as returned by Name() + "::", to ease test scoping.
Definition: testdata.cpp:424
std::streambuf * CoutStreamBuf
Used to store the buffer connected to the stdout while it is being redirected.
Definition: testdata.h:136
Enumerations and constant values associated with the Unit tests.
Used to aplly RAII to Stdout and STDERR buffers/streams.
Definition: testdata.h:287
virtual bool HasAutomaticTests() const
Used only to report skipped tests.
Definition: testdata.cpp:203
std::map< Mezzanine::String, UnitTestGroup * > CoreTestGroup
A group of testnames and the Actual test that implement those test(s).
Definition: testdata.h:108
virtual void ShouldRunAutomaticTests()
Sets a flag that indicatesz that is the process that should run this subprocess.
Definition: testdata.cpp:205
~OutputCaptureManager()
Restores original output buffers on creation.
Definition: testdata.h:297
This is the default behavior, because it is presumed failures should be visible so they can be fixed...
All the definitions for datatypes as well as some basic conversion functions are defined here...
void CaptureOutputBuffers()
This will direct any output that would have gone to an external process via cout to TestOutput Instea...
Definition: testdata.cpp:109
void LaunchInteractiveTest()
This launches all the interactice tests on the derived class if the flag is set to run them otherwise...
Definition: testdata.cpp:179
unsigned int LongestNameLength
Some basic variable for tracking simple statistics.
Definition: testdata.h:146
Mezzanine::String FileName
The File The test happened in.
Definition: testdata.h:73
virtual void RunSubprocessTest(const Mezzanine::String &Arg)
Does nothing by default, tests which need to run code in a subprocess should override this...
Definition: testdata.cpp:215
Mezzanine::Whole LineNumber
What line in the file this test occurred when the test was compiled.
Definition: testdata.h:75
bool DoSubProcessTest
Set to false if subprocess tests should not be executed. True if they should.
Definition: testdata.h:149
virtual void RunTests()
This will call RunAutomaticTests based on the values passed.
Definition: testdata.cpp:148
bool DoInteractiveTest
Sets the flag to run interactive tests.
Definition: testdata.h:153
std::streambuf * CerrStreamBuf
Used to store the buffer connected to the stderr while it is being redirected.
Definition: testdata.h:138
bool operator<(const TestData &Rhs) const
Used to sort TestData in std::std and other sorted containers, by TestName.
Definition: testdata.cpp:77
A single group of tests, suitable for being all the tests of a small subsystem or single class...
Definition: testdata.h:125
int PrintList(CoreTestGroup &TestGroups)
Print all the groups that exist in a given CoreTestGroup.
Definition: testdata.cpp:93
Int32 Completed
Used while running a test to see if.
Definition: testdata.h:156
OverWriteResults
This is used to control the behavior of the function UnitTestGroup::AddTestResult() ...
The information about a test and how to easily find it in the filesystem.
Definition: testdata.h:64
TestResult Results
How did the test turn out.
Definition: testdata.h:69
virtual void ShouldRunSubProcessTests()
Sets a flag that indicatesz that is the process that should run this subprocess.
Definition: testdata.cpp:219
std::set< TestData > TestDataStorage
Just a map to store the content of TestData, incidentally it will lexographically sort the list of te...
Definition: testdata.h:104
bool DoAutomaticTest
Set the flag to run automatic tests.
Definition: testdata.h:151
TestResult
Return values from tests.
OutputCaptureManager(UnitTestGroup *RAIITarget)
Captures Output buffers and configures test outputs on creation.
Definition: testdata.h:294
String GetAsXML() const
Get the Whole UnitTestGroup as a valid XML document.
Definition: testdata.cpp:348
const UnitTestGroup & operator+=(const UnitTestGroup &rhs)
Add all the items in another UnitTestGroup to this one.
Definition: testdata.cpp:290
void RestoreOutputBuffers()
This will direct any error messages that would have gone to an external process via cerr to TestOutpu...
Definition: testdata.cpp:117
virtual void ShouldRunInteractiveTests()
Sets a flag that indicatesz that is the process that should run this subprocess.
Definition: testdata.cpp:212
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
virtual bool HasInteractiveTests() const
Used only to report skipped tests.
Definition: testdata.cpp:210
TestData StringToTestData(Mezzanine::String Line)
Trim the whitespace from a line of text and try to interpret the remains as TestResults and a testnam...
Definition: testdata.cpp:100
UnitTestGroup()
Default constructor.
Definition: testdata.cpp:125
virtual Mezzanine::String Name()
Get Name of this UnitTestGroup.
Definition: testdata.cpp:222
TestData(const String &Name="", TestResult Result=Testing::Success, const String &FuncName="", const String &File="", Mezzanine::Whole Line=0)
Create a TestData.
Definition: testdata.cpp:61
Test was ran and appeared to work.
virtual void RunAutomaticTests()
This should be overloaded to run all tests that do require not user interaction.
Definition: testdata.cpp:201
virtual void DisplayResults(std::ostream &Output=std::cout, std::ostream &Error=std::cerr, bool Summary=true, bool FullOutput=true, bool HeaderOutput=true)
Print the results or save them to a file.
Definition: testdata.cpp:363
std::stringstream TestError
A destination for errors.
Definition: testdata.h:133
Mezzanine::String FunctionName
The function the test was called from.
Definition: testdata.h:71
std::stringstream TestOutput
A destination for all normal ouput in the tests.
Definition: testdata.h:131
String GetAsXML() const
Return a snippet of xml describing this TestData.
Definition: testdata.cpp:80
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
void AddTestsFromXML(pugi::xml_node Node)
Create and add all the tests in a given piece of parsed xml.
Definition: testdata.cpp:301
To allow this test harness to be used without the mezzanine it uses pugixml for xml parsing and this ...
void AddTestResult(TestData CurrentTest, OverWriteResults Behavior=OverWriteIfLessSuccessful)
Its expected that tests will be inserted using this.
Definition: testdata.cpp:225
Mezzanine::String TestName
The name of a given test.
Definition: testdata.h:67
virtual bool HasSubprocessTest() const
If this returns false then the test suite treats it like any other test, if true then it enables some...
Definition: testdata.cpp:217
virtual void RunInteractiveTests()
This should be overloaded to run all tests require user interaction.
Definition: testdata.cpp:208