Dune Core Modules (unstable)

testsuite.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_COMMON_TEST_TESTSUITE_HH
6 #define DUNE_COMMON_TEST_TESTSUITE_HH
7 
8 #include <iostream>
9 #include <sstream>
10 #include <string>
11 
13 #include <dune/common/test/collectorstream.hh>
14 
15 
16 
17 namespace Dune {
18 
19 
20 
30  class TestSuite
31  {
32  public:
33  enum ThrowPolicy
34  {
35  AlwaysThrow,
36  ThrowOnRequired
37  };
38 
45  TestSuite(ThrowPolicy policy, std::string name="") :
46  name_(name),
47  checks_(0),
48  failedChecks_(0),
49  throwPolicy_(policy==AlwaysThrow)
50  {}
51 
58  TestSuite(std::string name="", ThrowPolicy policy=ThrowOnRequired) :
59  name_(name),
60  checks_(0),
61  failedChecks_(0),
62  throwPolicy_(policy==AlwaysThrow)
63  {}
64 
74  CollectorStream check(bool condition, std::string name="")
75  {
76  ++checks_;
77  if (not condition)
78  ++failedChecks_;
79 
80  return CollectorStream([condition, name, this](std::string reason) {
81  if (not condition)
82  this->announceCheckResult(throwPolicy_, "CHECK ", name, reason);
83  });
84  }
85 
95  CollectorStream require(bool condition, std::string name="")
96  {
97  ++checks_;
98  if (not condition)
99  ++failedChecks_;
100 
101  return CollectorStream([condition, name, this](std::string reason) {
102  if (not condition)
103  this->announceCheckResult(true, "REQUIRED CHECK", name, reason);
104  });
105  }
106 
107 
108  private:
109  struct AnyException{};
110  struct NoException{};
111 
112  template <class Exception= AnyException,class Expression>
113  bool evaluateThrowCondition(Expression&& expr)
114  {
115  try { expr(); }
116  catch (const Exception& e)
117  {
118  return true;
119  }
120  catch (...) //If we end up here, but we wanted to catch a specific Exception, we consider this failed, but if Exception is AnyExpection, we pass.
121  {
122  return std::is_same_v<Exception,AnyException>;
123  }
124  // If we end up here we didn't catch any exception. Thus, if this is on purpose, i.e. 'Exception= NoException', we return true.
125  return std::is_same_v<Exception,NoException>;
126  }
127 
128  public:
129 
143  template <class Exception= AnyException,class Expression>
144  CollectorStream checkThrow(Expression&& expr, std::string name = "")
145  {
146  return check(evaluateThrowCondition<Exception>(expr),name);
147  }
148 
162  template <class Expression>
163  CollectorStream checkNoThrow(Expression&& expr, std::string name = "")
164  {
165  return check(evaluateThrowCondition<NoException>(expr),name);
166  }
167 
182  template <class Exception= AnyException,class Expression>
183  CollectorStream requireThrow(Expression&& expr, std::string name = "")
184  {
185  return require(evaluateThrowCondition<Exception>(expr),name);
186  }
187 
201  template <class Expression>
202  CollectorStream requireNoThrow(Expression&& expr, std::string name = "")
203  {
204  return require(evaluateThrowCondition<NoException>(expr),name);
205  }
206 
214  void subTest(const TestSuite& subTest)
215  {
216  checks_ += subTest.checks_;
217  failedChecks_ += subTest.failedChecks_;
218 
219  if (not subTest)
220  announceCheckResult(throwPolicy_, "SUBTEST", subTest.name(), std::to_string(subTest.failedChecks_)+"/"+std::to_string(subTest.checks_) + " checks failed in this subtest.");
221  }
222 
228  explicit operator bool () const
229  {
230  return (failedChecks_==0);
231  }
232 
238  std::string name() const
239  {
240  return name_;
241  }
242 
248  bool report() const
249  {
250  if (failedChecks_>0)
251  std::cout << composeMessage("TEST ", name(), std::to_string(failedChecks_)+"/"+std::to_string(checks_) + " checks failed in this test.") << std::endl;
252  return (failedChecks_==0);
253  }
254 
263  int exit() const
264  {
265  return (report() ? 0: 1);
266  }
267 
268  protected:
269 
270  // Compose a diagnostic message
271  static std::string composeMessage(std::string type, std::string name, std::string reason)
272  {
273  std::ostringstream s;
274  s << type << " FAILED";
275  if (name!="")
276  s << "(" << name << ")";
277  s << ": ";
278  if (reason!="")
279  s << reason;
280  return s.str();
281  }
282 
283  // Announce check results. To be called on failed checks
284  static void announceCheckResult(bool throwException, std::string type, std::string name, std::string reason)
285  {
286  std::string message = composeMessage(type, name, reason);
287  std::cout << message << std::endl;
288  if (throwException)
289  {
290  Dune::Exception ex;
291  ex.message(message);
292  throw ex;
293  }
294  }
295 
296  std::string name_;
297  std::size_t checks_;
298  std::size_t failedChecks_;
299  bool throwPolicy_;
300  };
301 
302 
303 
304 } // namespace Dune
305 
306 
307 
308 #endif // DUNE_COMMON_TEST_TESTSUITE_HH
Data collector stream.
Definition: collectorstream.hh:32
Base class for Dune-Exceptions.
Definition: exceptions.hh:96
A Simple helper class to organize your test suite.
Definition: testsuite.hh:31
std::string name() const
Query name.
Definition: testsuite.hh:238
CollectorStream checkNoThrow(Expression &&expr, std::string name="")
Checks that the expression doesn't throw.
Definition: testsuite.hh:163
CollectorStream requireNoThrow(Expression &&expr, std::string name="")
Requires that the expression doesn't throw.
Definition: testsuite.hh:202
TestSuite(std::string name="", ThrowPolicy policy=ThrowOnRequired)
Create TestSuite.
Definition: testsuite.hh:58
void subTest(const TestSuite &subTest)
Collect data from a sub-TestSuite.
Definition: testsuite.hh:214
TestSuite(ThrowPolicy policy, std::string name="")
Create TestSuite.
Definition: testsuite.hh:45
int exit() const
Exit the test.
Definition: testsuite.hh:263
CollectorStream require(bool condition, std::string name="")
Check a required condition.
Definition: testsuite.hh:95
CollectorStream check(bool condition, std::string name="")
Check condition.
Definition: testsuite.hh:74
CollectorStream checkThrow(Expression &&expr, std::string name="")
Checks that the expression throws.
Definition: testsuite.hh:144
CollectorStream requireThrow(Expression &&expr, std::string name="")
Requires that the expression throws.
Definition: testsuite.hh:183
bool report() const
Print a summary of this TestSuite.
Definition: testsuite.hh:248
A few common exception classes.
void message(const std::string &msg)
store string in internal message buffer
Definition: exceptions.cc:32
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 4, 22:30, 2024)