libMesh
driver.C
Go to the documentation of this file.
1 // Ignore overloaded-virtual warnings coming from cppunit headers
2 #include <libmesh/ignore_warnings.h>
3 #include <cppunit/extensions/TestFactoryRegistry.h>
4 #include <cppunit/ui/text/TestRunner.h>
5 #include <cppunit/BriefTestProgressListener.h>
6 #include <cppunit/TestPath.h>
7 #include <cppunit/TestResult.h>
8 #include <libmesh/restore_warnings.h>
9 
10 // libMesh includes
11 #include <libmesh/libmesh.h>
12 
13 #include "libmesh_cppunit.h"
14 #include "test_comm.h"
15 
16 #ifdef LIBMESH_HAVE_CXX11_REGEX
17 
18 // C++ includes
19 #include <regex>
20 
21 // We want to be able to add a selection of tests from our full suite
22 // to our test runner. But then the test runner will want to destruct
23 // those tests afterward, so we can't destruct the suite without it
24 // *also* trying to destruct all its tests (undefined behavior), and
25 // we can't not destruct the suite without the suite and its
26 // unselected tests being leaked (which would be fine since just exit
27 // afterward, except valgrind sees the leaks and screams).
28 //
29 // So, instead of adding selected tests, we add shims of selected
30 // tests that can be deleted without deleting the tests they shim.
31 class TestShim : public CppUnit::Test
32 {
33 public:
34  TestShim (CppUnit::Test & shimmed_test) : _shimmed_test(shimmed_test) {}
35 
36  virtual void run(CppUnit::TestResult * result) override { _shimmed_test.run(result); }
37 
38  virtual int countTestCases () const override { return _shimmed_test.countTestCases(); }
39 
40  virtual int getChildTestCount () const override { return _shimmed_test.getChildTestCount(); }
41 
42  virtual std::string getName () const override { return _shimmed_test.getName(); }
43 
44  virtual bool findTestPath (const std::string & testName, CppUnit::TestPath & testPath) const override { return _shimmed_test.findTestPath(testName, testPath); }
45 
46  virtual bool findTestPath (const CppUnit::Test * test, CppUnit::TestPath & testPath) const override { return _shimmed_test.findTestPath(test, testPath); }
47 
48  virtual CppUnit::Test * findTest(const std::string & testName) const override { return _shimmed_test.findTest(testName); }
49 
50  virtual CppUnit::TestPath resolveTestPath(const std::string & testPath) const override { return _shimmed_test.resolveTestPath(testPath); }
51 
52 protected:
53  virtual CppUnit::Test * doGetChildTestAt(int index) const override { return _shimmed_test.getChildTestAt(index); }
54 
55 private:
56  CppUnit::Test & _shimmed_test;
57 };
58 
59 // "Magic number" for when we're not doing allow or deny regex
60 static constexpr int added_whole_suite = -12345;
61 
62 // Add Tests to runner that match user-provided regex.
63 int add_matching_tests_to_runner(CppUnit::Test * test,
64  const std::string & allow_r_str,
65  const std::regex & allow_r,
66  const std::string & deny_r_str,
67  const std::regex & deny_r,
68  CppUnit::TextUi::TestRunner & runner)
69 {
70  int n_tests_added = 0;
71 
72  // If running all tests, just add the "All Tests" test and return
73  if (test->getName() == "All Tests" && allow_r_str == "All Tests" &&
74  deny_r_str == "^$")
75  {
76  libMesh::out << test->getName() << std::endl;
77  runner.addTest(test);
78  return added_whole_suite;
79  }
80 
81  if (test->getChildTestCount() == 0)
82  {
83  // Add the test to the runner
84  if ((allow_r_str == "All Tests" ||
85  std::regex_search(test->getName(), allow_r)) &&
86  !std::regex_search(test->getName(), deny_r))
87  {
88  libMesh::out << test->getName() << std::endl;
89  n_tests_added ++;
90 
91  // yes, explicit new; this is how CppUnit works
92  runner.addTest(new TestShim(*test));
93  }
94  }
95 
96  // Call this recursively on each of our children, if any.
97  for (int i = 0; i < test->getChildTestCount(); i++)
98  n_tests_added +=
99  add_matching_tests_to_runner(test->getChildTestAt(i), allow_r_str, allow_r,
100  deny_r_str, deny_r, runner);
101 
102  return n_tests_added;
103 }
104 
105 #endif
106 
107 
108 int main(int argc, char ** argv)
109 {
110  // Initialize the library. This is necessary because the library
111  // may depend on a number of other libraries (i.e. MPI and Petsc)
112  // that require initialization before use.
113  libMesh::LibMeshInit init(argc, argv);
114  TestCommWorld = &init.comm();
115 
116  // See how long each of our tests are taking to run. This should be
117  // coarse-grained enough to enable even if we're not performance
118  // logging inside the library itself. We need to do this early, so
119  // we can query unitlog when first initializing tests.
120  libMesh::PerfLog driver_unitlog ("Unit Tests");
121  unitlog = &driver_unitlog;
122 
123  // Print just logs summarized by test suite, not every test
124  // individually
125  if (!libMesh::on_command_line("--full-logs"))
126  driver_unitlog.enable_summarized_logs();
127 
128  // We can now run all tests that match a regular expression, for
129  // example, "--re PartitionerTest" will match all the Partitioner
130  // unit tests. If the user does not specify a regex, we run all the
131  // tests returned by makeTest().
132 
133  // An example regex_string that would _exactly_ match a _single_ test is:
134  // "PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh::testPartition2"
135  // On the other hand, the regex "HilbertSFC" would match all of the
136  // following tests:
137  //
138  // PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh
139  // PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh::testPartitionEmpty
140  // PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh::testPartition1
141  // PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh::testPartition2
142  // PartitionerTest_HilbertSFCPartitioner_ReplicatedMesh::testPartitionNProc
143  //
144  // If the user does not provide a a regex, the default re is "All Tests",
145  // which runs all the unit tests.
146 
147  // We can also skip tests that match a regular expression, with e.g.
148  // "--deny_re PartitionerTest" to skip all the Partitioner unit
149  // tests (even if a "--re" option would have included them.)
150 
151  // Read command line argument specifying the allowlist regular expression.
152  std::string allow_regex_string = "All Tests";
153  allow_regex_string = libMesh::command_line_next("--re", allow_regex_string);
154 
155  // Read command line argument specifying the allowlist regular expression.
156  std::string deny_regex_string = "^$";
157  deny_regex_string = libMesh::command_line_next("--deny_re", deny_regex_string);
158 
159  // We might have to delete the test suite ourselves, after the
160  // runner has deleted whatever subtests it has.
161  std::unique_ptr<CppUnit::Test> owned_suite;
162 
163  // Recursively add tests matching the regex to the runner object.
164  CppUnit::TextUi::TestRunner runner;
165 
166  // The Cppunit registry object that knows about all the tests, and
167  // the test suite it creates.
168  CppUnit::TestFactoryRegistry & registry = CppUnit::TestFactoryRegistry::getRegistry();
169  CppUnit::Test * suite = registry.makeTest();
170 
171 #ifdef LIBMESH_HAVE_CXX11_REGEX
172  // Make regex objects from user's input.
173  const std::regex allow_regex(allow_regex_string);
174  const std::regex deny_regex(deny_regex_string);
175 
176  // Add all tests which match the re to the runner object.
177  libMesh::out << "Will run the following tests:" << std::endl;
178  const int n_tests_added =
180  allow_regex_string, allow_regex,
181  deny_regex_string, deny_regex,
182  runner);
183  if (n_tests_added >= 0)
184  libMesh::out << "--- Running " << n_tests_added << " tests in total." << std::endl;
185 
186  // If we didn't add the whole suite to the runner, we need to clean
187  // it up ourselves
188  if (n_tests_added != added_whole_suite)
189  owned_suite.reset(suite);
190 #else
191  // If no C++11 <regex> just run all the tests.
192  runner.addTest(suite);
193 #endif
194 
195  std::unique_ptr<CppUnit::TestResult> controller;
196  std::unique_ptr<CppUnit::BriefTestProgressListener> listener;
197 
198  // Actually run all the requested tests, possibly with verbose
199  // output of test names as they are run
200  if (libMesh::on_command_line("--verbose"))
201  {
202  listener = std::make_unique<CppUnit::BriefTestProgressListener>();
203  runner.eventManager().addListener(listener.get());
204  }
205 
206  bool succeeded = runner.run();
207 
208  // Many users won't care at all about the PerfLog
209 #ifndef LIBMESH_ENABLE_PERFORMANCE_LOGGING
210  if (!libMesh::on_command_line("--full-logs"))
211  driver_unitlog.clear();
212 #endif
213 
214  // 1 for failure, 0 for success
215  return !succeeded;
216 }
217 
219 
T command_line_next(std::string name, T default_value)
Use GetPot&#39;s search()/next() functions to get following arguments from the command line...
Definition: libmesh.C:1025
virtual CppUnit::Test * findTest(const std::string &testName) const override
Definition: driver.C:48
virtual CppUnit::TestPath resolveTestPath(const std::string &testPath) const override
Definition: driver.C:50
virtual void run(CppUnit::TestResult *result) override
Definition: driver.C:36
libMesh::Parallel::Communicator * TestCommWorld
Definition: driver.C:218
virtual bool findTestPath(const CppUnit::Test *test, CppUnit::TestPath &testPath) const override
Definition: driver.C:46
virtual std::string getName() const override
Definition: driver.C:42
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:91
void reset(streamT &target)
Reset the proxy to point to a different target.
The PerfLog class allows monitoring of specific events.
Definition: perf_log.h:153
virtual int countTestCases() const override
Definition: driver.C:38
void enable_summarized_logs()
Tells the PerfLog to only print log results summarized by header.
Definition: perf_log.h:199
CppUnit::Test & _shimmed_test
Definition: driver.C:56
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition: perf_log.C:78
virtual int getChildTestCount() const override
Definition: driver.C:40
libMesh::PerfLog * unitlog
Definition: driver.C:220
OStreamProxy out
virtual bool findTestPath(const std::string &testName, CppUnit::TestPath &testPath) const override
Definition: driver.C:44
virtual CppUnit::Test * doGetChildTestAt(int index) const override
Definition: driver.C:53
TestShim(CppUnit::Test &shimmed_test)
Definition: driver.C:34
int main(int argc, char **argv)
Definition: driver.C:108
bool on_command_line(std::string arg)
Definition: libmesh.C:934
int add_matching_tests_to_runner(CppUnit::Test *test, const std::string &allow_r_str, const std::regex &allow_r, const std::string &deny_r_str, const std::regex &deny_r, CppUnit::TextUi::TestRunner &runner)
Definition: driver.C:63
static constexpr int added_whole_suite
Definition: driver.C:60