33#include <cppunit/extensions/TestFactoryRegistry.h>
44#include <cppunit/ui/text/TestRunner.h>
55#include <cppunit/BriefTestProgressListener.h>
6+ #include <cppunit/TestPath.h>
67#include <cppunit/TestResult.h>
78#include <libmesh/restore_warnings.h>
89
1718// C++ includes
1819#include <regex>
1920
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+
2059// Add Tests to runner that match user-provided regex.
2160int add_matching_tests_to_runner (CppUnit ::Test * test ,
2261 const std ::string & allow_r_str ,
2362 const std ::regex & allow_r ,
2463 const std ::string & deny_r_str ,
2564 const std ::regex & deny_r ,
26- CppUnit ::TextUi ::TestRunner & runner ,
27- CppUnit ::TestSuite & rejects )
65+ CppUnit ::TextUi ::TestRunner & runner )
2866{
2967 int n_tests_added = 0 ;
3068
@@ -46,18 +84,17 @@ int add_matching_tests_to_runner(CppUnit::Test * test,
4684 {
4785 libMesh ::out << test -> getName () << std ::endl ;
4886 n_tests_added ++ ;
49- runner .addTest (test );
87+
88+ // yes, explicit new; this is how CppUnit works
89+ runner .addTest (new TestShim (* test ));
5090 }
51- // Add the test to the rejects it can be cleaned up later
52- else
53- rejects .addTest (test );
5491 }
5592
5693 // Call this recursively on each of our children, if any.
5794 for (int i = 0 ; i < test -> getChildTestCount (); i ++ )
5895 n_tests_added +=
5996 add_matching_tests_to_runner (test -> getChildTestAt (i ), allow_r_str , allow_r ,
60- deny_r_str , deny_r , runner , rejects );
97+ deny_r_str , deny_r , runner );
6198
6299 return n_tests_added ;
63100}
@@ -128,10 +165,6 @@ int main(int argc, char ** argv)
128165 CppUnit ::TestFactoryRegistry & registry = CppUnit ::TestFactoryRegistry ::getRegistry ();
129166 CppUnit ::Test * suite = registry .makeTest ();
130167
131- // A test suite container for holding tests not matching the regex. When main's
132- // scope ends, this class's destructor will delete the rejected tests
133- CppUnit ::TestSuite rejects ("rejects" );
134-
135168#ifdef LIBMESH_HAVE_CXX11_REGEX
136169 // Make regex objects from user's input.
137170 const std ::regex allow_regex (allow_regex_string );
@@ -143,9 +176,12 @@ int main(int argc, char ** argv)
143176 add_matching_tests_to_runner (suite ,
144177 allow_regex_string , allow_regex ,
145178 deny_regex_string , deny_regex ,
146- runner , rejects );
179+ runner );
147180 if (n_tests_added >= 0 )
148181 libMesh ::out << "--- Running " << n_tests_added << " tests in total." << std ::endl ;
182+
183+ // If we didn't add the whole suite to the runner, we need to clean
184+ // it up ourselves
149185 if (n_tests_added != -12345 )
150186 owned_suite .reset (suite );
151187#else
0 commit comments