Skip to content

Commit

Permalink
Googletest export
Browse files Browse the repository at this point in the history
Add GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST to mark a paramaterized test as allowed to be un-instantiated.

This allows test suites, that are defined in libraries and, for other reasons, get linked in (which should probably be avoided, but isn't always possible) to be marked as allowed to go uninstantiated.

This can also be used to grandfather existing issues and expedite adoption of the checks with regards to new cases before they can be fixed.

PiperOrigin-RevId: 289581573
  • Loading branch information
Abseil Team authored and vslashg committed Jan 16, 2020
1 parent ed16134 commit 0b024bd
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 1 deletion.
11 changes: 11 additions & 0 deletions googletest/docs/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,17 @@ function scope.
NOTE: Don't forget this step! If you do your test will silently pass, but none
of its suites will ever run!
There is work in progress to make omitting `INSTANTIATE_TEST_SUITE_P` show up
under the `GoogleTestVerification` test suite and to then make that an error.
If you have a test suite where that omission is not an error, for example it is
in a library that may be linked in for other reason or where the list of test
cases is dynamic and may be empty, then this check can be suppressed by tagging
the test suite:
```c++
GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(FooTest);
```

To distinguish different instances of the pattern (yes, you can instantiate it
more than once), the first argument to `INSTANTIATE_TEST_SUITE_P` is a prefix
that will be added to the actual test suite name. Remember to pick unique
Expand Down
7 changes: 7 additions & 0 deletions googletest/include/gtest/gtest-param-test.h
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,13 @@ internal::CartesianProductHolder<Generator...> Combine(const Generator&... g) {
&gtest_##prefix##test_suite_name##_EvalGenerateName_, \
__FILE__, __LINE__)


// Allow Marking a Parameterized test class as not needing to be instantiated.
#define GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(T) \
namespace gtest_do_not_use_outside_namespace_scope {} \
static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \
GTEST_STRINGIFY_(T))

// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
#define INSTANTIATE_TEST_CASE_P \
Expand Down
2 changes: 2 additions & 0 deletions googletest/include/gtest/gtest.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ class FuchsiaDeathTest;
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
const std::string& message);
std::set<std::string>* GetIgnoredParameterizedTestSuites();

} // namespace internal

Expand Down Expand Up @@ -1418,6 +1419,7 @@ class GTEST_API_ UnitTest {
friend class internal::StreamingListenerTest;
friend class internal::UnitTestRecordPropertyTestHelper;
friend Environment* AddGlobalTestEnvironment(Environment* env);
friend std::set<std::string>* internal::GetIgnoredParameterizedTestSuites();
friend internal::UnitTestImpl* internal::GetUnitTestImpl();
friend void internal::ReportFailureInUnknownLocation(
TestPartResult::Type result_type,
Expand Down
8 changes: 8 additions & 0 deletions googletest/include/gtest/internal/gtest-param-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,14 @@ class ParameterizedTestSuiteInfoBase {
GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase);
};

// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Report a the name of a test_suit as safe to ignore
// as the side effect of construction of this type.
struct MarkAsIgnored {
explicit MarkAsIgnored(const char* test_suite);
};

GTEST_API_ void InsertSyntheticTestCase(const std::string& name,
CodeLocation location);

Expand Down
8 changes: 8 additions & 0 deletions googletest/src/gtest-internal-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,10 @@ class GTEST_API_ UnitTestImpl {
return parameterized_test_registry_;
}

std::set<std::string>* ignored_parameterized_test_suites() {
return &ignored_parameterized_test_suites_;
}

// Returns TypeParameterizedTestSuiteRegistry object used to keep track of
// type-parameterized tests and instantiations of them.
internal::TypeParameterizedTestSuiteRegistry&
Expand Down Expand Up @@ -884,6 +888,10 @@ class GTEST_API_ UnitTestImpl {
internal::TypeParameterizedTestSuiteRegistry
type_parameterized_test_registry_;

// The set holding the name of parameterized
// test suites that may go uninstantiated.
std::set<std::string> ignored_parameterized_test_suites_;

// Indicates whether RegisterParameterizedTests() has been called already.
bool parameterized_tests_registered_;

Expand Down
19 changes: 18 additions & 1 deletion googletest/src/gtest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -444,9 +444,21 @@ class FailureTest : public Test {

} // namespace

std::set<std::string>* GetIgnoredParameterizedTestSuites() {
return UnitTest::GetInstance()->impl()->ignored_parameterized_test_suites();
}

// Add a given test_suit to the list of them allow to go un-instantiated.
MarkAsIgnored::MarkAsIgnored(const char* test_suite) {
GetIgnoredParameterizedTestSuites()->insert(test_suite);
}

// If this parameterized test suite has no instantiations (and that
// has not been marked as okay), emit a test case reporting that.
void InsertSyntheticTestCase(const std::string &name, CodeLocation location) {
const auto& ignored = *GetIgnoredParameterizedTestSuites();
if (ignored.find(name) != ignored.end()) return;

std::string message =
"Paramaterized test suite " + name +
" is defined via TEST_P, but never instantiated. None of the test cases "
Expand All @@ -455,7 +467,12 @@ void InsertSyntheticTestCase(const std::string &name, CodeLocation location) {
"\n\n"
"Ideally, TEST_P definitions should only ever be included as part of "
"binaries that intend to use them. (As opposed to, for example, being "
"placed in a library that may be linked in to get other utilities.)";
"placed in a library that may be linked in to get other utilities.)"
"\n\n"
"To suppress this error for this test suite, insert the following line "
"(in a non-header) in the namespace it is defined in:"
"\n\n"
"GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(" + name + ");";

std::string full_name = "UninstantiatedParamaterizedTestSuite<" + name + ">";
RegisterTest( //
Expand Down
4 changes: 4 additions & 0 deletions googletest/test/googletest-output-test-golden-lin.txt
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,10 @@ Stack trace: (omitted)
Paramaterized test suite DetectNotInstantiatedTest is defined via TEST_P, but never instantiated. None of the test cases will run. Either no INSTANTIATE_TEST_SUITE_P is provided or the only ones provided expand to nothing.

Ideally, TEST_P definitions should only ever be included as part of binaries that intend to use them. (As opposed to, for example, being placed in a library that may be linked in to get other utilities.)

To suppress this error for this test suite, insert the following line (in a non-header) in the namespace it is defined in:

GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(DetectNotInstantiatedTest);
[ OK ] GoogleTestVerification.UninstantiatedParamaterizedTestSuite<DetectNotInstantiatedTest>
[ RUN ] GoogleTestVerification.UninstantiatedTypeParamaterizedTestSuite<DetectNotInstantiatedTypesTest>
Type paramaterized test suite DetectNotInstantiatedTypesTest is defined via REGISTER_TYPED_TEST_SUITE_P, but never instantiated via INSTANTIATE_TYPED_TEST_SUITE_P. None of the test cases will run.
Expand Down
11 changes: 11 additions & 0 deletions googletest/test/googletest-param-test-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,17 @@ class NotUsedTest : public testing::TestWithParam<int> {};
template <typename T>
class NotUsedTypeTest : public testing::Test {};
TYPED_TEST_SUITE_P(NotUsedTypeTest);

// Used but not instantiated, this would fail. but...
class NotInstantiatedTest : public testing::TestWithParam<int> {};
// ... we mark is as allowed.
GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(NotInstantiatedTest);

TEST_P(NotInstantiatedTest, Used) { }

using OtherName = NotInstantiatedTest;
GTEST_ALLOW_UNINSTANTIATED_PARAMTERIZED_TEST(OtherName);
TEST_P(OtherName, Used) { }
} // namespace works_here

int main(int argc, char **argv) {
Expand Down

0 comments on commit 0b024bd

Please sign in to comment.