Simpatico  v1.10
UnitTestRunner.h
1 #ifndef UNIT_TEST_RUNNER_H
2 #define UNIT_TEST_RUNNER_H
3 
4 /*
5 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include "TestRunner.h"
12 #include "TestException.h"
13 #include <vector>
14 
109 template <class UnitTestClass>
111 {
112 
113 public:
114 
115  using TestRunner::nFailure;
117 
121  typedef void (UnitTestClass::*MethodPtr)();
122 
126  UnitTestRunner();
127 
131  ~UnitTestRunner();
132 
133  // Use compiler generated destructor.
134 
138  void addTestMethod(MethodPtr methodPtr);
139 
143  int nTestMethod();
144 
150  void method(unsigned int i);
151 
155  virtual int run();
156 
157 private:
158 
159  std::vector<MethodPtr> methodPtrs_;
160 
161  #ifdef TEST_MPI
162  std::vector<int> results_;
163  #endif
164 
165 };
166 
167 
168 /*
169 * Constructor.
170 */
171 template <class UnitTestClass>
173  : TestRunner()
174 {
175  #ifdef TEST_MPI
176  if (isIoProcessor()) {
177  results_.reserve(mpiSize());
178  for (int i=0; i < mpiSize(); ++i) {
179  results_.push_back(false);
180  }
181  }
182  #endif
183 }
184 
185 /*
186 * Destructor.
187 */
188 template <class UnitTestClass>
190 {}
191 
192 /*
193 * Register a test method of the associated unit test class.
194 */
195 template <class UnitTestClass>
197 { methodPtrs_.push_back(methodPtr); }
198 
199 /*
200 * Return the number of registered test methods.
201 */
202 template <class UnitTestClass>
204 { return methodPtrs_.size(); }
205 
206 /*
207 * Run test method number i.
208 *
209 * \param i index of test method
210 */
211 template <class UnitTestClass>
213 {
214  UnitTestClass testCase;
215  #ifdef TEST_MPI
216  TestException exception;
217  int result;
218  #endif
219 
220  testCase.setFilePrefix(filePrefix());
221 
222  // Run test method (try / catch)
223  try {
224  testCase.setUp();
225  (testCase.*methodPtrs_[i])();
226  #ifndef TEST_MPI
227  std::cout << ".";
228  recordSuccess();
229  #else
230  result = 1;
231  #endif
232  } catch (TestException &e) {
233  #ifndef TEST_MPI
234  std::cout << std::endl;
235  std::cout << " Failure " << std::endl << std::endl;
236  std::cout << e.message() << std::endl;
237  std::cout << ".";
238  recordFailure();
239  #else
240  result = 0;
241  exception = e;
242  #endif
243  }
244  testCase.tearDown();
245 
246  #ifdef TEST_MPI
247  // Process MPI Tests from all processors
248  MPI::COMM_WORLD.Barrier();
249  if (mpiRank() == 0) {
250  results_[0] = result; // Result on processor 0
251  if (results_[0] == 0) {
252  std::cout << std::endl;
253  std::cout << " Failure on Processor 0"
254  << std::endl << std::endl;
255  std::cout << exception.message() << std::endl;
256  std::cout.flush();
257  }
258  for (int i=1; i < mpiSize(); ++i) {
259  // Receive result results_[i] of test on processor i.
260  MPI::COMM_WORLD.Recv(&(results_[i]), 1, MPI_INT, i, i);
261  // If the test failed on processor i
262  if (results_[i] == 0) {
263  result = 0; // fails (==0) if failure on any processor
264  // Send permission to print failure on processor i
265  MPI::COMM_WORLD.Send(&(results_[i]), 1, MPI_INT, i, mpiSize() + i);
266  // Receive confirmation that processor i completed printing
267  MPI::COMM_WORLD.Recv(&(results_[i]), 1, MPI_INT, i, 2*mpiSize() + i);
268  }
269  }
270  // Record success on master (rank == 0) iff success on all processors
271  if (result) {
272  recordSuccess();
273  } else {
274  recordFailure();
275  }
276  std::cout << ".";
277  std::cout.flush();
278  } else { // Slave node
279  // Send result of test on this processor to master, tag = mpiRank().
280  MPI::COMM_WORLD.Send(&result, 1, MPI_INT, 0, mpiRank());
281  // If test failed on this processor
282  if (result == 0) {
283  // Receive permission to print failure statement
284  MPI::COMM_WORLD.Recv(&result, 1, MPI_INT, 0,
285  mpiSize() + mpiRank());
286  std::cout.flush();
287  std::cout << std::endl;
288  std::cout << " Failure on Processor " << mpiRank()
289  << std::endl << std::endl;
290  std::cout << exception.message() << std::endl;
291  std::cout.flush();
292  // Confirm completion of print.
293  MPI::COMM_WORLD.Send(&result, 1, MPI_INT, 0,
294  2*mpiSize() + mpiRank());
295  }
296  }
297  MPI::COMM_WORLD.Barrier();
298  #endif // ifdef TEST_MPI
299 
300 }
301 
302 /*
303 * Run all registered test methods in the order added.
304 */
305 template <class UnitTestClass>
307 {
308  for (unsigned int i = 0; i < methodPtrs_.size(); ++i) {
309  method(i);
310  }
311  report();
312  return nFailure();
313 }
314 
315 // Preprocessor Macros -------------------------------------------------
316 
320 #define TEST_RUNNER(UnitTestClass) UnitTestClass##_Runner
321 
328 #define TEST_BEGIN(UnitTestClass) \
329  class TEST_RUNNER(UnitTestClass) \
330  : public UnitTestRunner<UnitTestClass> \
331  { public: TEST_RUNNER(UnitTestClass)() {
332 
336 #define TEST_ADD(UnitTestClass, Method) \
337  addTestMethod(&UnitTestClass::Method);
338 
344 #define TEST_END(UnitTestClass) } };
345 
346 #endif
int nTestMethod()
Return the number of registered test methods.
void addTestMethod(MethodPtr methodPtr)
Register a test method of the associated unit test class.
const std::string & message()
Return the error message.
~UnitTestRunner()
Destructor.
virtual int run()
Run all registered test methods in the order added.
void recordFailure()
Increment counter for failed tests, and that of parent (if any).
Definition: TestRunner.h:284
Abstract base class for classes that run tests.
Definition: TestRunner.h:73
bool isIoProcessor() const
Is this the IO processor of an MPI communicator?
Definition: TestRunner.h:236
int nFailure() const
Return number of failed tests run.
Definition: TestRunner.h:223
Template for a TestRunner that runs test methods of an associated UnitTest.
const std::string & filePrefix() const
Return file prefix by const reference.
Definition: TestRunner.h:230
void report() const
If this object has no parent, report success and failure counters.
Definition: TestRunner.h:310
void(UnitTestClass::* MethodPtr)()
Pointer to a test method of the associated UnitTest class.
void recordSuccess()
Increment counter for successful tests, and that of parent (if any).
Definition: TestRunner.h:297
void method(unsigned int i)
Run test method number i.
UnitTestRunner()
Constructor.
An exception thrown by a failed unit test.
Definition: TestException.h:19