summaryrefslogtreecommitdiff
path: root/src/mongo/unittest/unittest.h
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2019-10-02 00:03:00 +0000
committerevergreen <evergreen@mongodb.com>2019-10-02 00:03:00 +0000
commit6adefc73b4990253e4f277b49b119db1a05b7490 (patch)
treecbad4fe8afa2418bd2b7b4bd33303b0e6be66bc6 /src/mongo/unittest/unittest.h
parentdfb22aca7b1e62693fd5272d37239a40000c3d0e (diff)
downloadmongo-6adefc73b4990253e4f277b49b119db1a05b7490.tar.gz
SERVER-43367 unittest framework refactor/fixes
- Segregate old-style dbtests into their own Suite initialization system: OldStyleSuiteSpecification. This is where the funky deprecated features can live on without interfering with the Suite API. It also gives us a searchable base class to identify them in the future. OldStyleSuite has `setupTests()` and an `add<T>()` that Suite does not have. Suite API can shrink when it doesn't have to support these dbtest adaptor features. Suite only needs non-template `add(name, callback)`. - Add OldStyleSuiteInitializer to some dbtests that were missing it! These didn't use SuiteInstance to register themselves and were incorrect. They would self register, resulting in _allSuites() holding a std::shared_ptr to a static-duration Suite object! - Change `getSuite()` to return `Suite&` instead of `Suite*`. - No more "self-registering" in Suite constructor. Registration must be done as a separate post-construction step. This removes some unusual lifetime management code and is easier to document. Suite::getSuite(name) is the only way to make a Suite, and it does the make_shared and registration calls with a pseudo-private ConstructorEnable idiom. - Suite->run() returns std::unique_ptr<Result> instead of raw `Result*`. It's virtual to support OldStyleSuite behavior. - Suite._ran does nothing. Removed. - Result.cur does nothing. Removed. - Switch to pass-by-value and std::move for most ctor args. - Add explicit on 1-arg ctors. - Get rid of TestHolder. It's just a 2-field struct. - use fmt instead of snprintf - TEST and TEST_F macros: generate TEST_TYPE once. - TEST and TEST_F macros: inline the _agent variable. - Mark _doRun as `override`. - Terminology: replace CASE_NAME with SUITE_NAME. - rename DeathTestImpl -> DeathTestBase - move getDeathTestPattern into the test as a static member function - refactor out some repetition from the comparator decl macros - use if-constexpr and diamond relops to clean up the ComparisonAssertion class. - dbtests: conditionally skip some add<T> calls - further dedup (DEATH_)TEST(_F) macros
Diffstat (limited to 'src/mongo/unittest/unittest.h')
-rw-r--r--src/mongo/unittest/unittest.h505
1 files changed, 250 insertions, 255 deletions
diff --git a/src/mongo/unittest/unittest.h b/src/mongo/unittest/unittest.h
index 2d32dbc9cad..d1ec2d7d515 100644
--- a/src/mongo/unittest/unittest.h
+++ b/src/mongo/unittest/unittest.h
@@ -40,11 +40,13 @@
#include <functional>
#include <sstream>
#include <string>
+#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include "mongo/base/status_with.h"
+#include "mongo/base/string_data.h"
#include "mongo/logger/logstream_builder.h"
#include "mongo/logger/message_log_domain.h"
#include "mongo/unittest/bson_test_util.h"
@@ -191,13 +193,16 @@
* ASSERT_DOES_NOT_COMPILE(bool B = true, std::enable_if_t<B, int>{});
*
*/
-#define ASSERT_DOES_NOT_COMPILE(Alias, /*expr*/...) \
- static auto BOOST_PP_CAT(compileCheck_, __LINE__)(...)->std::true_type; \
- template <Alias> \
- static auto BOOST_PP_CAT(compileCheck_, __LINE__)(int) \
- ->std::conditional_t<true, std::false_type, decltype(__VA_ARGS__)>; \
- static_assert(decltype(BOOST_PP_CAT(compileCheck_, __LINE__)(0))::value, \
- "Expression '" #__VA_ARGS__ "' [with " #Alias "] shouldn't compile.");
+#define ASSERT_DOES_NOT_COMPILE(Alias, /*expr*/...) \
+ ASSERT_DOES_NOT_COMPILE_1_( \
+ BOOST_PP_CAT(compileCheck_, __LINE__), Alias, #Alias, (__VA_ARGS__), #__VA_ARGS__)
+
+#define ASSERT_DOES_NOT_COMPILE_1_(Id, Alias, AliasString, Expr, ExprString) \
+ static auto Id(...)->std::true_type; \
+ template <Alias> \
+ static auto Id(int)->std::conditional_t<true, std::false_type, decltype(Expr)>; \
+ static_assert(decltype(Id(0))::value, \
+ "Expression '" ExprString "' [with " AliasString "] shouldn't compile.");
/**
* This internal helper is used to ignore warnings about unused results. Some unit tests which test
@@ -261,7 +266,7 @@
} while (false)
/**
- * Construct a single test, named "TEST_NAME" within the test case "CASE_NAME".
+ * Construct a single test, named `TEST_NAME` within the test Suite `SUITE_NAME`.
*
* Usage:
*
@@ -269,22 +274,12 @@
* ASSERT_EQUALS(error_success, foo(invalidValue));
* }
*/
-#define TEST(CASE_NAME, TEST_NAME) \
- class UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, TEST_NAME) : public ::mongo::unittest::Test { \
- private: \
- virtual void _doTest(); \
- \
- static const RegistrationAgent<UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, TEST_NAME)> \
- _agent; \
- }; \
- const ::mongo::unittest::Test::RegistrationAgent<UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, \
- TEST_NAME)> \
- UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, TEST_NAME)::_agent(#CASE_NAME, #TEST_NAME); \
- void UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, TEST_NAME)::_doTest()
+#define TEST(SUITE_NAME, TEST_NAME) \
+ UNIT_TEST_DETAIL_DEFINE_TEST_(SUITE_NAME, TEST_NAME, ::mongo::unittest::Test)
/**
* Construct a single test named TEST_NAME that has access to a common class (a "fixture")
- * named "FIXTURE_NAME".
+ * named "FIXTURE_NAME". FIXTURE_NAME will be the name of the Suite in which the test appears.
*
* Usage:
*
@@ -298,29 +293,29 @@
* ASSERT_EQUALS(10, myVar);
* }
*/
-#define TEST_F(FIXTURE_NAME, TEST_NAME) \
- class UNIT_TEST_DETAIL_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME) : public FIXTURE_NAME { \
- private: \
- virtual void _doTest(); \
- \
- static const RegistrationAgent<UNIT_TEST_DETAIL_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME)> \
- _agent; \
- }; \
- const ::mongo::unittest::Test::RegistrationAgent<UNIT_TEST_DETAIL_TEST_TYPE_NAME(FIXTURE_NAME, \
- TEST_NAME)> \
- UNIT_TEST_DETAIL_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME)::_agent(#FIXTURE_NAME, \
- #TEST_NAME); \
- void UNIT_TEST_DETAIL_TEST_TYPE_NAME(FIXTURE_NAME, TEST_NAME)::_doTest()
+#define TEST_F(FIXTURE_NAME, TEST_NAME) \
+ UNIT_TEST_DETAIL_DEFINE_TEST_(FIXTURE_NAME, TEST_NAME, FIXTURE_NAME)
+
+#define UNIT_TEST_DETAIL_DEFINE_TEST_(SUITE_NAME, TEST_NAME, TEST_BASE) \
+ UNIT_TEST_DETAIL_DEFINE_TEST_PRIMITIVE_( \
+ SUITE_NAME, TEST_NAME, UNIT_TEST_DETAIL_TEST_TYPE_NAME(SUITE_NAME, TEST_NAME), TEST_BASE)
+
+#define UNIT_TEST_DETAIL_DEFINE_TEST_PRIMITIVE_(FIXTURE_NAME, TEST_NAME, TEST_TYPE, TEST_BASE) \
+ class TEST_TYPE : public TEST_BASE { \
+ private: \
+ void _doTest() override; \
+ static inline const RegistrationAgent<TEST_TYPE> _agent{#FIXTURE_NAME, #TEST_NAME}; \
+ }; \
+ void TEST_TYPE::_doTest()
/**
- * Macro to construct a type name for a test, from its "CASE_NAME" and "TEST_NAME".
+ * Macro to construct a type name for a test, from its `SUITE_NAME` and `TEST_NAME`.
* Do not use directly in test code.
*/
-#define UNIT_TEST_DETAIL_TEST_TYPE_NAME(CASE_NAME, TEST_NAME) \
- UnitTest_CaseName##CASE_NAME##TestName##TEST_NAME
+#define UNIT_TEST_DETAIL_TEST_TYPE_NAME(SUITE_NAME, TEST_NAME) \
+ UnitTest_SuiteName##SUITE_NAME##TestName##TEST_NAME
-namespace mongo {
-namespace unittest {
+namespace mongo::unittest {
class Result;
@@ -330,49 +325,155 @@ void setupTestLogger();
* Gets a LogstreamBuilder for logging to the unittest log domain, which may have
* different target from the global log domain.
*/
-mongo::logger::LogstreamBuilder log();
-mongo::logger::LogstreamBuilder warning();
+logger::LogstreamBuilder log();
+logger::LogstreamBuilder warning();
/**
- * Type representing the function composing a test.
+ * Representation of a collection of tests.
+ *
+ * One Suite is constructed for each SUITE_NAME when using the TEST macro.
+ *
+ * See `OldStyleSuiteSpecification` which adapts dbtests into this framework.
*/
-typedef std::function<void(void)> TestFunction;
+class Suite : public std::enable_shared_from_this<Suite> {
+private:
+ struct SuiteTest {
+ std::string name;
+ std::function<void()> fn;
+ };
+
+ struct ConstructorEnable {
+ explicit ConstructorEnable() = default;
+ };
+
+public:
+ explicit Suite(ConstructorEnable, std::string name);
+ Suite(const Suite&) = delete;
+ Suite& operator=(const Suite&) = delete;
+
+ void add(std::string name, std::function<void()> testFn);
+
+ std::unique_ptr<Result> run(const std::string& filter, int runsPerTest);
+
+ static int run(const std::vector<std::string>& suites,
+ const std::string& filter,
+ int runsPerTest);
+
+ /**
+ * Get a suite with the given name, creating and registering it if necessary.
+ * This is the only way to make a Suite object.
+ *
+ * Safe to call during static initialization.
+ */
+ static Suite& getSuite(const std::string& name);
+
+private:
+ std::string _name;
+ std::vector<SuiteTest> _tests;
+};
/**
- * Container holding a test function and its name. Suites
- * contain lists of these.
+ * Adaptor to set up a Suite from a dbtest-style suite.
+ * Support for deprecated dbtest-style test suites. Tests are are added by overriding setupTests()
+ * in a subclass of OldStyleSuiteSpecification, and defining an OldStyleSuiteInstance<T> object.
+ * This approach is
+ * deprecated.
+ *
+ * Example:
+ * class All : public OldStyleSuiteSpecification {
+ * public:
+ * All() : OldStyleSuiteSpecification("BunchaTests") {}
+ * void setupTests() {
+ * add<TestThis>();
+ * add<TestThat>();
+ * add<TestTheOtherThing>();
+ * }
+ * };
+ * OldStyleSuiteInitializer<All> all;
*/
-class TestHolder {
- TestHolder(const TestHolder&) = delete;
- TestHolder& operator=(const TestHolder&) = delete;
-
+class OldStyleSuiteSpecification {
public:
- TestHolder(const std::string& name, const TestFunction& fn) : _name(name), _fn(fn) {}
+ struct SuiteTest {
+ std::string name;
+ std::function<void()> fn;
+ };
- ~TestHolder() {}
- void run() const {
- _fn();
- }
- std::string getName() const {
+ OldStyleSuiteSpecification(std::string name) : _name(std::move(name)) {}
+ virtual ~OldStyleSuiteSpecification() = default;
+
+ // Note: setupTests() is run by a OldStyleSuiteInitializer at static initialization time.
+ // It should in most cases be just a simple sequence of add<T>() calls.
+ virtual void setupTests() = 0;
+
+ const std::string& name() const {
return _name;
}
+ const std::vector<SuiteTest>& tests() const {
+ return _tests;
+ }
+
+protected:
+ /**
+ * Add an old-style test of type `T` to this Suite, saving any test constructor args
+ * that would be needed at test run time.
+ * The added test's name will be synthesized as the demangled typename of T.
+ * At test run time, the test will be created and run with `T(args...).run()`.
+ */
+ template <typename T, typename... Args>
+ void add(Args&&... args) {
+ addNameCallback(nameForTestClass<T>(), [=] { T(args...).run(); });
+ }
+
+ void addNameCallback(std::string name, std::function<void()> cb) {
+ _tests.push_back({std::move(name), std::move(cb)});
+ }
+
+ template <typename T>
+ static std::string nameForTestClass() {
+ return demangleName(typeid(T));
+ }
+
private:
std::string _name;
- TestFunction _fn;
+ std::vector<SuiteTest> _tests;
+};
+
+/**
+ * Define a namespace-scope instance of `OldStyleSuiteInitializer<T>` to properly create and
+ * initialize an instance of `T` (an `OldStyleSuiteSpecification`). See
+ * `OldStyleSuiteSpecification`.
+ */
+template <typename T>
+struct OldStyleSuiteInitializer {
+ template <typename... Args>
+ explicit OldStyleSuiteInitializer(Args&&... args) {
+ T t(std::forward<Args>(args)...);
+ init(t);
+ }
+
+ void init(OldStyleSuiteSpecification& suiteSpec) const {
+ log() << "\t about to setupTests" << std::endl;
+ suiteSpec.setupTests();
+ log() << "\t done setupTests" << std::endl;
+ auto& suite = Suite::getSuite(suiteSpec.name());
+ for (auto&& t : suiteSpec.tests()) {
+ suite.add(t.name, t.fn);
+ }
+ }
};
+
/**
* Base type for unit test fixtures. Also, the default fixture type used
* by the TEST() macro.
*/
class Test {
- Test(const Test&) = delete;
- Test& operator=(const Test&) = delete;
-
public:
Test();
virtual ~Test();
+ Test(const Test&) = delete;
+ Test& operator=(const Test&) = delete;
void run();
@@ -388,21 +489,27 @@ public:
protected:
/**
- * Registration agent for adding tests to suites, used by TEST macro.
+ * Adds a Test to a Suite, used by TEST/TEST_F macros.
*/
template <typename T>
class RegistrationAgent {
- RegistrationAgent(const RegistrationAgent&) = delete;
- RegistrationAgent& operator=(const RegistrationAgent&) = delete;
-
public:
- RegistrationAgent(const std::string& suiteName, const std::string& testName);
- std::string getSuiteName() const;
- std::string getTestName() const;
+ RegistrationAgent(std::string suiteName, std::string testName)
+ : _suiteName(std::move(suiteName)), _testName(std::move(testName)) {
+ Suite::getSuite(_suiteName).add(_testName, [] { T{}.run(); });
+ }
+
+ const std::string& getSuiteName() const {
+ return _suiteName;
+ }
+
+ const std::string& getTestName() const {
+ return _testName;
+ }
private:
- const std::string _suiteName;
- const std::string _testName;
+ std::string _suiteName;
+ std::string _testName;
};
/**
@@ -457,103 +564,6 @@ private:
};
/**
- * Representation of a collection of tests.
- *
- * One suite is constructed for each "CASE_NAME" when using the TEST macro.
- * Additionally, tests that are part of dbtests are manually assigned to suites
- * by the programmer by overriding setupTests() in a subclass of Suite. This
- * approach is deprecated.
- */
-class Suite {
- Suite(const Suite&) = delete;
- Suite& operator=(const Suite&) = delete;
-
-public:
- Suite(const std::string& name);
- virtual ~Suite();
-
- template <class T>
- void add() {
- add<T>(demangleName(typeid(T)));
- }
-
- template <class T, class A>
- void add(const A& a) {
- add(demangleName(typeid(T)), [a] {
- T testObj(a);
- testObj.run();
- });
- }
-
- template <class T>
- void add(const std::string& name) {
- add(name, [] {
- T testObj;
- testObj.run();
- });
- }
-
- void add(const std::string& name, const TestFunction& testFn);
-
- Result* run(const std::string& filter, int runsPerTest);
-
- static int run(const std::vector<std::string>& suites,
- const std::string& filter,
- int runsPerTest);
-
- /**
- * Get a suite with the given name, creating it if necessary.
- *
- * The implementation of this function must be safe to call during the global static
- * initialization block before main() executes.
- */
- static Suite* getSuite(const std::string& name);
-
-protected:
- virtual void setupTests();
-
-private:
- typedef std::vector<std::unique_ptr<TestHolder>> TestHolderList;
-
- std::string _name;
- TestHolderList _tests;
- bool _ran;
-
- void registerSuite(const std::string& name, Suite* s);
-};
-
-// A type that makes it easy to declare a self registering suite for old style test
-// declarations. Suites are self registering so this is *not* a memory leak.
-template <typename T>
-struct SuiteInstance {
- SuiteInstance() {
- new T;
- }
-
- template <typename U>
- SuiteInstance(const U& u) {
- new T(u);
- }
-};
-
-template <typename T>
-Test::RegistrationAgent<T>::RegistrationAgent(const std::string& suiteName,
- const std::string& testName)
- : _suiteName(suiteName), _testName(testName) {
- Suite::getSuite(suiteName)->add<T>(testName);
-}
-
-template <typename T>
-std::string Test::RegistrationAgent<T>::getSuiteName() const {
- return _suiteName;
-}
-
-template <typename T>
-std::string Test::RegistrationAgent<T>::getTestName() const {
- return _testName;
-}
-
-/**
* Exception thrown when a test assertion fails.
*
* Typically thrown by helpers in the TestAssertion class and its ilk, below.
@@ -619,45 +629,36 @@ enum class ComparisonOp { kEq, kNe, kLt, kLe, kGt, kGe };
template <ComparisonOp op>
class ComparisonAssertion {
private:
- template <ComparisonOp val>
- using OpTag = std::integral_constant<ComparisonOp, val>;
-
- static auto comparator(OpTag<ComparisonOp::kEq>) {
- return [](auto&& a, auto&& b) { return a == b; };
- }
- static auto comparator(OpTag<ComparisonOp::kNe>) {
- return [](auto&& a, auto&& b) { return a != b; };
- }
- static auto comparator(OpTag<ComparisonOp::kLt>) {
- return [](auto&& a, auto&& b) { return a < b; };
- }
- static auto comparator(OpTag<ComparisonOp::kLe>) {
- return [](auto&& a, auto&& b) { return a <= b; };
- }
- static auto comparator(OpTag<ComparisonOp::kGt>) {
- return [](auto&& a, auto&& b) { return a > b; };
- }
- static auto comparator(OpTag<ComparisonOp::kGe>) {
- return [](auto&& a, auto&& b) { return a >= b; };
+ static constexpr auto comparator() {
+ if constexpr (op == ComparisonOp::kEq) {
+ return std::equal_to<>{};
+ } else if constexpr (op == ComparisonOp::kNe) {
+ return std::not_equal_to<>{};
+ } else if constexpr (op == ComparisonOp::kLt) {
+ return std::less<>{};
+ } else if constexpr (op == ComparisonOp::kLe) {
+ return std::less_equal<>{};
+ } else if constexpr (op == ComparisonOp::kGt) {
+ return std::greater<>{};
+ } else if constexpr (op == ComparisonOp::kGe) {
+ return std::greater_equal<>{};
+ }
}
- static constexpr StringData name(OpTag<ComparisonOp::kEq>) {
- return "=="_sd;
- }
- static constexpr StringData name(OpTag<ComparisonOp::kNe>) {
- return "!="_sd;
- }
- static constexpr StringData name(OpTag<ComparisonOp::kLt>) {
- return "<"_sd;
- }
- static constexpr StringData name(OpTag<ComparisonOp::kLe>) {
- return "<="_sd;
- }
- static constexpr StringData name(OpTag<ComparisonOp::kGt>) {
- return ">"_sd;
- }
- static constexpr StringData name(OpTag<ComparisonOp::kGe>) {
- return ">="_sd;
+ static constexpr StringData name() {
+ if constexpr (op == ComparisonOp::kEq) {
+ return "=="_sd;
+ } else if constexpr (op == ComparisonOp::kNe) {
+ return "!="_sd;
+ } else if constexpr (op == ComparisonOp::kLt) {
+ return "<"_sd;
+ } else if constexpr (op == ComparisonOp::kLe) {
+ return "<="_sd;
+ } else if constexpr (op == ComparisonOp::kGt) {
+ return ">"_sd;
+ } else if constexpr (op == ComparisonOp::kGe) {
+ return ">="_sd;
+ }
}
template <typename A, typename B>
@@ -667,13 +668,12 @@ private:
StringData bExpression,
const A& a,
const B& b) {
- if (comparator(OpTag<op>{})(a, b)) {
+ if (comparator()(a, b)) {
return;
}
std::ostringstream os;
- StringData opName = name(OpTag<op>{});
- os << "Expected " << aExpression << " " << opName << " " << bExpression << " (" << a << " "
- << opName << " " << b << ")";
+ os << "Expected " << aExpression << " " << name() << " " << bExpression << " (" << a << " "
+ << name() << " " << b << ")";
_assertion = std::make_unique<TestAssertionFailure>(theFile, theLine, os.str());
}
@@ -722,61 +722,57 @@ private:
std::unique_ptr<TestAssertionFailure> _assertion;
};
-// Explicit instantiation of ComparisonAssertion ctor and factory for a pair of types.
-#define TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(EXTERN, OP, A, B) \
+// Explicit instantiation of ComparisonAssertion ctor and factory, for "A OP B".
+#define TEMPLATE_COMPARISON_ASSERTION_CTOR_A_OP_B(EXTERN, OP, A, B) \
EXTERN template ComparisonAssertion<ComparisonOp::OP>::ComparisonAssertion( \
const char*, unsigned, StringData, StringData, const A&, const B&); \
EXTERN template ComparisonAssertion<ComparisonOp::OP> \
ComparisonAssertion<ComparisonOp::OP>::make( \
- const char*, unsigned, StringData, StringData, const A&, const B&); \
- EXTERN template ComparisonAssertion<ComparisonOp::OP>::ComparisonAssertion( \
- const char*, unsigned, StringData, StringData, const B&, const A&); \
- EXTERN template ComparisonAssertion<ComparisonOp::OP> \
- ComparisonAssertion<ComparisonOp::OP>::make( \
- const char*, unsigned, StringData, StringData, const B&, const A&)
+ const char*, unsigned, StringData, StringData, const A&, const B&);
+
+// Explicit instantiation of ComparisonAssertion ctor and factory for a pair of types.
+#define TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(EXTERN, OP, A, B) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_A_OP_B(EXTERN, OP, A, B) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_A_OP_B(EXTERN, OP, B, A)
// Explicit instantiation of ComparisonAssertion ctor and factory for a single type.
-#define TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(EXTERN, OP, T) \
- EXTERN template ComparisonAssertion<ComparisonOp::OP>::ComparisonAssertion( \
- const char*, unsigned, StringData, StringData, const T&, const T&); \
- EXTERN template ComparisonAssertion<ComparisonOp::OP> \
- ComparisonAssertion<ComparisonOp::OP>::make( \
- const char*, unsigned, StringData, StringData, const T&, const T&)
+#define TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(EXTERN, OP, T) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_A_OP_B(EXTERN, OP, T, T)
// Call with `extern` to declace extern instantiations, and with no args to explicitly instantiate.
-#define INSTANTIATE_COMPARISON_ASSERTION_CTORS(...) \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kEq>; \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kNe>; \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kGt>; \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kGe>; \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kLt>; \
- __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kLe>; \
- \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, int); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, long long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, unsigned int); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, unsigned long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, unsigned long long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, bool); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, double); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, OID); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, BSONType); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, Timestamp); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, Date_t); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, Status); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kEq, ErrorCodes::Error); \
- \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, int, long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, int, long long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, long, long long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, unsigned int, unsigned long); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, Status, ErrorCodes::Error); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_CROSS(__VA_ARGS__, kEq, ErrorCodes::Error, int); \
- \
- /* These are the only types that are often used with ASSERT_NE*/ \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kNe, Status); \
- TEMPLATE_COMPARISON_ASSERTION_CTOR_SELF(__VA_ARGS__, kNe, unsigned long);
+#define INSTANTIATE_COMPARISON_ASSERTION_CTORS(...) \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kEq>; \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kNe>; \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kGt>; \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kGe>; \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kLt>; \
+ __VA_ARGS__ template class ComparisonAssertion<ComparisonOp::kLe>; \
+ \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, int) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, long long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, unsigned int) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, unsigned long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, unsigned long long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, bool) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, double) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, OID) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, BSONType) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, Timestamp) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, Date_t) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, Status) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kEq, ErrorCodes::Error) \
+ \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, int, long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, int, long long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, long, long long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, unsigned int, unsigned long) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, Status, ErrorCodes::Error) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_SYMMETRIC(__VA_ARGS__, kEq, ErrorCodes::Error, int) \
+ \
+ /* These are the only types that are often used with ASSERT_NE*/ \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kNe, Status) \
+ TEMPLATE_COMPARISON_ASSERTION_CTOR_REFLEXIVE(__VA_ARGS__, kNe, unsigned long)
// Declare that these definitions will be provided in unittest.cpp.
INSTANTIATE_COMPARISON_ASSERTION_CTORS(extern);
@@ -801,5 +797,4 @@ T assertGet(StatusWith<T>&& swt) {
*/
std::vector<std::string> getAllSuiteNames();
-} // namespace unittest
-} // namespace mongo
+} // namespace mongo::unittest