Implémentation de RipplingMath.h
[GPU.git] / WCudaMSE / API_CppTest / SRC / core / suite.cpp
1 // ---
2 //
3 // $Id: suite.cpp,v 1.7 2010/03/26 04:38:25 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
27 #include <algorithm>
28 #include <cassert>
29 #include <cstring>
30 #include <functional>
31 #include <numeric>
32
33 #if (defined(__WIN32__) || defined(WIN32))
34 # include "winconfig.h"
35 #else
36 # include "config.h"
37 #endif
38
39 #include "cpptest-output.h"
40 #include "cpptest-source.h"
41 #include "cpptest-suite.h"
42
43 using namespace std;
44
45 namespace Test
46 {
47 namespace
48 {
49 // Destroys all dynamically allocated objects within the given range.
50 //
51 template <class FwdIter>
52 void
53 destroy_range(FwdIter first, FwdIter last)
54 {
55 while (first != last)
56 delete *first++;
57 }
58
59 } // anonymous namespace
60
61 /// Constructs an empty test suite.
62 ///
63 Suite::Suite()
64 : _cur_test(0),
65 _output(0),
66 _success(true)
67 {}
68
69 /// Destroys this suite object.
70 ///
71 Suite::~Suite()
72 {
73 destroy_range(_suites.begin(), _suites.end());
74 }
75
76 /// Starts the testing. All tests in this suite and embedded suites will
77 /// be executed.
78 ///
79 /// \param output Progress report destination.
80 /// \param cont_after_fail Continue functions despite failures.
81 ///
82 /// \return True if no test failed; false otherwise.
83 ///
84 bool
85 Suite::run(Output& output, bool cont_after_fail)
86 {
87 int ntests = total_tests();
88 output.initialize(ntests);
89 do_run(&output, cont_after_fail);
90 output.finished(ntests, total_time(true));
91 return _success;
92 }
93
94 /// \fn void Suite::setup()
95 ///
96 /// Setups a test fixture. This function is called before each test,
97 /// in this suite, is executed.
98 ///
99 /// This function should be overloaded by derived classes to provide
100 /// specialized behavior.
101 ///
102 /// \see tear_down()
103
104 /// \fn void Suite::tear_down()
105 ///
106 /// Tears down a test fixture. This function is called after each test,
107 /// in this suite, have been executed.
108 ///
109 /// This function should be overloaded by derived classes to provide
110 /// specialized behavior.
111 ///
112 /// \see setup()
113
114 /// Adds a suite to this suite. Tests in added suites will be executed
115 /// when run() of the top-level suite is called.
116 ///
117 /// \param suite %Test suite to add.
118 ///
119 void
120 Suite::add(auto_ptr<Suite> suite)
121 {
122 _suites.push_back(suite.release());
123 }
124
125 /// Registers a test function.
126 ///
127 /// \b Note: Do not call this function directly, use the TEST_ADD(func)
128 /// macro instead.
129 ///
130 /// \param func Pointer to a test function.
131 /// \param name Class and function name of the function. The format \b must
132 /// equal \e class::func.
133 ///
134 void
135 Suite::register_test(Func func, const string& name)
136 {
137 string::size_type pos = name.find_first_of(':');
138 assert(!name.empty() && name[pos + 1] == ':' && name[pos + 2] != '\0');
139
140 _name.assign(name, 0, pos);
141 _tests.push_back(Data(func, name.substr(pos + 2)));
142 }
143
144 /// Issues an assertment to the output handler.
145 ///
146 /// Do not call this function directly, use one of the available assertment
147 /// macros instead, see \ref asserts.
148 ///
149 /// \param s Assert point information.
150 ///
151 void
152 Suite::assertment(Source s)
153 {
154 s._suite = _name;
155 s._test = *_cur_test;
156 _output->assertment(s);
157 _result = _success = false;
158 }
159
160 // Functor to execute tests for the given suite.
161 //
162 struct Suite::ExecTests
163 {
164 Suite& _suite;
165
166 ExecTests(Suite& s) : _suite(s) {}
167
168 void operator()(Data& data)
169 {
170 _suite._cur_test = &data._name;
171 _suite._result = true; // assume success, assert will set to false
172 _suite._output->test_start(data._name);
173
174 _suite.setup();
175 Time start(Time::current());
176 // FIXME Also feedback exception to user
177 try
178 {
179 (_suite.*data._func)();
180 } catch (...) {
181 _suite._result = _suite._success = false;
182 }
183 Time end(Time::current());
184 _suite.tear_down();
185
186 data._time = end - start;
187 _suite._output->test_end(data._name, _suite._result, data._time);
188 }
189 };
190
191 // Functor to execute a suite.
192 //
193 struct Suite::DoRun
194 {
195 bool _continue;
196 Output* _output;
197
198 DoRun(Output* output, bool cont) : _continue(cont), _output(output) {}
199 void operator()(Suite* suite) { suite->do_run(_output, _continue); }
200 };
201
202 // Execute all tests in this and added suites.
203 //
204 void
205 Suite::do_run(Output* os, bool cont_after_fail)
206 {
207 _continue = cont_after_fail;
208 _output = os;
209
210 _output->suite_start(_tests.size(), _name);
211 for_each(_tests.begin(), _tests.end(), ExecTests(*this));
212 _output->suite_end(_tests.size(), _name, total_time(false));
213
214 for_each(_suites.begin(), _suites.end(), DoRun(_output, _continue));
215
216 // FIXME Find a cleaner way
217 Suites::const_iterator iter = _suites.begin();
218 while (iter != _suites.end())
219 {
220 if (!(*iter)->_success)
221 {
222 _success = false;
223 break;
224 }
225 iter++;
226 }
227 }
228
229 // Functor to count all tests in a suite.
230 //
231 struct Suite::SubSuiteTests
232 {
233 int operator()(size_t value, const Suite* s) const
234 {
235 return value + s->total_tests();
236 }
237 };
238
239 // Counts all tests in this and all its embedded suites.
240 //
241 int
242 Suite::total_tests() const
243 {
244 return accumulate(_suites.begin(), _suites.end(),
245 _tests.size(), SubSuiteTests());
246 }
247
248 // Functor to accumulate execution time for tests.
249 //
250 struct Suite::SuiteTime
251 {
252 Time operator()(const Time& time, const Data& data)
253 {
254 return time + data._time;
255 }
256 };
257
258 // Functor to accumulate execution time for suites.
259 //
260 struct Suite::SubSuiteTime
261 {
262 Time operator()(Time time, const Suite* s) const
263 {
264 return time + s->total_time(true);
265 }
266 };
267
268 // Counts time accumulated execution time for all tests in this and all
269 // its embedded suites.
270 //
271 Time
272 Suite::total_time(bool recursive) const
273 {
274 Time time = accumulate(_tests.begin(), _tests.end(),
275 Time(), SuiteTime());
276
277 return !recursive ? time : accumulate(_suites.begin(), _suites.end(),
278 time, SubSuiteTime());
279 }
280
281 } // namespace Test