From 75c46c112dbaf567075b4de791d014007d61f764 Mon Sep 17 00:00:00 2001 From: perryzhou Date: Tue, 28 May 2024 17:10:33 +0800 Subject: [PATCH 01/48] =?UTF-8?q?fix(log):=20=E5=86=99=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=80=92=E5=BD=92=E5=AF=BC=E8=87=B4=E6=A0=88=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mars/xlog/src/appender.cc | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/mars/xlog/src/appender.cc b/mars/xlog/src/appender.cc index 652f5949f..b07f10063 100644 --- a/mars/xlog/src/appender.cc +++ b/mars/xlog/src/appender.cc @@ -183,29 +183,25 @@ void XloggerAppender::Write(const XLoggerInfo* _info, const char* _log) { if (g_log_write_callback) { g_log_write_callback(_info, _log); } + if (recursion_count > 10) + return; - if (2 <= recursion_count && recursion_str.empty()) { - if (recursion_count > 10) - return; - - recursion_str.resize(kMaxDumpLength); - XLoggerInfo info = *_info; + if (recursion_str.empty()) { + + XLoggerInfo info = XLOGGER_INFO_INITIALIZER; + if (_info != nullptr){ + info = *_info; + } info.level = kLevelFatal; - - char recursive_log[256] = {0}; - snprintf(recursive_log, - sizeof(recursive_log), + + recursion_str.resize(kMaxDumpLength); + int length = snprintf(&recursion_str[0],kMaxDumpLength, "ERROR!!! xlogger_appender Recursive calls!!!, count:%u", recursion_count); - - PtrBuffer tmp((void*)recursion_str.data(), 0, kMaxDumpLength); - log_formater(&info, recursive_log, tmp); - - if (recursion_str.capacity() >= strnlen(_log, kMaxDumpLength)) { - recursion_str += _log; + if (length > 0){ + recursion_str.resize(length); + ConsoleLog(&info, recursion_str.c_str()); } - - ConsoleLog(&info, recursion_str.c_str()); } else { if (!recursion_str.empty()) { WriteTips2File(recursion_str.c_str()); From 4b5b8988cba2ef87167cbd982787a9d0f172ed91 Mon Sep 17 00:00:00 2001 From: perryzhou Date: Wed, 29 May 2024 18:20:11 +0800 Subject: [PATCH 02/48] fix(comm): certverify memory leak --- mars/comm/objc/platform_comm.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mars/comm/objc/platform_comm.mm b/mars/comm/objc/platform_comm.mm index b877e29cf..5c68eef95 100644 --- a/mars/comm/objc/platform_comm.mm +++ b/mars/comm/objc/platform_comm.mm @@ -559,7 +559,9 @@ int OSVerifyCertificate(const std::string& hostname, const std::vector Date: Wed, 29 May 2024 18:21:27 +0800 Subject: [PATCH 03/48] fix(comm): certverify memory leak --- mars/comm/objc/platform_comm.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mars/comm/objc/platform_comm.mm b/mars/comm/objc/platform_comm.mm index b877e29cf..5c68eef95 100644 --- a/mars/comm/objc/platform_comm.mm +++ b/mars/comm/objc/platform_comm.mm @@ -559,7 +559,9 @@ int OSVerifyCertificate(const std::string& hostname, const std::vector Date: Thu, 30 May 2024 10:30:57 +0800 Subject: [PATCH 04/48] =?UTF-8?q?fix(log):=20=E5=86=99=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=80=92=E5=BD=92=E5=AF=BC=E8=87=B4=E6=A0=88=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mars/xlog/src/appender.cc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/mars/xlog/src/appender.cc b/mars/xlog/src/appender.cc index b07f10063..2fcbfa2ce 100644 --- a/mars/xlog/src/appender.cc +++ b/mars/xlog/src/appender.cc @@ -186,26 +186,27 @@ void XloggerAppender::Write(const XLoggerInfo* _info, const char* _log) { if (recursion_count > 10) return; - if (recursion_str.empty()) { - + if (recursion_count > 2 && recursion_str.empty()) { XLoggerInfo info = XLOGGER_INFO_INITIALIZER; - if (_info != nullptr){ + if (_info != nullptr) { info = *_info; } info.level = kLevelFatal; - + recursion_str.resize(kMaxDumpLength); - int length = snprintf(&recursion_str[0],kMaxDumpLength, - "ERROR!!! xlogger_appender Recursive calls!!!, count:%u", - recursion_count); - if (length > 0){ + int length = snprintf(&recursion_str[0], + kMaxDumpLength, + "ERROR!!! xlogger_appender Recursive calls!!!, count:%u", + recursion_count); + if (length > 0) { recursion_str.resize(length); ConsoleLog(&info, recursion_str.c_str()); } } else { if (!recursion_str.empty()) { - WriteTips2File(recursion_str.c_str()); + std::string dump = recursion_str; recursion_str.clear(); + WriteTips2File(dump.c_str()); } if (kAppenderSync == config_.mode_) @@ -260,7 +261,8 @@ void XloggerAppender::Close() { thread_moveold_ = nullptr; thread_timeout_log_ = nullptr; - if (log_close_) return; + if (log_close_) + return; char mark_info[512] = {0}; __GetMarkInfo(mark_info, sizeof(mark_info)); @@ -283,7 +285,7 @@ void XloggerAppender::Close() { CloseMmapFile(mmap_file_); } else { if (nullptr != log_buff_) { - delete[](char*)((log_buff_->GetData()).Ptr()); + delete[] (char*)((log_buff_->GetData()).Ptr()); } } @@ -1223,7 +1225,7 @@ void XloggerAppender::TreatMappingAsFileAndFlush(TFileIOAction* _result) { } else { log_buff_ = new LogZlibBuffer(data.release(), kBufferBlockLength, true, config_.pub_key_.c_str()); } - + log_close_ = false; // try write mapping to logfile From 7cf40e659158bfe6d49189bba2342374ebac938c Mon Sep 17 00:00:00 2001 From: perryzhou Date: Thu, 30 May 2024 10:31:42 +0800 Subject: [PATCH 05/48] =?UTF-8?q?fix(log):=20=E5=86=99=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E9=80=92=E5=BD=92=E5=AF=BC=E8=87=B4=E6=A0=88=E6=BA=A2=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mars/xlog/src/appender.cc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/mars/xlog/src/appender.cc b/mars/xlog/src/appender.cc index b07f10063..2fcbfa2ce 100644 --- a/mars/xlog/src/appender.cc +++ b/mars/xlog/src/appender.cc @@ -186,26 +186,27 @@ void XloggerAppender::Write(const XLoggerInfo* _info, const char* _log) { if (recursion_count > 10) return; - if (recursion_str.empty()) { - + if (recursion_count > 2 && recursion_str.empty()) { XLoggerInfo info = XLOGGER_INFO_INITIALIZER; - if (_info != nullptr){ + if (_info != nullptr) { info = *_info; } info.level = kLevelFatal; - + recursion_str.resize(kMaxDumpLength); - int length = snprintf(&recursion_str[0],kMaxDumpLength, - "ERROR!!! xlogger_appender Recursive calls!!!, count:%u", - recursion_count); - if (length > 0){ + int length = snprintf(&recursion_str[0], + kMaxDumpLength, + "ERROR!!! xlogger_appender Recursive calls!!!, count:%u", + recursion_count); + if (length > 0) { recursion_str.resize(length); ConsoleLog(&info, recursion_str.c_str()); } } else { if (!recursion_str.empty()) { - WriteTips2File(recursion_str.c_str()); + std::string dump = recursion_str; recursion_str.clear(); + WriteTips2File(dump.c_str()); } if (kAppenderSync == config_.mode_) @@ -260,7 +261,8 @@ void XloggerAppender::Close() { thread_moveold_ = nullptr; thread_timeout_log_ = nullptr; - if (log_close_) return; + if (log_close_) + return; char mark_info[512] = {0}; __GetMarkInfo(mark_info, sizeof(mark_info)); @@ -283,7 +285,7 @@ void XloggerAppender::Close() { CloseMmapFile(mmap_file_); } else { if (nullptr != log_buff_) { - delete[](char*)((log_buff_->GetData()).Ptr()); + delete[] (char*)((log_buff_->GetData()).Ptr()); } } @@ -1223,7 +1225,7 @@ void XloggerAppender::TreatMappingAsFileAndFlush(TFileIOAction* _result) { } else { log_buff_ = new LogZlibBuffer(data.release(), kBufferBlockLength, true, config_.pub_key_.c_str()); } - + log_close_ = false; // try write mapping to logfile From aac2faa6db32e9f936d3eec9837723fd9a783003 Mon Sep 17 00:00:00 2001 From: perryzhou Date: Tue, 4 Jun 2024 15:07:00 +0800 Subject: [PATCH 06/48] feat(stn): update googletest --- mars/boot/context.h | 7 +- mars/comm/ini.h | 12 + mars/googlemock/.clang-format | 4 + mars/googlemock/include/gmock/gmock-actions.h | 1096 +++++++--- .../include/gmock/gmock-cardinalities.h | 12 +- .../include/gmock/gmock-function-mocker.h | 141 +- .../googlemock/include/gmock/gmock-matchers.h | 799 ++++--- .../include/gmock/gmock-more-actions.h | 621 +++--- .../include/gmock/gmock-more-matchers.h | 64 +- .../include/gmock/gmock-nice-strict.h | 40 +- .../include/gmock/gmock-spec-builders.h | 652 +++--- mars/googlemock/include/gmock/gmock.h | 8 +- .../include/gmock/internal/custom/README.md | 2 + .../internal/custom/gmock-generated-actions.h | 3 +- .../gmock/internal/custom/gmock-matchers.h | 7 +- .../gmock/internal/custom/gmock-port.h | 5 +- .../gmock/internal/gmock-internal-utils.h | 138 +- .../include/gmock/internal/gmock-port.h | 86 +- mars/googlemock/src/gmock-cardinalities.cc | 12 +- mars/googlemock/src/gmock-internal-utils.cc | 119 +- mars/googlemock/src/gmock-matchers.cc | 30 +- mars/googlemock/src/gmock-spec-builders.cc | 265 +-- mars/googlemock/src/gmock.cc | 64 +- mars/googlemock/src/gmock_main.cc | 13 +- mars/googletest/.clang-format | 4 + .../include/gtest/gtest-assertion-result.h | 237 ++ .../include/gtest/gtest-death-test.h | 93 +- .../googletest/include/gtest/gtest-matchers.h | 105 +- mars/googletest/include/gtest/gtest-message.h | 65 +- .../include/gtest/gtest-param-test.h | 125 +- .../googletest/include/gtest/gtest-printers.h | 208 +- mars/googletest/include/gtest/gtest-spi.h | 134 +- .../include/gtest/gtest-test-part.h | 20 +- .../include/gtest/gtest-typed-test.h | 72 +- mars/googletest/include/gtest/gtest.h | 631 ++---- .../include/gtest/gtest_pred_impl.h | 200 +- mars/googletest/include/gtest/gtest_prod.h | 9 +- .../include/gtest/internal/custom/README.md | 12 - .../internal/gtest-death-test-internal.h | 81 +- .../include/gtest/internal/gtest-filepath.h | 34 +- .../include/gtest/internal/gtest-internal.h | 346 +-- .../include/gtest/internal/gtest-param-util.h | 253 ++- .../include/gtest/internal/gtest-port-arch.h | 106 +- .../include/gtest/internal/gtest-port.h | 1382 ++++++------ .../include/gtest/internal/gtest-string.h | 21 +- .../include/gtest/internal/gtest-type-util.h | 55 +- mars/googletest/src/gtest-all.cc | 3 +- mars/googletest/src/gtest-assertion-result.cc | 77 + mars/googletest/src/gtest-death-test.cc | 623 +++--- mars/googletest/src/gtest-filepath.cc | 187 +- mars/googletest/src/gtest-internal-inl.h | 265 ++- mars/googletest/src/gtest-matchers.cc | 5 +- mars/googletest/src/gtest-port.cc | 447 ++-- mars/googletest/src/gtest-printers.cc | 136 +- mars/googletest/src/gtest-test-part.cc | 24 +- mars/googletest/src/gtest-typed-test.cc | 13 +- mars/googletest/src/gtest.cc | 1916 +++++++++-------- mars/googletest/src/gtest_main.cc | 41 +- mars/stn/stn.h | 15 + mars/stn/task_profile.h | 6 + 60 files changed, 7011 insertions(+), 5140 deletions(-) create mode 100644 mars/googlemock/.clang-format create mode 100644 mars/googletest/.clang-format create mode 100644 mars/googletest/include/gtest/gtest-assertion-result.h create mode 100644 mars/googletest/src/gtest-assertion-result.cc diff --git a/mars/boot/context.h b/mars/boot/context.h index 93ae12e16..c462ce9c1 100644 --- a/mars/boot/context.h +++ b/mars/boot/context.h @@ -5,11 +5,11 @@ #ifndef MMNET_BASE_CONTEXT_H #define MMNET_BASE_CONTEXT_H +#include #include #include #include #include -#include #include "base_manager.h" @@ -97,6 +97,11 @@ class Context { static std::atomic s_context_index; }; +template +std::shared_ptr make_context_ptr(Args&&... args) { + return std::shared_ptr(Context::CreateContext(std::forward(args)...), Context::DestroyContext); +} + } // namespace boot } // namespace mars diff --git a/mars/comm/ini.h b/mars/comm/ini.h index e05c24580..c8a2966c5 100644 --- a/mars/comm/ini.h +++ b/mars/comm/ini.h @@ -122,6 +122,14 @@ class INI { return sectionsit->second; } + const std::string& CurrentSection() const { + return currentsection; + } + + std::string FileName() const { + return filename; + } + template bool Set(const std::string& key, const V& value) { return Set(currentsection, key, value); @@ -154,6 +162,10 @@ class INI { return Get(currentsection, key, def); } + std::string Get(const std::string& key) { + return Get(key, ""); + } + const std::string& Get(const std::string& section, const std::string& key, const std::string& def) { if (!VerifyName(section)) { ASSERT2(false, "---%s---", section.c_str()); diff --git a/mars/googlemock/.clang-format b/mars/googlemock/.clang-format new file mode 100644 index 000000000..8e1095dd6 --- /dev/null +++ b/mars/googlemock/.clang-format @@ -0,0 +1,4 @@ +{ + "DisableFormat": true, + "SortIncludes": false, +} diff --git a/mars/googlemock/include/gmock/gmock-actions.h b/mars/googlemock/include/gmock/gmock-actions.h index f2393bd3a..bd9ba73ee 100644 --- a/mars/googlemock/include/gmock/gmock-actions.h +++ b/mars/googlemock/include/gmock/gmock-actions.h @@ -27,7 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // The ACTION* family of macros can be used in a namespace scope to @@ -123,15 +122,16 @@ // MORE INFORMATION: // // To learn more about using these macros, please search for 'ACTION' on -// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ #ifndef _WIN32_WCE -# include +#include #endif #include @@ -146,10 +146,7 @@ #include "gmock/internal/gmock-port.h" #include "gmock/internal/gmock-pp.h" -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4100) -#endif +GTEST_DISABLE_MSC_WARNINGS_PUSH_(4100) namespace testing { @@ -196,9 +193,7 @@ class BuiltInDefaultValue { public: // This function returns true if and only if type T has a built-in default // value. - static bool Exists() { - return ::std::is_default_constructible::value; - } + static bool Exists() { return ::std::is_default_constructible::value; } static T Get() { return BuiltInDefaultValueGetter< @@ -227,11 +222,11 @@ class BuiltInDefaultValue { // The following specializations define the default values for // specific types we care about. #define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ - template <> \ - class BuiltInDefaultValue { \ - public: \ - static bool Exists() { return true; } \ - static type Get() { return value; } \ + template <> \ + class BuiltInDefaultValue { \ + public: \ + static bool Exists() { return true; } \ + static type Get() { return value; } \ } GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT @@ -255,21 +250,309 @@ GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long long, 0); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT +GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long long, 0); // NOLINT GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); #undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ -// Simple two-arg form of std::disjunction. -template -using disjunction = typename ::std::conditional::type; +// Partial implementations of metaprogramming types from the standard library +// not available in C++11. + +template +struct negation + // NOLINTNEXTLINE + : std::integral_constant {}; + +// Base case: with zero predicates the answer is always true. +template +struct conjunction : std::true_type {}; + +// With a single predicate, the answer is that predicate. +template +struct conjunction : P1 {}; + +// With multiple predicates the answer is the first predicate if that is false, +// and we recurse otherwise. +template +struct conjunction + : std::conditional, P1>::type {}; + +template +struct disjunction : std::false_type {}; + +template +struct disjunction : P1 {}; + +template +struct disjunction + // NOLINTNEXTLINE + : std::conditional, P1>::type {}; + +template +using void_t = void; + +// Detects whether an expression of type `From` can be implicitly converted to +// `To` according to [conv]. In C++17, [conv]/3 defines this as follows: +// +// An expression e can be implicitly converted to a type T if and only if +// the declaration T t=e; is well-formed, for some invented temporary +// variable t ([dcl.init]). +// +// [conv]/2 implies we can use function argument passing to detect whether this +// initialization is valid. +// +// Note that this is distinct from is_convertible, which requires this be valid: +// +// To test() { +// return declval(); +// } +// +// In particular, is_convertible doesn't give the correct answer when `To` and +// `From` are the same non-moveable type since `declval` will be an rvalue +// reference, defeating the guaranteed copy elision that would otherwise make +// this function work. +// +// REQUIRES: `From` is not cv void. +template +struct is_implicitly_convertible { + private: + // A function that accepts a parameter of type T. This can be called with type + // U successfully only if U is implicitly convertible to T. + template + static void Accept(T); + + // A function that creates a value of type T. + template + static T Make(); + + // An overload be selected when implicit conversion from T to To is possible. + template (Make()))> + static std::true_type TestImplicitConversion(int); + + // A fallback overload selected in all other cases. + template + static std::false_type TestImplicitConversion(...); + + public: + using type = decltype(TestImplicitConversion(0)); + static constexpr bool value = type::value; +}; + +// Like std::invoke_result_t from C++17, but works only for objects with call +// operators (not e.g. member function pointers, which we don't need specific +// support for in OnceAction because std::function deals with them). +template +using call_result_t = decltype(std::declval()(std::declval()...)); + +template +struct is_callable_r_impl : std::false_type {}; + +// Specialize the struct for those template arguments where call_result_t is +// well-formed. When it's not, the generic template above is chosen, resulting +// in std::false_type. +template +struct is_callable_r_impl>, R, F, Args...> + : std::conditional< + std::is_void::value, // + std::true_type, // + is_implicitly_convertible, R>>::type {}; + +// Like std::is_invocable_r from C++17, but works only for objects with call +// operators. See the note on call_result_t. +template +using is_callable_r = is_callable_r_impl; + +// Like std::as_const from C++17. +template +typename std::add_const::type& as_const(T& t) { + return t; +} } // namespace internal +// Specialized for function types below. +template +class OnceAction; + +// An action that can only be used once. +// +// This is accepted by WillOnce, which doesn't require the underlying action to +// be copy-constructible (only move-constructible), and promises to invoke it as +// an rvalue reference. This allows the action to work with move-only types like +// std::move_only_function in a type-safe manner. +// +// For example: +// +// // Assume we have some API that needs to accept a unique pointer to some +// // non-copyable object Foo. +// void AcceptUniquePointer(std::unique_ptr foo); +// +// // We can define an action that provides a Foo to that API. Because It +// // has to give away its unique pointer, it must not be called more than +// // once, so its call operator is &&-qualified. +// struct ProvideFoo { +// std::unique_ptr foo; +// +// void operator()() && { +// AcceptUniquePointer(std::move(Foo)); +// } +// }; +// +// // This action can be used with WillOnce. +// EXPECT_CALL(mock, Call) +// .WillOnce(ProvideFoo{std::make_unique(...)}); +// +// // But a call to WillRepeatedly will fail to compile. This is correct, +// // since the action cannot correctly be used repeatedly. +// EXPECT_CALL(mock, Call) +// .WillRepeatedly(ProvideFoo{std::make_unique(...)}); +// +// A less-contrived example would be an action that returns an arbitrary type, +// whose &&-qualified call operator is capable of dealing with move-only types. +template +class OnceAction final { + private: + // True iff we can use the given callable type (or lvalue reference) directly + // via StdFunctionAdaptor. + template + using IsDirectlyCompatible = internal::conjunction< + // It must be possible to capture the callable in StdFunctionAdaptor. + std::is_constructible::type, Callable>, + // The callable must be compatible with our signature. + internal::is_callable_r::type, + Args...>>; + + // True iff we can use the given callable type via StdFunctionAdaptor once we + // ignore incoming arguments. + template + using IsCompatibleAfterIgnoringArguments = internal::conjunction< + // It must be possible to capture the callable in a lambda. + std::is_constructible::type, Callable>, + // The callable must be invocable with zero arguments, returning something + // convertible to Result. + internal::is_callable_r::type>>; + + public: + // Construct from a callable that is directly compatible with our mocked + // signature: it accepts our function type's arguments and returns something + // convertible to our result type. + template ::type>>, + IsDirectlyCompatible> // + ::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + : function_(StdFunctionAdaptor::type>( + {}, std::forward(callable))) {} + + // As above, but for a callable that ignores the mocked function's arguments. + template ::type>>, + // Exclude callables for which the overload above works. + // We'd rather provide the arguments if possible. + internal::negation>, + IsCompatibleAfterIgnoringArguments>::value, + int>::type = 0> + OnceAction(Callable&& callable) // NOLINT + // Call the constructor above with a callable + // that ignores the input arguments. + : OnceAction(IgnoreIncomingArguments::type>{ + std::forward(callable)}) {} + + // We are naturally copyable because we store only an std::function, but + // semantically we should not be copyable. + OnceAction(const OnceAction&) = delete; + OnceAction& operator=(const OnceAction&) = delete; + OnceAction(OnceAction&&) = default; + + // Invoke the underlying action callable with which we were constructed, + // handing it the supplied arguments. + Result Call(Args... args) && { + return function_(std::forward(args)...); + } + + private: + // An adaptor that wraps a callable that is compatible with our signature and + // being invoked as an rvalue reference so that it can be used as an + // StdFunctionAdaptor. This throws away type safety, but that's fine because + // this is only used by WillOnce, which we know calls at most once. + // + // Once we have something like std::move_only_function from C++23, we can do + // away with this. + template + class StdFunctionAdaptor final { + public: + // A tag indicating that the (otherwise universal) constructor is accepting + // the callable itself, instead of e.g. stealing calls for the move + // constructor. + struct CallableTag final {}; + + template + explicit StdFunctionAdaptor(CallableTag, F&& callable) + : callable_(std::make_shared(std::forward(callable))) {} + + // Rather than explicitly returning Result, we return whatever the wrapped + // callable returns. This allows for compatibility with existing uses like + // the following, when the mocked function returns void: + // + // EXPECT_CALL(mock_fn_, Call) + // .WillOnce([&] { + // [...] + // return 0; + // }); + // + // Such a callable can be turned into std::function. If we use an + // explicit return type of Result here then it *doesn't* work with + // std::function, because we'll get a "void function should not return a + // value" error. + // + // We need not worry about incompatible result types because the SFINAE on + // OnceAction already checks this for us. std::is_invocable_r_v itself makes + // the same allowance for void result types. + template + internal::call_result_t operator()( + ArgRefs&&... args) const { + return std::move(*callable_)(std::forward(args)...); + } + + private: + // We must put the callable on the heap so that we are copyable, which + // std::function needs. + std::shared_ptr callable_; + }; + + // An adaptor that makes a callable that accepts zero arguments callable with + // our mocked arguments. + template + struct IgnoreIncomingArguments { + internal::call_result_t operator()(Args&&...) { + return std::move(callable)(); + } + + Callable callable; + }; + + std::function function_; +}; + // When an unexpected function call is encountered, Google Mock will // let it return a default value if the user has specified one for its // return type, or if the return type has a built-in default value; @@ -328,7 +611,7 @@ class DefaultValue { private: class ValueProducer { public: - virtual ~ValueProducer() {} + virtual ~ValueProducer() = default; virtual T Produce() = 0; }; @@ -339,7 +622,8 @@ class DefaultValue { private: const T value_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer); + FixedValueProducer(const FixedValueProducer&) = delete; + FixedValueProducer& operator=(const FixedValueProducer&) = delete; }; class FactoryValueProducer : public ValueProducer { @@ -350,7 +634,8 @@ class DefaultValue { private: const FactoryFunction factory_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer); + FactoryValueProducer(const FactoryValueProducer&) = delete; + FactoryValueProducer& operator=(const FactoryValueProducer&) = delete; }; static ValueProducer* producer_; @@ -414,8 +699,8 @@ class ActionInterface { typedef typename internal::Function::Result Result; typedef typename internal::Function::ArgumentTuple ArgumentTuple; - ActionInterface() {} - virtual ~ActionInterface() {} + ActionInterface() = default; + virtual ~ActionInterface() = default; // Performs the action. This method is not const, as in general an // action can have side effects and be stateful. For example, a @@ -424,28 +709,34 @@ class ActionInterface { virtual Result Perform(const ArgumentTuple& args) = 0; private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface); + ActionInterface(const ActionInterface&) = delete; + ActionInterface& operator=(const ActionInterface&) = delete; }; -// An Action is a copyable and IMMUTABLE (except by assignment) -// object that represents an action to be taken when a mock function -// of type F is called. The implementation of Action is just a -// std::shared_ptr to const ActionInterface. Don't inherit from Action! -// You can view an object implementing ActionInterface as a -// concrete action (including its current state), and an Action -// object as a handle to it. template -class Action { +class Action; + +// An Action is a copyable and IMMUTABLE (except by assignment) +// object that represents an action to be taken when a mock function of type +// R(Args...) is called. The implementation of Action is just a +// std::shared_ptr to const ActionInterface. Don't inherit from Action! You +// can view an object implementing ActionInterface as a concrete action +// (including its current state), and an Action object as a handle to it. +template +class Action { + private: + using F = R(Args...); + // Adapter class to allow constructing Action from a legacy ActionInterface. // New code should create Actions from functors instead. struct ActionAdapter { // Adapter must be copyable to satisfy std::function requirements. ::std::shared_ptr> impl_; - template - typename internal::Function::Result operator()(Args&&... args) { + template + typename internal::Function::Result operator()(InArgs&&... args) { return impl_->Perform( - ::std::forward_as_tuple(::std::forward(args)...)); + ::std::forward_as_tuple(::std::forward(args)...)); } }; @@ -458,7 +749,7 @@ class Action { // Constructs a null Action. Needed for storing Action objects in // STL containers. - Action() {} + Action() = default; // Construct an Action from a specified callable. // This cannot take std::function directly, because then Action would not be @@ -480,7 +771,8 @@ class Action { // Action, as long as F's arguments can be implicitly converted // to Func's and Func's return type can be implicitly converted to F's. template - explicit Action(const Action& action) : fun_(action.fun_) {} + Action(const Action& action) // NOLINT + : fun_(action.fun_) {} // Returns true if and only if this is the DoDefault() action. bool IsDoDefault() const { return fun_ == nullptr; } @@ -498,6 +790,24 @@ class Action { return internal::Apply(fun_, ::std::move(args)); } + // An action can be used as a OnceAction, since it's obviously safe to call it + // once. + operator OnceAction() const { // NOLINT + // Return a OnceAction-compatible callable that calls Perform with the + // arguments it is provided. We could instead just return fun_, but then + // we'd need to handle the IsDoDefault() case separately. + struct OA { + Action action; + + R operator()(Args... args) && { + return action.Perform( + std::forward_as_tuple(std::forward(args)...)); + } + }; + + return OA{*this}; + } + private: template friend class Action; @@ -514,8 +824,8 @@ class Action { template struct IgnoreArgs { - template - Result operator()(const Args&...) const { + template + Result operator()(const InArgs&...) const { return function_impl(); } @@ -606,118 +916,198 @@ struct ByMoveWrapper { T payload; }; -// Implements the polymorphic Return(x) action, which can be used in -// any function that returns the type of x, regardless of the argument -// types. -// -// Note: The value passed into Return must be converted into -// Function::Result when this action is cast to Action rather than -// when that action is performed. This is important in scenarios like -// -// MOCK_METHOD1(Method, T(U)); -// ... -// { -// Foo foo; -// X x(&foo); -// EXPECT_CALL(mock, Method(_)).WillOnce(Return(x)); -// } -// -// In the example above the variable x holds reference to foo which leaves -// scope and gets destroyed. If copying X just copies a reference to foo, -// that copy will be left with a hanging reference. If conversion to T -// makes a copy of foo, the above code is safe. To support that scenario, we -// need to make sure that the type conversion happens inside the EXPECT_CALL -// statement, and conversion of the result of Return to Action is a -// good place for that. -// -// The real life example of the above scenario happens when an invocation -// of gtl::Container() is passed into Return. -// +// The general implementation of Return(R). Specializations follow below. template -class ReturnAction { +class ReturnAction final { public: - // Constructs a ReturnAction object from the value to be returned. - // 'value' is passed by value instead of by const reference in order - // to allow Return("string literal") to compile. - explicit ReturnAction(R value) : value_(new R(std::move(value))) {} + explicit ReturnAction(R value) : value_(std::move(value)) {} + + template >, // + negation>, // + std::is_convertible, // + std::is_move_constructible>::value>::type> + operator OnceAction() && { // NOLINT + return Impl(std::move(value_)); + } - // This template type conversion operator allows Return(x) to be - // used in ANY function that returns x's type. - template - operator Action() const { // NOLINT - // Assert statement belongs here because this is the best place to verify - // conditions on F. It produces the clearest error messages - // in most compilers. - // Impl really belongs in this scope as a local class but can't - // because MSVC produces duplicate symbols in different translation units - // in this case. Until MS fixes that bug we put Impl into the class scope - // and put the typedef both here (for use in assert statement) and - // in the Impl class. But both definitions must be the same. - typedef typename Function::Result Result; - GTEST_COMPILE_ASSERT_( - !std::is_reference::value, - use_ReturnRef_instead_of_Return_to_return_a_reference); - static_assert(!std::is_void::value, - "Can't use Return() on an action expected to return `void`."); - return Action(new Impl(value_)); + template >, // + negation>, // + std::is_convertible, // + std::is_copy_constructible>::value>::type> + operator Action() const { // NOLINT + return Impl(value_); } private: - // Implements the Return(x) action for a particular function type F. - template - class Impl : public ActionInterface { + // Implements the Return(x) action for a mock function that returns type U. + template + class Impl final { public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; + // The constructor used when the return value is allowed to move from the + // input value (i.e. we are converting to OnceAction). + explicit Impl(R&& input_value) + : state_(new State(std::move(input_value))) {} - // The implicit cast is necessary when Result has more than one - // single-argument constructor (e.g. Result is std::vector) and R - // has a type conversion operator template. In that case, value_(value) - // won't compile as the compiler doesn't known which constructor of - // Result to call. ImplicitCast_ forces the compiler to convert R to - // Result without considering explicit constructors, thus resolving the - // ambiguity. value_ is then initialized using its copy constructor. - explicit Impl(const std::shared_ptr& value) - : value_before_cast_(*value), - value_(ImplicitCast_(value_before_cast_)) {} + // The constructor used when the return value is not allowed to move from + // the input value (i.e. we are converting to Action). + explicit Impl(const R& input_value) : state_(new State(input_value)) {} - Result Perform(const ArgumentTuple&) override { return value_; } + U operator()() && { return std::move(state_->value); } + U operator()() const& { return state_->value; } private: - GTEST_COMPILE_ASSERT_(!std::is_reference::value, - Result_cannot_be_a_reference_type); - // We save the value before casting just in case it is being cast to a - // wrapper type. - R value_before_cast_; - Result value_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); + // We put our state on the heap so that the compiler-generated copy/move + // constructors work correctly even when U is a reference-like type. This is + // necessary only because we eagerly create State::value (see the note on + // that symbol for details). If we instead had only the input value as a + // member then the default constructors would work fine. + // + // For example, when R is std::string and U is std::string_view, value is a + // reference to the string backed by input_value. The copy constructor would + // copy both, so that we wind up with a new input_value object (with the + // same contents) and a reference to the *old* input_value object rather + // than the new one. + struct State { + explicit State(const R& input_value_in) + : input_value(input_value_in), + // Make an implicit conversion to Result before initializing the U + // object we store, avoiding calling any explicit constructor of U + // from R. + // + // This simulates the language rules: a function with return type U + // that does `return R()` requires R to be implicitly convertible to + // U, and uses that path for the conversion, even U Result has an + // explicit constructor from R. + value(ImplicitCast_(internal::as_const(input_value))) {} + + // As above, but for the case where we're moving from the ReturnAction + // object because it's being used as a OnceAction. + explicit State(R&& input_value_in) + : input_value(std::move(input_value_in)), + // For the same reason as above we make an implicit conversion to U + // before initializing the value. + // + // Unlike above we provide the input value as an rvalue to the + // implicit conversion because this is a OnceAction: it's fine if it + // wants to consume the input value. + value(ImplicitCast_(std::move(input_value))) {} + + // A copy of the value originally provided by the user. We retain this in + // addition to the value of the mock function's result type below in case + // the latter is a reference-like type. See the std::string_view example + // in the documentation on Return. + R input_value; + + // The value we actually return, as the type returned by the mock function + // itself. + // + // We eagerly initialize this here, rather than lazily doing the implicit + // conversion automatically each time Perform is called, for historical + // reasons: in 2009-11, commit a070cbd91c (Google changelist 13540126) + // made the Action conversion operator eagerly convert the R value to + // U, but without keeping the R alive. This broke the use case discussed + // in the documentation for Return, making reference-like types such as + // std::string_view not safe to use as U where the input type R is a + // value-like type such as std::string. + // + // The example the commit gave was not very clear, nor was the issue + // thread (https://github.com/google/googlemock/issues/86), but it seems + // the worry was about reference-like input types R that flatten to a + // value-like type U when being implicitly converted. An example of this + // is std::vector::reference, which is often a proxy type with an + // reference to the underlying vector: + // + // // Helper method: have the mock function return bools according + // // to the supplied script. + // void SetActions(MockFunction& mock, + // const std::vector& script) { + // for (size_t i = 0; i < script.size(); ++i) { + // EXPECT_CALL(mock, Call(i)).WillOnce(Return(script[i])); + // } + // } + // + // TEST(Foo, Bar) { + // // Set actions using a temporary vector, whose operator[] + // // returns proxy objects that references that will be + // // dangling once the call to SetActions finishes and the + // // vector is destroyed. + // MockFunction mock; + // SetActions(mock, {false, true}); + // + // EXPECT_FALSE(mock.AsStdFunction()(0)); + // EXPECT_TRUE(mock.AsStdFunction()(1)); + // } + // + // This eager conversion helps with a simple case like this, but doesn't + // fully make these types work in general. For example the following still + // uses a dangling reference: + // + // TEST(Foo, Baz) { + // MockFunction()> mock; + // + // // Return the same vector twice, and then the empty vector + // // thereafter. + // auto action = Return(std::initializer_list{ + // "taco", "burrito", + // }); + // + // EXPECT_CALL(mock, Call) + // .WillOnce(action) + // .WillOnce(action) + // .WillRepeatedly(Return(std::vector{})); + // + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), + // ElementsAre("taco", "burrito")); + // EXPECT_THAT(mock.AsStdFunction()(), IsEmpty()); + // } + // + U value; + }; + + const std::shared_ptr state_; }; - // Partially specialize for ByMoveWrapper. This version of ReturnAction will - // move its contents instead. - template - class Impl, F> : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; + R value_; +}; - explicit Impl(const std::shared_ptr& wrapper) - : performed_(false), wrapper_(wrapper) {} +// A specialization of ReturnAction when R is ByMoveWrapper for some T. +// +// This version applies the type system-defeating hack of moving from T even in +// the const call operator, checking at runtime that it isn't called more than +// once, since the user has declared their intent to do so by using ByMove. +template +class ReturnAction> final { + public: + explicit ReturnAction(ByMoveWrapper wrapper) + : state_(new State(std::move(wrapper.payload))) {} - Result Perform(const ArgumentTuple&) override { - GTEST_CHECK_(!performed_) - << "A ByMove() action should only be performed once."; - performed_ = true; - return std::move(wrapper_->payload); - } + T operator()() const { + GTEST_CHECK_(!state_->called) + << "A ByMove() action must be performed at most once."; - private: - bool performed_; - const std::shared_ptr wrapper_; + state_->called = true; + return std::move(state_->value); + } + + private: + // We store our state on the heap so that we are copyable as required by + // Action, despite the fact that we are stateful and T may not be copyable. + struct State { + explicit State(T&& value_in) : value(std::move(value_in)) {} + + T value; + bool called = false; }; - const std::shared_ptr value_; + const std::shared_ptr state_; }; // Implements the ReturnNull() action. @@ -759,8 +1149,8 @@ class ReturnRefAction { // Asserts that the function return type is a reference. This // catches the user error of using ReturnRef(x) when Return(x) // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_(std::is_reference::value, - use_Return_instead_of_ReturnRef_to_return_a_value); + static_assert(std::is_reference::value, + "use Return instead of ReturnRef to return a value"); return Action(new Impl(ref_)); } @@ -801,9 +1191,8 @@ class ReturnRefOfCopyAction { // Asserts that the function return type is a reference. This // catches the user error of using ReturnRefOfCopy(x) when Return(x) // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_( - std::is_reference::value, - use_Return_instead_of_ReturnRefOfCopy_to_return_a_value); + static_assert(std::is_reference::value, + "use Return instead of ReturnRefOfCopy to return a value"); return Action(new Impl(value_)); } @@ -839,7 +1228,7 @@ class ReturnRoundRobinAction { template T operator()(Args&&...) const { - return state_->Next(); + return state_->Next(); } private: @@ -862,7 +1251,9 @@ class DoDefaultAction { // This template type conversion operator allows DoDefault() to be // used in any function. template - operator Action() const { return Action(); } // NOLINT + operator Action() const { + return Action(); + } // NOLINT }; // Implements the Assign action to set a given pointer referent to a @@ -882,7 +1273,7 @@ class AssignAction { const T2 value_; }; -#if !GTEST_OS_WINDOWS_MOBILE +#ifndef GTEST_OS_WINDOWS_MOBILE // Implements the SetErrnoAndReturn action to simulate return from // various system calls and libc functions. @@ -890,8 +1281,7 @@ template class SetErrnoAndReturnAction { public: SetErrnoAndReturnAction(int errno_value, T result) - : errno_(errno_value), - result_(result) {} + : errno_(errno_value), result_(result) {} template Result Perform(const ArgumentTuple& /* args */) const { errno = errno_; @@ -1002,8 +1392,8 @@ class IgnoreResultAction { private: // Type OriginalFunction is the same as F except that its return // type is IgnoredValue. - typedef typename internal::Function::MakeResultIgnoredValue - OriginalFunction; + typedef + typename internal::Function::MakeResultIgnoredValue OriginalFunction; const Action action_; }; @@ -1013,55 +1403,243 @@ class IgnoreResultAction { template struct WithArgsAction { - InnerAction action; + InnerAction inner_action; - // The inner action could be anything convertible to Action. - // We use the conversion operator to detect the signature of the inner Action. + // The signature of the function as seen by the inner action, given an out + // action with the given result and argument types. template + using InnerSignature = + R(typename std::tuple_element>::type...); + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + struct OA { + OnceAction> inner_action; + + R operator()(Args&&... args) && { + return std::move(inner_action) + .Call(std::get( + std::forward_as_tuple(std::forward(args)...))...); + } + }; + + return OA{std::move(inner_action)}; + } + + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>...)>>::value, + int>::type = 0> operator Action() const { // NOLINT - using TupleType = std::tuple; - Action::type...)> - converted(action); + Action> converted(inner_action); - return [converted](Args... args) -> R { + return [converted](Args&&... args) -> R { return converted.Perform(std::forward_as_tuple( - std::get(std::forward_as_tuple(std::forward(args)...))...)); + std::get(std::forward_as_tuple(std::forward(args)...))...)); }; } }; template -struct DoAllAction { - private: +class DoAllAction; + +// Base case: only a single action. +template +class DoAllAction { + public: + struct UserConstructorTag {}; + template - using NonFinalType = - typename std::conditional::value, T, const T&>::type; + explicit DoAllAction(UserConstructorTag, T&& action) + : final_action_(std::forward(action)) {} + + // Rather than a call operator, we must define conversion operators to + // particular action types. This is necessary for embedded actions like + // DoDefault(), which rely on an action conversion operators rather than + // providing a call operator because even with a particular set of arguments + // they don't have a fixed return type. + + template >::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + return std::move(final_action_); + } - template - std::vector Convert(IndexSequence) const { - return {ActionT(std::get(actions))...}; + template < + typename R, typename... Args, + typename std::enable_if< + std::is_convertible>::value, + int>::type = 0> + operator Action() const { // NOLINT + return final_action_; } + private: + FinalAction final_action_; +}; + +// Recursive case: support N actions by calling the initial action and then +// calling through to the base class containing N-1 actions. +template +class DoAllAction + : private DoAllAction { + private: + using Base = DoAllAction; + + // The type of reference that should be provided to an initial action for a + // mocked function parameter of type T. + // + // There are two quirks here: + // + // * Unlike most forwarding functions, we pass scalars through by value. + // This isn't strictly necessary because an lvalue reference would work + // fine too and be consistent with other non-reference types, but it's + // perhaps less surprising. + // + // For example if the mocked function has signature void(int), then it + // might seem surprising for the user's initial action to need to be + // convertible to Action. This is perhaps less + // surprising for a non-scalar type where there may be a performance + // impact, or it might even be impossible, to pass by value. + // + // * More surprisingly, `const T&` is often not a const reference type. + // By the reference collapsing rules in C++17 [dcl.ref]/6, if T refers to + // U& or U&& for some non-scalar type U, then InitialActionArgType is + // U&. In other words, we may hand over a non-const reference. + // + // So for example, given some non-scalar type Obj we have the following + // mappings: + // + // T InitialActionArgType + // ------- ----------------------- + // Obj const Obj& + // Obj& Obj& + // Obj&& Obj& + // const Obj const Obj& + // const Obj& const Obj& + // const Obj&& const Obj& + // + // In other words, the initial actions get a mutable view of an non-scalar + // argument if and only if the mock function itself accepts a non-const + // reference type. They are never given an rvalue reference to an + // non-scalar type. + // + // This situation makes sense if you imagine use with a matcher that is + // designed to write through a reference. For example, if the caller wants + // to fill in a reference argument and then return a canned value: + // + // EXPECT_CALL(mock, Call) + // .WillOnce(DoAll(SetArgReferee<0>(17), Return(19))); + // + template + using InitialActionArgType = + typename std::conditional::value, T, const T&>::type; + public: - std::tuple actions; + struct UserConstructorTag {}; + + template + explicit DoAllAction(UserConstructorTag, T&& initial_action, + U&&... other_actions) + : Base({}, std::forward(other_actions)...), + initial_action_(std::forward(initial_action)) {} + + template ...)>>, + std::is_convertible>>::value, + int>::type = 0> + operator OnceAction() && { // NOLINT + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + OnceAction...)> initial_action; + OnceAction remaining_actions; + + R operator()(Args... args) && { + std::move(initial_action) + .Call(static_cast>(args)...); + + return std::move(remaining_actions).Call(std::forward(args)...); + } + }; - template + return OA{ + std::move(initial_action_), + std::move(static_cast(*this)), + }; + } + + template < + typename R, typename... Args, + typename std::enable_if< + conjunction< + // Both the initial action and the rest must support conversion to + // Action. + std::is_convertible...)>>, + std::is_convertible>>::value, + int>::type = 0> operator Action() const { // NOLINT - struct Op { - std::vector...)>> converted; - Action last; + // Return an action that first calls the initial action with arguments + // filtered through InitialActionArgType, then forwards arguments directly + // to the base class to deal with the remaining actions. + struct OA { + Action...)> initial_action; + Action remaining_actions; + R operator()(Args... args) const { - auto tuple_args = std::forward_as_tuple(std::forward(args)...); - for (auto& a : converted) { - a.Perform(tuple_args); - } - return last.Perform(std::move(tuple_args)); + initial_action.Perform(std::forward_as_tuple( + static_cast>(args)...)); + + return remaining_actions.Perform( + std::forward_as_tuple(std::forward(args)...)); } }; - return Op{Convert...)>>( - MakeIndexSequence()), - std::get(actions)}; + + return OA{ + initial_action_, + static_cast(*this), + }; } + + private: + InitialAction initial_action_; }; template @@ -1078,10 +1656,11 @@ struct ReturnNewAction { template struct ReturnArgAction { - template - auto operator()(const Args&... args) const -> - typename std::tuple_element>::type { - return std::get(std::tie(args...)); + template ::type> + auto operator()(Args&&... args) const -> decltype(std::get( + std::forward_as_tuple(std::forward(args)...))) { + return std::get(std::forward_as_tuple(std::forward(args)...)); } }; @@ -1203,7 +1782,8 @@ typedef internal::IgnoredValue Unused; template internal::DoAllAction::type...> DoAll( Action&&... action) { - return {std::forward_as_tuple(std::forward(action)...)}; + return internal::DoAllAction::type...>( + {}, std::forward(action)...); } // WithArg(an_action) creates an action that passes the k-th @@ -1212,8 +1792,8 @@ internal::DoAllAction::type...> DoAll( // multiple arguments. For convenience, we also provide // WithArgs(an_action) (defined below) as a synonym. template -internal::WithArgsAction::type, k> -WithArg(InnerAction&& action) { +internal::WithArgsAction::type, k> WithArg( + InnerAction&& action) { return {std::forward(action)}; } @@ -1232,14 +1812,35 @@ WithArgs(InnerAction&& action) { // argument. In other words, it adapts an action accepting no // argument to one that accepts (and ignores) arguments. template -internal::WithArgsAction::type> -WithoutArgs(InnerAction&& action) { +internal::WithArgsAction::type> WithoutArgs( + InnerAction&& action) { return {std::forward(action)}; } -// Creates an action that returns 'value'. 'value' is passed by value -// instead of const reference - otherwise Return("string literal") -// will trigger a compiler error about using array as initializer. +// Creates an action that returns a value. +// +// The returned type can be used with a mock function returning a non-void, +// non-reference type U as follows: +// +// * If R is convertible to U and U is move-constructible, then the action can +// be used with WillOnce. +// +// * If const R& is convertible to U and U is copy-constructible, then the +// action can be used with both WillOnce and WillRepeatedly. +// +// The mock expectation contains the R value from which the U return value is +// constructed (a move/copy of the argument to Return). This means that the R +// value will survive at least until the mock object's expectations are cleared +// or the mock object is destroyed, meaning that U can safely be a +// reference-like type such as std::string_view: +// +// // The mock function returns a view of a copy of the string fed to +// // Return. The view is valid even after the action is performed. +// MockFunction mock; +// EXPECT_CALL(mock, Call).WillOnce(Return(std::string("taco"))); +// const std::string_view result = mock.AsStdFunction()(); +// EXPECT_EQ("taco", result); +// template internal::ReturnAction Return(R value) { return internal::ReturnAction(std::move(value)); @@ -1273,6 +1874,8 @@ inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { return internal::ReturnRefOfCopyAction(x); } +// DEPRECATED: use Return(x) directly with WillOnce. +// // Modifies the parent action (a Return() action) to perform a move of the // argument instead of a copy. // Return(ByMove()) actions can only be executed once and will assert this @@ -1319,16 +1922,16 @@ internal::SetArgumentPointeeAction SetArgumentPointee(T value) { // Creates an action that sets a pointer referent to a given value. template -PolymorphicAction > Assign(T1* ptr, T2 val) { +PolymorphicAction> Assign(T1* ptr, T2 val) { return MakePolymorphicAction(internal::AssignAction(ptr, val)); } -#if !GTEST_OS_WINDOWS_MOBILE +#ifndef GTEST_OS_WINDOWS_MOBILE // Creates an action that sets errno and returns the appropriate error. template -PolymorphicAction > -SetErrnoAndReturn(int errval, T result) { +PolymorphicAction> SetErrnoAndReturn( + int errval, T result) { return MakePolymorphicAction( internal::SetErrnoAndReturnAction(errval, result)); } @@ -1482,7 +2085,8 @@ struct ExcessiveArg {}; // Builds an implementation of an Action<> for some particular signature, using // a class defined by an ACTION* macro. -template struct ActionImpl; +template +struct ActionImpl; template struct ImplBase { @@ -1502,7 +2106,7 @@ struct ActionImpl : ImplBase::type { using args_type = std::tuple; ActionImpl() = default; // Only defined if appropriate for Base. - explicit ActionImpl(std::shared_ptr impl) : Base{std::move(impl)} { } + explicit ActionImpl(std::shared_ptr impl) : Base{std::move(impl)} {} R operator()(Args&&... arg) const { static constexpr size_t kMaxArgs = @@ -1521,12 +2125,14 @@ struct ActionImpl : ImplBase::type { // args_type get passed, followed by a dummy of unspecified type for the // remainder up to 10 explicit args. static constexpr ExcessiveArg kExcessArg{}; - return static_cast(*this).template gmock_PerformImpl< - /*function_type=*/function_type, /*return_type=*/R, - /*args_type=*/args_type, - /*argN_type=*/typename std::tuple_element::type...>( - /*args=*/args, std::get(args)..., - ((void)excess_id, kExcessArg)...); + return static_cast(*this) + .template gmock_PerformImpl< + /*function_type=*/function_type, /*return_type=*/R, + /*args_type=*/args_type, + /*argN_type=*/ + typename std::tuple_element::type...>( + /*args=*/args, std::get(args)..., + ((void)excess_id, kExcessArg)...); } }; @@ -1545,7 +2151,7 @@ ::testing::Action MakeAction(std::shared_ptr impl) { #define GMOCK_INTERNAL_ARG_UNUSED(i, data, el) \ , const arg##i##_type& arg##i GTEST_ATTRIBUTE_UNUSED_ -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ +#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_ \ const args_type& args GTEST_ATTRIBUTE_UNUSED_ GMOCK_PP_REPEAT( \ GMOCK_INTERNAL_ARG_UNUSED, , 10) @@ -1584,42 +2190,47 @@ ::testing::Action MakeAction(std::shared_ptr impl) { #define GMOCK_ACTION_FIELD_PARAMS_(params) \ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_FIELD_PARAM, , params) -#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ - template \ - class full_name { \ - public: \ - explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ - : impl_(std::make_shared( \ - GMOCK_ACTION_GVALUE_PARAMS_(params))) { } \ - full_name(const full_name&) = default; \ - full_name(full_name&&) noexcept = default; \ - template \ - operator ::testing::Action() const { \ - return ::testing::internal::MakeAction(impl_); \ - } \ - private: \ - class gmock_Impl { \ - public: \ - explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ - : GMOCK_ACTION_INIT_PARAMS_(params) {} \ - template \ - return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ - GMOCK_ACTION_FIELD_PARAMS_(params) \ - }; \ - std::shared_ptr impl_; \ - }; \ - template \ - inline full_name name( \ - GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ - return full_name( \ - GMOCK_ACTION_GVALUE_PARAMS_(params)); \ - } \ - template \ - template \ - return_type full_name::gmock_Impl:: \ - gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const +#define GMOCK_INTERNAL_ACTION(name, full_name, params) \ + template \ + class full_name { \ + public: \ + explicit full_name(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : impl_(std::make_shared( \ + GMOCK_ACTION_GVALUE_PARAMS_(params))) {} \ + full_name(const full_name&) = default; \ + full_name(full_name&&) noexcept = default; \ + template \ + operator ::testing::Action() const { \ + return ::testing::internal::MakeAction(impl_); \ + } \ + \ + private: \ + class gmock_Impl { \ + public: \ + explicit gmock_Impl(GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) \ + : GMOCK_ACTION_INIT_PARAMS_(params) {} \ + template \ + return_type gmock_PerformImpl(GMOCK_ACTION_ARG_TYPES_AND_NAMES_) const; \ + GMOCK_ACTION_FIELD_PARAMS_(params) \ + }; \ + std::shared_ptr impl_; \ + }; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) GTEST_MUST_USE_RESULT_; \ + template \ + inline full_name name( \ + GMOCK_ACTION_TYPE_GVALUE_PARAMS_(params)) { \ + return full_name( \ + GMOCK_ACTION_GVALUE_PARAMS_(params)); \ + } \ + template \ + template \ + return_type \ + full_name::gmock_Impl::gmock_PerformImpl( \ + GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const } // namespace internal @@ -1627,12 +2238,13 @@ ::testing::Action MakeAction(std::shared_ptr impl) { #define ACTION(name) \ class name##Action { \ public: \ - explicit name##Action() noexcept {} \ - name##Action(const name##Action&) noexcept {} \ + explicit name##Action() noexcept {} \ + name##Action(const name##Action&) noexcept {} \ template \ operator ::testing::Action() const { \ return ::testing::internal::MakeAction(); \ } \ + \ private: \ class gmock_Impl { \ public: \ @@ -1680,8 +2292,6 @@ ::testing::Action MakeAction(std::shared_ptr impl) { } // namespace testing -#ifdef _MSC_VER -# pragma warning(pop) -#endif +GTEST_DISABLE_MSC_WARNINGS_POP_() // 4100 #endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ diff --git a/mars/googlemock/include/gmock/gmock-cardinalities.h b/mars/googlemock/include/gmock/gmock-cardinalities.h index fc7f803a7..533e604f3 100644 --- a/mars/googlemock/include/gmock/gmock-cardinalities.h +++ b/mars/googlemock/include/gmock/gmock-cardinalities.h @@ -27,21 +27,23 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // This file implements some commonly used cardinalities. More // cardinalities can be defined by the user implementing the // CardinalityInterface interface if necessary. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ #include + #include #include // NOLINT + #include "gmock/internal/gmock-port.h" #include "gtest/gtest.h" @@ -63,7 +65,7 @@ namespace testing { // The implementation of a cardinality. class CardinalityInterface { public: - virtual ~CardinalityInterface() {} + virtual ~CardinalityInterface() = default; // Conservative estimate on the lower/upper bound of the number of // calls allowed. @@ -90,7 +92,7 @@ class GTEST_API_ Cardinality { public: // Constructs a null cardinality. Needed for storing Cardinality // objects in STL containers. - Cardinality() {} + Cardinality() = default; // Constructs a Cardinality from its implementation. explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {} @@ -116,7 +118,7 @@ class GTEST_API_ Cardinality { // cardinality, i.e. exceed the maximum number of allowed calls. bool IsOverSaturatedByCallCount(int call_count) const { return impl_->IsSaturatedByCallCount(call_count) && - !impl_->IsSatisfiedByCallCount(call_count); + !impl_->IsSatisfiedByCallCount(call_count); } // Describes self to an ostream diff --git a/mars/googlemock/include/gmock/gmock-function-mocker.h b/mars/googlemock/include/gmock/gmock-function-mocker.h index 0fc6f6f3f..1a1f126e4 100644 --- a/mars/googlemock/include/gmock/gmock-function-mocker.h +++ b/mars/googlemock/include/gmock/gmock-function-mocker.h @@ -31,10 +31,11 @@ // // This file implements MOCK_METHOD. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* -#ifndef GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT -#define GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ // NOLINT +#ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ +#define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ #include // IWYU pragma: keep #include // IWYU pragma: keep @@ -64,6 +65,39 @@ struct ThisRefAdjuster { } }; +constexpr bool PrefixOf(const char* a, const char* b) { + return *a == 0 || (*a == *b && internal::PrefixOf(a + 1, b + 1)); +} + +template +constexpr bool StartsWith(const char (&prefix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(prefix, str); +} + +template +constexpr bool EndsWith(const char (&suffix)[N], const char (&str)[M]) { + return N <= M && internal::PrefixOf(suffix, str + M - N); +} + +template +constexpr bool Equals(const char (&a)[N], const char (&b)[M]) { + return N == M && internal::PrefixOf(a, b); +} + +template +constexpr bool ValidateSpec(const char (&spec)[N]) { + return internal::Equals("const", spec) || + internal::Equals("override", spec) || + internal::Equals("final", spec) || + internal::Equals("noexcept", spec) || + (internal::StartsWith("noexcept(", spec) && + internal::EndsWith(")", spec)) || + internal::Equals("ref(&)", spec) || + internal::Equals("ref(&&)", spec) || + (internal::StartsWith("Calltype(", spec) && + internal::EndsWith(")", spec)); +} + } // namespace internal // The style guide prohibits "using" statements in a namespace scope @@ -74,8 +108,11 @@ struct ThisRefAdjuster { using internal::FunctionMocker; } // namespace testing -#define MOCK_METHOD(...) \ - GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) +#define MOCK_METHOD(...) \ + GMOCK_INTERNAL_WARNING_PUSH() \ + GMOCK_INTERNAL_WARNING_CLANG(ignored, "-Wunused-member-function") \ + GMOCK_PP_VARIADIC_CALL(GMOCK_INTERNAL_MOCK_METHOD_ARG_, __VA_ARGS__) \ + GMOCK_INTERNAL_WARNING_POP() #define GMOCK_INTERNAL_MOCK_METHOD_ARG_1(...) \ GMOCK_INTERNAL_WRONG_ARITY(__VA_ARGS__) @@ -86,17 +123,18 @@ using internal::FunctionMocker; #define GMOCK_INTERNAL_MOCK_METHOD_ARG_3(_Ret, _MethodName, _Args) \ GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, ()) -#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ - GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ - GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ - GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ - GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ - GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ - GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ - GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ - GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ - GMOCK_INTERNAL_GET_CALLTYPE(_Spec), GMOCK_INTERNAL_GET_REF_SPEC(_Spec), \ +#define GMOCK_INTERNAL_MOCK_METHOD_ARG_4(_Ret, _MethodName, _Args, _Spec) \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Args); \ + GMOCK_INTERNAL_ASSERT_PARENTHESIS(_Spec); \ + GMOCK_INTERNAL_ASSERT_VALID_SIGNATURE( \ + GMOCK_PP_NARG0 _Args, GMOCK_INTERNAL_SIGNATURE(_Ret, _Args)); \ + GMOCK_INTERNAL_ASSERT_VALID_SPEC(_Spec) \ + GMOCK_INTERNAL_MOCK_METHOD_IMPL( \ + GMOCK_PP_NARG0 _Args, _MethodName, GMOCK_INTERNAL_HAS_CONST(_Spec), \ + GMOCK_INTERNAL_HAS_OVERRIDE(_Spec), GMOCK_INTERNAL_HAS_FINAL(_Spec), \ + GMOCK_INTERNAL_GET_NOEXCEPT_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Spec), \ + GMOCK_INTERNAL_GET_REF_SPEC(_Spec), \ (GMOCK_INTERNAL_SIGNATURE(_Ret, _Args))) #define GMOCK_INTERNAL_MOCK_METHOD_ARG_5(...) \ @@ -142,8 +180,9 @@ using internal::FunctionMocker; _Signature)>::Result \ GMOCK_INTERNAL_EXPAND(_CallType) \ _MethodName(GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER, _Signature, _N)) \ - GMOCK_PP_IF(_Constness, const, ) _RefSpec _NoexceptSpec \ - GMOCK_PP_IF(_Override, override, ) GMOCK_PP_IF(_Final, final, ) { \ + GMOCK_PP_IF(_Constness, const, ) \ + _RefSpec _NoexceptSpec GMOCK_PP_IF(_Override, override, ) \ + GMOCK_PP_IF(_Final, final, ) { \ GMOCK_MOCKER_(_N, _Constness, _MethodName) \ .SetOwnerAndName(this, #_MethodName); \ return GMOCK_MOCKER_(_N, _Constness, _MethodName) \ @@ -166,11 +205,11 @@ using internal::FunctionMocker; GMOCK_INTERNAL_A_MATCHER_ARGUMENT, _Signature, _N)); \ } \ mutable ::testing::FunctionMocker \ - GMOCK_MOCKER_(_N, _Constness, _MethodName) + GMOCK_MOCKER_(_N, _Constness, _MethodName) #define GMOCK_INTERNAL_EXPAND(...) __VA_ARGS__ -// Five Valid modifiers. +// Valid modifiers. #define GMOCK_INTERNAL_HAS_CONST(_Tuple) \ GMOCK_PP_HAS_COMMA(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_DETECT_CONST, ~, _Tuple)) @@ -189,6 +228,14 @@ using internal::FunctionMocker; GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)), \ _elem, ) +#define GMOCK_INTERNAL_GET_CALLTYPE_SPEC(_Tuple) \ + GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE, ~, _Tuple) + +#define GMOCK_INTERNAL_CALLTYPE_SPEC_IF_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_IF( \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem)), \ + GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) + #define GMOCK_INTERNAL_GET_REF_SPEC(_Tuple) \ GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_REF_SPEC_IF_REF, ~, _Tuple) @@ -196,19 +243,25 @@ using internal::FunctionMocker; GMOCK_PP_IF(GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)), \ GMOCK_PP_CAT(GMOCK_INTERNAL_UNPACK_, _elem), ) -#define GMOCK_INTERNAL_GET_CALLTYPE(_Tuple) \ - GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_GET_CALLTYPE_IMPL, ~, _Tuple) - -#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ - static_assert( \ - (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ - GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \ - GMOCK_INTERNAL_IS_CALLTYPE(_elem)) == 1, \ - GMOCK_PP_STRINGIZE( \ +#ifdef GMOCK_INTERNAL_STRICT_SPEC_ASSERT +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + ::testing::internal::ValidateSpec(GMOCK_PP_STRINGIZE(_elem)), \ + "Token \'" GMOCK_PP_STRINGIZE( \ + _elem) "\' cannot be recognized as a valid specification " \ + "modifier. Is a ',' missing?"); +#else +#define GMOCK_INTERNAL_ASSERT_VALID_SPEC_ELEMENT(_i, _, _elem) \ + static_assert( \ + (GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_OVERRIDE(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_FINAL(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_NOEXCEPT(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_REF(_i, _, _elem)) + \ + GMOCK_PP_HAS_COMMA(GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem))) == 1, \ + GMOCK_PP_STRINGIZE( \ _elem) " cannot be recognized as a valid specification modifier."); +#endif // GMOCK_INTERNAL_STRICT_SPEC_ASSERT // Modifiers implementation. #define GMOCK_INTERNAL_DETECT_CONST(_i, _, _elem) \ @@ -238,26 +291,12 @@ using internal::FunctionMocker; #define GMOCK_INTERNAL_UNPACK_ref(x) x -#define GMOCK_INTERNAL_GET_CALLTYPE_IMPL(_i, _, _elem) \ - GMOCK_PP_IF(GMOCK_INTERNAL_IS_CALLTYPE(_elem), \ - GMOCK_INTERNAL_GET_VALUE_CALLTYPE, GMOCK_PP_EMPTY) \ - (_elem) - -// TODO(iserna): GMOCK_INTERNAL_IS_CALLTYPE and -// GMOCK_INTERNAL_GET_VALUE_CALLTYPE needed more expansions to work on windows -// maybe they can be simplified somehow. -#define GMOCK_INTERNAL_IS_CALLTYPE(_arg) \ - GMOCK_INTERNAL_IS_CALLTYPE_I( \ - GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) -#define GMOCK_INTERNAL_IS_CALLTYPE_I(_arg) GMOCK_PP_IS_ENCLOSED_PARENS(_arg) +#define GMOCK_INTERNAL_DETECT_CALLTYPE(_i, _, _elem) \ + GMOCK_PP_CAT(GMOCK_INTERNAL_DETECT_CALLTYPE_I_, _elem) -#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE(_arg) \ - GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I( \ - GMOCK_PP_CAT(GMOCK_INTERNAL_IS_CALLTYPE_HELPER_, _arg)) -#define GMOCK_INTERNAL_GET_VALUE_CALLTYPE_I(_arg) \ - GMOCK_PP_IDENTITY _arg +#define GMOCK_INTERNAL_DETECT_CALLTYPE_I_Calltype , -#define GMOCK_INTERNAL_IS_CALLTYPE_HELPER_Calltype +#define GMOCK_INTERNAL_UNPACK_Calltype(...) __VA_ARGS__ // Note: The use of `identity_t` here allows _Ret to represent return types that // would normally need to be specified in a different way. For example, a method @@ -476,4 +515,4 @@ using internal::FunctionMocker; #define GMOCK_MOCKER_(arity, constness, Method) \ GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__) -#endif // GOOGLEMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_FUNCTION_MOCKER_H_ +#endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_FUNCTION_MOCKER_H_ diff --git a/mars/googlemock/include/gmock/gmock-matchers.h b/mars/googlemock/include/gmock/gmock-matchers.h index 86be9c176..0f6771377 100644 --- a/mars/googlemock/include/gmock/gmock-matchers.h +++ b/mars/googlemock/include/gmock/gmock-matchers.h @@ -27,7 +27,6 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // Google Mock - a framework for writing C++ mock classes. // // The MATCHER* family of macros can be used in a namespace scope to @@ -241,7 +240,7 @@ // // To learn more about using these macros, please search for 'MATCHER' // on -// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md +// https://github.com/google/googletest/blob/main/docs/gmock_cook_book.md // // This file also implements some commonly used argument matchers. More // matchers can be defined by the user implementing the @@ -250,14 +249,18 @@ // See googletest/include/gtest/gtest-matchers.h for the definition of class // Matcher, class MatcherInterface, and others. -// GOOGLETEST_CM0002 DO NOT DELETE +// IWYU pragma: private, include "gmock/gmock.h" +// IWYU pragma: friend gmock/.* #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ #include #include +#include +#include #include +#include #include #include #include @@ -313,7 +316,9 @@ class StringMatchResultListener : public MatchResultListener { private: ::std::stringstream ss_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); + StringMatchResultListener(const StringMatchResultListener&) = delete; + StringMatchResultListener& operator=(const StringMatchResultListener&) = + delete; }; // Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION @@ -396,7 +401,7 @@ class MatcherCastImpl { // is already a Matcher. This only compiles when type T can be // statically converted to type U. template -class MatcherCastImpl > { +class MatcherCastImpl> { public: static Matcher Cast(const Matcher& source_matcher) { return Matcher(new Impl(source_matcher)); @@ -450,7 +455,7 @@ class MatcherCastImpl > { // This even more specialized version is used for efficiently casting // a matcher to its own type. template -class MatcherCastImpl > { +class MatcherCastImpl> { public: static Matcher Cast(const Matcher& matcher) { return matcher; } }; @@ -533,19 +538,18 @@ inline Matcher SafeMatcherCast(const Matcher& matcher) { "T must be implicitly convertible to U"); // Enforce that we are not converting a non-reference type T to a reference // type U. - GTEST_COMPILE_ASSERT_( - std::is_reference::value || !std::is_reference::value, - cannot_convert_non_reference_arg_to_reference); + static_assert(std::is_reference::value || !std::is_reference::value, + "cannot convert non reference arg to reference"); // In case both T and U are arithmetic types, enforce that the // conversion is not lossy. typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; - GTEST_COMPILE_ASSERT_( + static_assert( kTIsOther || kUIsOther || - (internal::LosslessArithmeticConvertible::value), - conversion_of_arithmetic_types_must_be_lossless); + (internal::LosslessArithmeticConvertible::value), + "conversion of arithmetic types must be lossless"); return MatcherCast(matcher); } @@ -560,7 +564,7 @@ namespace internal { // If the explanation is not empty, prints it to the ostream. inline void PrintIfNotEmpty(const std::string& explanation, ::std::ostream* os) { - if (explanation != "" && os != nullptr) { + if (!explanation.empty() && os != nullptr) { *os << ", " << explanation; } } @@ -678,9 +682,9 @@ bool TupleMatches(const MatcherTuple& matcher_tuple, const ValueTuple& value_tuple) { // Makes sure that matcher_tuple and value_tuple have the same // number of fields. - GTEST_COMPILE_ASSERT_(std::tuple_size::value == - std::tuple_size::value, - matcher_and_value_have_different_numbers_of_fields); + static_assert(std::tuple_size::value == + std::tuple_size::value, + "matcher and value have different numbers of fields"); return TuplePrefix::value>::Matches(matcher_tuple, value_tuple); } @@ -689,8 +693,7 @@ bool TupleMatches(const MatcherTuple& matcher_tuple, // is no failure, nothing will be streamed to os. template void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, - const ValueTuple& values, - ::std::ostream* os) { + const ValueTuple& values, ::std::ostream* os) { TuplePrefix::value>::ExplainMatchFailuresTo( matchers, values, os); } @@ -714,14 +717,14 @@ class TransformTupleValuesHelper { private: template struct IterateOverTuple { - OutIter operator() (Func f, const Tup& t, OutIter out) const { + OutIter operator()(Func f, const Tup& t, OutIter out) const { *out++ = f(::std::get(t)); return IterateOverTuple()(f, t, out); } }; template struct IterateOverTuple { - OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { + OutIter operator()(Func /* f */, const Tup& /* t */, OutIter out) const { return out; } }; @@ -767,9 +770,7 @@ class IsNullMatcher { } void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "isn't NULL"; - } + void DescribeNegationTo(::std::ostream* os) const { *os << "isn't NULL"; } }; // Implements the polymorphic NotNull() matcher, which matches any raw or smart @@ -783,9 +784,7 @@ class NotNullMatcher { } void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "is NULL"; - } + void DescribeNegationTo(::std::ostream* os) const { *os << "is NULL"; } }; // Ref(variable) matches any argument that is a reference to @@ -871,8 +870,7 @@ inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, // String comparison for narrow or wide strings that can have embedded NUL // characters. template -bool CaseInsensitiveStringEquals(const StringType& s1, - const StringType& s2) { +bool CaseInsensitiveStringEquals(const StringType& s1, const StringType& s2) { // Are the heads equal? if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { return false; @@ -933,8 +931,8 @@ class StrEqualityMatcher { bool MatchAndExplain(const MatcheeStringType& s, MatchResultListener* /* listener */) const { const StringType s2(s); - const bool eq = case_sensitive_ ? s2 == string_ : - CaseInsensitiveStringEquals(s2, string_); + const bool eq = case_sensitive_ ? s2 == string_ + : CaseInsensitiveStringEquals(s2, string_); return expect_eq_ == eq; } @@ -1021,8 +1019,7 @@ class HasSubstrMatcher { template class StartsWithMatcher { public: - explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { - } + explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {} #if GTEST_INTERNAL_HAS_STRING_VIEW bool MatchAndExplain(const internal::StringView& s, @@ -1053,7 +1050,7 @@ class StartsWithMatcher { MatchResultListener* /* listener */) const { const StringType& s2(s); return s2.length() >= prefix_.length() && - s2.substr(0, prefix_.length()) == prefix_; + s2.substr(0, prefix_.length()) == prefix_; } void DescribeTo(::std::ostream* os) const { @@ -1107,7 +1104,7 @@ class EndsWithMatcher { MatchResultListener* /* listener */) const { const StringType& s2(s); return s2.length() >= suffix_.length() && - s2.substr(s2.length() - suffix_.length()) == suffix_; + s2.substr(s2.length() - suffix_.length()) == suffix_; } void DescribeTo(::std::ostream* os) const { @@ -1124,6 +1121,45 @@ class EndsWithMatcher { const StringType suffix_; }; +// Implements the polymorphic WhenBase64Unescaped(matcher) matcher, which can be +// used as a Matcher as long as T can be converted to a string. +class WhenBase64UnescapedMatcher { + public: + using is_gtest_matcher = void; + + explicit WhenBase64UnescapedMatcher( + const Matcher& internal_matcher) + : internal_matcher_(internal_matcher) {} + + // Matches anything that can convert to std::string. + template + bool MatchAndExplain(const MatcheeStringType& s, + MatchResultListener* listener) const { + const std::string s2(s); // NOLINT (needed for working with string_view). + std::string unescaped; + if (!internal::Base64Unescape(s2, &unescaped)) { + if (listener != nullptr) { + *listener << "is not a valid base64 escaped string"; + } + return false; + } + return MatchPrintAndExplain(unescaped, internal_matcher_, listener); + } + + void DescribeTo(::std::ostream* os) const { + *os << "matches after Base64Unescape "; + internal_matcher_.DescribeTo(os); + } + + void DescribeNegationTo(::std::ostream* os) const { + *os << "does not match after Base64Unescape "; + internal_matcher_.DescribeTo(os); + } + + private: + const Matcher internal_matcher_; +}; + // Implements a matcher that compares the two fields of a 2-tuple // using one of the ==, <=, <, etc, operators. The two fields being // compared don't have to have the same type. @@ -1165,27 +1201,27 @@ class PairMatchBase { }; }; -class Eq2Matcher : public PairMatchBase { +class Eq2Matcher : public PairMatchBase> { public: static const char* Desc() { return "an equal pair"; } }; -class Ne2Matcher : public PairMatchBase { +class Ne2Matcher : public PairMatchBase> { public: static const char* Desc() { return "an unequal pair"; } }; -class Lt2Matcher : public PairMatchBase { +class Lt2Matcher : public PairMatchBase> { public: static const char* Desc() { return "a pair where the first < the second"; } }; -class Gt2Matcher : public PairMatchBase { +class Gt2Matcher : public PairMatchBase> { public: static const char* Desc() { return "a pair where the first > the second"; } }; -class Le2Matcher : public PairMatchBase { +class Le2Matcher : public PairMatchBase> { public: static const char* Desc() { return "a pair where the first <= the second"; } }; -class Ge2Matcher : public PairMatchBase { +class Ge2Matcher : public PairMatchBase> { public: static const char* Desc() { return "a pair where the first >= the second"; } }; @@ -1197,8 +1233,7 @@ class Ge2Matcher : public PairMatchBase { template class NotMatcherImpl : public MatcherInterface { public: - explicit NotMatcherImpl(const Matcher& matcher) - : matcher_(matcher) {} + explicit NotMatcherImpl(const Matcher& matcher) : matcher_(matcher) {} bool MatchAndExplain(const T& x, MatchResultListener* listener) const override { @@ -1242,7 +1277,7 @@ class NotMatcher { template class AllOfMatcherImpl : public MatcherInterface { public: - explicit AllOfMatcherImpl(std::vector > matchers) + explicit AllOfMatcherImpl(std::vector> matchers) : matchers_(std::move(matchers)) {} void DescribeTo(::std::ostream* os) const override { @@ -1293,7 +1328,7 @@ class AllOfMatcherImpl : public MatcherInterface { } private: - const std::vector > matchers_; + const std::vector> matchers_; }; // VariadicMatcher is used for the variadic implementation of @@ -1316,14 +1351,14 @@ class VariadicMatcher { // all of the provided matchers (Matcher1, Matcher2, ...) can match. template operator Matcher() const { - std::vector > values; + std::vector> values; CreateVariadicMatcher(&values, std::integral_constant()); return Matcher(new CombiningMatcher(std::move(values))); } private: template - void CreateVariadicMatcher(std::vector >* values, + void CreateVariadicMatcher(std::vector>* values, std::integral_constant) const { values->push_back(SafeMatcherCast(std::get(matchers_))); CreateVariadicMatcher(values, std::integral_constant()); @@ -1331,7 +1366,7 @@ class VariadicMatcher { template void CreateVariadicMatcher( - std::vector >*, + std::vector>*, std::integral_constant) const {} std::tuple matchers_; @@ -1347,7 +1382,7 @@ using AllOfMatcher = VariadicMatcher; template class AnyOfMatcherImpl : public MatcherInterface { public: - explicit AnyOfMatcherImpl(std::vector > matchers) + explicit AnyOfMatcherImpl(std::vector> matchers) : matchers_(std::move(matchers)) {} void DescribeTo(::std::ostream* os) const override { @@ -1398,13 +1433,35 @@ class AnyOfMatcherImpl : public MatcherInterface { } private: - const std::vector > matchers_; + const std::vector> matchers_; }; // AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). template using AnyOfMatcher = VariadicMatcher; +// ConditionalMatcher is the implementation of Conditional(cond, m1, m2) +template +class ConditionalMatcher { + public: + ConditionalMatcher(bool condition, MatcherTrue matcher_true, + MatcherFalse matcher_false) + : condition_(condition), + matcher_true_(std::move(matcher_true)), + matcher_false_(std::move(matcher_false)) {} + + template + operator Matcher() const { // NOLINT(runtime/explicit) + return condition_ ? SafeMatcherCast(matcher_true_) + : SafeMatcherCast(matcher_false_); + } + + private: + bool condition_; + MatcherTrue matcher_true_; + MatcherFalse matcher_false_; +}; + // Wrapper for implementation of Any/AllOfArray(). template