You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
6.3KB

  1. // ---
  2. //
  3. // $Id: suite.cpp,v 1.6 2008/07/15 20:33:31 hartwork Exp $
  4. //
  5. // CppTest - A C++ Unit Testing Framework
  6. // Copyright (c) 2003 Niklas Lundell
  7. //
  8. // ---
  9. //
  10. // This library is free software; you can redistribute it and/or
  11. // modify it under the terms of the GNU Lesser General Public
  12. // License as published by the Free Software Foundation; either
  13. // version 2 of the License, or (at your option) any later version.
  14. //
  15. // This library is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. // Lesser General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU Lesser General Public
  21. // License along with this library; if not, write to the
  22. // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  23. // Boston, MA 02111-1307, USA.
  24. //
  25. // ---
  26. #include "cpptest-output.h"
  27. #include "cpptest-source.h"
  28. #include "cpptest-suite.h"
  29. namespace Test
  30. {
  31. namespace
  32. {
  33. // Destroys all dynamically allocated objects within the given range.
  34. //
  35. template <class FwdIter>
  36. void
  37. destroy_range(FwdIter first, FwdIter last)
  38. {
  39. while (first != last)
  40. delete *first++;
  41. }
  42. } // anonymous namespace
  43. /// Constructs an empty test suite.
  44. ///
  45. Suite::Suite()
  46. : _cur_test(0),
  47. _output(0),
  48. _success(true)
  49. {}
  50. /// Destroys this suite object.
  51. ///
  52. Suite::~Suite()
  53. {
  54. destroy_range(_suites.begin(), _suites.end());
  55. }
  56. /// Starts the testing. All tests in this suite and embedded suites will
  57. /// be executed.
  58. ///
  59. /// \param output Progress report destination.
  60. /// \param cont_after_fail Continue functions despite failures.
  61. ///
  62. /// \return True if no test failed; false otherwise.
  63. ///
  64. bool
  65. Suite::run(Output& output, bool cont_after_fail)
  66. {
  67. int ntests = total_tests();
  68. output.initialize(ntests);
  69. do_run(&output, cont_after_fail);
  70. output.finished(ntests, total_time(true));
  71. return _success;
  72. }
  73. /// \fn void Suite::setup()
  74. ///
  75. /// Setups a test fixture. This function is called before each test,
  76. /// in this suite, is executed.
  77. ///
  78. /// This function should be overloaded by derived classes to provide
  79. /// specialized behavior.
  80. ///
  81. /// \see tear_down()
  82. /// \fn void Suite::tear_down()
  83. ///
  84. /// Tears down a test fixture. This function is called after each test,
  85. /// in this suite, have been executed.
  86. ///
  87. /// This function should be overloaded by derived classes to provide
  88. /// specialized behavior.
  89. ///
  90. /// \see setup()
  91. /// Adds a suite to this suite. Tests in added suites will be executed
  92. /// when run() of the top-level suite is called.
  93. ///
  94. /// \param suite %Test suite to add.
  95. ///
  96. void
  97. Suite::add(Suite* suite)
  98. {
  99. _suites.push_back(suite);
  100. }
  101. /// Registers a test function.
  102. ///
  103. /// \b Note: Do not call this function directly, use the TEST_ADD(func)
  104. /// macro instead.
  105. ///
  106. /// \param func Pointer to a test function.
  107. /// \param name Class and function name of the function. The format \b must
  108. /// equal \e class::func.
  109. ///
  110. void
  111. Suite::register_test(Func func, const std::string& name)
  112. {
  113. string::size_type pos = name.find_first_of(':');
  114. //assert(!name.empty() && name[pos + 1] == ':' && name[pos + 2] != '\0');
  115. _name.assign(name, 0, pos);
  116. _tests.push_back(Data(func, name.substr(pos + 2)));
  117. }
  118. /// Issues an assertment to the output handler.
  119. ///
  120. /// Do not call this function directly, use one of the available assertment
  121. /// macros instead, see \ref asserts.
  122. ///
  123. /// \param s Assert point information.
  124. ///
  125. void
  126. Suite::assertment(Source s)
  127. {
  128. s._suite = _name;
  129. s._test = *_cur_test;
  130. _output->assertment(s);
  131. _result = _success = false;
  132. }
  133. // Functor to execute tests for the given suite.
  134. //
  135. struct Suite::ExecTests
  136. {
  137. Suite& _suite;
  138. ExecTests(Suite& s) : _suite(s) {}
  139. void operator()(Data& data)
  140. {
  141. _suite._cur_test = &data._name;
  142. _suite._result = true; // assume success, assert will set to false
  143. _suite._output->test_start(data._name);
  144. _suite.setup();
  145. Time start(Time::current());
  146. // FIXME Also feedback exception to user
  147. try
  148. {
  149. (_suite.*data._func)();
  150. } catch (...) {
  151. _suite._result = false;
  152. }
  153. Time end(Time::current());
  154. _suite.tear_down();
  155. data._time = end - start;
  156. _suite._output->test_end(data._name, _suite._result, data._time);
  157. }
  158. };
  159. // Functor to execute a suite.
  160. //
  161. struct Suite::DoRun
  162. {
  163. bool _continue;
  164. Output* _output;
  165. DoRun(Output* output, bool cont) : _continue(cont), _output(output) {}
  166. void operator()(Suite* suite) { suite->do_run(_output, _continue); }
  167. };
  168. // Execute all tests in this and added suites.
  169. //
  170. void
  171. Suite::do_run(Output* os, bool cont_after_fail)
  172. {
  173. _continue = cont_after_fail;
  174. _output = os;
  175. _output->suite_start(_tests.size(), _name);
  176. std::for_each(_tests.begin(), _tests.end(), ExecTests(*this));
  177. _output->suite_end(_tests.size(), _name, total_time(false));
  178. std::for_each(_suites.begin(), _suites.end(), DoRun(_output, _continue));
  179. // FIXME Find a cleaner way
  180. Suites::const_iterator iter = _suites.begin();
  181. while (iter != _suites.end())
  182. {
  183. if (!(*iter)->_success)
  184. {
  185. _success = false;
  186. break;
  187. }
  188. iter++;
  189. }
  190. }
  191. // Functor to count all tests in a suite.
  192. //
  193. struct Suite::SubSuiteTests
  194. {
  195. int operator()(size_t value, const Suite* s) const
  196. {
  197. return value + s->total_tests();
  198. }
  199. };
  200. // Counts all tests in this and all its embedded suites.
  201. //
  202. int
  203. Suite::total_tests() const
  204. {
  205. return accumulate(_suites.begin(), _suites.end(),
  206. _tests.size(), SubSuiteTests());
  207. }
  208. // Functor to accumulate execution time for tests.
  209. //
  210. struct Suite::SuiteTime
  211. {
  212. Time operator()(const Time& time, const Data& data)
  213. {
  214. return time + data._time;
  215. }
  216. };
  217. // Functor to accumulate execution time for suites.
  218. //
  219. struct Suite::SubSuiteTime
  220. {
  221. Time operator()(Time time, const Suite* s) const
  222. {
  223. return time + s->total_time(true);
  224. }
  225. };
  226. // Counts time accumulated execution time for all tests in this and all
  227. // its embedded suites.
  228. //
  229. Time
  230. Suite::total_time(bool recursive) const
  231. {
  232. Time time = accumulate(_tests.begin(), _tests.end(),
  233. Time(), SuiteTime());
  234. return !recursive ? time : accumulate(_suites.begin(), _suites.end(),
  235. time, SubSuiteTime());
  236. }
  237. } // namespace Test