libMesh
Loading...
Searching...
No Matches
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.
31class TestShim : public CppUnit::Test
32{
33public:
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
52protected:
53 virtual CppUnit::Test * doGetChildTestAt(int index) const override { return _shimmed_test.getChildTestAt(index); }
54
55private:
56 CppUnit::Test & _shimmed_test;
57};
58
59// "Magic number" for when we're not doing allow or deny regex
60static constexpr int added_whole_suite = -12345;
61
62// Add Tests to runner that match user-provided regex.
63int 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
108int 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
virtual int getChildTestCount() const override
Definition driver.C:40
virtual std::string getName() const override
Definition driver.C:42
virtual void run(CppUnit::TestResult *result) override
Definition driver.C:36
virtual int countTestCases() const override
Definition driver.C:38
virtual bool findTestPath(const CppUnit::Test *test, CppUnit::TestPath &testPath) const override
Definition driver.C:46
TestShim(CppUnit::Test &shimmed_test)
Definition driver.C:34
virtual CppUnit::TestPath resolveTestPath(const std::string &testPath) const override
Definition driver.C:50
virtual CppUnit::Test * findTest(const std::string &testName) const override
Definition driver.C:48
virtual CppUnit::Test * doGetChildTestAt(int index) const override
Definition driver.C:53
CppUnit::Test & _shimmed_test
Definition driver.C:56
virtual bool findTestPath(const std::string &testName, CppUnit::TestPath &testPath) const override
Definition driver.C:44
void reset(streamT &target)
Reset the proxy to point to a different target.
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
The PerfLog class allows monitoring of specific events.
Definition perf_log.h:154
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition perf_log.C:78
void enable_summarized_logs()
Tells the PerfLog to only print log results summarized by header.
Definition perf_log.h:199
static constexpr int added_whole_suite
Definition driver.C:60
libMesh::PerfLog * unitlog
Definition driver.C:220
libMesh::Parallel::Communicator * TestCommWorld
Definition driver.C:218
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
OStreamProxy out
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line.
Definition libmesh.C:1025
bool on_command_line(std::string arg)
Definition libmesh.C:934
int main()