From fb3cd3c113cbffcc79860b1b861fb87b4c01efd2 Mon Sep 17 00:00:00 2001 From: liyang Date: Sat, 25 Nov 2023 18:18:54 +0800 Subject: [PATCH 1/5] update gtest for windows unittest Signed-off-by: liyang --- .../gtest/include/gtest/gtest-death-test.h | 45 +- 3rdparty/gtest/include/gtest/gtest-matchers.h | 416 ++- 3rdparty/gtest/include/gtest/gtest-message.h | 7 +- .../gtest/include/gtest/gtest-param-test.h | 30 +- 3rdparty/gtest/include/gtest/gtest-printers.h | 665 ++-- 3rdparty/gtest/include/gtest/gtest-spi.h | 6 +- .../gtest/include/gtest/gtest-test-part.h | 6 +- .../gtest/include/gtest/gtest-typed-test.h | 69 +- 3rdparty/gtest/include/gtest/gtest.h | 119 +- .../gtest/include/gtest/gtest_pred_impl.h | 6 +- 3rdparty/gtest/include/gtest/gtest_prod.h | 6 +- .../gtest/include/gtest/hwext/gtest-ext.h | 83 + .../gtest/include/gtest/hwext/gtest-filter.h | 48 + .../include/gtest/hwext/gtest-multithread.h | 117 + .../gtest/include/gtest/hwext/gtest-tag.h | 115 + .../gtest/include/gtest/hwext/gtest-utils.h | 21 + .../gtest/internal/custom/gtest-port.h | 6 +- .../gtest/internal/custom/gtest-printers.h | 6 +- .../include/gtest/internal/custom/gtest.h | 6 +- .../internal/gtest-death-test-internal.h | 6 +- .../include/gtest/internal/gtest-filepath.h | 8 +- .../include/gtest/internal/gtest-internal.h | 380 +- .../include/gtest/internal/gtest-param-util.h | 94 +- .../include/gtest/internal/gtest-port-arch.h | 13 +- .../gtest/include/gtest/internal/gtest-port.h | 334 +- .../include/gtest/internal/gtest-string.h | 12 +- .../include/gtest/internal/gtest-type-util.h | 3282 +---------------- .../mingw64/src/gtest/src/hwext/gtest-ext.cc | 220 ++ .../src/gtest/src/hwext/gtest-filter.cc | 226 ++ .../src/gtest/src/hwext/gtest-multithread.cpp | 96 + .../mingw64/src/gtest/src/hwext/gtest-tag.cc | 197 + .../src/gtest/src/hwext/gtest-utils.cc | 81 + .../ipc_core/include/message_parcel.h | 230 +- .../native/src/core/source/message_parcel.cpp | 635 +++- .../services/utils/media_data_source.cpp | 23 +- .../ohos/utils/native/base/include/parcel.h | 533 +-- .../ohos/utils/native/base/src/parcel.cpp | 951 ++++- 37 files changed, 4662 insertions(+), 4436 deletions(-) create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-ext.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-filter.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-multithread.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-tag.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-utils.h create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc diff --git a/3rdparty/gtest/include/gtest/gtest-death-test.h b/3rdparty/gtest/include/gtest/gtest-death-test.h index dc878ff..9b4d4d1 100644 --- a/3rdparty/gtest/include/gtest/gtest-death-test.h +++ b/3rdparty/gtest/include/gtest/gtest-death-test.h @@ -35,8 +35,8 @@ // directly. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ #include "gtest/internal/gtest-death-test-internal.h" @@ -97,6 +97,10 @@ GTEST_API_ bool InDeathTestChild(); // // ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); // +// The final parameter to each of these macros is a matcher applied to any data +// the sub-process wrote to stderr. For compatibility with existing tests, a +// bare string is interpreted as a regular expression matcher. +// // On the regular expressions used in death tests: // // GOOGLETEST_CM0005 DO NOT DELETE @@ -162,27 +166,27 @@ GTEST_API_ bool InDeathTestChild(); // directory in PATH. // -// Asserts that a given statement causes the program to exit, with an -// integer exit status that satisfies predicate, and emitting error output -// that matches regex. -# define ASSERT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) +// Asserts that a given `statement` causes the program to exit, with an +// integer exit status that satisfies `predicate`, and emitting error output +// that matches `matcher`. +# define ASSERT_EXIT(statement, predicate, matcher) \ + GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_) -// Like ASSERT_EXIT, but continues on to successive tests in the +// Like `ASSERT_EXIT`, but continues on to successive tests in the // test suite, if any: -# define EXPECT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) +# define EXPECT_EXIT(statement, predicate, matcher) \ + GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_) -// Asserts that a given statement causes the program to exit, either by +// Asserts that a given `statement` causes the program to exit, either by // explicitly exiting with a nonzero exit code or being killed by a -// signal, and emitting error output that matches regex. -# define ASSERT_DEATH(statement, regex) \ - ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) +// signal, and emitting error output that matches `matcher`. +# define ASSERT_DEATH(statement, matcher) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher) -// Like ASSERT_DEATH, but continues on to successive tests in the +// Like `ASSERT_DEATH`, but continues on to successive tests in the // test suite, if any: -# define EXPECT_DEATH(statement, regex) \ - EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) +# define EXPECT_DEATH(statement, matcher) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher) // Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: @@ -190,11 +194,10 @@ GTEST_API_ bool InDeathTestChild(); class GTEST_API_ ExitedWithCode { public: explicit ExitedWithCode(int exit_code); + ExitedWithCode(const ExitedWithCode&) = default; + void operator=(const ExitedWithCode& other) = delete; bool operator()(int exit_status) const; private: - // No implementation - assignment is unsupported. - void operator=(const ExitedWithCode& other); - const int exit_code_; }; @@ -340,4 +343,4 @@ class GTEST_API_ KilledBySignal { } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-matchers.h b/3rdparty/gtest/include/gtest/gtest-matchers.h index 9de6c2e..9fa34a0 100644 --- a/3rdparty/gtest/include/gtest/gtest-matchers.h +++ b/3rdparty/gtest/include/gtest/gtest-matchers.h @@ -32,13 +32,10 @@ // This file implements just enough of the matcher interface to allow // EXPECT_DEATH and friends to accept a matcher argument. -// IWYU pragma: private, include "testing/base/public/gunit.h" -// IWYU pragma: friend third_party/googletest/googlemock/.* -// IWYU pragma: friend third_party/googletest/googletest/.* - -#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#include #include #include #include @@ -63,20 +60,16 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_( namespace testing { // To implement a matcher Foo for type T, define: -// 1. a class FooMatcherImpl that implements the -// MatcherInterface interface, and -// 2. a factory function that creates a Matcher object from a -// FooMatcherImpl*. -// -// The two-level delegation design makes it possible to allow a user -// to write "v" instead of "Eq(v)" where a Matcher is expected, which -// is impossible if we pass matchers by pointers. It also eases -// ownership management as Matcher objects can now be copied like -// plain values. - -// MatchResultListener is an abstract class. Its << operator can be -// used by a matcher to explain why a value matches or doesn't match. +// 1. a class FooMatcherMatcher that implements the matcher interface: +// using is_gtest_matcher = void; +// bool MatchAndExplain(const T&, std::ostream*); +// (MatchResultListener* can also be used instead of std::ostream*) +// void DescribeTo(std::ostream*); +// void DescribeNegationTo(std::ostream*); // +// 2. a factory function that creates a Matcher object from a +// FooMatcherMatcher. + class MatchResultListener { public: // Creates a listener object with the given underlying ostream. The @@ -113,7 +106,7 @@ inline MatchResultListener::~MatchResultListener() { // An instance of a subclass of this knows how to describe itself as a // matcher. -class MatcherDescriberInterface { +class GTEST_API_ MatcherDescriberInterface { public: virtual ~MatcherDescriberInterface() {} @@ -181,31 +174,6 @@ class MatcherInterface : public MatcherDescriberInterface { namespace internal { -// Converts a MatcherInterface to a MatcherInterface. -template -class MatcherInterfaceAdapter : public MatcherInterface { - public: - explicit MatcherInterfaceAdapter(const MatcherInterface* impl) - : impl_(impl) {} - ~MatcherInterfaceAdapter() override { delete impl_; } - - void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); } - - void DescribeNegationTo(::std::ostream* os) const override { - impl_->DescribeNegationTo(os); - } - - bool MatchAndExplain(const T& x, - MatchResultListener* listener) const override { - return impl_->MatchAndExplain(x, listener); - } - - private: - const MatcherInterface* const impl_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); -}; - struct AnyEq { template bool operator()(const A& a, const B& b) const { return a == b; } @@ -252,16 +220,35 @@ class StreamMatchResultListener : public MatchResultListener { GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); }; +struct SharedPayloadBase { + std::atomic ref{1}; + void Ref() { ref.fetch_add(1, std::memory_order_relaxed); } + bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; } +}; + +template +struct SharedPayload : SharedPayloadBase { + explicit SharedPayload(const T& v) : value(v) {} + explicit SharedPayload(T&& v) : value(std::move(v)) {} + + static void Destroy(SharedPayloadBase* shared) { + delete static_cast(shared); + } + + T value; +}; + // An internal class for implementing Matcher, which will derive // from it. We put functionalities common to all Matcher // specializations here to avoid code duplication. template -class MatcherBase { +class MatcherBase : private MatcherDescriberInterface { public: // Returns true if and only if the matcher matches x; also explains the // match result to 'listener'. bool MatchAndExplain(const T& x, MatchResultListener* listener) const { - return impl_->MatchAndExplain(x, listener); + GTEST_CHECK_(vtable_ != nullptr); + return vtable_->match_and_explain(*this, x, listener); } // Returns true if and only if this matcher matches x. @@ -271,11 +258,15 @@ class MatcherBase { } // Describes this matcher to an ostream. - void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + void DescribeTo(::std::ostream* os) const final { + GTEST_CHECK_(vtable_ != nullptr); + vtable_->describe(*this, os, false); + } // Describes the negation of this matcher to an ostream. - void DescribeNegationTo(::std::ostream* os) const { - impl_->DescribeNegationTo(os); + void DescribeNegationTo(::std::ostream* os) const final { + GTEST_CHECK_(vtable_ != nullptr); + vtable_->describe(*this, os, true); } // Explains why x matches, or doesn't match, the matcher. @@ -288,31 +279,194 @@ class MatcherBase { // of the describer, which is only guaranteed to be alive when // this matcher object is alive. const MatcherDescriberInterface* GetDescriber() const { - return impl_.get(); + if (vtable_ == nullptr) return nullptr; + return vtable_->get_describer(*this); } protected: - MatcherBase() {} + MatcherBase() : vtable_(nullptr) {} // Constructs a matcher from its implementation. - explicit MatcherBase(const MatcherInterface* impl) : impl_(impl) {} - template - explicit MatcherBase( - const MatcherInterface* impl, - typename std::enable_if::value>::type* = - nullptr) - : impl_(new internal::MatcherInterfaceAdapter(impl)) {} + explicit MatcherBase(const MatcherInterface* impl) { + Init(impl); + } + + template ::type::is_gtest_matcher> + MatcherBase(M&& m) { // NOLINT + Init(std::forward(m)); + } + + MatcherBase(const MatcherBase& other) + : vtable_(other.vtable_), buffer_(other.buffer_) { + if (IsShared()) buffer_.shared->Ref(); + } + + MatcherBase& operator=(const MatcherBase& other) { + if (this == &other) return *this; + Destroy(); + vtable_ = other.vtable_; + buffer_ = other.buffer_; + if (IsShared()) buffer_.shared->Ref(); + return *this; + } - MatcherBase(const MatcherBase&) = default; - MatcherBase& operator=(const MatcherBase&) = default; - MatcherBase(MatcherBase&&) = default; - MatcherBase& operator=(MatcherBase&&) = default; + MatcherBase(MatcherBase&& other) + : vtable_(other.vtable_), buffer_(other.buffer_) { + other.vtable_ = nullptr; + } + + MatcherBase& operator=(MatcherBase&& other) { + if (this == &other) return *this; + Destroy(); + vtable_ = other.vtable_; + buffer_ = other.buffer_; + other.vtable_ = nullptr; + return *this; + } - virtual ~MatcherBase() {} + ~MatcherBase() override { Destroy(); } private: - std::shared_ptr> impl_; + struct VTable { + bool (*match_and_explain)(const MatcherBase&, const T&, + MatchResultListener*); + void (*describe)(const MatcherBase&, std::ostream*, bool negation); + // Returns the captured object if it implements the interface, otherwise + // returns the MatcherBase itself. + const MatcherDescriberInterface* (*get_describer)(const MatcherBase&); + // Called on shared instances when the reference count reaches 0. + void (*shared_destroy)(SharedPayloadBase*); + }; + + bool IsShared() const { + return vtable_ != nullptr && vtable_->shared_destroy != nullptr; + } + + // If the implementation uses a listener, call that. + template + static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, + MatchResultListener* listener) + -> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) { + return P::Get(m).MatchAndExplain(value, listener->stream()); + } + + template + static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, + MatchResultListener* listener) + -> decltype(P::Get(m).MatchAndExplain(value, listener)) { + return P::Get(m).MatchAndExplain(value, listener); + } + + template + static void DescribeImpl(const MatcherBase& m, std::ostream* os, + bool negation) { + if (negation) { + P::Get(m).DescribeNegationTo(os); + } else { + P::Get(m).DescribeTo(os); + } + } + + template + static const MatcherDescriberInterface* GetDescriberImpl( + const MatcherBase& m) { + // If the impl is a MatcherDescriberInterface, then return it. + // Otherwise use MatcherBase itself. + // This allows us to implement the GetDescriber() function without support + // from the impl, but some users really want to get their impl back when + // they call GetDescriber(). + // We use std::get on a tuple as a workaround of not having `if constexpr`. + return std::get<( + std::is_convertible::value + ? 1 + : 0)>(std::make_tuple(&m, &P::Get(m))); + } + + template + const VTable* GetVTable() { + static constexpr VTable kVTable = {&MatchAndExplainImpl

, + &DescribeImpl

, &GetDescriberImpl

, + P::shared_destroy}; + return &kVTable; + } + + union Buffer { + // Add some types to give Buffer some common alignment/size use cases. + void* ptr; + double d; + int64_t i; + // And add one for the out-of-line cases. + SharedPayloadBase* shared; + }; + + void Destroy() { + if (IsShared() && buffer_.shared->Unref()) { + vtable_->shared_destroy(buffer_.shared); + } + } + + template + static constexpr bool IsInlined() { + return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && + std::is_trivially_copy_constructible::value && + std::is_trivially_destructible::value; + } + + template ()> + struct ValuePolicy { + static const M& Get(const MatcherBase& m) { + // When inlined along with Init, need to be explicit to avoid violating + // strict aliasing rules. + const M *ptr = static_cast( + static_cast(&m.buffer_)); + return *ptr; + } + static void Init(MatcherBase& m, M impl) { + ::new (static_cast(&m.buffer_)) M(impl); + } + static constexpr auto shared_destroy = nullptr; + }; + + template + struct ValuePolicy { + using Shared = SharedPayload; + static const M& Get(const MatcherBase& m) { + return static_cast(m.buffer_.shared)->value; + } + template + static void Init(MatcherBase& m, Arg&& arg) { + m.buffer_.shared = new Shared(std::forward(arg)); + } + static constexpr auto shared_destroy = &Shared::Destroy; + }; + + template + struct ValuePolicy*, B> { + using M = const MatcherInterface; + using Shared = SharedPayload>; + static const M& Get(const MatcherBase& m) { + return *static_cast(m.buffer_.shared)->value; + } + static void Init(MatcherBase& m, M* impl) { + m.buffer_.shared = new Shared(std::unique_ptr(impl)); + } + + static constexpr auto shared_destroy = &Shared::Destroy; + }; + + template + void Init(M&& m) { + using MM = typename std::decay::type; + using Policy = ValuePolicy; + vtable_ = GetVTable(); + Policy::Init(*this, std::forward(m)); + } + + const VTable* vtable_; + Buffer buffer_; }; } // namespace internal @@ -340,6 +494,10 @@ class Matcher : public internal::MatcherBase { nullptr) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) : internal::MatcherBase(std::forward(m)) {} // NOLINT + // Implicit constructor here allows people to write // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes Matcher(T value); // NOLINT @@ -357,6 +515,11 @@ class GTEST_API_ Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} + // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. Matcher(const std::string& s); // NOLINT @@ -376,6 +539,11 @@ class GTEST_API_ Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} + // Allows the user to write str instead of Eq(str) sometimes, where // str is a string object. Matcher(const std::string& s); // NOLINT @@ -384,18 +552,24 @@ class GTEST_API_ Matcher Matcher(const char* s); // NOLINT }; -#if GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW // The following two specializations allow the user to write str // instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view // matcher is expected. template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { +class GTEST_API_ Matcher + : public internal::MatcherBase { public: Matcher() {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) { + } // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. @@ -404,20 +578,25 @@ class GTEST_API_ Matcher // Allows the user to write "foo" instead of Eq("foo") sometimes. Matcher(const char* s); // NOLINT - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT + // Allows the user to pass absl::string_views or std::string_views directly. + Matcher(internal::StringView s); // NOLINT }; template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { +class GTEST_API_ Matcher + : public internal::MatcherBase { public: Matcher() {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. @@ -426,10 +605,10 @@ class GTEST_API_ Matcher // Allows the user to write "foo" instead of Eq("foo") sometimes. Matcher(const char* s); // NOLINT - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT + // Allows the user to pass absl::string_views or std::string_views directly. + Matcher(internal::StringView s); // NOLINT }; -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Prints a matcher in a human-readable format. template @@ -474,13 +653,13 @@ class PolymorphicMatcher { public: explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); } + void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); } - virtual void DescribeNegationTo(::std::ostream* os) const { + void DescribeNegationTo(::std::ostream* os) const override { impl_.DescribeNegationTo(os); } - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + bool MatchAndExplain(T x, MatchResultListener* listener) const override { return impl_.MatchAndExplain(x, listener); } @@ -529,37 +708,32 @@ template class ComparisonBase { public: explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} + + using is_gtest_matcher = void; + template - operator Matcher() const { - return Matcher(new Impl(rhs_)); + bool MatchAndExplain(const Lhs& lhs, std::ostream*) const { + return Op()(lhs, Unwrap(rhs_)); + } + void DescribeTo(std::ostream* os) const { + *os << D::Desc() << " "; + UniversalPrint(Unwrap(rhs_), os); + } + void DescribeNegationTo(std::ostream* os) const { + *os << D::NegatedDesc() << " "; + UniversalPrint(Unwrap(rhs_), os); } private: template - static const T& Unwrap(const T& v) { return v; } + static const T& Unwrap(const T& v) { + return v; + } template - static const T& Unwrap(std::reference_wrapper v) { return v; } - - template - class Impl : public MatcherInterface { - public: - explicit Impl(const Rhs& rhs) : rhs_(rhs) {} - bool MatchAndExplain(Lhs lhs, - MatchResultListener* /* listener */) const override { - return Op()(lhs, Unwrap(rhs_)); - } - void DescribeTo(::std::ostream* os) const override { - *os << D::Desc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } - void DescribeNegationTo(::std::ostream* os) const override { - *os << D::NegatedDesc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } + static const T& Unwrap(std::reference_wrapper v) { + return v; + } - private: - Rhs rhs_; - }; Rhs rhs_; }; @@ -612,6 +786,10 @@ class GeMatcher : public ComparisonBase, Rhs, AnyGe> { static const char* NegatedDesc() { return "isn't >="; } }; +template ::value>::type> +using StringLike = T; + // Implements polymorphic matchers MatchesRegex(regex) and // ContainsRegex(regex), which can be used as a Matcher as long as // T can be converted to a string. @@ -620,12 +798,12 @@ class MatchesRegexMatcher { MatchesRegexMatcher(const RE* regex, bool full_match) : regex_(regex), full_match_(full_match) {} -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { return MatchAndExplain(std::string(s), listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -672,9 +850,10 @@ inline PolymorphicMatcher MatchesRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); } -inline PolymorphicMatcher MatchesRegex( - const std::string& regex) { - return MatchesRegex(new internal::RE(regex)); +template +PolymorphicMatcher MatchesRegex( + const internal::StringLike& regex) { + return MatchesRegex(new internal::RE(std::string(regex))); } // Matches a string that contains regular expression 'regex'. @@ -683,9 +862,10 @@ inline PolymorphicMatcher ContainsRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); } -inline PolymorphicMatcher ContainsRegex( - const std::string& regex) { - return ContainsRegex(new internal::RE(regex)); +template +PolymorphicMatcher ContainsRegex( + const internal::StringLike& regex) { + return ContainsRegex(new internal::RE(std::string(regex))); } // Creates a polymorphic matcher that matches anything equal to x. @@ -747,4 +927,4 @@ inline internal::NeMatcher Ne(Rhs x) { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 -#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-message.h b/3rdparty/gtest/include/gtest/gtest-message.h index 4a80e11..becfd49 100644 --- a/3rdparty/gtest/include/gtest/gtest-message.h +++ b/3rdparty/gtest/include/gtest/gtest-message.h @@ -44,11 +44,12 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #include #include +#include #include "gtest/internal/gtest-port.h" @@ -215,4 +216,4 @@ std::string StreamableToString(const T& streamable) { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-param-test.h b/3rdparty/gtest/include/gtest/gtest-param-test.h index c2e6eae..804e702 100644 --- a/3rdparty/gtest/include/gtest/gtest-param-test.h +++ b/3rdparty/gtest/include/gtest/gtest-param-test.h @@ -30,12 +30,9 @@ // Macros and functions for implementing parameterized tests // in Google C++ Testing and Mocking Framework (Google Test) // -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ - +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ // Value-parameterized tests allow you to test your code with different // parameters without writing multiple copies of the same test. @@ -371,8 +368,6 @@ inline internal::ParamGenerator Bool() { // std::tuple where T1, T2, ..., TN are the types // of elements from sequences produces by gen1, gen2, ..., genN. // -// Combine can have up to 10 arguments. -// // Example: // // This will instantiate tests in test suite AnimalTest each one with @@ -416,19 +411,20 @@ internal::CartesianProductHolder Combine(const Generator&... g) { : public test_suite_name { \ public: \ GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ - virtual void TestBody(); \ + void TestBody() override; \ \ private: \ static int AddToRegistry() { \ ::testing::UnitTest::GetInstance() \ ->parameterized_test_registry() \ .GetTestSuitePatternHolder( \ - #test_suite_name, \ + GTEST_STRINGIFY_(test_suite_name), \ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ ->AddTestPattern( \ GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \ new ::testing::internal::TestMetaFactory()); \ + test_suite_name, test_name)>(), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)); \ return 0; \ } \ static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ @@ -483,13 +479,21 @@ internal::CartesianProductHolder Combine(const Generator&... g) { ::testing::UnitTest::GetInstance() \ ->parameterized_test_registry() \ .GetTestSuitePatternHolder( \ - #test_suite_name, \ + GTEST_STRINGIFY_(test_suite_name), \ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ ->AddTestSuiteInstantiation( \ - #prefix, >est_##prefix##test_suite_name##_EvalGenerator_, \ + GTEST_STRINGIFY_(prefix), \ + >est_##prefix##test_suite_name##_EvalGenerator_, \ >est_##prefix##test_suite_name##_EvalGenerateName_, \ __FILE__, __LINE__) + +// Allow Marking a Parameterized test class as not needing to be instantiated. +#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \ + namespace gtest_do_not_use_outside_namespace_scope {} \ + static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \ + GTEST_STRINGIFY_(T)) + // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #define INSTANTIATE_TEST_CASE_P \ @@ -500,4 +504,4 @@ internal::CartesianProductHolder Combine(const Generator&... g) { } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-printers.h b/3rdparty/gtest/include/gtest/gtest-printers.h index 56a0545..076c9de 100644 --- a/3rdparty/gtest/include/gtest/gtest-printers.h +++ b/3rdparty/gtest/include/gtest/gtest-printers.h @@ -97,10 +97,11 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #include +#include #include // NOLINT #include #include @@ -108,64 +109,124 @@ #include #include #include + #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" -#if GTEST_HAS_ABSL -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" -#include "absl/types/variant.h" -#endif // GTEST_HAS_ABSL - namespace testing { -// Definitions in the 'internal' and 'internal2' name spaces are -// subject to change without notice. DO NOT USE THEM IN USER CODE! -namespace internal2 { +// Definitions in the internal* namespaces are subject to change without notice. +// DO NOT USE THEM IN USER CODE! +namespace internal { -// Prints the given number of bytes in the given object to the given -// ostream. -GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, - size_t count, - ::std::ostream* os); +template +void UniversalPrint(const T& value, ::std::ostream* os); -// For selecting which printer to use when a given type has neither << -// nor PrintTo(). -enum TypeKind { - kProtobuf, // a protobuf type - kConvertibleToInteger, // a type implicitly convertible to BiggestInt - // (e.g. a named or unnamed enum type) -#if GTEST_HAS_ABSL - kConvertibleToStringView, // a type implicitly convertible to - // absl::string_view -#endif - kOtherType // anything else +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +struct ContainerPrinter { + template (0)) == sizeof(IsContainer)) && + !IsRecursiveContainer::value>::type> + static void PrintValue(const T& container, std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (auto&& elem : container) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(elem, os) here as PrintTo() doesn't + // handle `elem` being a native array. + internal::UniversalPrint(elem, os); + ++count; + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; + } }; -// TypeWithoutFormatter::PrintValue(value, os) is called -// by the universal printer to print a value of type T when neither -// operator<< nor PrintTo() is defined for T, where kTypeKind is the -// "kind" of T as defined by enum TypeKind. -template -class TypeWithoutFormatter { - public: - // This default version is called when kTypeKind is kOtherType. +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +struct FunctionPointerPrinter { + template ::value>::type> + static void PrintValue(T* p, ::std::ostream* os) { + if (p == nullptr) { + *os << "NULL"; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. + *os << reinterpret_cast(p); + } + } +}; + +struct PointerPrinter { + template + static void PrintValue(T* p, ::std::ostream* os) { + if (p == nullptr) { + *os << "NULL"; + } else { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } + } +}; + +namespace internal_stream_operator_without_lexical_name_lookup { + +// The presence of an operator<< here will terminate lexical scope lookup +// straight away (even though it cannot be a match because of its argument +// types). Thus, the two operator<< calls in StreamPrinter will find only ADL +// candidates. +struct LookupBlocker {}; +void operator<<(LookupBlocker, LookupBlocker); + +struct StreamPrinter { + template ::value>::type, + // Only accept types for which we can find a streaming operator via + // ADL (possibly involving implicit conversions). + typename = decltype(std::declval() + << std::declval())> static void PrintValue(const T& value, ::std::ostream* os) { - PrintBytesInObjectTo( - static_cast( - reinterpret_cast(std::addressof(value))), - sizeof(value), os); + // Call streaming operator found by ADL, possibly with implicit conversions + // of the arguments. + *os << value; } }; -// We print a protobuf using its ShortDebugString() when the string -// doesn't exceed this many characters; otherwise we print it using -// DebugString() for better readability. -const size_t kProtobufOneLinerMaxLength = 50; +} // namespace internal_stream_operator_without_lexical_name_lookup -template -class TypeWithoutFormatter { - public: +struct ProtobufPrinter { + // We print a protobuf using its ShortDebugString() when the string + // doesn't exceed this many characters; otherwise we print it using + // DebugString() for better readability. + static const size_t kProtobufOneLinerMaxLength = 50; + + template ::value>::type> static void PrintValue(const T& value, ::std::ostream* os) { std::string pretty_str = value.ShortDebugString(); if (pretty_str.length() > kProtobufOneLinerMaxLength) { @@ -175,9 +236,7 @@ class TypeWithoutFormatter { } }; -template -class TypeWithoutFormatter { - public: +struct ConvertibleToIntegerPrinter { // Since T has no << operator or PrintTo() but can be implicitly // converted to BiggestInt, we print it as a BiggestInt. // @@ -185,112 +244,73 @@ class TypeWithoutFormatter { // case printing it as an integer is the desired behavior. In case // T is not an enum, printing it as an integer is the best we can do // given that it has no user-defined printer. - static void PrintValue(const T& value, ::std::ostream* os) { - const internal::BiggestInt kBigInt = value; - *os << kBigInt; + static void PrintValue(internal::BiggestInt value, ::std::ostream* os) { + *os << value; } }; -#if GTEST_HAS_ABSL -template -class TypeWithoutFormatter { - public: - // Since T has neither operator<< nor PrintTo() but can be implicitly - // converted to absl::string_view, we print it as a absl::string_view. - // - // Note: the implementation is further below, as it depends on - // internal::PrintTo symbol which is defined later in the file. - static void PrintValue(const T& value, ::std::ostream* os); -}; -#endif - -// Prints the given value to the given ostream. If the value is a -// protocol message, its debug string is printed; if it's an enum or -// of a type implicitly convertible to BiggestInt, it's printed as an -// integer; otherwise the bytes in the value are printed. This is -// what UniversalPrinter::Print() does when it knows nothing about -// type T and T has neither << operator nor PrintTo(). -// -// A user can override this behavior for a class type Foo by defining -// a << operator in the namespace where Foo is defined. -// -// We put this operator in namespace 'internal2' instead of 'internal' -// to simplify the implementation, as much code in 'internal' needs to -// use << in STL, which would conflict with our own << were it defined -// in 'internal'. -// -// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If -// we define it to take an std::ostream instead, we'll get an -// "ambiguous overloads" compiler error when trying to print a type -// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether -// operator<<(std::ostream&, const T&) or -// operator<<(std::basic_stream, const Foo&) is more -// specific. -template -::std::basic_ostream& operator<<( - ::std::basic_ostream& os, const T& x) { - TypeWithoutFormatter::value - ? kProtobuf - : std::is_convertible< - const T&, internal::BiggestInt>::value - ? kConvertibleToInteger - : -#if GTEST_HAS_ABSL - std::is_convertible< - const T&, absl::string_view>::value - ? kConvertibleToStringView - : +struct ConvertibleToStringViewPrinter { +#if GTEST_INTERNAL_HAS_STRING_VIEW + static void PrintValue(internal::StringView value, ::std::ostream* os) { + internal::UniversalPrint(value, os); + } #endif - kOtherType)>::PrintValue(x, &os); - return os; -} +}; -} // namespace internal2 -} // namespace testing -// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up -// magic needed for implementing UniversalPrinter won't work. -namespace testing_internal { +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); +struct RawBytesPrinter { + // SFINAE on `sizeof` to make sure we have a complete type. + template + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo( + static_cast( + // Load bearing cast to void* to support iOS + reinterpret_cast(std::addressof(value))), + sizeof(value), os); + } +}; -// Used to print a value that is not an STL-style container when the -// user doesn't define PrintTo() for it. -template -void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { - // With the following statement, during unqualified name lookup, - // testing::internal2::operator<< appears as if it was declared in - // the nearest enclosing namespace that contains both - // ::testing_internal and ::testing::internal2, i.e. the global - // namespace. For more details, refer to the C++ Standard section - // 7.3.4-1 [namespace.udir]. This allows us to fall back onto - // testing::internal2::operator<< in case T doesn't come with a << - // operator. - // - // We cannot write 'using ::testing::internal2::operator<<;', which - // gcc 3.3 fails to compile due to a compiler bug. - using namespace ::testing::internal2; // NOLINT +struct FallbackPrinter { + template + static void PrintValue(const T&, ::std::ostream* os) { + *os << "(incomplete type)"; + } +}; - // Assuming T is defined in namespace foo, in the next statement, - // the compiler will consider all of: - // - // 1. foo::operator<< (thanks to Koenig look-up), - // 2. ::operator<< (as the current namespace is enclosed in ::), - // 3. testing::internal2::operator<< (thanks to the using statement above). - // - // The operator<< whose type matches T best will be picked. - // - // We deliberately allow #2 to be a candidate, as sometimes it's - // impossible to define #1 (e.g. when foo is ::std, defining - // anything in it is undefined behavior unless you are a compiler - // vendor.). - *os << value; -} +// Try every printer in order and return the first one that works. +template +struct FindFirstPrinter : FindFirstPrinter {}; -} // namespace testing_internal +template +struct FindFirstPrinter< + T, decltype(Printer::PrintValue(std::declval(), nullptr)), + Printer, Printers...> { + using type = Printer; +}; -namespace testing { -namespace internal { +// Select the best printer in the following order: +// - Print containers (they have begin/end/etc). +// - Print function pointers. +// - Print object pointers. +// - Use the stream operator, if available. +// - Print protocol buffers. +// - Print types convertible to BiggestInt. +// - Print types convertible to StringView, if available. +// - Fallback to printing the raw bytes of the object. +template +void PrintWithFallback(const T& value, ::std::ostream* os) { + using Printer = typename FindFirstPrinter< + T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter, + internal_stream_operator_without_lexical_name_lookup::StreamPrinter, + ProtobufPrinter, ConvertibleToIntegerPrinter, + ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type; + Printer::PrintValue(value, os); +} // FormatForComparison::Format(value) formats a // value of type ToPrint that is an operand of a comparison assertion @@ -340,6 +360,14 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); +#ifdef __cpp_char8_t +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t); +#endif +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t); #undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ @@ -357,6 +385,14 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); +#ifdef __cpp_char8_t +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string); +#endif +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string); #if GTEST_HAS_STD_WSTRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); @@ -389,85 +425,6 @@ std::string FormatForComparisonFailureMessage( template class UniversalPrinter; -template -void UniversalPrint(const T& value, ::std::ostream* os); - -enum DefaultPrinterType { - kPrintContainer, - kPrintPointer, - kPrintFunctionPointer, - kPrintOther, -}; -template struct WrapPrinterType {}; - -// Used to print an STL-style container when the user doesn't define -// a PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const C& container, ::std::ostream* os) { - const size_t kMaxCount = 32; // The maximum number of elements to print. - *os << '{'; - size_t count = 0; - for (typename C::const_iterator it = container.begin(); - it != container.end(); ++it, ++count) { - if (count > 0) { - *os << ','; - if (count == kMaxCount) { // Enough has been printed. - *os << " ..."; - break; - } - } - *os << ' '; - // We cannot call PrintTo(*it, os) here as PrintTo() doesn't - // handle *it being a native array. - internal::UniversalPrint(*it, os); - } - - if (count > 0) { - *os << ' '; - } - *os << '}'; -} - -// Used to print a pointer that is neither a char pointer nor a member -// pointer, when the user doesn't define PrintTo() for it. (A member -// variable pointer or member function pointer doesn't really point to -// a location in the address space. Their representation is -// implementation-defined. Therefore they will be printed as raw -// bytes.) -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is not a function type. We just call << to print p, - // relying on ADL to pick up user-defined << for their pointer - // types, if any. - *os << p; - } -} -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is a function type, so '*os << p' doesn't do what we want - // (it just prints p as bool). We want to print p as a const - // void*. - *os << reinterpret_cast(p); - } -} - -// Used to print a non-container, non-pointer value when the user -// doesn't define PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const T& value, ::std::ostream* os) { - ::testing_internal::DefaultPrintNonContainerTo(value, os); -} - // Prints the given value using the << operator if it has one; // otherwise prints the bytes in it. This is what // UniversalPrinter::Print() does when PrintTo() is not specialized @@ -481,36 +438,7 @@ void DefaultPrintTo(WrapPrinterType /* dummy */, // wants). template void PrintTo(const T& value, ::std::ostream* os) { - // DefaultPrintTo() is overloaded. The type of its first argument - // determines which version will be picked. - // - // Note that we check for container types here, prior to we check - // for protocol message types in our operator<<. The rationale is: - // - // For protocol messages, we want to give people a chance to - // override Google Mock's format by defining a PrintTo() or - // operator<<. For STL containers, other formats can be - // incompatible with Google Mock's format for the container - // elements; therefore we check for container types here to ensure - // that our format is used. - // - // Note that MSVC and clang-cl do allow an implicit conversion from - // pointer-to-function to pointer-to-object, but clang-cl warns on it. - // So don't use ImplicitlyConvertible if it can be helped since it will - // cause this warning, and use a separate overload of DefaultPrintTo for - // function pointers so that the `*os << p` in the object pointer overload - // doesn't cause that warning either. - DefaultPrintTo( - WrapPrinterType < - (sizeof(IsContainerTest(0)) == sizeof(IsContainer)) && - !IsRecursiveContainer::value - ? kPrintContainer - : !std::is_pointer::value - ? kPrintOther - : std::is_function::type>::value - ? kPrintFunctionPointer - : kPrintPointer > (), - value, os); + internal::PrintWithFallback(value, os); } // The following list of PrintTo() overloads tells @@ -541,6 +469,16 @@ inline void PrintTo(bool x, ::std::ostream* os) { // is implemented as an unsigned type. GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); +GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os); +inline void PrintTo(char16_t c, ::std::ostream* os) { + PrintTo(ImplicitCast_(c), os); +} +#ifdef __cpp_char8_t +inline void PrintTo(char8_t c, ::std::ostream* os) { + PrintTo(ImplicitCast_(c), os); +} +#endif + // Overloads for C strings. GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); inline void PrintTo(char* s, ::std::ostream* os) { @@ -561,6 +499,23 @@ inline void PrintTo(const unsigned char* s, ::std::ostream* os) { inline void PrintTo(unsigned char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } +#ifdef __cpp_char8_t +// Overloads for u8 strings. +GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os); +inline void PrintTo(char8_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif +// Overloads for u16 strings. +GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os); +inline void PrintTo(char16_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +// Overloads for u32 strings. +GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os); +inline void PrintTo(char32_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} // MSVC can be configured to define wchar_t as a typedef of unsigned // short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native @@ -595,6 +550,26 @@ inline void PrintTo(const ::std::string& s, ::std::ostream* os) { PrintStringTo(s, os); } +// Overloads for ::std::u8string +#ifdef __cpp_char8_t +GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) { + PrintU8StringTo(s, os); +} +#endif + +// Overloads for ::std::u16string +GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) { + PrintU16StringTo(s, os); +} + +// Overloads for ::std::u32string +GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) { + PrintU32StringTo(s, os); +} + // Overloads for ::std::wstring. #if GTEST_HAS_STD_WSTRING GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); @@ -603,12 +578,12 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { } #endif // GTEST_HAS_STD_WSTRING -#if GTEST_HAS_ABSL -// Overload for absl::string_view. -inline void PrintTo(absl::string_view sp, ::std::ostream* os) { +#if GTEST_INTERNAL_HAS_STRING_VIEW +// Overload for internal::StringView. +inline void PrintTo(internal::StringView sp, ::std::ostream* os) { PrintTo(::std::string(sp), os); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } @@ -617,6 +592,43 @@ void PrintTo(std::reference_wrapper ref, ::std::ostream* os) { UniversalPrinter::Print(ref.get(), os); } +inline const void* VoidifyPointer(const void* p) { return p; } +inline const void* VoidifyPointer(volatile const void* p) { + return const_cast(p); +} + +template +void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) { + if (ptr == nullptr) { + *os << "(nullptr)"; + } else { + // We can't print the value. Just print the pointer.. + *os << "(" << (VoidifyPointer)(ptr.get()) << ")"; + } +} +template ::value && + !std::is_array::value>::type> +void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) { + if (ptr == nullptr) { + *os << "(nullptr)"; + } else { + *os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = "; + UniversalPrinter::Print(*ptr, os); + *os << ")"; + } +} + +template +void PrintTo(const std::unique_ptr& ptr, std::ostream* os) { + (PrintSmartPointer)(ptr, os, 0); +} + +template +void PrintTo(const std::shared_ptr& ptr, std::ostream* os) { + (PrintSmartPointer)(ptr, os, 0); +} + // Helper function for printing a tuple. T must be instantiated with // a tuple type. template @@ -682,14 +694,46 @@ class UniversalPrinter { GTEST_DISABLE_MSC_WARNINGS_POP_() }; -#if GTEST_HAS_ABSL +// Remove any const-qualifiers before passing a type to UniversalPrinter. +template +class UniversalPrinter : public UniversalPrinter {}; + +#if GTEST_INTERNAL_HAS_ANY + +// Printer for std::any / absl::any -// Printer for absl::optional +template <> +class UniversalPrinter { + public: + static void Print(const Any& value, ::std::ostream* os) { + if (value.has_value()) { + *os << "value of type " << GetTypeName(value); + } else { + *os << "no value"; + } + } + + private: + static std::string GetTypeName(const Any& value) { +#if GTEST_HAS_RTTI + return internal::GetTypeName(value.type()); +#else + static_cast(value); // possibly unused + return ""; +#endif // GTEST_HAS_RTTI + } +}; + +#endif // GTEST_INTERNAL_HAS_ANY + +#if GTEST_INTERNAL_HAS_OPTIONAL + +// Printer for std::optional / absl::optional template -class UniversalPrinter<::absl::optional> { +class UniversalPrinter> { public: - static void Print(const ::absl::optional& value, ::std::ostream* os) { + static void Print(const Optional& value, ::std::ostream* os) { *os << '('; if (!value) { *os << "nullopt"; @@ -700,14 +744,22 @@ class UniversalPrinter<::absl::optional> { } }; -// Printer for absl::variant +#endif // GTEST_INTERNAL_HAS_OPTIONAL + +#if GTEST_INTERNAL_HAS_VARIANT + +// Printer for std::variant / absl::variant template -class UniversalPrinter<::absl::variant> { +class UniversalPrinter> { public: - static void Print(const ::absl::variant& value, ::std::ostream* os) { + static void Print(const Variant& value, ::std::ostream* os) { *os << '('; - absl::visit(Visitor{os}, value); +#if GTEST_HAS_ABSL + absl::visit(Visitor{os, value.index()}, value); +#else + std::visit(Visitor{os, value.index()}, value); +#endif // GTEST_HAS_ABSL *os << ')'; } @@ -715,14 +767,16 @@ class UniversalPrinter<::absl::variant> { struct Visitor { template void operator()(const U& u) const { - *os << "'" << GetTypeName() << "' with value "; + *os << "'" << GetTypeName() << "(index = " << index + << ")' with value "; UniversalPrint(u, os); } ::std::ostream* os; + std::size_t index; }; }; -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_VARIANT // UniversalPrintArray(begin, len, os) prints an array of 'len' // elements, starting at address 'begin'. @@ -751,6 +805,20 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { GTEST_API_ void UniversalPrintArray( const char* begin, size_t len, ::std::ostream* os); +#ifdef __cpp_char8_t +// This overload prints a (const) char8_t array compactly. +GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len, + ::std::ostream* os); +#endif + +// This overload prints a (const) char16_t array compactly. +GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len, + ::std::ostream* os); + +// This overload prints a (const) char32_t array compactly. +GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len, + ::std::ostream* os); + // This overload prints a (const) wchar_t array compactly. GTEST_API_ void UniversalPrintArray( const wchar_t* begin, size_t len, ::std::ostream* os); @@ -823,12 +891,55 @@ class UniversalTersePrinter { } }; template <> -class UniversalTersePrinter { +class UniversalTersePrinter : public UniversalTersePrinter { +}; + +#ifdef __cpp_char8_t +template <> +class UniversalTersePrinter { public: - static void Print(char* str, ::std::ostream* os) { - UniversalTersePrinter::Print(str, os); + static void Print(const char8_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u8string(str), os); + } } }; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(const char16_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u16string(str), os); + } + } +}; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; + +template <> +class UniversalTersePrinter { + public: + static void Print(const char32_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u32string(str), os); + } + } +}; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; #if GTEST_HAS_STD_WSTRING template <> @@ -901,16 +1012,6 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { } // namespace internal -#if GTEST_HAS_ABSL -namespace internal2 { -template -void TypeWithoutFormatter::PrintValue( - const T& value, ::std::ostream* os) { - internal::PrintTo(absl::string_view(value), os); -} -} // namespace internal2 -#endif - template ::std::string PrintToString(const T& value) { ::std::stringstream ss; @@ -925,4 +1026,4 @@ template // declarations from this file. #include "gtest/internal/custom/gtest-printers.h" -#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-spi.h b/3rdparty/gtest/include/gtest/gtest-spi.h index aa38870..eacef44 100644 --- a/3rdparty/gtest/include/gtest/gtest-spi.h +++ b/3rdparty/gtest/include/gtest/gtest-spi.h @@ -33,8 +33,8 @@ // GOOGLETEST_CM0004 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ -#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ #include "gtest/gtest.h" @@ -235,4 +235,4 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 }\ } while (::testing::internal::AlwaysFalse()) -#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-test-part.h b/3rdparty/gtest/include/gtest/gtest-test-part.h index 05a7985..203fdf9 100644 --- a/3rdparty/gtest/include/gtest/gtest-test-part.h +++ b/3rdparty/gtest/include/gtest/gtest-test-part.h @@ -29,8 +29,8 @@ // // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #include #include @@ -181,4 +181,4 @@ class GTEST_API_ HasNewFatalFailureHelper GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-typed-test.h b/3rdparty/gtest/include/gtest/gtest-typed-test.h index 095ce05..9fdc6be 100644 --- a/3rdparty/gtest/include/gtest/gtest-typed-test.h +++ b/3rdparty/gtest/include/gtest/gtest-typed-test.h @@ -27,11 +27,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ // This header implements typed tests and type-parameterized tests. @@ -170,13 +169,12 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #endif // 0 +#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-type-util.h" // Implements typed tests. -#if GTEST_HAS_TYPED_TEST - // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the typedef for the type parameters of the @@ -188,24 +186,25 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #define GTEST_NAME_GENERATOR_(TestSuiteName) \ gtest_type_params_##TestSuiteName##_NameGenerator -#define TYPED_TEST_SUITE(CaseName, Types, ...) \ - typedef ::testing::internal::TypeList::type GTEST_TYPE_PARAMS_( \ - CaseName); \ - typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ +#define TYPED_TEST_SUITE(CaseName, Types, ...) \ + typedef ::testing::internal::GenerateTypeList::type \ + GTEST_TYPE_PARAMS_(CaseName); \ + typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ GTEST_NAME_GENERATOR_(CaseName) -# define TYPED_TEST(CaseName, TestName) \ +#define TYPED_TEST(CaseName, TestName) \ + static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \ + "test-name must not be empty"); \ template \ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ : public CaseName { \ private: \ typedef CaseName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ + void TestBody() override; \ }; \ static bool gtest_##CaseName##_##TestName##_registered_ \ - GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTest< \ + GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \ CaseName, \ ::testing::internal::TemplateSel, \ @@ -213,7 +212,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); CaseName)>::Register("", \ ::testing::internal::CodeLocation( \ __FILE__, __LINE__), \ - #CaseName, #TestName, 0, \ + GTEST_STRINGIFY_(CaseName), \ + GTEST_STRINGIFY_(TestName), 0, \ ::testing::internal::GenerateNames< \ GTEST_NAME_GENERATOR_(CaseName), \ GTEST_TYPE_PARAMS_(CaseName)>()); \ @@ -228,12 +228,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); TYPED_TEST_SUITE #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#endif // GTEST_HAS_TYPED_TEST - // Implements type-parameterized tests. -#if GTEST_HAS_TYPED_TEST_P - // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the namespace name that the type-parameterized tests for @@ -276,24 +272,26 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); private: \ typedef SuiteName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ + void TestBody() override; \ }; \ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \ - __FILE__, __LINE__, #SuiteName, #TestName); \ + __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \ + GTEST_STRINGIFY_(TestName)); \ } \ template \ void GTEST_SUITE_NAMESPACE_( \ SuiteName)::TestName::TestBody() -#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ - namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ - typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ - } \ - static const char* const GTEST_REGISTERED_TEST_NAMES_( \ - SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ - __FILE__, __LINE__, #__VA_ARGS__) +// Note: this won't work correctly if the trailing arguments are macros. +#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ + namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_( \ + SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ + GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__) // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ @@ -304,18 +302,21 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ + static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \ + "test-suit-prefix must not be empty"); \ static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ ::testing::internal::TypeParameterizedTestSuite< \ SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ - ::testing::internal::TypeList::type>:: \ - Register(#Prefix, \ + ::testing::internal::GenerateTypeList::type>:: \ + Register(GTEST_STRINGIFY_(Prefix), \ ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \ + >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \ + GTEST_STRINGIFY_(SuiteName), \ GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ ::testing::internal::GenerateNames< \ ::testing::internal::NameGeneratorSelector< \ __VA_ARGS__>::type, \ - ::testing::internal::TypeList::type>()) + ::testing::internal::GenerateTypeList::type>()) // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ @@ -325,6 +326,4 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); INSTANTIATE_TYPED_TEST_SUITE_P #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#endif // GTEST_HAS_TYPED_TEST_P - -#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest.h b/3rdparty/gtest/include/gtest/gtest.h index dbe5b1c..74a28dd 100644 --- a/3rdparty/gtest/include/gtest/gtest.h +++ b/3rdparty/gtest/include/gtest/gtest.h @@ -49,8 +49,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_ #include #include @@ -70,6 +70,10 @@ #include "gtest/gtest-test-part.h" #include "gtest/gtest-typed-test.h" +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-ext.h" +#include "gtest/hwext/gtest-filter.h" + GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ /* class A needs to have dll-interface to be used by clients of class B */) @@ -101,6 +105,10 @@ GTEST_DECLARE_bool_(catch_exceptions); // to let Google Test decide. GTEST_DECLARE_string_(color); +// This flag controls whether the test runner should continue execution past +// first failure. +GTEST_DECLARE_bool_(fail_fast); + // This flag sets up the filter to select by name using a glob pattern // the tests to run. If the filter is not given all tests are executed. GTEST_DECLARE_string_(filter); @@ -117,6 +125,9 @@ GTEST_DECLARE_bool_(list_tests); // in addition to its normal textual output. GTEST_DECLARE_string_(output); +// This flags control whether Google Test prints only test failures. +GTEST_DECLARE_bool_(brief); + // This flags control whether Google Test prints the elapsed time for each // test. GTEST_DECLARE_bool_(print_time); @@ -177,6 +188,7 @@ class FuchsiaDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); +std::set* GetIgnoredParameterizedTestSuites(); } // namespace internal @@ -278,7 +290,11 @@ class GTEST_API_ AssertionResult { // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult(const AssertionResult& other); -#if defined(_MSC_VER) && _MSC_VER < 1910 +// C4800 is a level 3 warning in Visual Studio 2015 and earlier. +// This warning is not emitted in Visual Studio 2017. +// This warning is off by default starting in Visual Studio 2019 but can be +// enabled with command-line options. +#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */) #endif @@ -298,7 +314,7 @@ class GTEST_API_ AssertionResult { = nullptr) : success_(success) {} -#if defined(_MSC_VER) && _MSC_VER < 1910 +#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920) GTEST_DISABLE_MSC_WARNINGS_POP_() #endif @@ -406,27 +422,24 @@ class GTEST_API_ Test { // The d'tor is virtual as we intend to inherit from Test. virtual ~Test(); - // Sets up the stuff shared by all tests in this test case. + // Sets up the stuff shared by all tests in this test suite. // // Google Test will call Foo::SetUpTestSuite() before running the first - // test in test case Foo. Hence a sub-class can define its own + // test in test suite Foo. Hence a sub-class can define its own // SetUpTestSuite() method to shadow the one defined in the super // class. - // Failures that happen during SetUpTestSuite are logged but otherwise - // ignored. static void SetUpTestSuite() {} // Tears down the stuff shared by all tests in this test suite. // // Google Test will call Foo::TearDownTestSuite() after running the last - // test in test case Foo. Hence a sub-class can define its own + // test in test suite Foo. Hence a sub-class can define its own // TearDownTestSuite() method to shadow the one defined in the super // class. - // Failures that happen during TearDownTestSuite are logged but otherwise - // ignored. static void TearDownTestSuite() {} - // Legacy API is deprecated but still available + // Legacy API is deprecated but still available. Use SetUpTestSuite and + // TearDownTestSuite instead. #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ static void TearDownTestCase() {} static void SetUpTestCase() {} @@ -664,7 +677,7 @@ class GTEST_API_ TestResult { // Protects mutable state of the property vector and of owned // properties, whose values may be updated. - internal::Mutex test_properites_mutex_; + internal::Mutex test_properties_mutex_; // The vector of TestPartResults std::vector test_part_results_; @@ -794,6 +807,9 @@ class GTEST_API_ TestInfo { // deletes it. void Run(); + // Skip and records the test result for this object. + void Skip(); + static void ClearTestResult(TestInfo* test_info) { test_info->result_.Clear(); } @@ -889,7 +905,9 @@ class GTEST_API_ TestSuite { bool Passed() const { return !Failed(); } // Returns true if and only if the test suite failed. - bool Failed() const { return failed_test_count() > 0; } + bool Failed() const { + return failed_test_count() > 0 || ad_hoc_test_result().Failed(); + } // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } @@ -940,6 +958,9 @@ class GTEST_API_ TestSuite { // Runs every test in this TestSuite. void Run(); + // Skips the execution of tests under this TestSuite + void Skip(); + // Runs SetUpTestSuite() for this TestSuite. This wrapper is needed // for catching exceptions thrown from SetUpTestSuite(). void RunSetUpTestSuite() { @@ -1420,6 +1441,7 @@ class GTEST_API_ UnitTest { friend class internal::StreamingListenerTest; friend class internal::UnitTestRecordPropertyTestHelper; friend Environment* AddGlobalTestEnvironment(Environment* env); + friend std::set* internal::GetIgnoredParameterizedTestSuites(); friend internal::UnitTestImpl* internal::GetUnitTestImpl(); friend void internal::ReportFailureInUnknownLocation( TestPartResult::Type result_type, @@ -1531,14 +1553,6 @@ AssertionResult CmpHelperEQ(const char* lhs_expression, return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); } -// With this overloaded version, we allow anonymous enums to be used -// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums -// can be implicitly cast to BiggestInt. -GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression, - const char* rhs_expression, - BiggestInt lhs, - BiggestInt rhs); - class EqHelper { public: // This templatized version is for the general case. @@ -1595,11 +1609,6 @@ AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2, // ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste // of similar code. // -// For each templatized helper function, we also define an overloaded -// version for BiggestInt in order to reduce code bloat and allow -// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled -// with gcc 4. -// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. #define GTEST_IMPL_CMP_HELPER_(op_name, op)\ @@ -1611,22 +1620,20 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ } else {\ return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\ }\ -}\ -GTEST_API_ AssertionResult CmpHelper##op_name(\ - const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) +} // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // Implements the helper function for {ASSERT|EXPECT}_NE -GTEST_IMPL_CMP_HELPER_(NE, !=); +GTEST_IMPL_CMP_HELPER_(NE, !=) // Implements the helper function for {ASSERT|EXPECT}_LE -GTEST_IMPL_CMP_HELPER_(LE, <=); +GTEST_IMPL_CMP_HELPER_(LE, <=) // Implements the helper function for {ASSERT|EXPECT}_LT -GTEST_IMPL_CMP_HELPER_(LT, <); +GTEST_IMPL_CMP_HELPER_(LT, <) // Implements the helper function for {ASSERT|EXPECT}_GE -GTEST_IMPL_CMP_HELPER_(GE, >=); +GTEST_IMPL_CMP_HELPER_(GE, >=) // Implements the helper function for {ASSERT|EXPECT}_GT -GTEST_IMPL_CMP_HELPER_(GT, >); +GTEST_IMPL_CMP_HELPER_(GT, >) #undef GTEST_IMPL_CMP_HELPER_ @@ -1803,12 +1810,6 @@ class GTEST_API_ AssertHelper { GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); }; -enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; - -GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color, - const char* fmt, - ...); - } // namespace internal // The pure interface class that all value-parameterized tests inherit from. @@ -1889,7 +1890,7 @@ class TestWithParam : public Test, public WithParamInterface { // Skips test in runtime. // Skipping test aborts current function. // Skipped tests are neither successful nor failed. -#define GTEST_SKIP() GTEST_SKIP_("Skipped") +#define GTEST_SKIP() GTEST_SKIP_("") // ADD_FAILURE unconditionally adds a failure to the current test. // SUCCEED generates a success - it doesn't automatically make the @@ -1965,19 +1966,38 @@ class TestWithParam : public Test, public WithParamInterface { // Boolean assertions. Condition can be either a Boolean expression or an // AssertionResult. For more information on how to use AssertionResult with // these macros see comments on that class. -#define EXPECT_TRUE(condition) \ +#define GTEST_EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) -#define EXPECT_FALSE(condition) \ +#define GTEST_EXPECT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_NONFATAL_FAILURE_) -#define ASSERT_TRUE(condition) \ +#define GTEST_ASSERT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_FATAL_FAILURE_) -#define ASSERT_FALSE(condition) \ +#define GTEST_ASSERT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_FATAL_FAILURE_) +// Define these macros to 1 to omit the definition of the corresponding +// EXPECT or ASSERT, which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_EXPECT_TRUE +#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition) +#endif + +#if !GTEST_DONT_DEFINE_EXPECT_FALSE +#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_TRUE +#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_FALSE +#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition) +#endif + // Macros for testing equalities and inequalities. // // * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2 @@ -2298,8 +2318,7 @@ class GTEST_API_ ScopedTrace { // to cause a compiler error. template constexpr bool StaticAssertTypeEq() noexcept { - static_assert(std::is_same::value, - "type1 and type2 are not the same type"); + static_assert(std::is_same::value, "T1 and T2 are not the same type"); return true; } @@ -2365,9 +2384,11 @@ constexpr bool StaticAssertTypeEq() noexcept { // } // // GOOGLETEST_CM0011 DO NOT DELETE +#if !GTEST_DONT_DEFINE_TEST #define TEST_F(test_fixture, test_name)\ GTEST_TEST_(test_fixture, test_name, test_fixture, \ ::testing::internal::GetTypeId()) +#endif // !GTEST_DONT_DEFINE_TEST // Returns a path to temporary directory. // Tries to determine an appropriate directory for the platform. @@ -2475,4 +2496,4 @@ inline int RUN_ALL_TESTS() { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest_pred_impl.h b/3rdparty/gtest/include/gtest/gtest_pred_impl.h index d514255..5029a9b 100644 --- a/3rdparty/gtest/include/gtest/gtest_pred_impl.h +++ b/3rdparty/gtest/include/gtest/gtest_pred_impl.h @@ -33,8 +33,8 @@ // Implements a family of generic predicate assertion macros. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #include "gtest/gtest.h" @@ -356,4 +356,4 @@ AssertionResult AssertPred5Helper(const char* pred_text, } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ diff --git a/3rdparty/gtest/include/gtest/gtest_prod.h b/3rdparty/gtest/include/gtest/gtest_prod.h index e651671..38b9d85 100644 --- a/3rdparty/gtest/include/gtest/gtest_prod.h +++ b/3rdparty/gtest/include/gtest/gtest_prod.h @@ -31,8 +31,8 @@ // Google C++ Testing and Mocking Framework definitions useful in production code. // GOOGLETEST_CM0003 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ // When you need to test the private or protected members of a class, // use the FRIEND_TEST macro to declare your tests as friends of the @@ -58,4 +58,4 @@ #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test -#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-ext.h b/3rdparty/gtest/include/gtest/hwext/gtest-ext.h new file mode 100644 index 0000000..e44b3bb --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-ext.h @@ -0,0 +1,83 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_EXT_H_ +#define GTEST_INCLUDE_GTEST_GTEST_EXT_H_ + +#include +#include "gtest/gtest.h" + +namespace testing { + namespace ext { + + // helper macro to create unique variable name + #define GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, file_line) \ + test_case_name##_##test_name##_##file_line + + // 1. define a extended TEST supporting test flags registing + #if !GTEST_DONT_DEFINE_TEST + # define HWTEST(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Plain);\ + TEST(test_case_name, test_name) + #endif + + // 2. define a extended TEST_F supporting test flags registing + # define HWTEST_F(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Fixtured);\ + TEST_F(test_case_name, test_name) + + // 3. define a extended TYPED_TEST supporting test flags registing + # define HWTYPED_TEST(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Typed);\ + TYPED_TEST(test_case_name, test_name) + + // 4. define a extended TYPED_TEST_P supporting test flags registing + # define HWTYPED_TEST_P(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::PatternTyped);\ + TYPED_TEST_P(test_case_name, test_name) + + // 5. define a extended TEST_P supporting test flags registing + # define HWTEST_P(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Parameterized);\ + TEST_P(test_case_name, test_name) + + // test definition types + enum TestDefType { + Plain, Fixtured, Typed, PatternTyped, Parameterized + }; + // case_name/test_name matchNaming pattern + enum NamingMatchType { + AEqualsB, AStartsWithB, AContainsB, AEndsWithB + }; + + // information of a test difinition + class TestDefInfo { + public: + friend class TestDefManager; + private: + const static char kNamingSepchar = '/'; + const char* const test_case_name; + const char* const name; + const int flags; + const TestDefType def_type; + TestDefInfo(const char* tcn, const char* n, int fs, TestDefType tdf); + }; + + class TestDefManager { + private: + TestDefManager() {}; + std::vector testDefInfos; + const TestDefInfo* findDefFor(const TestInfo* test) const; + bool matchNaming(const char* const a, const char* const b, NamingMatchType mt) const; + public: + static TestDefManager* instance(); + static const TestDefManager* cinstance(); + bool regist(const char* test_case_name, const char* test_name, int test_flags, TestDefType tdf); + int queryFlagsFor(const TestInfo* test, int def_value) const; + int getLevel(const std::string testcasename, const std::string testname) const; + int* getTestFlags(const std::string testcasename, const std::string testname) const; + }; + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_EXT_H_ \ No newline at end of file diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-filter.h b/3rdparty/gtest/include/gtest/hwext/gtest-filter.h new file mode 100644 index 0000000..3be4481 --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-filter.h @@ -0,0 +1,48 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ +#define GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ + +#include +#include +#include + +namespace testing { + namespace ext { + + using ::std::string; + using ::std::map; + using ::std::vector; + + class TestFilter { + public: + map& getAllFilterFlagsKv(); + void printHelp() const; + bool postParsingArguments(); + bool accept(int flags) const; + void reset(); + static TestFilter* instance(); + + private: + TestFilter() {}; + static const char* const kStrictFilter; + int requiredFlags; + // strcit filter requires the entirely same test flags and require no + bool strictMode; + bool flag_kvs_inited; // teels iff the filter kvs has been parsed + bool ready; // teels iff the filter are ready to be used + void postSetType(vector vectemp); + void postSetSize(vector vectemp); + void postSetRank(vector vectemp); + map filterFlagsKv; + vector vecTestLevel; + vector vecType; + vector vecSize; + vector vecRank; + }; + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ + diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h b/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h new file mode 100644 index 0000000..e7254e6 --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h @@ -0,0 +1,117 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +* Description:多线程测试框架(GTEST-MULTITHREAD)库接口声明 +* Author: +* Create:2023/2/24 +*/ + +#ifndef __MULTI_THREAD_TEST_H__ +#define __MULTI_THREAD_TEST_H__ + +#include +#include +#include +#include +#include "gtest/gtest.h" + +using ::testing::TestPartResult; + +namespace testing{ + namespace mt { + using PF = void(*)(); + using uint = unsigned int; + const uint RANDOM_THREAD_ID = 0x3f3f3f3f; //线程ID常量 + static uint g_thread_count = 10 ; //全局变量,默认线程数是10 + inline void setThreadNum(uint num) + { + g_thread_count = num; + } + class TestTask { + public: + TestTask() = default; + TestTask(std::string ts, std::string tc, PF func) : m_testsuite(ts), m_testcase(tc), m_func(func){} + std::string m_testsuite; + std::string m_testcase; + PF m_func; + }; + class ThreadTaskEntry { + public: + ThreadTaskEntry(std::vector v_task) : funcList(v_task) {} + std::thread *thread; + std::vector funcList; + }; + class MultiThreadTest { + private: + std::vector> threadTasks; + std::vector threadTestEntryList; + std::map> randomTasks; + + public: + void doTest(); + void run(); + MultiThreadTest() {} + unsigned m_threadNum; + MultiThreadTest(unsigned int t_cnt) : m_threadNum(t_cnt) {} + uint runTask(unsigned thread_num, PF func, std::string testsuite, std::string testcase); + void appendTaskToList(unsigned thread_id, PF func, std::string testsuite, std::string testcase); + }; + + static MultiThreadTest testInstance; + static MultiThreadTest *getMTestSingleton() + { + return &testInstance; + } + + inline void getMTest() + { + auto ret = getMTestSingleton(); + if (ret == nullptr) { + return; + } + } + + class MultiThreadFailCaseListener : public EmptyTestEventListener { + private: + MultiThreadTest *testInstance; + public: + MultiThreadFailCaseListener(MultiThreadTest *ins) + { + this->testInstance = ins; + } + }; + + inline void addPostTest(unsigned thread_id, PF func, std::string testsuite = "NA", std::string testcase = "NA") + { + for (unsigned int i = 0; i < g_thread_count; i++) { + testInstance.appendTaskToList(thread_id, func, testsuite, testcase); + } + } + + #define MTEST_ADD_TASK(thread_id, func) addPostTest(thread_id, func) + + #define MTEST_POST_RUN() \ + do { \ + getMTestSingleton()->run(); \ + } while (0) + + #define SET_THREAD_NUM(n) setThreadNum(n) + #define MTEST_FUNC_NAME(x, y) TC_##x_##y + #define GTEST_RUN_TASK(hook) \ + do { \ + MultiThreadTest _test(g_thread_count); \ + _test.runTask(_test.m_threadNum, hook, this->test_info_->test_case_name(), this->test_info_->name()); \ + } while (0) + + #define MTEST_TYPE(x, y, z, n) \ + void MTEST_FUNC_NAME(x, y)(); \ + z(x, y) \ + { \ + SET_THREAD_NUM(n); \ + GTEST_RUN_TASK(MTEST_FUNC_NAME(x, y)); \ + } \ + void MTEST_FUNC_NAME(x, y)() + #define HWMTEST(x, y, w, n) MTEST_TYPE(x, y, TEST, n) + #define HWMTEST_F(x, y, w, n) MTEST_TYPE(x, y, TEST_F, n) + } +} +#endif /* __MULTI_THREAD_TEST_H__ */ \ No newline at end of file diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-tag.h b/3rdparty/gtest/include/gtest/hwext/gtest-tag.h new file mode 100644 index 0000000..e9b9f4d --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-tag.h @@ -0,0 +1,115 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TAG_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TAG_H_ + +#include +#include +#include +#include + +namespace testing { + namespace ext { + + using ::std::string; + using ::std::map; + using ::std::pair; + using ::std::vector; + + enum TestTypeFlag { + Function = 1 << 8, Performance = 2 << 8, Power = 3 << 8, Reliability = 4 << 8, + Security = 5 << 8, Global = 6 << 8, Compatibility = 7 << 8, User = 8 << 8, + Standard = 9 << 8, Safety = 10 << 8, Resilience = 11 << 8 + }; + + enum TestSizeFlag { + SmallTest = 1 << 4, MediumTest = 2 << 4, LargeTest = 3 << 4 + }; + + enum TestRankFlag { + Level0 = 1, Level1 = 2, Level2 = 3, Level3 = 4, Level4 = 5 + }; + + // base class of tag flag::bitwise integers + class TestFlag { + public: + static const int None = 0; + + private: + const char* const name; + const char* const desc; + const int mask; + map elementMap; + int eleCount; + protected: + TestFlag(const char* n, const char* d, int m); + void element(const char* desc, int hex); + public: + bool verify(const int hex, char* err) const; + const char* naming() const { return name; } + const char* description() const { return desc; } + bool eleForName(const char* name, int& result) const; + void printHelp(const char** indents) const; + }; + + // test size scope + class TestSizeSet : public TestFlag { + public: + TestSizeSet(); + static const int Level0 = 1 << 24; + static const int Level1 = 2 << 24; + static const int Level2 = 4 << 24; + static const int Level3 = 8 << 24; + static const int Level4 = 16 << 24; + }; + + extern const TestSizeSet TestSize; + + // test type scope + class TypeSet : public TestFlag { + public: + TypeSet(); + static const int function = Function; + static const int performance = Performance; + static const int power = Power; + static const int reliability = Reliability; + static const int security = Security; + static const int global = Global; + static const int compatibility = Compatibility; + static const int user = User; + static const int standard = Standard; + static const int safety = Safety; + static const int resilience = Resilience; + }; + + // test size scope + class SizeSet : public TestFlag { + public: + SizeSet(); + static const int smallTest = SmallTest; + static const int mediumTest = MediumTest; + static const int largeTest = LargeTest; + }; + + // test rank scope + class RankSet : public TestFlag { + public: + RankSet(); + static const int level0 = Level0; + static const int level1 = Level1; + static const int level2 = Level2; + static const int level3 = Level3; + static const int level4 = Level4; + }; + + // get each instance of all the TestFlag implementions + const vector& AllHextTagSets(); + // verify the test flagset, returns false if the flagset is illegal + bool CheckFlagsLegality(int flags); + // convert name string to test flag value + bool flagForName(const char* set_name, const char* ele_name, int& result); + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TAG_H_ diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-utils.h b/3rdparty/gtest/include/gtest/hwext/gtest-utils.h new file mode 100644 index 0000000..676bc9d --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-utils.h @@ -0,0 +1,21 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_UTILS_H_ +#define GTEST_INCLUDE_GTEST_UTILS_H_ + +#include +#include +#include + +namespace testing { + + using ::std::string; + using ::std::vector; + + bool compareStringsByIgnoreCase(const char* one, const char* two); + bool IsElementInVector(vector vec, int element); + vector SplitString(const string& str, const string& delim); + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_UTILS_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h b/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h index cd85d95..db02881 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h @@ -31,7 +31,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h b/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h index eb4467a..b9495d8 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h @@ -36,7 +36,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest.h b/3rdparty/gtest/include/gtest/internal/custom/gtest.h index 4c8e07b..afaaf17 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest.h @@ -31,7 +31,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h b/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h index 68bd353..490296d 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h @@ -33,8 +33,8 @@ // death tests. They are subject to change without notice. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ #include "gtest/gtest-matchers.h" #include "gtest/internal/gtest-internal.h" @@ -301,4 +301,4 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-filepath.h b/3rdparty/gtest/include/gtest/internal/gtest-filepath.h index c11b101..0c033ab 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-filepath.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-filepath.h @@ -37,8 +37,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #include "gtest/internal/gtest-string.h" @@ -195,7 +195,7 @@ class GTEST_API_ FilePath { void Normalize(); - // Returns a pointer to the last occurence of a valid path separator in + // Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FindLastPathSeparator() const; @@ -208,4 +208,4 @@ class GTEST_API_ FilePath { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-internal.h b/3rdparty/gtest/include/gtest/internal/gtest-internal.h index 94c816a..f8cbdbd 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-internal.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-internal.h @@ -34,8 +34,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #include "gtest/internal/gtest-port.h" @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -78,9 +79,20 @@ #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar // Stringifies its argument. -#define GTEST_STRINGIFY_(name) #name +// Work around a bug in visual studio which doesn't accept code like this: +// +// #define GTEST_STRINGIFY_(name) #name +// #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ... +// MACRO(, x, y) +// +// Complaining about the argument to GTEST_STRINGIFY_ being empty. +// This is allowed by the spec. +#define GTEST_STRINGIFY_HELPER_(name, ...) #name +#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, ) -namespace proto2 { class Message; } +namespace proto2 { +class MessageLite; +} namespace testing { @@ -275,7 +287,7 @@ class FloatingPoint { // // See the following article for more details on ULP: // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - static const size_t kMaxUlps = 4; + static const uint32_t kMaxUlps = 4; // Constructs a FloatingPoint from a raw floating-point number. // @@ -508,6 +520,7 @@ struct SuiteApiResolver : T { static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, int line_num) { +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ SetUpTearDownSuiteFuncType test_case_fp = GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); SetUpTearDownSuiteFuncType test_suite_fp = @@ -519,10 +532,16 @@ struct SuiteApiResolver : T { << filename << ":" << line_num; return test_case_fp != nullptr ? test_case_fp : test_suite_fp; +#else + (void)(filename); + (void)(line_num); + return &T::SetUpTestSuite; +#endif } static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, int line_num) { +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ SetUpTearDownSuiteFuncType test_case_fp = GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); SetUpTearDownSuiteFuncType test_suite_fp = @@ -534,6 +553,11 @@ struct SuiteApiResolver : T { << filename << ":" << line_num; return test_case_fp != nullptr ? test_case_fp : test_suite_fp; +#else + (void)(filename); + (void)(line_num); + return &T::TearDownTestSuite; +#endif } }; @@ -542,11 +566,11 @@ struct SuiteApiResolver : T { // // Arguments: // -// test_suite_name: name of the test suite +// test_suite_name: name of the test suite // name: name of the test -// type_param the name of the test's type parameter, or NULL if +// type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. -// value_param text representation of the test's value parameter, +// value_param: text representation of the test's value parameter, // or NULL if this is not a type-parameterized test. // code_location: code location where the test is defined // fixture_class_id: ID of the test fixture class @@ -566,8 +590,6 @@ GTEST_API_ TestInfo* MakeAndRegisterTestInfo( // and returns false. None of pstr, *pstr, and prefix can be NULL. GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ /* class A needs to have dll-interface to be used by clients of class B */) @@ -607,8 +629,9 @@ class GTEST_API_ TypedTestSuitePState { // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or // aborts the program otherwise. - const char* VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests); + const char* VerifyRegisteredTestNames(const char* test_suite_name, + const char* file, int line, + const char* registered_tests); private: typedef ::std::map RegisteredTestsMap; @@ -662,7 +685,7 @@ struct NameGeneratorSelector { }; template -void GenerateNamesRecursively(Types0, std::vector*, int) {} +void GenerateNamesRecursively(internal::None, std::vector*, int) {} template void GenerateNamesRecursively(Types, std::vector* result, int i) { @@ -729,7 +752,7 @@ class TypeParameterizedTest { // The base case for the compile time recursion. template -class TypeParameterizedTest { +class TypeParameterizedTest { public: static bool Register(const char* /*prefix*/, const CodeLocation&, const char* /*case_name*/, const char* /*test_names*/, @@ -740,6 +763,11 @@ class TypeParameterizedTest { } }; +GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name, + CodeLocation code_location); +GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation( + const char* case_name); + // TypeParameterizedTestSuite::Register() // registers *all combinations* of 'Tests' and 'Types' with Google // Test. The return value is insignificant - we just need to return @@ -752,6 +780,7 @@ class TypeParameterizedTestSuite { const char* test_names, const std::vector& type_names = GenerateNames()) { + RegisterTypeParameterizedTestSuiteInstantiation(case_name); std::string test_name = StripTrailingSpaces( GetPrefixUntilComma(test_names)); if (!state->TestExists(test_name)) { @@ -781,7 +810,7 @@ class TypeParameterizedTestSuite { // The base case for the compile time recursion. template -class TypeParameterizedTestSuite { +class TypeParameterizedTestSuite { public: static bool Register(const char* /*prefix*/, const CodeLocation&, const TypedTestSuitePState* /*state*/, @@ -792,8 +821,6 @@ class TypeParameterizedTestSuite { } }; -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by @@ -825,6 +852,16 @@ struct GTEST_API_ ConstCharPtr { const char* value; }; +// Helper for declaring std::string within 'if' statement +// in pre C++17 build environment. +struct TrueWithString { + TrueWithString() = default; + explicit TrueWithString(const char* str) : value(str) {} + explicit TrueWithString(const std::string& str) : value(str) {} + explicit operator bool() const { return true; } + std::string value; +}; + // A simple Linear Congruential Generator for generating random // numbers with a uniform distribution. Unlike rand() and srand(), it // doesn't use global state (and therefore can't interfere with user @@ -832,18 +869,18 @@ struct GTEST_API_ ConstCharPtr { // but it's good enough for our purposes. class GTEST_API_ Random { public: - static const UInt32 kMaxRange = 1u << 31; + static const uint32_t kMaxRange = 1u << 31; - explicit Random(UInt32 seed) : state_(seed) {} + explicit Random(uint32_t seed) : state_(seed) {} - void Reseed(UInt32 seed) { state_ = seed; } + void Reseed(uint32_t seed) { state_ = seed; } // Generates a random number from [0, range). Crashes if 'range' is // 0 or greater than kMaxRange. - UInt32 Generate(UInt32 range); + uint32_t Generate(uint32_t range); private: - UInt32 state_; + uint32_t state_; GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); }; @@ -851,12 +888,34 @@ class GTEST_API_ Random { #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ typename std::remove_const::type>::type -// IsAProtocolMessage::value is a compile-time bool constant that's -// true if and only if T is type proto2::Message or a subclass of it. +// HasDebugStringAndShortDebugString::value is a compile-time bool constant +// that's true if and only if T has methods DebugString() and ShortDebugString() +// that return std::string. template -struct IsAProtocolMessage - : public bool_constant< - std::is_convertible::value> {}; +class HasDebugStringAndShortDebugString { + private: + template + static auto CheckDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().DebugString())>::type; + template + static std::false_type CheckDebugString(...); + + template + static auto CheckShortDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().ShortDebugString())>::type; + template + static std::false_type CheckShortDebugString(...); + + using HasDebugStringType = decltype(CheckDebugString(nullptr)); + using HasShortDebugStringType = decltype(CheckShortDebugString(nullptr)); + + public: + static constexpr bool value = + HasDebugStringType::value && HasShortDebugStringType::value; +}; + +template +constexpr bool HasDebugStringAndShortDebugString::value; // When the compiler sees expression IsContainerTest(0), if C is an // STL-style container class, the first overload of IsContainerTest @@ -1092,8 +1151,6 @@ class NativeArray { const Element* array_; size_t size_; void (NativeArray::*clone_)(const Element*, size_t); - - GTEST_DISALLOW_ASSIGN_(NativeArray); }; // Backport of std::index_sequence. @@ -1117,32 +1174,44 @@ struct DoubleSequence, sizeofT> { // Backport of std::make_index_sequence. // It uses O(ln(N)) instantiation depth. template -struct MakeIndexSequence - : DoubleSequence::type, +struct MakeIndexSequenceImpl + : DoubleSequence::type, N / 2>::type {}; template <> -struct MakeIndexSequence<0> : IndexSequence<> {}; +struct MakeIndexSequenceImpl<0> : IndexSequence<> {}; + +template +using MakeIndexSequence = typename MakeIndexSequenceImpl::type; -// FIXME: This implementation of ElemFromList is O(1) in instantiation depth, -// but it is O(N^2) in total instantiations. Not sure if this is the best -// tradeoff, as it will make it somewhat slow to compile. -template -struct ElemFromListImpl {}; +template +using IndexSequenceFor = typename MakeIndexSequence::type; + +template +struct Ignore { + Ignore(...); // NOLINT +}; -template -struct ElemFromListImpl { - using type = T; +template +struct ElemFromListImpl; +template +struct ElemFromListImpl> { + // We make Ignore a template to solve a problem with MSVC. + // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but + // MSVC doesn't understand how to deal with that pack expansion. + // Use `0 * I` to have a single instantiation of Ignore. + template + static R Apply(Ignore<0 * I>..., R (*)(), ...); }; -// Get the Nth element from T... -// It uses O(1) instantiation depth. -template -struct ElemFromList; +template +struct ElemFromList { + using type = + decltype(ElemFromListImpl::type>::Apply( + static_cast(nullptr)...)); +}; -template -struct ElemFromList, T...> - : ElemFromListImpl... {}; +struct FlatTupleConstructTag {}; template class FlatTuple; @@ -1152,11 +1221,11 @@ struct FlatTupleElemBase; template struct FlatTupleElemBase, I> { - using value_type = - typename ElemFromList::type, - T...>::type; + using value_type = typename ElemFromList::type; FlatTupleElemBase() = default; - explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} + template + explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t) + : value(std::forward(t)) {} value_type value; }; @@ -1168,13 +1237,35 @@ struct FlatTupleBase, IndexSequence> : FlatTupleElemBase, Idx>... { using Indices = IndexSequence; FlatTupleBase() = default; - explicit FlatTupleBase(T... t) - : FlatTupleElemBase, Idx>(std::move(t))... {} + template + explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args) + : FlatTupleElemBase, Idx>(FlatTupleConstructTag{}, + std::forward(args))... {} + + template + const typename ElemFromList::type& Get() const { + return FlatTupleElemBase, I>::value; + } + + template + typename ElemFromList::type& Get() { + return FlatTupleElemBase, I>::value; + } + + template + auto Apply(F&& f) -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } + + template + auto Apply(F&& f) const -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } }; // Analog to std::tuple but with different tradeoffs. // This class minimizes the template instantiation depth, thus allowing more -// elements that std::tuple would. std::tuple has been seen to require an +// elements than std::tuple would. std::tuple has been seen to require an // instantiation depth of more than 10x the number of elements in some // implementations. // FlatTuple and ElemFromList are not recursive and have a fixed depth @@ -1185,21 +1276,17 @@ template class FlatTuple : private FlatTupleBase, typename MakeIndexSequence::type> { - using Indices = typename FlatTuple::FlatTupleBase::Indices; + using Indices = typename FlatTupleBase< + FlatTuple, typename MakeIndexSequence::type>::Indices; public: FlatTuple() = default; - explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} - - template - const typename ElemFromList::type& Get() const { - return static_cast*>(this)->value; - } + template + explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args) + : FlatTuple::FlatTupleBase(tag, std::forward(args)...) {} - template - typename ElemFromList::type& Get() { - return static_cast*>(this)->value; - } + using FlatTuple::FlatTupleBase::Apply; + using FlatTuple::FlatTupleBase::Get; }; // Utility functions to be called with static_assert to induce deprecation @@ -1232,6 +1319,22 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } } // namespace internal } // namespace testing +namespace std { +// Some standard library implementations use `struct tuple_size` and some use +// `class tuple_size`. Clang warns about the mismatch. +// https://reviews.llvm.org/D55466 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +struct tuple_size> + : std::integral_constant {}; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +} // namespace std + #define GTEST_MESSAGE_AT_(file, line, message, result_type) \ ::testing::internal::AssertHelper(result_type, file, line, message) \ = ::testing::Message() @@ -1254,48 +1357,122 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } // Suppress MSVC warning 4072 (unreachable code) for the code following // statement if it returns or throws (or doesn't return or throw in some // situations). +// NOTE: The "else" is important to keep this expansion to prevent a top-level +// "else" from attaching to our "if". #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ - if (::testing::internal::AlwaysTrue()) { statement; } + if (::testing::internal::AlwaysTrue()) { \ + statement; \ + } else /* NOLINT */ \ + static_assert(true, "") // User must have a semicolon after expansion. -#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::ConstCharPtr gtest_msg = "") { \ - bool gtest_caught_expected = false; \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } \ - catch (expected_exception const&) { \ - gtest_caught_expected = true; \ - } \ - catch (...) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws a different type."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - if (!gtest_caught_expected) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws nothing."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ - fail(gtest_msg.value) +#if GTEST_HAS_EXCEPTIONS + +namespace testing { +namespace internal { + +class NeverThrown { + public: + const char* what() const noexcept { + return "this exception should never be thrown"; + } +}; + +} // namespace internal +} // namespace testing + +#if GTEST_HAS_RTTI + +#define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e)) + +#else // GTEST_HAS_RTTI + +#define GTEST_EXCEPTION_TYPE_(e) \ + std::string { "an std::exception-derived error" } + +#endif // GTEST_HAS_RTTI + +#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ + catch (typename std::conditional< \ + std::is_same::type>::type, \ + std::exception>::value, \ + const ::testing::internal::NeverThrown&, const std::exception&>::type \ + e) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws "; \ + gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ + gtest_msg.value += " with description \""; \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) + +#endif // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ + catch (...) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else /*NOLINT*/ \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \ + : fail(gtest_msg.value.c_str()) + +#if GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ + catch (std::exception const& e) { \ + gtest_msg.value = "it throws "; \ + gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ + gtest_msg.value += " with description \""; \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() + +#endif // GTEST_HAS_EXCEPTIONS #define GTEST_TEST_NO_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ + GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ catch (...) { \ + gtest_msg.value = "it throws."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ - fail("Expected: " #statement " doesn't throw an exception.\n" \ - " Actual: it throws.") + fail(("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: " + gtest_msg.value).c_str()) #define GTEST_TEST_ANY_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ @@ -1318,7 +1495,7 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } // Implements Boolean test assertions such as EXPECT_TRUE. expression can be // either a boolean expression or an AssertionResult. text is a textual -// represenation of expression as it was passed into the EXPECT_TRUE. +// representation of expression as it was passed into the EXPECT_TRUE. #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const ::testing::AssertionResult gtest_ar_ = \ @@ -1355,13 +1532,16 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ : public parent_class { \ public: \ - GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \ + ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ + GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ \ private: \ - virtual void TestBody(); \ + void TestBody() override; \ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)); \ }; \ \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ @@ -1377,4 +1557,4 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } test_suite_name, test_name)>); \ void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-param-util.h b/3rdparty/gtest/include/gtest/internal/gtest-param-util.h index 9753399..c2ef6e3 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-param-util.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-param-util.h @@ -32,8 +32,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #include @@ -42,12 +42,14 @@ #include #include #include +#include #include #include #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" #include "gtest/gtest-printers.h" +#include "gtest/gtest-test-part.h" namespace testing { // Input to a parameterized test name generator, describing a test parameter. @@ -457,7 +459,7 @@ class ParameterizedTestSuiteInfoBase { // Base part of test suite name for display purposes. virtual const std::string& GetTestSuiteName() const = 0; - // Test case id to verify identity. + // Test suite id to verify identity. virtual TypeId GetTestSuiteTypeId() const = 0; // UnitTest class invokes this method to register tests in this // test suite right before running them in RUN_ALL_TESTS macro. @@ -472,6 +474,17 @@ class ParameterizedTestSuiteInfoBase { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); }; +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Report a the name of a test_suit as safe to ignore +// as the side effect of construction of this type. +struct GTEST_API_ MarkAsIgnored { + explicit MarkAsIgnored(const char* test_suite); +}; + +GTEST_API_ void InsertSyntheticTestCase(const std::string& name, + CodeLocation location, bool has_test_p); + // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P @@ -494,11 +507,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { CodeLocation code_location) : test_suite_name_(name), code_location_(code_location) {} - // Test case base name for display purposes. + // Test suite base name for display purposes. const std::string& GetTestSuiteName() const override { return test_suite_name_; } - // Test case id to verify identity. + // Test suite id to verify identity. TypeId GetTestSuiteTypeId() const override { return GetTypeId(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. @@ -507,9 +520,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // test suite base name and DoBar is test base name. void AddTestPattern(const char* test_suite_name, const char* test_base_name, - TestMetaFactoryBase* meta_factory) { - tests_.push_back(std::shared_ptr( - new TestInfo(test_suite_name, test_base_name, meta_factory))); + TestMetaFactoryBase* meta_factory, + CodeLocation code_location) { + tests_.push_back(std::shared_ptr(new TestInfo( + test_suite_name, test_base_name, meta_factory, code_location))); } // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // about a generator. @@ -522,11 +536,13 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { return 0; // Return value used only to run this method in namespace scope. } // UnitTest class invokes this method to register tests in this test suite - // test suites right before running tests in RUN_ALL_TESTS macro. + // right before running tests in RUN_ALL_TESTS macro. // This method should not be called more than once on any single // instance of a ParameterizedTestSuiteInfoBase derived class. // UnitTest has a guard to prevent from calling this method more than once. void RegisterTests() override { + bool generated_instantiations = false; + for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { std::shared_ptr test_info = *test_it; @@ -549,6 +565,8 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { for (typename ParamGenerator::iterator param_it = generator.begin(); param_it != generator.end(); ++param_it, ++i) { + generated_instantiations = true; + Message test_name_stream; std::string param_name = name_func( @@ -572,7 +590,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { MakeAndRegisterTestInfo( test_suite_name.c_str(), test_name_stream.GetString().c_str(), nullptr, // No type parameter. - PrintToString(*param_it).c_str(), code_location_, + PrintToString(*param_it).c_str(), test_info->code_location, GetTestSuiteTypeId(), SuiteApiResolver::GetSetUpCaseOrSuite(file, line), SuiteApiResolver::GetTearDownCaseOrSuite(file, line), @@ -580,6 +598,12 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { } // for param_it } // for gen_it } // for test_it + + if (!generated_instantiations) { + // There are no generaotrs, or they all generate nothing ... + InsertSyntheticTestCase(GetTestSuiteName(), code_location_, + !tests_.empty()); + } } // RegisterTests private: @@ -587,14 +611,17 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // with TEST_P macro. struct TestInfo { TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, - TestMetaFactoryBase* a_test_meta_factory) + TestMetaFactoryBase* a_test_meta_factory, + CodeLocation a_code_location) : test_suite_base_name(a_test_suite_base_name), test_base_name(a_test_base_name), - test_meta_factory(a_test_meta_factory) {} + test_meta_factory(a_test_meta_factory), + code_location(a_code_location) {} const std::string test_suite_base_name; const std::string test_base_name; const std::unique_ptr > test_meta_factory; + const CodeLocation code_location; }; using TestInfoContainer = ::std::vector >; // Records data received from INSTANTIATE_TEST_SUITE_P macros: @@ -627,7 +654,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // Check for invalid characters for (std::string::size_type index = 0; index < name.size(); ++index) { - if (!isalnum(name[index]) && name[index] != '_') + if (!IsAlNum(name[index]) && name[index] != '_') return false; } @@ -717,6 +744,34 @@ class ParameterizedTestSuiteRegistry { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); }; +// Keep track of what type-parameterized test suite are defined and +// where as well as which are intatiated. This allows susequently +// identifying suits that are defined but never used. +class TypeParameterizedTestSuiteRegistry { + public: + // Add a suite definition + void RegisterTestSuite(const char* test_suite_name, + CodeLocation code_location); + + // Add an instantiation of a suit. + void RegisterInstantiation(const char* test_suite_name); + + // For each suit repored as defined but not reported as instantiation, + // emit a test that reports that fact (configurably, as an error). + void CheckForInstantiations(); + + private: + struct TypeParameterizedTestSuiteInfo { + explicit TypeParameterizedTestSuiteInfo(CodeLocation c) + : code_location(c), instantiated(false) {} + + CodeLocation code_location; + bool instantiated; + }; + + std::map suites_; +}; + } // namespace internal // Forward declarations of ValuesIn(), which is implemented in @@ -728,10 +783,15 @@ internal::ParamGenerator ValuesIn( namespace internal { // Used in the Values() function to provide polymorphic capabilities. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template class ValueArray { public: - ValueArray(Ts... v) : v_{std::move(v)...} {} + explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {} template operator ParamGenerator() const { // NOLINT @@ -747,6 +807,10 @@ class ValueArray { FlatTuple v_; }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + template class CartesianProductGenerator : public ParamGeneratorInterface<::std::tuple> { @@ -880,4 +944,4 @@ class CartesianProductHolder { } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h b/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h index cece93d..dd84591 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h @@ -32,8 +32,8 @@ // This header file defines the GTEST_OS_* macro. // It is separate from gtest-port.h so that custom/gtest-port.h can include it. -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ // Determines the platform on which Google Test is compiled. #ifdef __CYGWIN__ @@ -68,6 +68,7 @@ # define GTEST_OS_OS2 1 #elif defined __APPLE__ # define GTEST_OS_MAC 1 +# include # if TARGET_OS_IPHONE # define GTEST_OS_IOS 1 # endif @@ -102,6 +103,12 @@ # define GTEST_OS_QNX 1 #elif defined(__HAIKU__) #define GTEST_OS_HAIKU 1 +#elif defined ESP8266 +#define GTEST_OS_ESP8266 1 +#elif defined ESP32 +#define GTEST_OS_ESP32 1 +#elif defined(__XTENSA__) +#define GTEST_OS_XTENSA 1 #endif // __CYGWIN__ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-port.h b/3rdparty/gtest/include/gtest/internal/gtest-port.h index 063fcb1..0953a78 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-port.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-port.h @@ -40,8 +40,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ // Environment-describing macros // ----------------------------- @@ -190,13 +190,27 @@ // GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. // GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a // variable don't have to be used. -// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_ASSIGN_ - disables copy operator=. // GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_DISALLOW_MOVE_ASSIGN_ - disables move operator=. +// GTEST_DISALLOW_MOVE_AND_ASSIGN_ - disables move ctor and operator=. // GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. // GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is // suppressed (constant conditional). // GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127 // is suppressed. +// GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter or +// UniversalPrinter specializations. +// GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter +// or +// UniversalPrinter +// specializations. +// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher or +// Matcher +// specializations. +// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter or +// UniversalPrinter +// specializations. // // Synchronization: // Mutex, MutexLock, ThreadLocal, GetThreadCount() @@ -223,8 +237,7 @@ // // Integer types: // TypeWithSize - maps an integer to a int type. -// Int32, UInt32, Int64, UInt64, TimeInMillis -// - integers of known sizes. +// TimeInMillis - integers of known sizes. // BiggestInt - the biggest signed integer type. // // Command-line utilities: @@ -235,7 +248,7 @@ // Environment variable utilities: // GetEnv() - gets the value of an environment variable. // BoolFromGTestEnv() - parses a bool environment variable. -// Int32FromGTestEnv() - parses an Int32 environment variable. +// Int32FromGTestEnv() - parses an int32_t environment variable. // StringFromGTestEnv() - parses a string environment variable. // // Deprecation warnings: @@ -248,7 +261,10 @@ #include #include #include -#include + +#include +#include +#include #include #ifndef _WIN32_WCE @@ -261,16 +277,15 @@ # include #endif -#include // NOLINT -#include // NOLINT -#include // NOLINT -#include // NOLINT +#include // NOLINT +#include +#include +#include // NOLINT #include -#include #include // NOLINT -#include "gtest/internal/gtest-port-arch.h" #include "gtest/internal/custom/gtest-port.h" +#include "gtest/internal/gtest-port-arch.h" #if !defined(GTEST_DEV_EMAIL_) # define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" @@ -344,6 +359,10 @@ typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION; // WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION. typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #endif +#elif GTEST_OS_XTENSA +#include +// Xtensa toolchains define strcasecmp in the string.h header instead of +// strings.h. string.h is already included. #else // This assumes that non-Windows OSes provide unistd.h. For OSes where this // is not the case, we need to include headers that provide the functions @@ -364,7 +383,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // On Android, is only available starting with Gingerbread. # define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) # else -# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +#define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS && !GTEST_OS_XTENSA) # endif #endif @@ -441,15 +460,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # endif // defined(_MSC_VER) || defined(__BORLANDC__) #endif // GTEST_HAS_EXCEPTIONS -#if !defined(GTEST_HAS_STD_STRING) -// Even though we don't use this macro any longer, we keep it in case -// some clients still depend on it. -# define GTEST_HAS_STD_STRING 1 -#elif !GTEST_HAS_STD_STRING -// The user told us that ::std::string isn't available. -# error "::std::string isn't available." -#endif // !defined(GTEST_HAS_STD_STRING) - #ifndef GTEST_HAS_STD_WSTRING // The user didn't tell us whether ::std::wstring is available, so we need // to figure it out. @@ -458,7 +468,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // no support for it at least as recent as Froyo (2.2). #define GTEST_HAS_STD_WSTRING \ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ - GTEST_OS_HAIKU)) + GTEST_OS_HAIKU || GTEST_OS_ESP32 || GTEST_OS_ESP8266 || GTEST_OS_XTENSA)) #endif // GTEST_HAS_STD_WSTRING @@ -582,7 +592,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #ifndef GTEST_HAS_STREAM_REDIRECTION // By default, we assume that stream redirection is supported on all // platforms except known mobile ones. -# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA # define GTEST_HAS_STREAM_REDIRECTION 0 # else # define GTEST_HAS_STREAM_REDIRECTION 1 @@ -676,16 +687,27 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #endif -// A macro to disallow operator= +// A macro to disallow copy operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_ASSIGN_(type) \ - void operator=(type const &) = delete + type& operator=(type const &) = delete // A macro to disallow copy constructor and operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ - type(type const &) = delete; \ - GTEST_DISALLOW_ASSIGN_(type) + type(type const&) = delete; \ + type& operator=(type const&) = delete + +// A macro to disallow move operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_MOVE_ASSIGN_(type) \ + type& operator=(type &&) noexcept = delete + +// A macro to disallow move constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_MOVE_AND_ASSIGN_(type) \ + type(type&&) noexcept = delete; \ + type& operator=(type&&) noexcept = delete // Tell the compiler to warn about unused return values for functions declared // with this macro. The macro should be used on function declarations @@ -856,9 +878,6 @@ class Secret; // expression is false, compiler will issue an error containing this identifier. #define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg) -// Evaluates to the number of elements in 'array'. -#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) - // A helper for suppressing warnings on constant condition. It just // returns 'condition'. GTEST_API_ bool IsTrue(bool condition); @@ -915,8 +934,6 @@ class GTEST_API_ RE { const char* full_pattern_; // For FullMatch(); # endif - - GTEST_DISALLOW_ASSIGN_(RE); }; #endif // GTEST_USES_PCRE @@ -1599,7 +1616,7 @@ class ThreadLocal : public ThreadLocalBase { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -1608,7 +1625,7 @@ class ThreadLocal : public ThreadLocalBase { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -1808,7 +1825,7 @@ class GTEST_API_ ThreadLocal { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -1817,7 +1834,7 @@ class GTEST_API_ ThreadLocal { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -1887,18 +1904,12 @@ class GTEST_API_ ThreadLocal { // we cannot detect it. GTEST_API_ size_t GetThreadCount(); -template -using bool_constant = std::integral_constant; - #if GTEST_OS_WINDOWS # define GTEST_PATH_SEP_ "\\" # define GTEST_HAS_ALT_PATH_SEP_ 1 -// The biggest signed integer type the compiler supports. -typedef __int64 BiggestInt; #else # define GTEST_PATH_SEP_ "/" # define GTEST_HAS_ALT_PATH_SEP_ 0 -typedef long long BiggestInt; // NOLINT #endif // GTEST_OS_WINDOWS // Utilities for char. @@ -1929,6 +1940,19 @@ inline bool IsUpper(char ch) { inline bool IsXDigit(char ch) { return isxdigit(static_cast(ch)) != 0; } +#ifdef __cpp_char8_t +inline bool IsXDigit(char8_t ch) { + return isxdigit(static_cast(ch)) != 0; +} +#endif +inline bool IsXDigit(char16_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} +inline bool IsXDigit(char32_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} inline bool IsXDigit(wchar_t ch) { const unsigned char low_byte = static_cast(ch); return ch == low_byte && isxdigit(low_byte) != 0; @@ -1963,16 +1987,16 @@ namespace posix { typedef struct _stat StatStruct; # ifdef __BORLANDC__ -inline int IsATTY(int fd) { return isatty(fd); } +inline int DoIsATTY(int fd) { return isatty(fd); } inline int StrCaseCmp(const char* s1, const char* s2) { return stricmp(s1, s2); } inline char* StrDup(const char* src) { return strdup(src); } # else // !__BORLANDC__ # if GTEST_OS_WINDOWS_MOBILE -inline int IsATTY(int /* fd */) { return 0; } +inline int DoIsATTY(int /* fd */) { return 0; } # else -inline int IsATTY(int fd) { return _isatty(fd); } +inline int DoIsATTY(int fd) { return _isatty(fd); } # endif // GTEST_OS_WINDOWS_MOBILE inline int StrCaseCmp(const char* s1, const char* s2) { return _stricmp(s1, s2); @@ -1993,12 +2017,28 @@ inline bool IsDir(const StatStruct& st) { } # endif // GTEST_OS_WINDOWS_MOBILE +#elif GTEST_OS_ESP8266 +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int DoIsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { + // stat function not implemented on ESP8266 + return 0; +} +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + #else typedef struct stat StatStruct; inline int FileNo(FILE* file) { return fileno(file); } -inline int IsATTY(int fd) { return isatty(fd); } +inline int DoIsATTY(int fd) { return isatty(fd); } inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } inline int StrCaseCmp(const char* s1, const char* s2) { return strcasecmp(s1, s2); @@ -2009,23 +2049,39 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } #endif // GTEST_OS_WINDOWS +inline int IsATTY(int fd) { + // DoIsATTY might change errno (for example ENOTTY in case you redirect stdout + // to a file on Linux), which is unexpected, so save the previous value, and + // restore it after the call. + int savedErrno = errno; + int isAttyValue = DoIsATTY(fd); + errno = savedErrno; + + return isAttyValue; +} + // Functions deprecated by MSVC 8.0. GTEST_DISABLE_MSC_DEPRECATED_PUSH_() -inline const char* StrNCpy(char* dest, const char* src, size_t n) { - return strncpy(dest, src, n); -} - // ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and // StrError() aren't needed on Windows CE at this time and thus not // defined there. -#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT +#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && \ + !GTEST_OS_WINDOWS_RT && !GTEST_OS_ESP8266 && !GTEST_OS_XTENSA inline int ChDir(const char* dir) { return chdir(dir); } #endif inline FILE* FOpen(const char* path, const char* mode) { +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW + struct wchar_codecvt : public std::codecvt {}; + std::wstring_convert converter; + std::wstring wide_path = converter.from_bytes(path); + std::wstring wide_mode = converter.from_bytes(mode); + return _wfopen(wide_path.c_str(), wide_mode.c_str()); +#else // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW return fopen(path, mode); +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW } #if !GTEST_OS_WINDOWS_MOBILE inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { @@ -2045,8 +2101,9 @@ inline int Close(int fd) { return close(fd); } inline const char* StrError(int errnum) { return strerror(errnum); } #endif inline const char* GetEnv(const char* name) { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT - // We are on Windows CE, which has no environment variables. +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA + // We are on an embedded platform, which has no environment variables. static_cast(name); // To prevent 'unused argument' warning. return nullptr; #elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) @@ -2088,15 +2145,13 @@ GTEST_DISABLE_MSC_DEPRECATED_POP_() # define GTEST_SNPRINTF_ snprintf #endif -// The maximum number a BiggestInt can represent. This definition -// works no matter BiggestInt is represented in one's complement or -// two's complement. +// The biggest signed integer type the compiler supports. // -// We cannot rely on numeric_limits in STL, as __int64 and long long -// are not part of standard C++ and numeric_limits doesn't need to be -// defined for them. -const BiggestInt kMaxBiggestInt = - ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); +// long long is guaranteed to be at least 64-bits in C++11. +using BiggestInt = long long; // NOLINT + +// The maximum number a BiggestInt can represent. +constexpr BiggestInt kMaxBiggestInt = (std::numeric_limits::max)(); // This template class serves as a compile-time function from size to // type. It maps a size in bytes to a primitive type with that @@ -2121,40 +2176,27 @@ class TypeWithSize { public: // This prevents the user from using TypeWithSize with incorrect // values of N. - typedef void UInt; + using UInt = void; }; // The specialization for size 4. template <> class TypeWithSize<4> { public: - // unsigned int has size 4 in both gcc and MSVC. - // - // As base/basictypes.h doesn't compile on Windows, we cannot use - // uint32, uint64, and etc here. - typedef int Int; - typedef unsigned int UInt; + using Int = std::int32_t; + using UInt = std::uint32_t; }; // The specialization for size 8. template <> class TypeWithSize<8> { public: -#if GTEST_OS_WINDOWS - typedef __int64 Int; - typedef unsigned __int64 UInt; -#else - typedef long long Int; // NOLINT - typedef unsigned long long UInt; // NOLINT -#endif // GTEST_OS_WINDOWS + using Int = std::int64_t; + using UInt = std::uint64_t; }; // Integer types of known sizes. -typedef TypeWithSize<4>::Int Int32; -typedef TypeWithSize<4>::UInt UInt32; -typedef TypeWithSize<8>::Int Int64; -typedef TypeWithSize<8>::UInt UInt64; -typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. +using TimeInMillis = int64_t; // Represents time in milliseconds. // Utilities for command line flags and environment variables. @@ -2173,7 +2215,7 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Macros for declaring flags. # define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) # define GTEST_DECLARE_int32_(name) \ - GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) + GTEST_API_ extern std::int32_t GTEST_FLAG(name) # define GTEST_DECLARE_string_(name) \ GTEST_API_ extern ::std::string GTEST_FLAG(name) @@ -2181,7 +2223,7 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. # define GTEST_DEFINE_bool_(name, default_val, doc) \ GTEST_API_ bool GTEST_FLAG(name) = (default_val) # define GTEST_DEFINE_int32_(name, default_val, doc) \ - GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) + GTEST_API_ std::int32_t GTEST_FLAG(name) = (default_val) # define GTEST_DEFINE_string_(name, default_val, doc) \ GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) @@ -2196,12 +2238,13 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Parses 'str' for a 32-bit signed integer. If successful, writes the result // to *value and returns true; otherwise leaves *value unchanged and returns // false. -bool ParseInt32(const Message& src_text, const char* str, Int32* value); +GTEST_API_ bool ParseInt32(const Message& src_text, const char* str, + int32_t* value); -// Parses a bool/Int32/string from the environment variable +// Parses a bool/int32_t/string from the environment variable // corresponding to the given Google Test flag. bool BoolFromGTestEnv(const char* flag, bool default_val); -GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +GTEST_API_ int32_t Int32FromGTestEnv(const char* flag, int32_t default_val); std::string OutputFlagAlsoCheckEnvVar(); const char* StringFromGTestEnv(const char* flag, const char* default_val); @@ -2228,4 +2271,119 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val); #endif // !defined(GTEST_INTERNAL_DEPRECATED) -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#if GTEST_HAS_ABSL +// Always use absl::any for UniversalPrinter<> specializations if googletest +// is built with absl support. +#define GTEST_INTERNAL_HAS_ANY 1 +#include "absl/types/any.h" +namespace testing { +namespace internal { +using Any = ::absl::any; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::any for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_ANY 1 +#include +namespace testing { +namespace internal { +using Any = ::std::any; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::any is not +// supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::optional for UniversalPrinter<> specializations if +// googletest is built with absl support. +#define GTEST_INTERNAL_HAS_OPTIONAL 1 +#include "absl/types/optional.h" +namespace testing { +namespace internal { +template +using Optional = ::absl::optional; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::optional for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_OPTIONAL 1 +#include +namespace testing { +namespace internal { +template +using Optional = ::std::optional; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::optional is not +// supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::string_view for Matcher<> specializations if googletest +// is built with absl support. +# define GTEST_INTERNAL_HAS_STRING_VIEW 1 +#include "absl/strings/string_view.h" +namespace testing { +namespace internal { +using StringView = ::absl::string_view; +} // namespace internal +} // namespace testing +#else +# ifdef __has_include +# if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::string_view for Matcher<> +// specializations. +# define GTEST_INTERNAL_HAS_STRING_VIEW 1 +#include +namespace testing { +namespace internal { +using StringView = ::std::string_view; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::string_view is not +// supported. +# endif // __has_include() && __cplusplus >= 201703L +# endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::variant for UniversalPrinter<> specializations if googletest +// is built with absl support. +#define GTEST_INTERNAL_HAS_VARIANT 1 +#include "absl/types/variant.h" +namespace testing { +namespace internal { +template +using Variant = ::absl::variant; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::variant for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_VARIANT 1 +#include +namespace testing { +namespace internal { +template +using Variant = ::std::variant; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::variant is not supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-string.h b/3rdparty/gtest/include/gtest/internal/gtest-string.h index 82aaa63..10f774f 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-string.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-string.h @@ -38,8 +38,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #ifdef __BORLANDC__ // string.h is not guaranteed to provide strcpy on C++ Builder. @@ -47,6 +47,7 @@ #endif #include +#include #include #include "gtest/internal/gtest-port.h" @@ -148,11 +149,14 @@ class GTEST_API_ String { // Formats an int value as "%02d". static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + // Formats an int value to given width with leading zeros. + static std::string FormatIntWidthN(int value, int width); + // Formats an int value as "%X". static std::string FormatHexInt(int value); // Formats an int value as "%X". - static std::string FormatHexUInt32(UInt32 value); + static std::string FormatHexUInt32(uint32_t value); // Formats a byte as "%02X". static std::string FormatByte(unsigned char value); @@ -168,4 +172,4 @@ GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-type-util.h b/3rdparty/gtest/include/gtest/internal/gtest-type-util.h index 3d7542d..b87a2e2 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-type-util.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-type-util.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py gtest-type-util.h.pump -// DO NOT EDIT BY HAND!!! - // Copyright 2008 Google Inc. // All Rights Reserved. // @@ -32,17 +28,12 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most 50 types in a list, and at most 50 -// type-parameterized tests in one type-parameterized test suite. -// Please contact googletestframework@googlegroups.com if you need -// more. +// tests. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ #include "gtest/internal/gtest-port.h" @@ -73,1556 +64,43 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) { return s; } -// GetTypeName() returns a human-readable name of type T. -// NB: This function is also used in Google Mock, so don't move it inside of -// the typed-test-only section below. -template -std::string GetTypeName() { -# if GTEST_HAS_RTTI - - const char* const name = typeid(T).name(); -# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) +#if GTEST_HAS_RTTI +// GetTypeName(const std::type_info&) returns a human-readable name of type T. +inline std::string GetTypeName(const std::type_info& type) { + const char* const name = type.name(); +#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) int status = 0; // gcc's implementation of typeid(T).name() mangles the type name, // so we have to demangle it. -# if GTEST_HAS_CXXABI_H_ +#if GTEST_HAS_CXXABI_H_ using abi::__cxa_demangle; -# endif // GTEST_HAS_CXXABI_H_ +#endif // GTEST_HAS_CXXABI_H_ char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); const std::string name_str(status == 0 ? readable_name : name); free(readable_name); return CanonicalizeForStdLibVersioning(name_str); -# else +#else return name; -# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC - -# else +#endif // GTEST_HAS_CXXABI_H_ || __HP_aCC +} +#endif // GTEST_HAS_RTTI +// GetTypeName() returns a human-readable name of type T if and only if +// RTTI is enabled, otherwise it returns a dummy type name. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +#if GTEST_HAS_RTTI + return GetTypeName(typeid(T)); +#else return ""; - -# endif // GTEST_HAS_RTTI +#endif // GTEST_HAS_RTTI } -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. +// A unique type indicating an empty node struct None {}; -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; -template -struct Types2 { - typedef T1 Head; - typedef Types1 Tail; -}; - -template -struct Types3 { - typedef T1 Head; - typedef Types2 Tail; -}; - -template -struct Types4 { - typedef T1 Head; - typedef Types3 Tail; -}; - -template -struct Types5 { - typedef T1 Head; - typedef Types4 Tail; -}; - -template -struct Types6 { - typedef T1 Head; - typedef Types5 Tail; -}; - -template -struct Types7 { - typedef T1 Head; - typedef Types6 Tail; -}; - -template -struct Types8 { - typedef T1 Head; - typedef Types7 Tail; -}; - -template -struct Types9 { - typedef T1 Head; - typedef Types8 Tail; -}; - -template -struct Types10 { - typedef T1 Head; - typedef Types9 Tail; -}; - -template -struct Types11 { - typedef T1 Head; - typedef Types10 Tail; -}; - -template -struct Types12 { - typedef T1 Head; - typedef Types11 Tail; -}; - -template -struct Types13 { - typedef T1 Head; - typedef Types12 Tail; -}; - -template -struct Types14 { - typedef T1 Head; - typedef Types13 Tail; -}; - -template -struct Types15 { - typedef T1 Head; - typedef Types14 Tail; -}; - -template -struct Types16 { - typedef T1 Head; - typedef Types15 Tail; -}; - -template -struct Types17 { - typedef T1 Head; - typedef Types16 Tail; -}; - -template -struct Types18 { - typedef T1 Head; - typedef Types17 Tail; -}; - -template -struct Types19 { - typedef T1 Head; - typedef Types18 Tail; -}; - -template -struct Types20 { - typedef T1 Head; - typedef Types19 Tail; -}; - -template -struct Types21 { - typedef T1 Head; - typedef Types20 Tail; -}; - -template -struct Types22 { - typedef T1 Head; - typedef Types21 Tail; -}; - -template -struct Types23 { - typedef T1 Head; - typedef Types22 Tail; -}; - -template -struct Types24 { - typedef T1 Head; - typedef Types23 Tail; -}; - -template -struct Types25 { - typedef T1 Head; - typedef Types24 Tail; -}; - -template -struct Types26 { - typedef T1 Head; - typedef Types25 Tail; -}; - -template -struct Types27 { - typedef T1 Head; - typedef Types26 Tail; -}; - -template -struct Types28 { - typedef T1 Head; - typedef Types27 Tail; -}; - -template -struct Types29 { - typedef T1 Head; - typedef Types28 Tail; -}; - -template -struct Types30 { - typedef T1 Head; - typedef Types29 Tail; -}; - -template -struct Types31 { - typedef T1 Head; - typedef Types30 Tail; -}; - -template -struct Types32 { - typedef T1 Head; - typedef Types31 Tail; -}; - -template -struct Types33 { - typedef T1 Head; - typedef Types32 Tail; -}; - -template -struct Types34 { - typedef T1 Head; - typedef Types33 Tail; -}; - -template -struct Types35 { - typedef T1 Head; - typedef Types34 Tail; -}; - -template -struct Types36 { - typedef T1 Head; - typedef Types35 Tail; -}; - -template -struct Types37 { - typedef T1 Head; - typedef Types36 Tail; -}; - -template -struct Types38 { - typedef T1 Head; - typedef Types37 Tail; -}; - -template -struct Types39 { - typedef T1 Head; - typedef Types38 Tail; -}; - -template -struct Types40 { - typedef T1 Head; - typedef Types39 Tail; -}; - -template -struct Types41 { - typedef T1 Head; - typedef Types40 Tail; -}; - -template -struct Types42 { - typedef T1 Head; - typedef Types41 Tail; -}; - -template -struct Types43 { - typedef T1 Head; - typedef Types42 Tail; -}; - -template -struct Types44 { - typedef T1 Head; - typedef Types43 Tail; -}; - -template -struct Types45 { - typedef T1 Head; - typedef Types44 Tail; -}; - -template -struct Types46 { - typedef T1 Head; - typedef Types45 Tail; -}; - -template -struct Types47 { - typedef T1 Head; - typedef Types46 Tail; -}; - -template -struct Types48 { - typedef T1 Head; - typedef Types47 Tail; -}; - -template -struct Types49 { - typedef T1 Head; - typedef Types48 Tail; -}; - -template -struct Types50 { - typedef T1 Head; - typedef Types49 Tail; -}; - - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. -template -struct Types { - typedef internal::Types50 type; -}; - -template <> -struct Types { - typedef internal::Types0 type; -}; -template -struct Types { - typedef internal::Types1 type; -}; -template -struct Types { - typedef internal::Types2 type; -}; -template -struct Types { - typedef internal::Types3 type; -}; -template -struct Types { - typedef internal::Types4 type; -}; -template -struct Types { - typedef internal::Types5 type; -}; -template -struct Types { - typedef internal::Types6 type; -}; -template -struct Types { - typedef internal::Types7 type; -}; -template -struct Types { - typedef internal::Types8 type; -}; -template -struct Types { - typedef internal::Types9 type; -}; -template -struct Types { - typedef internal::Types10 type; -}; -template -struct Types { - typedef internal::Types11 type; -}; -template -struct Types { - typedef internal::Types12 type; -}; -template -struct Types { - typedef internal::Types13 type; -}; -template -struct Types { - typedef internal::Types14 type; -}; -template -struct Types { - typedef internal::Types15 type; -}; -template -struct Types { - typedef internal::Types16 type; -}; -template -struct Types { - typedef internal::Types17 type; -}; -template -struct Types { - typedef internal::Types18 type; -}; -template -struct Types { - typedef internal::Types19 type; -}; -template -struct Types { - typedef internal::Types20 type; -}; -template -struct Types { - typedef internal::Types21 type; -}; -template -struct Types { - typedef internal::Types22 type; -}; -template -struct Types { - typedef internal::Types23 type; -}; -template -struct Types { - typedef internal::Types24 type; -}; -template -struct Types { - typedef internal::Types25 type; -}; -template -struct Types { - typedef internal::Types26 type; -}; -template -struct Types { - typedef internal::Types27 type; -}; -template -struct Types { - typedef internal::Types28 type; -}; -template -struct Types { - typedef internal::Types29 type; -}; -template -struct Types { - typedef internal::Types30 type; -}; -template -struct Types { - typedef internal::Types31 type; -}; -template -struct Types { - typedef internal::Types32 type; -}; -template -struct Types { - typedef internal::Types33 type; -}; -template -struct Types { - typedef internal::Types34 type; -}; -template -struct Types { - typedef internal::Types35 type; -}; -template -struct Types { - typedef internal::Types36 type; -}; -template -struct Types { - typedef internal::Types37 type; -}; -template -struct Types { - typedef internal::Types38 type; -}; -template -struct Types { - typedef internal::Types39 type; -}; -template -struct Types { - typedef internal::Types40 type; -}; -template -struct Types { - typedef internal::Types41 type; -}; -template -struct Types { - typedef internal::Types42 type; -}; -template -struct Types { - typedef internal::Types43 type; -}; -template -struct Types { - typedef internal::Types44 type; -}; -template -struct Types { - typedef internal::Types45 type; -}; -template -struct Types { - typedef internal::Types46 type; -}; -template -struct Types { - typedef internal::Types47 type; -}; -template -struct Types { - typedef internal::Types48 type; -}; -template -struct Types { - typedef internal::Types49 type; -}; - -namespace internal { - # define GTEST_TEMPLATE_ template class // The template "selector" struct TemplateSel is used to @@ -1644,1692 +122,62 @@ struct TemplateSel { # define GTEST_BIND_(TmplSel, T) \ TmplSel::template Bind::type -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; -template -struct Templates2 { - typedef TemplateSel Head; - typedef Templates1 Tail; -}; - -template -struct Templates3 { - typedef TemplateSel Head; - typedef Templates2 Tail; -}; - -template -struct Templates4 { - typedef TemplateSel Head; - typedef Templates3 Tail; -}; - -template -struct Templates5 { - typedef TemplateSel Head; - typedef Templates4 Tail; -}; - -template -struct Templates6 { - typedef TemplateSel Head; - typedef Templates5 Tail; -}; - -template -struct Templates7 { - typedef TemplateSel Head; - typedef Templates6 Tail; -}; - -template -struct Templates8 { - typedef TemplateSel Head; - typedef Templates7 Tail; -}; - -template -struct Templates9 { - typedef TemplateSel Head; - typedef Templates8 Tail; -}; - -template -struct Templates10 { - typedef TemplateSel Head; - typedef Templates9 Tail; -}; - -template -struct Templates11 { - typedef TemplateSel Head; - typedef Templates10 Tail; -}; - -template -struct Templates12 { - typedef TemplateSel Head; - typedef Templates11 Tail; -}; - -template -struct Templates13 { - typedef TemplateSel Head; - typedef Templates12 Tail; -}; - -template -struct Templates14 { - typedef TemplateSel Head; - typedef Templates13 Tail; -}; - -template -struct Templates15 { - typedef TemplateSel Head; - typedef Templates14 Tail; -}; - -template -struct Templates16 { - typedef TemplateSel Head; - typedef Templates15 Tail; -}; - -template -struct Templates17 { - typedef TemplateSel Head; - typedef Templates16 Tail; -}; - -template -struct Templates18 { - typedef TemplateSel Head; - typedef Templates17 Tail; -}; - -template -struct Templates19 { - typedef TemplateSel Head; - typedef Templates18 Tail; -}; - -template -struct Templates20 { - typedef TemplateSel Head; - typedef Templates19 Tail; -}; - -template -struct Templates21 { - typedef TemplateSel Head; - typedef Templates20 Tail; -}; - -template -struct Templates22 { - typedef TemplateSel Head; - typedef Templates21 Tail; -}; - -template -struct Templates23 { - typedef TemplateSel Head; - typedef Templates22 Tail; -}; - -template -struct Templates24 { - typedef TemplateSel Head; - typedef Templates23 Tail; -}; - -template -struct Templates25 { - typedef TemplateSel Head; - typedef Templates24 Tail; -}; - -template -struct Templates26 { - typedef TemplateSel Head; - typedef Templates25 Tail; -}; - -template -struct Templates27 { - typedef TemplateSel Head; - typedef Templates26 Tail; -}; - -template -struct Templates28 { - typedef TemplateSel Head; - typedef Templates27 Tail; -}; - -template -struct Templates29 { - typedef TemplateSel Head; - typedef Templates28 Tail; -}; - -template -struct Templates30 { - typedef TemplateSel Head; - typedef Templates29 Tail; -}; - -template -struct Templates31 { - typedef TemplateSel Head; - typedef Templates30 Tail; -}; - -template -struct Templates32 { - typedef TemplateSel Head; - typedef Templates31 Tail; -}; - -template -struct Templates33 { - typedef TemplateSel Head; - typedef Templates32 Tail; -}; - -template -struct Templates34 { - typedef TemplateSel Head; - typedef Templates33 Tail; -}; - -template -struct Templates35 { - typedef TemplateSel Head; - typedef Templates34 Tail; -}; - -template -struct Templates36 { - typedef TemplateSel Head; - typedef Templates35 Tail; -}; - -template -struct Templates37 { - typedef TemplateSel Head; - typedef Templates36 Tail; -}; - -template -struct Templates38 { - typedef TemplateSel Head; - typedef Templates37 Tail; -}; - -template -struct Templates39 { - typedef TemplateSel Head; - typedef Templates38 Tail; -}; - -template -struct Templates40 { - typedef TemplateSel Head; - typedef Templates39 Tail; -}; - -template -struct Templates41 { - typedef TemplateSel Head; - typedef Templates40 Tail; -}; - -template -struct Templates42 { - typedef TemplateSel Head; - typedef Templates41 Tail; -}; - -template -struct Templates43 { - typedef TemplateSel Head; - typedef Templates42 Tail; -}; - -template -struct Templates44 { - typedef TemplateSel Head; - typedef Templates43 Tail; -}; - -template -struct Templates45 { - typedef TemplateSel Head; - typedef Templates44 Tail; -}; - -template -struct Templates46 { - typedef TemplateSel Head; - typedef Templates45 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = Templates; }; -template -struct Templates47 { - typedef TemplateSel Head; - typedef Templates46 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = None; }; -template -struct Templates48 { - typedef TemplateSel Head; - typedef Templates47 Tail; +// Tuple-like type lists +template +struct Types { + using Head = Head_; + using Tail = Types; }; -template -struct Templates49 { - typedef TemplateSel Head; - typedef Templates48 Tail; +template +struct Types { + using Head = Head_; + using Tail = None; }; -template -struct Templates50 { - typedef TemplateSel Head; - typedef Templates49 Tail; +// Helper metafunctions to tell apart a single type from types +// generated by ::testing::Types +template +struct ProxyTypeList { + using type = Types; }; +template +struct is_proxy_type_list : std::false_type {}; -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. -template -struct Templates { - typedef Templates50 type; -}; - -template <> -struct Templates { - typedef Templates0 type; -}; -template -struct Templates { - typedef Templates1 type; -}; -template -struct Templates { - typedef Templates2 type; -}; -template -struct Templates { - typedef Templates3 type; -}; -template -struct Templates { - typedef Templates4 type; -}; -template -struct Templates { - typedef Templates5 type; -}; -template -struct Templates { - typedef Templates6 type; -}; -template -struct Templates { - typedef Templates7 type; -}; -template -struct Templates { - typedef Templates8 type; -}; -template -struct Templates { - typedef Templates9 type; -}; -template -struct Templates { - typedef Templates10 type; -}; -template -struct Templates { - typedef Templates11 type; -}; -template -struct Templates { - typedef Templates12 type; -}; -template -struct Templates { - typedef Templates13 type; -}; -template -struct Templates { - typedef Templates14 type; -}; -template -struct Templates { - typedef Templates15 type; -}; -template -struct Templates { - typedef Templates16 type; -}; -template -struct Templates { - typedef Templates17 type; -}; -template -struct Templates { - typedef Templates18 type; -}; -template -struct Templates { - typedef Templates19 type; -}; -template -struct Templates { - typedef Templates20 type; -}; -template -struct Templates { - typedef Templates21 type; -}; -template -struct Templates { - typedef Templates22 type; -}; -template -struct Templates { - typedef Templates23 type; -}; -template -struct Templates { - typedef Templates24 type; -}; -template -struct Templates { - typedef Templates25 type; -}; -template -struct Templates { - typedef Templates26 type; -}; -template -struct Templates { - typedef Templates27 type; -}; -template -struct Templates { - typedef Templates28 type; -}; -template -struct Templates { - typedef Templates29 type; -}; -template -struct Templates { - typedef Templates30 type; -}; -template -struct Templates { - typedef Templates31 type; -}; -template -struct Templates { - typedef Templates32 type; -}; -template -struct Templates { - typedef Templates33 type; -}; -template -struct Templates { - typedef Templates34 type; -}; -template -struct Templates { - typedef Templates35 type; -}; -template -struct Templates { - typedef Templates36 type; -}; -template -struct Templates { - typedef Templates37 type; -}; -template -struct Templates { - typedef Templates38 type; -}; -template -struct Templates { - typedef Templates39 type; -}; -template -struct Templates { - typedef Templates40 type; -}; -template -struct Templates { - typedef Templates41 type; -}; -template -struct Templates { - typedef Templates42 type; -}; -template -struct Templates { - typedef Templates43 type; -}; -template -struct Templates { - typedef Templates44 type; -}; -template -struct Templates { - typedef Templates45 type; -}; -template -struct Templates { - typedef Templates46 type; -}; -template -struct Templates { - typedef Templates47 type; -}; -template -struct Templates { - typedef Templates48 type; -}; -template -struct Templates { - typedef Templates49 type; -}; - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_SUITE() and -// INSTANTIATE_TYPED_TEST_SUITE_P(). +template +struct is_proxy_type_list> : std::true_type {}; +// Generator which conditionally creates type lists. +// It recognizes if a requested type list should be created +// and prevents creating a new type list nested within another one. template -struct TypeList { - typedef Types1 type; -}; +struct GenerateTypeList { + private: + using proxy = typename std::conditional::value, T, + ProxyTypeList>::type; -template -struct TypeList > { - typedef typename Types::type type; + public: + using type = typename proxy::type; }; -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - } // namespace internal + +template +using Types = internal::ProxyTypeList; + } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc new file mode 100644 index 0000000..12d383b --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc @@ -0,0 +1,220 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: CPPTest框架中ext入口 + */ + +#include +#include +#include +#include +#include "gtest/hwext/gtest-ext.h" + + +namespace testing { + namespace ext { + #define GTEST_EXT_DEBUG 0 + + TestDefManager* TestDefManager::instance() + { + static TestDefManager* instance_ = NULL; + if (instance_ == NULL) { + instance_ = new TestDefManager(); + } + return instance_; + } + + const TestDefManager* TestDefManager::cinstance() + { + return instance(); + } + + // c'tor, all members immutable + TestDefInfo::TestDefInfo(const char* tcn, const char* n, int fs, TestDefType tdf) :\ + test_case_name(tcn), name(n), flags(fs), def_type(tdf) {}; + + bool TestDefManager::regist(const char* test_case_name, const char* test_name, int test_flags, TestDefType tdf) + { + TestDefManager::testDefInfos.push_back(new TestDefInfo(test_case_name, test_name, test_flags, tdf)); + return true; + } + + int TestDefManager::queryFlagsFor(const TestInfo* test, int def_value) const + { + const TestDefInfo* def = findDefFor(test); + return def == NULL ? def_value : def->flags; + } + + const TestDefInfo* TestDefManager::findDefFor(const TestInfo* test) const + { + // search by matching test definition information + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) + { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(test->test_case_name(), info->test_case_name, case_name_mt) + && matchNaming(test->name(), info->name, test_name_mt); + if (matched) { + return info; + } + } + + #if GTEST_EXT_DEBUG + printf("cannot find test definition for: %s.%s\n", test->test_case_name(), test->name()); + #endif + return NULL; + } + + bool TestDefManager::matchNaming(const char * const a, const char * const b, NamingMatchType mt) const + { + const char sep = TestDefInfo::kNamingSepchar; + const int len_a = strlen(a); + const int len_b = strlen(b); + int i; + switch (mt) { + case AEqualsB: + // a=b + return strcmp(a, b) == 0; + case AStartsWithB: + // a=b/xxx + return strstr(a, b) == a && a[len_b] == sep; + case AContainsB: + // a=xxx/b/yyy + for (i = 1; i < len_a - len_b; i++) { + if (a[i - 1] == sep&&a[i + len_b] == sep&&strstr(a + i, b) == a + i) { + return true; + } + } + return false; + case AEndsWithB: + // a=xxx/b + return len_a > len_b&&a[len_a - len_b - 1] == sep&&strcmp(a + len_a - len_b, b) == 0; + default: + fprintf(stderr, "Illegal NamingMatchType: %d", mt); + return false; + } + } + + int TestDefManager::getLevel(const std::string testcasename, const std::string testname) const + { + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + int levelShift = 24; + int levelList[5] = {1, 2, 4, 8, 16}; + enum indexEnum {I0 = 0, I1, I2, I3, I4}; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(testcasename.c_str(), info->test_case_name, case_name_mt) + && matchNaming(testname.c_str(), info->name, test_name_mt); + if (matched) { + int level = (info->flags >> levelShift); + if (level == levelList[I0]) return I0; + if (level == levelList[I1]) return I1; + if (level == levelList[I2]) return I2; + if (level == levelList[I3]) return I3; + if (level == levelList[I4]) return I4; + } + } + return -1; + } + + int* TestDefManager::getTestFlags (const std::string testcasename, const std::string testname) const + { + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + static int flagList[3] = {-1, -1, -1}; + int posType = 8; + int posSize = 4; + int indexType = 0; + int indexSize = 1; + int indexRank = 2; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(testcasename.c_str(), info->test_case_name, case_name_mt) + && matchNaming(testname.c_str(), info->name, test_name_mt); + if (matched) { + // get the three flag + int type = (info->flags >> posType); + int size = (info->flags >> posSize); + int rank = info->flags; + + // add three flag value in the flag list + flagList[indexType] = type; + flagList[indexSize] = size; + flagList[indexRank] = rank; + } + } + return flagList; + } + + } //namespace ext +} //namespace testing diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc new file mode 100644 index 0000000..d7bfc6c --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc @@ -0,0 +1,226 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: CPPTest框架中通过Flag标识实现用例过滤 + */ + +#include "gtest/hwext/gtest-filter.h" +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + namespace ext { + + const char* const TestFilter::kStrictFilter = "strict_tags"; + enum IndexEnum {A = 1, B, C, D, E, F, G, H, I, J, K}; + + TestFilter* TestFilter::instance() + { + static TestFilter* instance_ = NULL; + if (instance_ == NULL) { + instance_ = new TestFilter(); + instance_->reset(); + } + return instance_; + } + + void TestFilter::printHelp() const + { + printf("\nTest Filtering:\n"); + const std::vector& sets = AllHextTagSets(); + // help message line indents + const char* indents[] = { " ", " " }; + + for (unsigned int i = 0; i < sets.size(); i++) { + sets.at(i)->printHelp(indents); + } + + printf("%sSelect tests by test level, may be a list seperated by ',' or ';'.\n", indents[1]); + } + + map& TestFilter::getAllFilterFlagsKv() + { + // no need to consider concurrence so for, because we do + // this before running tests + if (flag_kvs_inited) { + return filterFlagsKv; + } + + flag_kvs_inited = true; + const std::vector& sets = AllHextTagSets(); + for (unsigned int i = 0; i < sets.size(); i++) { + filterFlagsKv.insert(pair(sets.at(i)->naming(), new string(""))); + } + + // strict mode + filterFlagsKv.insert(pair(kStrictFilter, new string("false"))); + return filterFlagsKv; + } + + void TestFilter::postSetType (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Function") { + vecType.push_back(A); + } else if (curr == "Performance") { + vecType.push_back(B); + } else if (curr == "Power") { + vecType.push_back(C); + } else if (curr == "Reliability") { + vecType.push_back(D); + } else if (curr == "Security") { + vecType.push_back(E); + } else if (curr == "Global") { + vecType.push_back(F); + } else if (curr == "Compatibility") { + vecType.push_back(G); + } else if (curr == "User") { + vecType.push_back(H); + } else if (curr == "Standard") { + vecType.push_back(I); + } else if (curr == "Safety") { + vecType.push_back(J); + } else if (curr == "Resilience") { + vecType.push_back(K); + } + } + } + + void TestFilter::postSetSize (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "SmallTest") { + vecSize.push_back(A); + } else if (curr == "MediumTest") { + vecSize.push_back(B); + } else if (curr == "LargeTest") { + vecSize.push_back(C); + } + } + } + + void TestFilter::postSetRank (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Level0") { + vecRank.push_back(A); + } else if (curr == "Level1") { + vecRank.push_back(B); + } else if (curr == "Level2") { + vecRank.push_back(C); + } else if (curr == "Level3") { + vecRank.push_back(D); + } else if (curr == "Level4") { + vecRank.push_back(E); + } + } + } + + bool TestFilter::postParsingArguments() + { + if (ready || !flag_kvs_inited) { + // only run setup logic once + return true; + } + + const char *kCandidateSeps = ",;|/"; + ready = true; + bool error = false; + map::iterator iter; + + for (iter = filterFlagsKv.begin(); iter != filterFlagsKv.end(); iter++) { + const char *kstr = iter->first; + const char *vstr = iter->second->c_str(); + int flag = TestFlag::None; + + if (compareStringsByIgnoreCase(kStrictFilter, kstr)) { + strictMode = compareStringsByIgnoreCase("true", vstr) || compareStringsByIgnoreCase("t", vstr); + } else if (flagForName(kstr, vstr, flag)) { + string strname = string(kstr); + string strval = string(vstr); + vector vectemp = SplitString(strval, kCandidateSeps); + + if (strname == "testsize") { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Level0") { + vecTestLevel.push_back(1); + } else if (curr == "Level1") { + vecTestLevel.push_back(2); + } else if (curr == "Level2") { + vecTestLevel.push_back(4); + } else if (curr == "Level3") { + vecTestLevel.push_back(8); + } else if (curr == "Level4") { + vecTestLevel.push_back(16); + } + } + } else if (strname == "type") { + this->postSetType(vectemp); + } else if (strname == "size") { + this->postSetSize(vectemp); + } else if (strname == "rank") { + this->postSetRank(vectemp); + } + } else { + // illegal arguments + error = true; + } + // free the newed strings + delete iter->second; + } + + filterFlagsKv.clear(); + return !error; + } + + bool TestFilter::accept(int flags) const + { + // both of flags and req_no should be accepted + if (!ready) { + return true; + } + + int posType = 8; + int posSize = 4; + int level = (flags >> 24); + int type = (flags >> posType); + int size = (flags >> posSize); + int rank = flags; + bool flags_type = false; + bool flags_size = false; + bool flags_rank = false; + bool flags_level = false; + bool flags_accepted = false; + + if (!strictMode) { + flags_type = IsElementInVector(vecType, type); + flags_size = IsElementInVector(vecSize, size); + flags_rank = IsElementInVector(vecRank, rank); + flags_level = IsElementInVector(vecTestLevel, level); + flags_accepted = (flags_type & flags_size & flags_rank) | (flags_level); + } + else { + flags_accepted = ((flags&requiredFlags) == requiredFlags); + } + + if (!flags_accepted) { + return false; + } + + return true; + } + + void TestFilter::reset() + { + filterFlagsKv.clear(); + requiredFlags = TestFlag::None; + flag_kvs_inited = false; + strictMode = false; + ready = false; + } + + } // namespace ext +} // namespace testing \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp new file mode 100644 index 0000000..2ca22fa --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp @@ -0,0 +1,96 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +* Description:多线程测试框架(GTEST-MULTITHREAD)库,源码移植自CDK +* Author: +* Create:2023/2/24 +*/ + +#include "gtest/hwext/gtest-multithread.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace testing{ + namespace mt { + static inline void doThreadTestTask(ThreadTaskEntry *task) + { + for (const auto &f : task->funcList){ + f.m_func(); + } + } + + void MultiThreadTest::run() + { + int i = 0; + for (const auto &_ : randomTasks) { + for (const auto &val : _.second) { + auto pid = rand() % 100 + i; + appendTaskToList(pid, val.m_func, val.m_testsuite, val.m_testcase); + } + i++; + } + doTest(); + } + + void MultiThreadTest::doTest() + { + threadTestEntryList.clear(); + for (const auto &task : threadTasks){ + threadTestEntryList.push_back(ThreadTaskEntry(task)); + } + for (auto &test : threadTestEntryList){ + test.thread = new std::thread(doThreadTestTask, &test); + } + auto check = [&](ThreadTaskEntry &t) -> void { + if (t.thread){ + t.thread->join(); + delete t.thread; + t.thread = nullptr; + } + }; + std::for_each(threadTestEntryList.begin(), threadTestEntryList.end(), check); + } + + unsigned MultiThreadTest::runTask(unsigned thread_num, PF func, std::string testsuite, std::string testcase) + { + MultiThreadFailCaseListener *listener = new MultiThreadFailCaseListener(this); + testing::UnitTest::GetInstance()->listeners().Append(listener); + if (thread_num == 0){ + func(); + } + unsigned i = 0; + for(; i < thread_num; i++){ + appendTaskToList(i, func, testsuite, testcase); + } + i = 0; + for (const auto &_ : randomTasks){ + for (const auto &val : _.second){ + auto pid = rand() % 100 + i; + appendTaskToList(pid, val.m_func, val.m_testsuite, val.m_testcase); + } + i++; + } + doTest(); + testing::UnitTest::GetInstance()->listeners().Release(listener); + return 0; + } + + void MultiThreadTest::appendTaskToList(unsigned thread_id, PF func, std::string testsuite, std::string testcase) + { + TestTask task(testsuite, testcase, func); + if (thread_id == RANDOM_THREAD_ID){ + randomTasks[testsuite].emplace_back(task); + return; + } + while (thread_id >= threadTasks.size()){ + threadTasks.push_back(std::vector()); + } + threadTasks[thread_id].push_back(task); + } + } +} \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc new file mode 100644 index 0000000..e21a117 --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc @@ -0,0 +1,197 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: 实现CPPTest的flag标识设置 + */ + +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + namespace ext { + + const TestSizeSet TestSize; + const TypeSet G_TYPE; + const SizeSet G_SIZE; + const RankSet G_RANK; + const int G_TESTSIZESHIFT = 24; + const int G_TYPESHIFT = 8; + const int G_SIZESHIFT = 4; + + TestFlag::TestFlag(const char* n, const char* d, int m) : name(n), desc(d), mask(m) + { + eleCount = 0; + } + + void TestFlag::element(const char* desc, int hex) + { + elementMap.insert(pair(hex, desc)); + } + + void TestFlag::printHelp(const char** indents) const + { + map::const_iterator c_iter; + int i = 0; + printf("%s--gtest_%s=(", indents[0], naming()); + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + printf("%s%s", (i > 0) ? "|" : "", c_iter->second); + i++; + } + printf(")\n"); + printf("%s%s\n", indents[1], description()); + } + + bool TestFlag::verify(int hex, char* err) const + { + // wipe bits not belong to this set + int masked = hex&mask; + + map::const_iterator c_iter; + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + // wipe each bit defined in this set + masked &= ~c_iter->first; + } + + // masked!=0 means find undefined bit(s) + const bool nice = masked == 0; + if (!nice&&err != NULL) { + sprintf(err, "Illegal %s value '0x%08x'\n", naming(), hex); + } + + return nice; + } + + bool TestFlag::eleForName(const char* name, int& result) const + { + if (name == NULL) { + // NOTE:: strlen(NULL) will cause seg fault + return false; + } + + const int result_raw = result; + // must set to 0 here, because we will do bit-OR arithmetic later + result = 0; + // the parameter 'name' may contatin more than one element + const char* kCandidateSeps = ",;|/"; + char name_cpoy[256]; + memset(name_cpoy, 0, 256); + memcpy(name_cpoy, name, strlen(name)); + + char * pch; + pch = strtok(name_cpoy, kCandidateSeps); + while (pch != NULL) + { + map::const_iterator c_iter; + bool matched = false; + // try to matchNaming all the elements + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + const char* ele_name = c_iter->second; + const string ele_full_name_string = string(naming()) + "." + ele_name; + if (compareStringsByIgnoreCase(pch, ele_name) || compareStringsByIgnoreCase(pch, ele_full_name_string.c_str())) { + // set this bit + result |= c_iter->first; + matched = true; + break; + } + } + if (!matched) { + fprintf(stderr, "Unrecognized %s value '%s'\n", naming(), pch); + // abort the matching, recover result to raw value + result = result_raw; + return false; + } + pch = strtok(NULL, kCandidateSeps); + } + return true; + } + + TestSizeSet::TestSizeSet() : TestFlag ("testsize", "Select tests by test level hint.", 0xff << G_TESTSIZESHIFT) + { + element("Level0", Level0); + element("Level1", Level1); + element("Level2", Level2); + element("Level3", Level3); + element("Level4", Level4); + } + + TypeSet::TypeSet() : TestFlag ("type", "Select testcase by type hint.", 0x0f << G_TYPESHIFT) + { + element("Function", function); + element("Performance", performance); + element("Power", power); + element("Reliability", reliability); + element("Security", security); + element("Global", global); + element("Compatibility", compatibility); + element("User", user); + element("Standard", standard); + element("Safety", safety); + element("Resilience", resilience); + } + + + SizeSet::SizeSet() : TestFlag ("size", "Select testcase by size hint.", 0x0f << G_SIZESHIFT) + { + element("SmallTest", smallTest); + element("MediumTest", mediumTest); + element("LargeTest", largeTest); + } + + + RankSet::RankSet() : TestFlag("rank", "Select testcase by rank hint.", 0x0f) + { + element("Level0", level0); + element("Level1", level1); + element("Level2", level2); + element("Level3", level3); + element("Level4", level4); + } + + static std::vector sets; + + static void ensureSetsInit() { + if (sets.size() > 0) { + return; + } + sets.push_back(&TestSize); + sets.push_back(&G_TYPE); + sets.push_back(&G_SIZE); + sets.push_back(&G_RANK); + } + + const std::vector& AllHextTagSets() + { + ensureSetsInit(); + return sets; + } + + bool CheckFlagsLegality(int flags) + { + ensureSetsInit(); + char buf[256]; + for (unsigned int i = 0; i < sets.size(); i++) + { + const TestFlag* set = sets.at(i); + memset(buf, 0, 256); + if (!set->verify(flags, buf)) { + return false; + } + } + return true; + } + + bool flagForName(const char* set_name, const char* ele_name, int& result) { + ensureSetsInit(); + for (unsigned int i = 0; i < sets.size(); i++) + { + const TestFlag* set = sets.at(i); + if (!compareStringsByIgnoreCase(set_name, set->naming())) { + continue; + } + return set->eleForName(ele_name, result); + } + fprintf(stderr, "Unrecognized flagset '%s'\n", set_name); + return false; + } + + } // namespace ext +} // namespace testing \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc new file mode 100644 index 0000000..416b88d --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#include +#include +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + + /* + * Function: compareStringsByIgnoreCase + * Description: Ignore case to compare two strings + * Input: one: first string + * two: second string + * Output: N/A + * Return: true(equal),flase(not equal) + * Others: N/A + */ + bool compareStringsByIgnoreCase(const char* one, const char* two) { + if (one == NULL && two == NULL) { + return true; + } + + if (one == NULL || two == NULL) { + return false; + } + + if (strcmp(one, two) == 0) { + return true; + } + + const int len_one = strlen(one); + const int len_two = strlen(two); + + if (len_one != len_two) { + return false; + } + + if (len_one == 0 && len_two == 0) { + return true; + } + + for (int i = 0; i < len_one; i++) { + if (tolower(one[i]) != tolower(two[i])) { + return false; + } + } + + return true; + } + + bool IsElementInVector(vector vec, int element){ + vector::iterator it = find(vec.begin(), vec.end(), element); + if (it != vec.end()) { + return true; + } + return false; + } + + vector SplitString(const string& str, const string& delim) { + vector result; + if (str != "") { + int len = str.length(); + char *src = new char[len + 1]; + memset(src, 0, len + 1); + strcpy(src, str.c_str()); + src[len] = '\0'; + + char *tokenptr = strtok(src, delim.c_str()); + while (tokenptr != NULL) + { + string tk = tokenptr; + result.emplace_back(tk); + tokenptr = strtok(NULL, delim.c_str()); + } + delete[] src; + } + + return result; + } + +} // namespace testing diff --git a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h index c28b6e9..c154b5e 100755 --- a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h +++ b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,57 +16,195 @@ #ifndef OHOS_IPC_MESSAGE_PARCEL_H #define OHOS_IPC_MESSAGE_PARCEL_H -#include -#include +#include #include "parcel.h" #include "refbase.h" -#include +#include namespace OHOS { -class IRemoteObject; -class MessageParcel : public Parcel { -public: - MessageParcel(); - ~MessageParcel(); - explicit MessageParcel(Allocator *allocator); - bool WriteRemoteObject(const sptr &object); - sptr ReadRemoteObject(); - bool WriteFileDescriptor(int fd); - int ReadFileDescriptor(); - bool ContainFileDescriptors() const; - bool WriteInterfaceToken(std::u16string name); - std::u16string ReadInterfaceToken(); - bool WriteRawData(const void *data, size_t size); - const void *ReadRawData(size_t size); - bool RestoreRawData(std::shared_ptr rawData, size_t size); - const void *GetRawData() const; - size_t GetRawDataSize() const; - size_t GetRawDataCapacity() const; - void WriteNoException(); - int32_t ReadException(); - bool WriteAshmem(sptr ashmem); - sptr ReadAshmem(); - void ClearFileDescriptor(); - bool Append(MessageParcel &parcel) { return false; }; - void SetClearFdFlag() - { - needCloseFd_ = true; - }; + class IRemoteObject; + class MessageParcel : public Parcel { + public: + MessageParcel(); + ~MessageParcel(); + explicit MessageParcel(Allocator *allocator); + + /** + * @brief Serializes the remote object and writes it. + * @param object Indicates the remote object to serialize. + * @return Returns true if it is successful; returns false otherwise. + * @since 9 + */ + bool WriteRemoteObject(const sptr &object); + + /** + * @brief Reads a remote object. + * @return Returns the IRemoteObject pointer object. + * @since 9 + */ + sptr ReadRemoteObject(); + + /** + * @brief Writes an file descriptor into the object. + * @param fd Indicates file descriptor to write. + * @return Returns true if the write succeeds; return false otherwise. + * @since 9 + */ + bool WriteFileDescriptor(int fd); + + /** + * @brief Reads an file descriptor from the object. + * @return Returns the corresponding descriptor If the read is successful; returns {@code -1} otherwise. + * @since 9 + */ + int ReadFileDescriptor(); + + /** + * @brief Check whether the file descriptor is included. + * @return Returns true if checking for inclusion; returns false Otherwise. + * @since 9 + */ + bool ContainFileDescriptors() const; + + /** + * @brief Writes an interface token into the object. + * @param name Indicates the string type name. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteInterfaceToken(std::u16string name); + + /** + * @brief Reads an interface token from the object. + * @return Returns a string value. + * @since 9 + */ + std::u16string ReadInterfaceToken(); + + /** + * @brief Writes raw data to the object. + * @param data Indicates the original data written. + * @param size Indicates the size of the raw data sent. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteRawData(const void *data, size_t size); + + /** + * @brief Reads raw data from the object. + * @param size Indicates the size of the raw data to read. + * @return void + * @since 9 + */ + const void *ReadRawData(size_t size); -private: + /** + * @brief Restore raw data. + * @param rawData Indicates the original data to be recovered. + * @param size Indicates the size of the raw data to read. + * @return Returns true if recovery is successful; returns false Otherwise. + * @since 9 + */ + bool RestoreRawData(std::shared_ptr rawData, size_t size); + + /** + * @brief Obtains raw data from the object. + * @return void + * @since 9 + */ + const void *GetRawData() const; + + /** + * @brief Gets the raw data size. + * @return Returns the resulting raw data size. + * @since 9 + */ + size_t GetRawDataSize() const; + + /** + * @brief Get raw data capacity. + * @return Returns the maximum value of the raw data capacity. + * @since 9 + */ + size_t GetRawDataCapacity() const; + + /** + * @brief writes information to the object indicating that no exception occurred. + * @return void + * @since 9 + */ + void WriteNoException(); + + /** + * @brief Reads the exception information from the object. + * @return Returns the read error code. + * @since 9 + */ + int32_t ReadException(); + + /** + * @brief Writes an anonymous shared memory object to the object. + * @param ashmem Indicates anonymous shared memory object to wrote. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteAshmem(sptr ashmem); + + /** + * @brief Reads the anonymous shared memory object from the object. + * @return Returns anonymous share object obtained. + * @since 9 + */ + sptr ReadAshmem(); + + /** + * @brief Clear the file descriptor. + * @return void + * @since 9 + */ + void ClearFileDescriptor(); + + /** + * @brief Sets the Clear specified file descriptor flag. + * @return void + * @since 9 + */ + void SetClearFdFlag() + { + needCloseFd_ = true; + }; + + /** + * @brief Append a MessageParcel object to the end of the current MessageParcel. + * @param data Indicates the data to append. + * @return Returns true if append succeeds; returns false Otherwise. + * @since 9 + */ + bool Append(MessageParcel &data); + + private: #ifndef CONFIG_IPC_SINGLE - bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); + + /** + * @brief Write to the DBinder proxy object. + * @param object Indicates an IRemoteObject type object. + * @param handle Indicates the handle to write. + * @param stubIndex Indicates the stub index to write to. + * @return Returns true if the write succeeds; returns false otherwise. + * @since + */ + bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); #endif - static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M - static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k - bool needCloseFd_ = false; - std::vector> holders_; - int writeRawDataFd_; - int readRawDataFd_; - void *kernelMappedWrite_; - void *kernelMappedRead_; - std::shared_ptr rawData_; - size_t rawDataSize_; -}; + static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M + static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k + bool needCloseFd_ = false; + std::vector> holders_; + int writeRawDataFd_; + int readRawDataFd_; + void *kernelMappedWrite_; + void *kernelMappedRead_; + std::shared_ptr rawData_; + size_t rawDataSize_; + }; } // namespace OHOS #endif // OHOS_IPC_MESSAGE_PARCEL_H diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp index e6a879e..b226d2c 100644 --- a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp @@ -1,10 +1,10 @@ /* - * Copyright (C) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -15,126 +15,529 @@ #include "message_parcel.h" +#include +#include +#include +#include + +#include "ashmem.h" +#include "hilog/log_c.h" +#include "hilog/log_cpp.h" +#include "ipc_file_descriptor.h" +#include "ipc_process_skeleton.h" +#include "iremote_invoker.h" #include "iremote_object.h" +#include "log_tags.h" +#include "memory" +#include "new" +#include "parcel.h" +#include "refbase.h" +#include "securec.h" +#include "string" +#include "sys_binder.h" +#include "vector" +#include "ipc_debug.h" + +#ifndef CONFIG_IPC_SINGLE +#include "dbinder_callback_stub.h" +#include "dbinder_session_object.h" +#endif namespace OHOS { -MessageParcel::MessageParcel() - : Parcel(), - writeRawDataFd_(-1), - readRawDataFd_(-1), - kernelMappedWrite_(nullptr), - kernelMappedRead_(nullptr), - rawData_(nullptr), - rawDataSize_(0) -{} - -MessageParcel::MessageParcel(Allocator *allocator) - : Parcel(allocator), - writeRawDataFd_(-1), - readRawDataFd_(-1), - kernelMappedWrite_(nullptr), - kernelMappedRead_(nullptr), - rawData_(nullptr), - rawDataSize_(0) -{} - -MessageParcel::~MessageParcel() -{ -} +#ifdef CONFIG_IPC_SINGLE + using namespace IPC_SINGLE; +#endif + static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "MessageParcel" }; + + void AcquireObject(flat_binder_object *flat, const void *cookie) + { + switch (flat->hdr.type) { + case BINDER_TYPE_BINDER: + if (flat->binder) { + reinterpret_cast(flat->cookie)->IncStrongRef(cookie); + } + break; + case BINDER_TYPE_HANDLE: { + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + IRemoteObject *remoteObject = nullptr; + if (current != nullptr) { + remoteObject = current->QueryObject(current->MakeHandleDescriptor(flat->handle)); + } + if (remoteObject != nullptr) { + remoteObject->IncStrongRef(cookie); + } + break; + } + case BINDER_TYPE_FD: + flat->handle = static_cast(dup(flat->handle)); + flat->cookie = 1; + break; + default: + ZLOGE(LOG_LABEL, "binder object type is invalid."); + break; + } + } + + MessageParcel::MessageParcel() + : Parcel(), + writeRawDataFd_(-1), + readRawDataFd_(-1), + kernelMappedWrite_(nullptr), + kernelMappedRead_(nullptr), + rawData_(nullptr), + rawDataSize_(0) + {} + + MessageParcel::MessageParcel(Allocator *allocator) + : Parcel(allocator), + writeRawDataFd_(-1), + readRawDataFd_(-1), + kernelMappedWrite_(nullptr), + kernelMappedRead_(nullptr), + rawData_(nullptr), + rawDataSize_(0) + {} + + MessageParcel::~MessageParcel() + { + if (kernelMappedWrite_ != nullptr) { + ::munmap(kernelMappedWrite_, rawDataSize_); + kernelMappedWrite_ = nullptr; + } + if (kernelMappedRead_ != nullptr) { + ::munmap(kernelMappedRead_, rawDataSize_); + kernelMappedRead_ = nullptr; + } + + if (readRawDataFd_ > 0) { + ::close(readRawDataFd_); + readRawDataFd_ = -1; + } + if (writeRawDataFd_ > 0) { + ::close(writeRawDataFd_); + writeRawDataFd_ = -1; + } + + ClearFileDescriptor(); + rawData_ = nullptr; + rawDataSize_ = 0; + } + +#ifndef CONFIG_IPC_SINGLE + bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) + { + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + if (current == nullptr) { + ZLOGE(LOG_LABEL, "current is nullptr"); + return false; + } + std::shared_ptr sessionOfPeer = current->ProxyQueryDBinderSession(handle); + if (sessionOfPeer == nullptr) { + ZLOGE(LOG_LABEL, "sessionOfPeer is null, handle: %{public}u, stubIndex: %{public}" PRIu64, handle, stubIndex); + return false; + } + std::string peerName = sessionOfPeer->GetServiceName(); + std::string peerId = sessionOfPeer->GetDeviceId(); + std::string localId = current->GetLocalDeviceID(); + uint32_t tokenId = sessionOfPeer->GetTokenId(); + + sptr fakeStub = current->QueryDBinderCallbackStub(object); + if (fakeStub == nullptr) { + // note that cannot use this proxy's descriptor, this stub is now stored and strong refered + // and need to be erased in an approprite time + fakeStub = new (std::nothrow) DBinderCallbackStub(peerName, peerId, localId, sessionOfPeer->GetStubIndex(), + handle, tokenId); + if (fakeStub == nullptr) { + ZLOGE(LOG_LABEL, "create DBinderCallbackStub object failed"); + return false; + } + if (!current->AttachDBinderCallbackStub(object, fakeStub)) { + ZLOGE(LOG_LABEL, "save callback of fake stub failed"); + return false; + } + } + return WriteRemoteObject(fakeStub); + } +#endif + + bool MessageParcel::WriteRemoteObject(const sptr &object) + { + if (object == nullptr) { + return false; + } + // Increase object's refcount temporarily in case of premature deallocation, + // object's refcount will be decreased when this MessageParcel destroyed. + holders_.push_back(object); #ifndef CONFIG_IPC_SINGLE -bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) -{ - (void)object; - (void)handle; - (void)stubIndex; - return false; -} + if (object->IsProxyObject()) { + const IPCObjectProxy *proxy = reinterpret_cast(object.GetRefPtr()); + const uint32_t handle = proxy ? proxy->GetHandle() : 0; + if (IPCProcessSkeleton::IsHandleMadeByUser(handle)) { + /* this is a fake proxy which handle get by MakeRemoteHandle(), Not binder driver of kernel */ + ZLOGI(LOG_LABEL, "send a dbinder proxy to another process in this device"); + return WriteDBinderProxy(object, handle, 0); + } + } #endif + auto result = WriteObject(object); + if (result == false) { + return result; + } + return result; + } + + sptr MessageParcel::ReadRemoteObject() + { + sptr temp = ReadObject(); +#ifndef CONFIG_IPC_SINGLE + if (temp != nullptr && !temp->IsProxyObject()) { + // if this stub is a DBinderCallbackStub, return corresponding proxy + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + if (current != nullptr) { + sptr proxy = current->QueryDBinderCallbackProxy(temp); + if (proxy != nullptr) { + temp = proxy; + } + } + } +#endif + return temp; + } + + bool MessageParcel::WriteFileDescriptor(int fd) + { + if (fd < 0) { + return false; + } + int dupFd = dup(fd); + if (dupFd < 0) { + return false; + } + sptr descriptor = new (std::nothrow) IPCFileDescriptor(dupFd); + if (descriptor == nullptr) { + ZLOGE(LOG_LABEL, "create IPCFileDescriptor object failed"); + return false; + } + return WriteObject(descriptor); + } + + int MessageParcel::ReadFileDescriptor() + { + sptr descriptor = ReadObject(); + if (descriptor == nullptr) { + return -1; + } + int fd = descriptor->GetFd(); + if (fd < 0) { + return -1; + } + return dup(fd); + } + + void MessageParcel::ClearFileDescriptor() + { + size_t dataOffset = 0; + binder_size_t *object = nullptr; + const flat_binder_object *flat = nullptr; + for (size_t i = 0; i < GetOffsetsSize(); i++) { + object = reinterpret_cast(GetObjectOffsets()); + if (object == nullptr) { + ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); + break; + } + // offset + size + dataOffset = object[i] + sizeof(flat_binder_object); + if (dataOffset > GetDataSize()) { + ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", + dataOffset, GetDataSize()); + break; + } + uintptr_t data = GetData(); + if (data == 0) { + ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); + break; + } + flat = reinterpret_cast(data + object[i]); + if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) { + ::close(flat->handle); + } + } + } + + bool MessageParcel::ContainFileDescriptors() const + { + size_t dataOffset = 0; + binder_size_t *object = nullptr; + const flat_binder_object *flat = nullptr; + for (size_t i = 0; i < GetOffsetsSize(); i++) { + object = reinterpret_cast(GetObjectOffsets()); + if (object == nullptr) { + ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); + break; + } + // offset + size + dataOffset = object[i] + sizeof(flat_binder_object); + if (dataOffset > GetDataSize()) { + ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", + dataOffset, GetDataSize()); + break; + } + uintptr_t data = GetData(); + if (data == 0) { + ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); + break; + } + flat = reinterpret_cast(data + object[i]); + if (flat->hdr.type == BINDER_TYPE_FD) { + return true; + } + } + + return false; + } + + bool MessageParcel::WriteInterfaceToken(std::u16string name) + { + constexpr int strictModePolicy = 0x100; + constexpr int workSource = 0; + size_t rewindPos = GetWritePosition(); + if (!WriteInt32(strictModePolicy)) { + return false; + } + + if (!WriteInt32(workSource)) { + if (!RewindWrite(rewindPos)) { + FlushBuffer(); + } + return false; + } + + return WriteString16(name); + } + + std::u16string MessageParcel::ReadInterfaceToken() + { + [[maybe_unused]] int32_t strictModePolicy = ReadInt32(); + [[maybe_unused]] int32_t workSource = ReadInt32(); + return ReadString16(); + } + + bool MessageParcel::WriteRawData(const void *data, size_t size) + { + if (data == nullptr || size > MAX_RAWDATA_SIZE || size == 0) { + ZLOGE(LOG_LABEL, "data is null or size:%{public}zu not ok", size); + return false; + } + if (kernelMappedWrite_ != nullptr) { + return false; + } + if (!WriteInt32(size)) { + return false; + } + if (size <= MIN_RAWDATA_SIZE) { + rawDataSize_ = size; + return WriteUnpadBuffer(data, size); + } + int fd = AshmemCreate("Parcel RawData", size); + if (fd < 0) { + return false; + } + writeRawDataFd_ = fd; + + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + if (result < 0) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return false; + } + void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return false; + } + if (!WriteFileDescriptor(fd)) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ::munmap(ptr, size); + return false; + } + if (memcpy_s(ptr, size, data, size) != EOK) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ::munmap(ptr, size); + return false; + } + kernelMappedWrite_ = ptr; + rawDataSize_ = size; + return true; + } + + bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) + { + if (rawData_ != nullptr || rawData == nullptr) { + return false; + } + rawData_ = rawData; + rawDataSize_ = size; + writeRawDataFd_ = 0; + return true; + } + + const void *MessageParcel::ReadRawData(size_t size) + { + if (size == 0) { + ZLOGE(LOG_LABEL, "the parameter size is 0"); + return nullptr; + } + size_t bufferSize = static_cast(ReadInt32()); + if (bufferSize != size) { + ZLOGE(LOG_LABEL, "ReadRawData: the buffersize %{public}zu not equal the parameter size %{public}zu", + bufferSize, size); + return nullptr; + } + if (bufferSize <= MIN_RAWDATA_SIZE) { + rawDataSize_ = size; + return ReadUnpadBuffer(size); + } + + /* if rawDataFd_ == 0 means rawData is received from remote */ + if (rawData_ != nullptr && writeRawDataFd_ == 0) { + /* should read fd for move readCursor of parcel */ + if (ReadFileDescriptor()) { + // do nothing + } + if (rawDataSize_ != size) { + ZLOGE(LOG_LABEL, "rawData is received from remote, the rawDataSize_ %{public}zu" + " not equal size %{public}zu", rawDataSize_, size); + return nullptr; + } + return rawData_.get(); + } + int fd = ReadFileDescriptor(); + if (fd < 0) { + return nullptr; + } + readRawDataFd_ = fd; + + int ashmemSize = AshmemGetSize(fd); + if (ashmemSize < 0 || size_t(ashmemSize) < size) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ZLOGE(LOG_LABEL, "ashmemSize %{public}d less than size %{public}zu", + ashmemSize, size); + return nullptr; + } + void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return nullptr; + } + kernelMappedRead_ = ptr; + rawDataSize_ = size; + return ptr; + } + + const void *MessageParcel::GetRawData() const + { + if (rawData_ != nullptr) { + return rawData_.get(); + } + if (kernelMappedWrite_ != nullptr) { + return kernelMappedWrite_; + } + if (kernelMappedRead_ != nullptr) { + return kernelMappedRead_; + } + return nullptr; + } + + size_t MessageParcel::GetRawDataSize() const + { + return rawDataSize_; + } + + size_t MessageParcel::GetRawDataCapacity() const + { + return MAX_RAWDATA_SIZE; + } + + void MessageParcel::WriteNoException() + { + WriteInt32(0); + } + + int32_t MessageParcel::ReadException() + { + int32_t errorCode = ReadInt32(); + if (errorCode != 0) { + ReadString16(); + } + return errorCode; + } + + bool MessageParcel::WriteAshmem(sptr ashmem) + { + int fd = ashmem->GetAshmemFd(); + int32_t size = ashmem->GetAshmemSize(); + if (fd < 0 || size <= 0) { + return false; + } + if (!WriteFileDescriptor(fd) || !WriteInt32(size)) { + return false; + } + return true; + } + + sptr MessageParcel::ReadAshmem() + { + int fd = ReadFileDescriptor(); + if (fd < 0) { + return nullptr; + } + + int32_t size = ReadInt32(); + if (size <= 0) { + ::close(fd); + return nullptr; + } + return new (std::nothrow) Ashmem(fd, size); + } -bool MessageParcel::WriteRemoteObject(const sptr &object) -{ - (void)object; - return false; -} - -sptr MessageParcel::ReadRemoteObject() -{ - return nullptr; -} - -bool MessageParcel::WriteFileDescriptor(int fd) -{ - return false; -} - -int MessageParcel::ReadFileDescriptor() -{ - return -1; -} - -void MessageParcel::ClearFileDescriptor() -{ -} - -bool MessageParcel::ContainFileDescriptors() const -{ - return false; -} - -bool MessageParcel::WriteInterfaceToken(std::u16string name) -{ - (void)name; - return false; -} - -std::u16string MessageParcel::ReadInterfaceToken() -{ - return u""; -} - -bool MessageParcel::WriteRawData(const void *data, size_t size) -{ - (void)data; - (void)size; - return false; -} - -bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) -{ - (void)rawData; - (void)size; - return false; -} - -const void *MessageParcel::ReadRawData(size_t size) -{ - (void)size; - return nullptr; -} - -const void *MessageParcel::GetRawData() const -{ - return nullptr; -} - -size_t MessageParcel::GetRawDataSize() const -{ - return -1; -} - -size_t MessageParcel::GetRawDataCapacity() const -{ - return -1; -} - -void MessageParcel::WriteNoException() -{ -} - -int32_t MessageParcel::ReadException() -{ - return -1; -} + bool MessageParcel::Append(MessageParcel &data) + { + size_t dataSize = data.GetDataSize(); + if (dataSize == 0) { + ZLOGE(LOG_LABEL, "no data to append"); + return true; + } + uintptr_t dataPtr = data.GetData(); + size_t writeCursorOld = this->GetWritePosition(); + if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { + ZLOGE(LOG_LABEL, "failed to append data with writebuffer."); + return false; + } + size_t objectSize = data.GetOffsetsSize(); + if (objectSize == 0) { + return true; + } + binder_size_t objectOffsets = data.GetObjectOffsets(); + auto *newObjectOffsets = reinterpret_cast(objectOffsets); + for (size_t index = 0; index < objectSize; index++) { + if (EnsureObjectsCapacity()) { + size_t offset = writeCursorOld + newObjectOffsets[index]; + if (!WriteObjectOffset(offset)) { + ZLOGE(LOG_LABEL, "failed to write object offset"); + return false; + } + flat_binder_object *flat = reinterpret_cast(this->GetData() + offset); + if (flat == nullptr) { + ZLOGE(LOG_LABEL, "flat binder object is nullptr"); + return false; + } + AcquireObject(flat, this); + } else { + ZLOGE(LOG_LABEL, "Failed to ensure parcel capacity"); + return false; + } + } + return true; + } } // namespace OHOS diff --git a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp index ca21d77..81b71fe 100644 --- a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp +++ b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp @@ -26,6 +26,7 @@ #else #include "inner_api/osal/utils/util.h" #endif +#include namespace OHOS { namespace Media { @@ -43,10 +44,30 @@ namespace Media { return GetDataFromSource(mem, length); } + char *realpath(const char *__restrict name, char *__restrict resolved) + { + return _fullpath(resolved, name, PATH_MAX); + } + + bool ConvertFullPath(const std::string& partialPath, std::string& fullPath) + { + if (partialPath.empty() || partialPath.length() >= PATH_MAX) { + return false; + } + char tmpPath[PATH_MAX] = {0}; + if (realpath(partialPath.c_str(), tmpPath) == nullptr) { + return false; + } + if (access(tmpPath, F_OK) || access(tmpPath, R_OK)) { + return false; + } + fullPath = tmpPath; + return true; + } int IMediaDataSourceImpl::ReadDataFromFile() { std::string dataFullPath; - if (OHOS::Media::OSAL::ConvertFullPath(url_, dataFullPath) && !dataFullPath.empty()) { + if (ConvertFullPath(url_, dataFullPath) && !dataFullPath.empty()) { url_ = dataFullPath; } std::fstream fs(url_); diff --git a/3rdparty/ohos/utils/native/base/include/parcel.h b/3rdparty/ohos/utils/native/base/include/parcel.h index 774f4ad..08453bb 100755 --- a/3rdparty/ohos/utils/native/base/include/parcel.h +++ b/3rdparty/ohos/utils/native/base/include/parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,9 +16,10 @@ /** * @file parcel.h * - * @brief Provide classes for data container implemented in c_utils. + * @brief Provides classes for the data container implemented in c_utils. * - * Including class Parcel, Parcelable and related memory Allocator. + * The Parcel and Parcelable classes and the related memory + * allocator are provided. */ #ifndef OHOS_UTILS_PARCEL_H @@ -35,10 +36,10 @@ namespace OHOS { class Parcel; /** - * @brief Interface for class whose Instance can be written into a Parcel. + * @brief Defines a class for which the instance can be written into a parcel. * - * @note If this object is remote, its position intends to - * use in kernel data transaction. + * @note If this object is remote, its position will be used in + * kernel data transaction. */ class Parcelable : public virtual RefBase { public: @@ -46,39 +47,41 @@ public: Parcelable(); /** - * @brief Construct a new Parcelable object. + * @brief Creates a `Parcelable` object. * - * @param asRemote Specifies whether this object is remote. + * @param asRemote Specifies whether the object is remote. */ explicit Parcelable(bool asRemote); /** - * @brief Write a parcelable object to the given parcel. + * @brief Writes a `Parcelable` object into a parcel. * - * @param parcel Target parcel to write to. - * @return Return true being written on success or false if any error occur. - * @note If this object is remote, its position will be saved in the parcel. - * @note A static Unmarshalling function must also be implemented, so that - * you can get data from the given parcel into this parcelable object. + * @param parcel Indicates the parcel. + * @return Returns `true` if the operation is successful; returns `false` + * otherwise. + * @note If the `Parcelable` object is remote, its position will be saved + * in the parcel. + * @note You must implement a static Unmarshalling function to + * fetch data from the given parcel into this `Parcelable` object. * See `static TestParcelable *Unmarshalling(Parcel &parcel)` as an example. */ virtual bool Marshalling(Parcel &parcel) const = 0; /** - * @brief Enum flag to describe behaviors of the Parcelable object. + * @brief Enumerates the behavior types of a `Parcelable` object. * - * @var IPC Indicate the object can be used in IPC. - * @var RPC Indicate the object can be used in RPC. - * @var HOLD_OBJECT Indicate the object will ensure - * alive during data transaction. + * @var IPC Indicate an object that can be used in IPC. + * @var RPC Indicate an object that can be used in RPC. + * @var HOLD_OBJECT Indicate an object that will be always alive + * during data transaction. * */ enum BehaviorFlag { IPC = 0x01, RPC = 0x02, HOLD_OBJECT = 0x10 }; /** - * @brief Enable specified behavior. + * @brief Enables the specified behavior. * - * @param b Specific flag value. + * @param b Indicates the behavior. * @see BehaviorFlag. */ inline void SetBehavior(BehaviorFlag b) const @@ -87,9 +90,10 @@ public: } /** - * @brief Disable specified behavior. + * @brief Disables the specified behavior. * - * @param b Specific flag value. See BehaviorFlag. + * @param b Indicates the behavior. + * @see BehaviorFlag. */ inline void ClearBehavior(BehaviorFlag b) const { @@ -97,9 +101,12 @@ public: } /** - * @brief Check whether specified behavior is enabled. + * @brief Checks whether the specified behavior is enabled. * - * @param b Specific flag value. + * @param b Indicates the behavior. + + * @return Returns `true` if the behavior is enabled; returns `false` + * otherwise. * @see BehaviorFlag. */ inline bool TestBehavior(BehaviorFlag b) const @@ -108,12 +115,12 @@ public: } public: - bool asRemote_; // if the object is remote - mutable uint8_t behavior_; // value of flag of behaviors + bool asRemote_; // If the object is remote. + mutable uint8_t behavior_; // Behavior of the object. }; /** - * @brief Interface for memory allocator of the data in Parcel. + * @brief Defines a memory allocator for data in `Parcel`. */ class Allocator { public: @@ -127,144 +134,150 @@ public: }; /** - * @brief Default implement of Allocator. + * @brief Provides the default implementation for a memory allocator. * - * @note Allocator defined by user for a parcel need be specified manually. + * @note A non-default allocator for a parcel must be specified manually. */ class DefaultAllocator : public Allocator { public: /** - * @brief Use `malloc()` to allocate memory for a parcel. + * @brief Allocates memory for this parcel. * - * @param size Size of desired memory region. - * @return Void-type pointer to the memory region. + * @param size Indicates the size of the memory to allocate. + * @return Returns the void pointer to the memory region. */ void *Alloc(size_t size) override; /** - * @brief Use `free()` to deallocate memory for a parcel. + * @brief Deallocates memory for this parcel. * - * @param data Void-type pointer to the memory region. + * @param data Indicates the void pointer to the memory region. */ void Dealloc(void *data) override; private: /** - * @brief Use `realloc()` to reallocate memory for a parcel. + * @brief Reallocates memory for this parcel. * - * @param data Void-type pointer to the existed memory region. - * @param newSize New desired size of memory region. - * @return Void-type pointer to the new memory region. + * @param data Indicates the void pointer to the existing memory region. + * @param newSize Indicates the size of the memory to reallocate. + * @return Returns the void pointer to the new memory region. */ void *Realloc(void *data, size_t newSize) override; }; /** - * @brief A data/message container. + * @brief Provides a data/message container. * - * Contains interfaces for writing and reading data of various types, - * including primitives, Parcelable objects etc. + * This class provides methods for writing and reading data of various types, + * including primitives and parcelable objects. * - * @note Usually used in IPC, RPC. + * @note This class is usually used in IPC and RPC scenarios. */ class Parcel { public: Parcel(); /** - * @brief Construct a new Parcel object with specified Allocator. + * @brief Creates a `Parcel` object with the specified memory allocator. * - * @param allocator Specified Allocator. + * @param allocator Indicates the memory allocator. */ explicit Parcel(Allocator *allocator); virtual ~Parcel(); /** - * @brief Get total size of existed data in this parcel. + * @brief Obtains the total size of existing data in this parcel. * - * @return Value of the size in bytes. + * @return Returns the size, in bytes. */ size_t GetDataSize() const; /** - * @brief Get the pointer to the beginning of data in this parcel. + * @brief Obtains the pointer to the beginning of data in this parcel. * - * @return `uintptr_t`-type pointer. + * @return Returns a pointer of the `uintptr_t` type. */ uintptr_t GetData() const; /** - * @brief Get position of every object written in this parcel. + * @brief Obtains the position (offset) of every object written + * in this parcel. * - * @return `binder_size_t`-type pointer to + * @return Returns a pointer of the `binder_size_t` type to * the first slot of the position array. * @see flat_obj.h */ binder_size_t GetObjectOffsets() const; /** - * @brief Get total size of all of the current positions. + * @brief Obtains the size of the position array. * - * @return Value of the size in bytes. + * @return Returns the size, in bytes. */ size_t GetOffsetsSize() const; /** - * @brief Get total availiable bytes to write to this parcel. + * @brief Obtains the total number of available bytes to write + * into this parcel. * - * @return Amount of the availiable bytes. + * @return Returns the number of available bytes. */ size_t GetWritableBytes() const; /** - * @brief Get total availiable bytes to read from this parcel. + * @brief Obtains the total number of available bytes to read + * from this parcel. * - * @return Amount of the availiable bytes. + * @return Returns the number of available bytes. */ size_t GetReadableBytes() const; /** - * @brief Get total capacity of this parcel, - * i.e. size of current data region in parcel. + * @brief Obtains the total capacity of this parcel, that is, the size of + * the current data region in the parcel. * - * @return Value of the capacity in bytes. + * @return Returns the capacity, in bytes. */ size_t GetDataCapacity() const; /** - * @brief Get maximum capacity of this parcel. + * @brief Obtains the maximum capacity of this parcel. * - * @return Value of the capacity in bytes. + * @return Returns the capacity, in bytes. */ size_t GetMaxCapacity() const; /** - * @brief Set capacity of this parcel, - * i.e. size of current data region in parcel. + * @brief Sets the capacity for this parcel, that is, the size of the + * current data region in the parcel. * - * @param newCapacity Desired new capacity. - * @return Return True on success, or false if any error occur. - * @note Corresponding Allocator will try to reallocate - * the data region with new capacity. + * @param newCapacity Indicates the capacity to set. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note The memory allocator will try to reallocate the data region + * with the new capacity. * */ bool SetDataCapacity(size_t newCapacity); /** - * @brief Set total size of existed data in this parcel. + * @brief Sets the total size of existing data in this parcel. * - * @param dataSize Desired value of size in bytes. - * @return Return True on success, or false if any error occur. - * @note Avoid using it independently, otherwise it may not - * represents the correct size of existed data. + * @param dataSize Indicates the size, in bytes. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note Do not call this function independently; otherwise, it may fail to + * return the correct data size. */ bool SetDataSize(size_t dataSize); /** - * @brief Set maximux capacity of this parcel. + * @brief Sets the maximum capacity for this parcel. * - * @param maxCapacity Desired value of maximum capacity. - * @return Return True on success, or false if any error occur. + * @param maxCapacity Indicates the maximum capacity to set. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool SetMaxCapacity(size_t maxCapacity); @@ -283,150 +296,166 @@ public: bool WritePointer(uintptr_t value); /** - * @brief Write a data region(buffer) to this parcel. + * @brief Writes a data region (buffer) to this parcel. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteBuffer(const void *data, size_t size); /** - * @brief Write a data region(buffer) to this parcel - * in alignment and with terminator replaced. + * @brief Writes a data region (buffer) to this parcel in alignment + * and with the terminator replaced. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @param typeSize Size of the terminator. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @param typeSize Indicates the size of the terminator. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. * @note The last several bytes specified by `typeSize` of the aligned data - * will be deemed as a terminator, and then will be replaced by - * '0b00000000'. + * will be treated as a terminator and replaced by '0b00000000'. */ bool WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize); /** - * @brief Write a data region(buffer) to this parcel without padding. + * @brief Writes a data region (buffer) to this parcel. + * + * Currently, this function provides the same capability as `WriteBuffer()`. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteUnpadBuffer(const void *data, size_t size); /** - * @brief Write a C-style string to this parcel. + * @brief Writes a C-style string to this parcel. * - * Default terminator `\0` of C-style string will also write. + * The default terminator `\0` of the C-style string will also be written. * - * @param value A C-style string, i.e. char-type pointer. - * @return Return True on success, or false if any error occur. + * @param value Indicates a pointer of the char type to a C-style string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteCString(const char *value); /** - * @brief Write a C++ string(`std::u16string`) to this parcel. + * @brief Writes a C++ string (`std::string`) to this parcel. * - * The exact length of the string will write first, then the string itself - * with an appended terminator `\0` will write. + * The exact length of the string will be written first, and then the string + * itself with the appended terminator `\0` will be written. * - * @param value An `std::string` object passed by reference. - * @return Return True on success, or false if any error occur. + * @param value Indicates the reference to an `std::string` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString(const std::string &value); /** - * @brief Write a C++ UTF-16 encoded string(`std::string`) to this parcel. + * @brief Writes a C++ UTF-16 encoded string (`std::u16string`) + * to this parcel. * - * The exact length of the string will write first, then the string itself - * with an appended terminator `\0` will write. + * The exact length of the string will be written first, and then the string + * itself with the appended terminator `\0` will be written. * - * @param value An `std::u16string` object passed by reference. - * @return Return True on success, or false if any error occur. + * @param value Indicates the reference to an `std::u16string` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString16(const std::u16string &value); /** - * @brief Write a UTF-16 encoded string - * with specified length to this parcel. + * @brief Writes a UTF-16 encoded string with the specified length + * to this parcel. * - * An `std::u16string` object will be constructed by input `char16_t*` + * An `std::u16string` object will be constructed based on the `char16_t*` * pointer and the length `len` first. Then the input length and the string - * data in `u16string` object with an appended terminator `\0` will write. + * data in the `u16string` object with the appended terminator `\0` will + * be written. * - * @param value Pointer to the UTF-16 encoded string. - * @param len Exact length of the input string. - * @return Return True on success, or false if any error occur. + * @param value Indicates the pointer to a UTF-16 encoded string. + * @param len Indicates the exact length of the input string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString16WithLength(const char16_t *value, size_t len); /** - * @brief Write a UTF-8 encoded string - * with specified length to this parcel. + * @brief Writes a UTF-8 encoded string with the specified length + * to this parcel. * - * The input length `len` and the string data - * with an appended terminator `\0` will write. + * The input length `len` and the string itself + * with the appended terminator `\0` will be written. * - * @param value Pointer to the UTF-8 encoded string. - * @param len Exact length of the input string. - * @return Return True on success, or false if any error occur. + * @param value Indicates the pointer to a UTF-8 encoded string. + * @param len Indicates the exact length of the input string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString8WithLength(const char *value, size_t len); /** - * @brief Write a Parcelable object to this parcel. + * @brief Writes a `Parcelable` object to this parcel. * - * Remote object will be written by `WriteRemoteObject(const Parcelable *)`. - * Non-remote object will be written by its own - * `Marshalling(Parcel &parcel)`. + * Call `WriteRemoteObject(const Parcelable *)` to write a remote object. + * Call `Marshalling(Parcel &parcel)` to write a non-remote object. * - * @param object Pointer to the input Parcelable object. - * @return Return True on success, or false if any error occur. - * @note '0' of `Int32_t` will write if input pointer is `nullptr`. + * @param object Indicates the pointer to a `Parcelable` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note The value '0' of `Int32_t` will be written if a null pointer + * is passed in. */ bool WriteParcelable(const Parcelable *object); /** - * @brief Write a Parcelable object to this parcel, - * and enable its behavior of `HOLD_OBJECT`. + * @brief Writes a `Parcelable` object to this parcel, and enables its + * behavior of `HOLD_OBJECT`. * - * @param object Smart pointer to the input parcelable object. - * @return Return True on success, or false if any error occur. + * @param object Indicates the smart pointer to a `Parcelable` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteStrongParcelable(const sptr &object); /** - * @brief Write a remote object to this parcel. + * @brief Writes a remote object to this parcel. * - * @param object Pointer to a remote object. - * @return Return True on success, or false if any error occur. - * @note If `HOLD_OBJECT` is enabled for the input object, it will stay + * @param object Indicates the pointer to a remote object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note If `HOLD_OBJECT` is enabled for the remote object, it will stay * alive as long as this parcel is alive. * */ bool WriteRemoteObject(const Parcelable *object); /** - * @brief Write an object to this parcel. + * @brief Writes an object to this parcel. * - * Use its own `Marshalling(Parcel &parcel)` when `nullptr` as input, - * otherwise use `WriteRemoteObject(const Parcelable *)`. + * Use its own `Marshalling(Parcel &parcel)` when a null pointer is passed + * in; in other scenarios, use `WriteRemoteObject(const Parcelable *)`. * - * @tparam T Specific class type of the input object. - * @param object Smart pointer to the input object. - * @return Return True on success, or false if any error occur. + * @tparam T Indicates the class type of the object. + * @param object Indicates the smart pointer to the object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool WriteObject(const sptr &object); /** - * @brief Parse input data by this parcel. + * @brief Parses input data by this parcel. * - * @param data Pointer to input data. - * @param size Size of input data(Bytes). - * @return Return True on success, or false if any error occur. - * @note Only read operation from this parcel is permitted after successful - * calling this method. + * @param data Indicates the pointer to input data. + * @param size Indicates the size of the input data, in bytes. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note Only the read operation from this parcel is allowed after + * successful calling of this method. */ bool ParseFrom(uintptr_t data, size_t size); @@ -477,200 +506,212 @@ public: bool ReadDouble(double &value); /** - * @brief Read a block of data(buffer data) from this parcel. + * @brief Reads a block of data (buffer data) from this parcel. * - * @param length Size of the buffer(Bytes). - * @return A `uint8_t` pointer to the buffer. + * @param length Indicates the size of the buffer, in bytes. + * @return Returns a pointer of the `uint8_t` type to the buffer. */ const uint8_t *ReadBuffer(size_t length); /** - * @brief Read a block of data(buffer data) without padding(alignment) from - * this parcel. + * @brief Reads a block of data (buffer data) without padding (alignment) + * from this parcel. * - * This method will read the effective data whose length specified by - * `length` and discard bytes for padding. + * This method will read the effective data with the specified + * `length` and discard the bytes used for padding. * - * @param length Effective size of the buffer(Bytes). - * @return A `uint8_t` pointer to the buffer. + * @param length Indicates the effective size of the buffer, in bytes. + * @return Returns a pointer of the `uint8_t` type to the buffer. * */ const uint8_t *ReadUnpadBuffer(size_t length); /** - * @brief Skip the next several bytes specifed by `bytes` in read process. + * @brief Skips the next several bytes specified by `bytes` in the read + * operation. * - * @param bytes Skipped number of bytes. + * @param bytes Indicates the number of bytes to skip. */ void SkipBytes(size_t bytes); /** - * @brief Read a C-style string from this parcel. + * @brief Reads a C-style string from this parcel. * - * @return A C-style string, which is represented by a `char`-type pointer. + * @return Returns a pointer of the `char` type to the C-style string. */ const char *ReadCString(); /** - * @brief Read a C++ string(`std::string`) object from this parcel. + * @brief Reads a C++ string (`std::string`) object from this parcel. * - * @return An `std::string` object. + * @return Returns a pointer of the `std::string` type to the C-style + * string. */ const std::string ReadString(); /** - * @brief Read a C++ string(`std::string`) object from this parcel to input - * object. + * @brief Reads a C++ string (`std::string`) object from this parcel to + * an object. * - * @param value Target receiver `std::string` object. - * @return Return True on success, or false if any error occur. + * @param value Indicates the `std::string` object to hold the data read. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool ReadString(std::string &value); /** - * @brief Read a C++ UTF-16 encoded string(`std::string`) object from this - * parcel. + * @brief Reads a C++ UTF-16 encoded string (`std::u16string`) object + * from this parcel. * - * @return An `std::u16string` object. + * @return Returns a pointer of the `std::u16string` type to the C-style + * string. */ const std::u16string ReadString16(); /** - * @brief Read a C++ UTF-16 string(`std::u16string`) object from this - * parcel to input object. + * @brief Reads a C++ UTF-16 string (`std::u16string`) object from this + * parcel to an object. * - * @param value Target receiver `std::string` object. - * @return Return True on success, or false if any error occur. + * @param value Indicates the `std::u16string` object to hold the data read. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool ReadString16(std::u16string &value); /** - * @brief Read a C++ UTF-16 string(`std::u16string`) object and its length + * @brief Reads a C++ UTF-16 string (`std::u16string`) object and its length * from this parcel. * - * @param len `int32_t`-type variable passed by reference to receive the - * length. - * @return An output `std::u16string` object. + * @param len Indicates the reference to a variable of the `int32_t` type + * to receive the length. + * @return Returns an `std::u16string` object. */ const std::u16string ReadString16WithLength(int32_t &len); /** - * @brief Read a C++ string(`std::string`) object and its length from this - * parcel. + * @brief Reads a C++ string (`std::string`) object and its length from + * this parcel. * - * @param len `int32_t`-type variable passed by reference to receive the - * length. - * @return An output `std::u8string` object. + * @param len Indicates the reference to a variable of the `int32_t` type + * to receive the length. + * @return Returns an `std::string` object. */ const std::string ReadString8WithLength(int32_t &len); /** - * @brief Set the read cursor to specified position. + * @brief Sets the read cursor to the specified position. * - * @param newPosition Specified position represented by offsets relative to - * the beginning of the data region. - * @return Return True on success, or false if any error occur. + * @param newPosition Indicates the position, represented by the offset + * (in bytes) from the beginning of the data region. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool RewindRead(size_t newPosition); /** - * @brief Set the write cursor to specified position. + * @brief Sets the write cursor to the specified position. * - * @param offsets Specified position represented by offsets(Bytes) relative - * to the beginning of the data region. - * @return Return True on success, or false if any error occur. + * @param offsets Indicates the position, represented by the offset + * (in bytes) from the beginning of the data region. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool RewindWrite(size_t offsets); /** - * @brief Get current position of read cursor. + * @brief Obtains the current position of the read cursor. * - * @return Position represented by offsets(Bytes) relative to the beginning - * of the data region. + * @return Returns the position, represented by the offset (in bytes) + * from the beginning of the data region. */ size_t GetReadPosition(); /** - * @brief Get current position of write cursor. + * @brief Obtains the current position of the write cursor. * - * @return Position represented by offsets(Bytes) relative to the beginning - * of the data region. + * @return Returns the position, represented by the offset (in bytes) + * from the beginning of the data region. */ size_t GetWritePosition(); /** - * @brief Read a Parcelable(and its subclass) object from this parcel. + * @brief Reads a `Parcelable` object and its child class objects + * from this parcel. * - * @tparam T Specific class type of the output object. - * @return Object of specific class. - * @note `nullptr` will return if a '0' is read. + * @tparam T Indicates the class type of the output object. + * @return Returns the object read. + * @note A null pointer will be returned if '0' is read. */ template T *ReadParcelable(); /** - * @brief Read a Parcelable object from this parcel, and manage it by a + * @brief Reads a `Parcelable` object from this parcel and manages it by a * smart pointer. * - * @tparam T Specific class type of the output object. - * @return Object managed by a smart pointer. - * @note `nullptr` will return if a '0' is read. + * @tparam T Indicates the class type of the output object. + * @return Returns the object managed by a smart pointer. + * @note A null pointer will be returned if '0' is read. */ template sptr ReadStrongParcelable(); /** - * @brief Check if it is valid to read an object from current cursor. + * @brief Checks whether it is valid to read an object from the current + * cursor. * - * @return Return true if valid, otherwise return false. + * @return Returns `true` if valid; returns `false` otherwise. */ bool CheckOffsets(); /** - * @brief Read an object from this parcel. + * @brief Reads an object from this parcel. * - * `CheckOffsets()` will call first to check whether it is valid to read an + * Call `CheckOffsets()` first to check whether it is valid to read an * object. * - * @tparam T Specific class type of the output object. - * @return A smart pointer to the object. - * @note `nullptr` will return if `CheckOffsets()` fail. + * @tparam T Indicates the class type of the output object. + * @return Returns the smart pointer to the object. + * @note A null pointer will be returned if `CheckOffsets()` fails + * to be called. */ template sptr ReadObject(); /** - * @brief Set the Allocator object of this parcel. + * @brief Sets a memory allocator for this parcel. * - * New Allocator will reallocate the data region to which has been written. + * The new allocator will reallocate the data region that has been written. * - * @param allocator Specified Allocator object. - * @return Return True on success, or false if any error occur. + * @param allocator Indicates the pointer to an `Allocator` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool SetAllocator(Allocator *allocator); /** - * @brief Record an array of offsets of the object. + * @brief Records an array of positions of this parcel. * - * @param offsets A pointer to the input array. - * @param offsetSize Size of the input array. - * @note It will return directly if fail. + * @param offsets Indicates the pointer to the position array. + * @param offsetSize Indicates the size of the position array. + * @note The method returns directly if the call fail. */ void InjectOffsets(binder_size_t offsets, size_t offsetSize); /** - * @brief Deallocate the data region, and reset this parcel. + * @brief Deallocates the data region and resets this parcel. */ void FlushBuffer(); /** - * @brief Write an `std::vector` object to this parcel. + * @brief Writes an `std::vector` object to this parcel. * - * @tparam T1 Specific class type for input vector. - * @tparam T2 Specific class type for write method of this parcel. - * @param val Input vector object passed by reference. - * @param Write Specific `Parcel::Write(T2 value)` method. - * @return Return True on success, or false if any error occur. + * @tparam T1 Indicates the class type for the vector. + * @tparam T2 Indicates the class type for the write method of this parcel. + * @param val Indicates the reference to the vector. + * @param Write Indicates the `Parcel::Write(T2 value)` method. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool WriteVector(const std::vector &val, bool (Parcel::*Write)(T2)); @@ -689,13 +730,14 @@ public: bool WriteString16Vector(const std::vector &val); /** - * @brief Read an `std::vector` object from this parcel. + * @brief Reads an `std::vector` object from this parcel. * - * @tparam T1 Specific class type for output vector. - * @tparam T2 Specific class type for read method of this parcel. - * @param val Pointer to the output vector object. - * @param Write Specific `Parcel::Read(T2 value)` method. - * @return Return True on success, or false if any error occur. + * @tparam T1 Indicates the class type for the vector. + * @tparam T2 Indicates the class type for the read method of this parcel. + * @param val Indicates the pointer to the vector. + * @param Write Indicates the `Parcel::Read(T2 value)` method. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool ReadVector(std::vector *val, bool (Parcel::*Read)(T &)); @@ -728,21 +770,23 @@ public: protected: /** - * @brief Record position of the written object, which are represented by - * offset from the beginning of the data region. + * @brief Records the position of the written object, which is represented + * by the offset from the beginning of the data region. * - * @param offset Specific position. - * @return Return True on success, or false if any error occur. + * @param offset Indicates the position. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteObjectOffset(binder_size_t offset); /** - * @brief Ensure number of the written objects is lower than the capacity of - * objects. + * @brief Ensures that the number of written objects is less than + * the capacity of objects. * - * If it is full, the capacity will be expanded. + * If the data region is full, the capacity will be expanded. * - * @return Return True on success, or false if any error occur. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool EnsureObjectsCapacity(); @@ -776,6 +820,12 @@ private: bool WriteParcelableOffset(size_t offset); + const uint8_t *BasicReadBuffer(size_t length); + + bool ValidateReadData(size_t upperBound); + + void ClearObjects(); + private: uint8_t *data_; size_t readCursor_; @@ -784,6 +834,7 @@ private: size_t dataCapacity_; size_t maxDataCapacity_; binder_size_t *objectOffsets_; + size_t nextObjectIdx_; size_t objectCursor_; size_t objectsCapacity_; Allocator *allocator_; @@ -821,7 +872,7 @@ T *Parcel::ReadParcelable() return T::Unmarshalling(*this); } -// Read data from the given parcel into this parcelable object, return sptr. +// Read data from the given parcel into this parcelable object, and return sptr. template sptr Parcel::ReadStrongParcelable() { diff --git a/3rdparty/ohos/utils/native/base/src/parcel.cpp b/3rdparty/ohos/utils/native/base/src/parcel.cpp index 4d3038c..86f0215 100644 --- a/3rdparty/ohos/utils/native/base/src/parcel.cpp +++ b/3rdparty/ohos/utils/native/base/src/parcel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,20 +14,43 @@ */ #include "parcel.h" -#include +#include "securec.h" #include "utils_log.h" namespace OHOS { +static const size_t DEFAULT_CPACITY = 204800; // 200K +static const size_t CAPACITY_THRESHOLD = 4096; // 4k + Parcelable::Parcelable() : Parcelable(false) {} Parcelable::Parcelable(bool asRemote) { + asRemote_ = asRemote; + behavior_ = 0; } Parcel::Parcel(Allocator *allocator) { + if (allocator != nullptr) { + allocator_ = allocator; + } else { + allocator_ = new DefaultAllocator(); + } + + writeCursor_ = 0; + readCursor_ = 0; + + data_ = nullptr; + dataSize_ = 0; + dataCapacity_ = 0; + + maxDataCapacity_ = DEFAULT_CPACITY; + objectOffsets_ = nullptr; + nextObjectIdx_ = 0; + objectCursor_ = 0; + objectsCapacity_ = 0; } Parcel::Parcel() : Parcel(new DefaultAllocator()) @@ -35,119 +58,386 @@ Parcel::Parcel() : Parcel(new DefaultAllocator()) Parcel::~Parcel() { + FlushBuffer(); + delete allocator_; + allocator_ = nullptr; } size_t Parcel::GetWritableBytes() const { - return {}; + if (dataCapacity_ > writeCursor_) { + return dataCapacity_ - writeCursor_; + } + + return 0; } size_t Parcel::GetReadableBytes() const { - return {}; + if (dataSize_ > readCursor_) { + return dataSize_ - readCursor_; + } + + return 0; } size_t Parcel::CalcNewCapacity(size_t minNewCapacity) { - return {}; + size_t threshold = CAPACITY_THRESHOLD; + + if (minNewCapacity == threshold) { + return threshold; + } + + // If over threshold, step by threshold. + if (minNewCapacity > threshold) { + size_t newCapacity = minNewCapacity / threshold * threshold; + + if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_ - threshold)) { + newCapacity = maxDataCapacity_; + } else { + newCapacity += threshold; + } + + return newCapacity; + } + + // Not over threshold. Double it. + size_t newCapacity = 64; + + while (newCapacity < minNewCapacity) { + newCapacity = newCapacity * 2; + } + + if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_)) { + newCapacity = maxDataCapacity_; + } + + return newCapacity; } bool Parcel::EnsureWritableCapacity(size_t desireCapacity) { - return {}; + if (!writable_) { + UTILS_LOGW("this parcel data is alloc by driver, which is can not be writen"); + return false; + } + if (desireCapacity <= GetWritableBytes()) { + return true; + } + + size_t minNewCapacity = desireCapacity + writeCursor_; + size_t newCapacity = CalcNewCapacity(minNewCapacity); + if ((newCapacity <= dataCapacity_) || (newCapacity < minNewCapacity)) { + UTILS_LOGW("Failed to ensure parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu, " + "minNewCapacity = %{public}zu", + newCapacity, dataCapacity_, minNewCapacity); + return false; + } + + if (allocator_ != nullptr) { + void *newData = allocator_->Realloc(data_, newCapacity); + if (newData != nullptr) { + data_ = reinterpret_cast(newData); + dataCapacity_ = newCapacity; + return true; + } + UTILS_LOGW("Failed to realloc parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu", + newCapacity, dataCapacity_); + } + + return false; +} + +// ValidateReadData only works in basic type read. It doesn't work when read remote object. +// And read/write remote object has no effect on "nextObjectIdx_". +bool Parcel::ValidateReadData([[maybe_unused]]size_t upperBound) +{ +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_ == nullptr || objectCursor_ == 0) { + return true; + } + size_t readPos = readCursor_; + size_t objSize = objectCursor_; + binder_size_t *objects = objectOffsets_; + if (nextObjectIdx_ < objSize && upperBound > objects[nextObjectIdx_]) { + size_t nextObj = nextObjectIdx_; + do { + if (readPos < objects[nextObj] + sizeof(parcel_flat_binder_object)) { + UTILS_LOGE("Non-object Read object data, readPos = %{public}zu, upperBound = %{public}zu", + readPos, upperBound); + return false; + } + nextObj++; + } while (nextObj < objSize && upperBound > objects[nextObj]); + nextObjectIdx_ = nextObj; + } +#endif + return true; } size_t Parcel::GetDataSize() const { - return {}; + return dataSize_; } uintptr_t Parcel::GetData() const { - return {}; + return reinterpret_cast(data_); } binder_size_t Parcel::GetObjectOffsets() const { - return {}; + return reinterpret_cast(objectOffsets_); } size_t Parcel::GetOffsetsSize() const { - return {}; + return objectCursor_; } size_t Parcel::GetDataCapacity() const { - return {}; + return dataCapacity_; } size_t Parcel::GetMaxCapacity() const { - return {}; + return maxDataCapacity_; } bool Parcel::SetMaxCapacity(size_t maxCapacity) { - return {}; + if (maxCapacity > maxDataCapacity_) { + maxDataCapacity_ = maxCapacity; + return true; + } + + return false; } bool Parcel::SetAllocator(Allocator *allocator) { - return {}; + if ((allocator == nullptr) || (allocator_ == allocator)) { + return false; + } + + if ((data_ != nullptr) && (dataSize_ > 0)) { + if (allocator_ == nullptr) { + return false; + } + + void *newData = allocator->Alloc(dataSize_); + if (newData == nullptr) { + UTILS_LOGE("Failed to alloc parcel size, dataSize_ = %{public}zu", dataSize_); + return false; + } + + if (memcpy_s(newData, dataSize_, data_, dataSize_) != EOK) { + allocator->Dealloc(newData); + return false; + } + allocator_->Dealloc(data_); + data_ = reinterpret_cast(newData); + dataCapacity_ = dataSize_; + } + + delete allocator_; + allocator_ = allocator; + return true; } bool Parcel::CheckOffsets() { - return {}; + size_t readPos = readCursor_; + if ((readPos + sizeof(parcel_flat_binder_object)) > dataSize_) { + UTILS_LOGW("CheckOffsets Invalid obj, obj size overflow. objSize:%{public}zu, dataSize:%{public}zu", + readPos + sizeof(parcel_flat_binder_object), dataSize_); + return false; + } + + size_t objSize = objectCursor_; + binder_size_t *objects = objectOffsets_; + size_t objCount = 0; + while (objCount < objSize) { + if (objects[objCount] == readPos) { + return true; + } + objCount++; + } + UTILS_LOGW("CheckOffsets Invalid obj: obj not found."); + return false; } void Parcel::InjectOffsets(binder_size_t offsets, size_t offsetSize) { + if (offsetSize <= 0) { + return; + } + + auto *newObjectOffsets = reinterpret_cast(offsets); + for (size_t index = 0; index < offsetSize; index++) { + if (EnsureObjectsCapacity()) { + WriteObjectOffset(newObjectOffsets[index]); + } + } +} + +void Parcel::ClearObjects() +{ + objectHolder_.clear(); + free(objectOffsets_); + nextObjectIdx_ = 0; + objectCursor_ = 0; + objectOffsets_ = nullptr; + objectsCapacity_ = 0; } void Parcel::FlushBuffer() { + if (allocator_ == nullptr) { + return; + } + + if (data_ != nullptr) { + allocator_->Dealloc(data_); + dataSize_ = 0; + writeCursor_ = 0; + readCursor_ = 0; + dataCapacity_ = 0; + data_ = nullptr; + } + + if (objectOffsets_) { + ClearObjects(); + } } bool Parcel::SetDataCapacity(size_t newCapacity) { - return {}; + if (allocator_ == nullptr || dataSize_ >= newCapacity) { + return false; + } + + void *newData = allocator_->Realloc(data_, newCapacity); + if (newData != nullptr) { + data_ = reinterpret_cast(newData); + dataCapacity_ = newCapacity; + return true; + } + return false; } bool Parcel::SetDataSize(size_t dataSize) { - return {}; + if (dataSize > dataCapacity_) { + return false; + } + + dataSize_ = dataSize; + return true; } bool Parcel::WriteDataBytes(const void *data, size_t size) { - return {}; + void *dest = data_ + writeCursor_; + size_t writableBytes = GetWritableBytes(); + if (memcpy_s(dest, writableBytes, data, size) != EOK) { + return false; + } + writeCursor_ += size; + dataSize_ += size; + return true; } void Parcel::WritePadBytes(size_t padSize) { + uint8_t *dest = data_ + writeCursor_; + static const int MAX_MASK_NUM = 4; +#if __BYTE_ORDER == __LITTLE_ENDIAN + static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0x00ffffff, 0x0000ffff, 0x000000ff }; +#else + static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0xffffff00, 0xffff0000, 0xff000000 }; +#endif + *reinterpret_cast(dest + padSize - MAX_MASK_NUM) &= mask[padSize]; + writeCursor_ += padSize; + dataSize_ += padSize; } bool Parcel::WriteBuffer(const void *data, size_t size) { - return {}; + if (data == nullptr || size == 0) { + return false; + } + + size_t padSize = GetPadSize(size); + size_t desireCapacity = size + padSize; + + // in case of desireCapacity overflow + if (desireCapacity < size || desireCapacity < padSize) { + return false; + } + + if (EnsureWritableCapacity(desireCapacity)) { + if (!WriteDataBytes(data, size)) { + return false; + } + WritePadBytes(padSize); + return true; + } + + return false; } bool Parcel::WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize) { - return {}; + if (data == nullptr || size < typeSize) { + return false; + } + + size_t padSize = GetPadSize(size); + size_t desireCapacity = size + padSize; + + // in case of desireCapacity overflow + if (desireCapacity < size || desireCapacity < padSize) { + return false; + } + + if (EnsureWritableCapacity(desireCapacity)) { + if (!WriteDataBytes(data, size - typeSize)) { + return false; + } + + // Reserved for 32 bits + const char terminator[] = {0, 0, 0, 0}; + if (!WriteDataBytes(terminator, typeSize)) { + return false; + } + WritePadBytes(padSize); + return true; + } + + return false; } bool Parcel::WriteUnpadBuffer(const void *data, size_t size) { - return {}; + return WriteBuffer(data, size); } template bool Parcel::Write(T value) { - return {}; + size_t desireCapacity = sizeof(T); + + if (EnsureWritableCapacity(desireCapacity)) { + *reinterpret_cast(data_ + writeCursor_) = value; + writeCursor_ += desireCapacity; + dataSize_ += desireCapacity; + return true; + } + + return false; } bool Parcel::WriteBool(bool value) @@ -237,103 +527,352 @@ bool Parcel::WritePointer(uintptr_t value) bool Parcel::WriteCString(const char *value) { - return {}; + if (value == nullptr) { + return false; + } + int32_t dataLength = strlen(value); + int32_t desireCapacity = (dataLength + 1) * sizeof(char); + return WriteBuffer(value, desireCapacity); } bool Parcel::WriteString(const std::string &value) { - return {}; + if (value.data() == nullptr) { + return WriteInt32(-1); + } + + int32_t dataLength = value.length(); + int32_t typeSize = sizeof(char); + int32_t desireCapacity = dataLength + typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16(const std::u16string &value) { - return {}; + if (value.data() == nullptr) { + return WriteInt32(-1); + } + + int32_t dataLength = value.length(); + int32_t typeSize = sizeof(char16_t); + int32_t desireCapacity = (dataLength + 1) * typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16WithLength(const char16_t *value, size_t len) { - return {}; + if (!value) { + return WriteInt32(-1); + } + + int32_t dataLength = len; + int32_t typeSize = sizeof(char16_t); + int32_t desireCapacity = (dataLength + 1) * typeSize; + std::u16string u16str(reinterpret_cast(value), len); + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(u16str.data(), desireCapacity, typeSize); } bool Parcel::WriteString8WithLength(const char *value, size_t len) { - return {}; + if (!value) { + return WriteInt32(-1); + } + + int32_t dataLength = len; + int32_t typeSize = sizeof(char); + int32_t desireCapacity = (dataLength + 1) * typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value, desireCapacity, typeSize); } bool Parcel::EnsureObjectsCapacity() { - return {}; + if ((objectsCapacity_ - objectCursor_) >= 1) { + return true; + } + + if (allocator_ == nullptr) { + return false; + } + + const int NEW_CAPACITY_ADD = 2; + const int NEW_CAPACITY_MULTI = 3; + const int NEW_CAPACITY_DIV = 2; + size_t newCapacity = ((objectsCapacity_ + NEW_CAPACITY_ADD) * NEW_CAPACITY_MULTI) / NEW_CAPACITY_DIV; + size_t newBytes = newCapacity * sizeof(binder_size_t); + + void *newOffsets = realloc(objectOffsets_, newBytes); + if (newOffsets == nullptr) { + return false; + } + + objectOffsets_ = reinterpret_cast(newOffsets); + objectsCapacity_ = newCapacity; + return true; } bool Parcel::WriteObjectOffset(binder_size_t offset) { - return {}; + if (offset > dataSize_) { + return false; + } + + for (size_t index = 0; index < objectCursor_; index++) { + if (objectOffsets_[index] == offset) { + return false; + } + } + + objectOffsets_[objectCursor_] = offset; + objectCursor_++; + return true; } bool Parcel::WriteRemoteObject(const Parcelable *object) { - return {}; + size_t placeholder = writeCursor_; + // Parcelable is nullptr + if ((object == nullptr) || (!object->asRemote_)) { + return false; + } + + if (!EnsureObjectsCapacity()) { + return false; + } + + if (!object->Marshalling(*this)) { + return false; + } + + WriteObjectOffset(placeholder); + + if (object->TestBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT)) { + sptr tmp(const_cast(object)); + objectHolder_.push_back(tmp); + } + + return true; } bool Parcel::WriteParcelable(const Parcelable *object) { - return {}; + size_t placeholder = writeCursor_; + size_t restorSize = dataSize_; + + // Parcelable is nullptr + if (object == nullptr) { + // write the meta data to indicate pass an null object. + return WriteInt32(0); + } + + if (!object->asRemote_) { + // meta data indicate we have an parcelable object. + if (!WriteInt32(1)) { + return false; + } + + return object->Marshalling(*this); + } + + // Write the remote object flag + if (!WriteInt32(1)) { + return false; + } + + if (WriteRemoteObject(const_cast(object))) { + return true; + } + + // rollback the write position. + writeCursor_ = placeholder; + dataSize_ = restorSize; + return false; } bool Parcel::WriteStrongParcelable(const sptr &object) { - return {}; + if (object == nullptr) { + WriteInt32(0); + return true; + } + + object->SetBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT); + return WriteParcelable(object.GetRefPtr()); } template bool Parcel::Read(T &value) { - return {}; + size_t desireCapacity = sizeof(T); + + if (desireCapacity <= GetReadableBytes()) { + const void *data = data_ + readCursor_; +#ifdef PARCEL_OBJECT_CHECK + size_t upperBound = readCursor_ + desireCapacity; + if (!ValidateReadData(upperBound)) { + readCursor_ += desireCapacity; + return false; + } +#endif + readCursor_ += desireCapacity; + value = *reinterpret_cast(data); + return true; + } + + return false; } template T Parcel::Read() { - return {}; + T lvalue {}; + return Read(lvalue) ? lvalue : 0; } bool Parcel::ParseFrom(uintptr_t data, size_t size) { - return {}; + if (data_ != nullptr) { + return false; + } + + data_ = reinterpret_cast(data); + dataCapacity_ = size; + dataSize_ = size; + /* data is alloc by driver, can not write again */ + writable_ = false; +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_) { + ClearObjects(); + } +#endif + return true; } const uint8_t *Parcel::ReadBuffer(size_t length) { - return {}; + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + readCursor_ += length; + return buffer; + } + + return nullptr; +} + +const uint8_t *Parcel::BasicReadBuffer([[maybe_unused]]size_t length) +{ +#ifdef PARCEL_OBJECT_CHECK + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + size_t upperBound = readCursor_ + length; + if (!ValidateReadData(upperBound)) { + readCursor_ += length; + return nullptr; + } + readCursor_ += length; + return buffer; + } +#endif + return nullptr; } const uint8_t *Parcel::ReadUnpadBuffer(size_t length) { - return {}; + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + readCursor_ += length; + SkipBytes(GetPadSize(length)); + return buffer; + } + + return nullptr; } void Parcel::SkipBytes(size_t bytes) { + if (GetReadableBytes() >= bytes) { + readCursor_ += bytes; + } else if (readCursor_ < dataCapacity_) { + readCursor_ = dataCapacity_; + } } size_t Parcel::GetReadPosition() { - return {}; + return readCursor_; } bool Parcel::RewindRead(size_t newPosition) { - return {}; + if (newPosition > dataSize_) { + return false; + } + readCursor_ = newPosition; + nextObjectIdx_ = 0; + return true; } size_t Parcel::GetWritePosition() { - return {}; + return writeCursor_; } bool Parcel::RewindWrite(size_t newPosition) { - return {}; + if (newPosition > dataSize_) { + return false; + } + writeCursor_ = newPosition; + dataSize_ = newPosition; +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_ == nullptr || objectCursor_ == 0) { + return true; + } + size_t objectSize = objectCursor_; + if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) > newPosition) { + while (objectSize > 0) { + if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) <= newPosition) { + break; + } + objectSize--; + } + if (objectSize == 0) { + ClearObjects(); + return true; + } + size_t newBytes = objectSize * sizeof(binder_size_t); + void *newOffsets = realloc(objectOffsets_, newBytes); + if (newOffsets == nullptr) { + return false; + } + objectOffsets_ = reinterpret_cast(newOffsets); + objectCursor_ = objectSize; + objectsCapacity_ = objectCursor_; + objectHolder_.resize(objectSize); + nextObjectIdx_ = 0; + return true; + } +#endif + return true; } bool Parcel::ReadBool() @@ -404,7 +943,13 @@ double Parcel::ReadDouble() template bool Parcel::ReadPadded(T &value) { - return {}; + int32_t temp; + bool result = Read(temp); + if (result) { + value = static_cast(temp); + } + + return result; } bool Parcel::ReadBool(bool &value) @@ -489,42 +1034,216 @@ uintptr_t Parcel::ReadPointer() const char *Parcel::ReadCString() { - return {}; + size_t oldCursor = readCursor_; + const size_t avail = GetReadableBytes(); + const char* cstr = reinterpret_cast(data_ + readCursor_); + // is the string's trailing NUL within the parcel's valid bounds? + const char* eos = reinterpret_cast(memchr(cstr, 0, avail)); + if (eos != nullptr) { + const size_t dataLength = eos - cstr; + readCursor_ += (dataLength + 1); + SkipBytes(GetPadSize(dataLength + 1)); + return cstr; + } + readCursor_ = oldCursor; + return nullptr; } const std::string Parcel::ReadString() { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + return std::string(); + } + + size_t readCapacity = static_cast(dataLength) + 1; + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *dest = BasicReadBuffer(readCapacity); +#else + const uint8_t *dest = ReadBuffer(readCapacity); +#endif + if (dest != nullptr) { + const auto *str = reinterpret_cast(dest); + SkipBytes(GetPadSize(readCapacity)); + if (str[dataLength] == 0) { + return std::string(str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::string(); } bool Parcel::ReadString(std::string &value) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + value = std::string(); + return false; + } + + size_t readCapacity = static_cast(dataLength) + 1; + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *dest = BasicReadBuffer(readCapacity); +#else + const uint8_t *dest = ReadBuffer(readCapacity); +#endif + if (dest != nullptr) { + const auto *str = reinterpret_cast(dest); + SkipBytes(GetPadSize(readCapacity)); + if (str[dataLength] == 0) { + value = std::string(str, dataLength); + return true; + } + } + } + + readCursor_ = oldCursor; + value = std::string(); + return false; } const std::u16string Parcel::ReadString16() { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + return std::u16string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + return std::u16string(u16Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::u16string(); } bool Parcel::ReadString16(std::u16string &value) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + value = std::u16string(); + return false; + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + value = std::u16string(u16Str, dataLength); + return true; + } + } + } + + readCursor_ = oldCursor; + value = std::u16string(); + return false; } const std::u16string Parcel::ReadString16WithLength(int32_t &readLength) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength)) { + return std::u16string(); + } + + if (dataLength < 0 || dataLength >= INT32_MAX) { + readLength = dataLength; + return std::u16string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + readLength = dataLength; + return std::u16string(u16Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::u16string(); } const std::string Parcel::ReadString8WithLength(int32_t &readLength) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength)) { + return std::string(); + } + + if (dataLength < 0 || dataLength >= INT32_MAX) { + readLength = dataLength; + return std::string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char); + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u8Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u8Str[dataLength] == 0) { + readLength = dataLength; + return std::string(u8Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::string(); } void *DefaultAllocator::Alloc(size_t size) { - return nullptr; + return malloc(size); } void DefaultAllocator::Dealloc(void *data) @@ -536,13 +1255,29 @@ void DefaultAllocator::Dealloc(void *data) void *DefaultAllocator::Realloc(void *data, size_t newSize) { - return nullptr; + return realloc(data, newSize); } template bool Parcel::WriteVector(const std::vector &val, bool (Parcel::*Write)(T2)) { - return {}; + if (val.size() > INT_MAX) { + return false; + } + + if (!this->WriteInt32(static_cast(val.size()))) { + return false; + } + + for (const auto &v : val) { + if (!(this->*Write)(v)) { + return false; + } + } + + size_t padSize = this->GetPadSize(val.size() * sizeof(T1)); + this->WritePadBytes(padSize); + return true; } bool Parcel::WriteBoolVector(const std::vector &val) @@ -613,12 +1348,66 @@ bool Parcel::WriteString16Vector(const std::vector &val) template bool Parcel::ReadVector(std::vector *val, bool (Parcel::*Read)(T &)) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes() / sizeof(T); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > val->max_size())) { + UTILS_LOGE("Failed to read vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + if (!(this->*Read)(v)) { + return false; + } + } + + size_t padSize = this->GetPadSize(size * sizeof(T)); + this->SkipBytes(padSize); + return true; } bool Parcel::ReadBoolVector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read bool vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (size_t i = 0; i < size; ++i) { + (*val)[i] = ReadBool(); + } + + size_t padSize = this->GetPadSize(size * sizeof(bool)); + this->SkipBytes(padSize); + return true; } bool Parcel::ReadInt8Vector(std::vector *val) @@ -673,11 +1462,61 @@ bool Parcel::ReadDoubleVector(std::vector *val) bool Parcel::ReadStringVector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read string vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + v = ReadString(); + } + + return true; } bool Parcel::ReadString16Vector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read u16string vector, size = %{public}zu, readAbleSize = %{public}zu", + size, readAbleSize); + return false; + } + + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + v = ReadString16(); + } + + return true; } } // namespace OHOS -- Gitee From 3f30c1c1214df41d90e1b396170d79d84da51304 Mon Sep 17 00:00:00 2001 From: liyang Date: Wed, 6 Dec 2023 11:37:42 +0800 Subject: [PATCH 2/5] update gtest for windows unittest Signed-off-by: liyang --- .../ipc_core/include/message_parcel.h | 178 ++----- .../native/src/core/source/message_parcel.cpp | 453 +----------------- .../ipc/native/src/mock/include/sys_binder.h | 292 +++++++++++ .../media_standard/services/utils/format.cpp | 215 --------- adapter/linux/types.h | 0 adapter/windows/sys/mman.h | 0 6 files changed, 352 insertions(+), 786 deletions(-) create mode 100644 3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h create mode 100644 adapter/linux/types.h create mode 100644 adapter/windows/sys/mman.h diff --git a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h index c154b5e..cffffca 100755 --- a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h +++ b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,10 +16,11 @@ #ifndef OHOS_IPC_MESSAGE_PARCEL_H #define OHOS_IPC_MESSAGE_PARCEL_H -#include +#include +#include #include "parcel.h" #include "refbase.h" -#include +#include namespace OHOS { class IRemoteObject; @@ -28,171 +29,62 @@ namespace OHOS { MessageParcel(); ~MessageParcel(); explicit MessageParcel(Allocator *allocator); - - /** - * @brief Serializes the remote object and writes it. - * @param object Indicates the remote object to serialize. - * @return Returns true if it is successful; returns false otherwise. - * @since 9 - */ bool WriteRemoteObject(const sptr &object); - - /** - * @brief Reads a remote object. - * @return Returns the IRemoteObject pointer object. - * @since 9 - */ sptr ReadRemoteObject(); - - /** - * @brief Writes an file descriptor into the object. - * @param fd Indicates file descriptor to write. - * @return Returns true if the write succeeds; return false otherwise. - * @since 9 - */ bool WriteFileDescriptor(int fd); - - /** - * @brief Reads an file descriptor from the object. - * @return Returns the corresponding descriptor If the read is successful; returns {@code -1} otherwise. - * @since 9 - */ int ReadFileDescriptor(); - - /** - * @brief Check whether the file descriptor is included. - * @return Returns true if checking for inclusion; returns false Otherwise. - * @since 9 - */ bool ContainFileDescriptors() const; - - /** - * @brief Writes an interface token into the object. - * @param name Indicates the string type name. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteInterfaceToken(std::u16string name); - - /** - * @brief Reads an interface token from the object. - * @return Returns a string value. - * @since 9 - */ std::u16string ReadInterfaceToken(); - - /** - * @brief Writes raw data to the object. - * @param data Indicates the original data written. - * @param size Indicates the size of the raw data sent. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteRawData(const void *data, size_t size); - - /** - * @brief Reads raw data from the object. - * @param size Indicates the size of the raw data to read. - * @return void - * @since 9 - */ const void *ReadRawData(size_t size); - - /** - * @brief Restore raw data. - * @param rawData Indicates the original data to be recovered. - * @param size Indicates the size of the raw data to read. - * @return Returns true if recovery is successful; returns false Otherwise. - * @since 9 - */ bool RestoreRawData(std::shared_ptr rawData, size_t size); - - /** - * @brief Obtains raw data from the object. - * @return void - * @since 9 - */ const void *GetRawData() const; - - /** - * @brief Gets the raw data size. - * @return Returns the resulting raw data size. - * @since 9 - */ size_t GetRawDataSize() const; - - /** - * @brief Get raw data capacity. - * @return Returns the maximum value of the raw data capacity. - * @since 9 - */ size_t GetRawDataCapacity() const; - - /** - * @brief writes information to the object indicating that no exception occurred. - * @return void - * @since 9 - */ void WriteNoException(); - - /** - * @brief Reads the exception information from the object. - * @return Returns the read error code. - * @since 9 - */ int32_t ReadException(); - - /** - * @brief Writes an anonymous shared memory object to the object. - * @param ashmem Indicates anonymous shared memory object to wrote. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteAshmem(sptr ashmem); - - /** - * @brief Reads the anonymous shared memory object from the object. - * @return Returns anonymous share object obtained. - * @since 9 - */ sptr ReadAshmem(); - - /** - * @brief Clear the file descriptor. - * @return void - * @since 9 - */ void ClearFileDescriptor(); - - /** - * @brief Sets the Clear specified file descriptor flag. - * @return void - * @since 9 - */ + std::vector vectorParcel; + bool Append(MessageParcel &data) + { + size_t dataSize = data.GetDataSize(); + if (dataSize == 0) { + return true; + } + uintptr_t dataPtr = data.GetData(); + size_t writeCursorOld = this->GetWritePosition(); + if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { + return false; + } + size_t objectSize = data.GetOffsetsSize(); + if (objectSize == 0) { + return true; + } + binder_size_t objectOffsets = data.GetObjectOffsets(); + auto *newObjectOffsets = reinterpret_cast(objectOffsets); + for (size_t index = 0; index < objectSize; index++) { + if (EnsureObjectsCapacity()) { + size_t offset = writeCursorOld + newObjectOffsets[index]; + if (!WriteObjectOffset(offset)) { + return false; + } + + } else { + return false; + } + } + return true; + }; void SetClearFdFlag() { needCloseFd_ = true; }; - /** - * @brief Append a MessageParcel object to the end of the current MessageParcel. - * @param data Indicates the data to append. - * @return Returns true if append succeeds; returns false Otherwise. - * @since 9 - */ - bool Append(MessageParcel &data); - private: #ifndef CONFIG_IPC_SINGLE - - /** - * @brief Write to the DBinder proxy object. - * @param object Indicates an IRemoteObject type object. - * @param handle Indicates the handle to write. - * @param stubIndex Indicates the stub index to write to. - * @return Returns true if the write succeeds; returns false otherwise. - * @since - */ bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); #endif static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp index b226d2c..4eac1e3 100644 --- a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp @@ -1,10 +1,10 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -15,69 +15,9 @@ #include "message_parcel.h" -#include -#include -#include -#include - -#include "ashmem.h" -#include "hilog/log_c.h" -#include "hilog/log_cpp.h" -#include "ipc_file_descriptor.h" -#include "ipc_process_skeleton.h" -#include "iremote_invoker.h" #include "iremote_object.h" -#include "log_tags.h" -#include "memory" -#include "new" -#include "parcel.h" -#include "refbase.h" -#include "securec.h" -#include "string" -#include "sys_binder.h" -#include "vector" -#include "ipc_debug.h" - -#ifndef CONFIG_IPC_SINGLE -#include "dbinder_callback_stub.h" -#include "dbinder_session_object.h" -#endif namespace OHOS { -#ifdef CONFIG_IPC_SINGLE - using namespace IPC_SINGLE; -#endif - static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "MessageParcel" }; - - void AcquireObject(flat_binder_object *flat, const void *cookie) - { - switch (flat->hdr.type) { - case BINDER_TYPE_BINDER: - if (flat->binder) { - reinterpret_cast(flat->cookie)->IncStrongRef(cookie); - } - break; - case BINDER_TYPE_HANDLE: { - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - IRemoteObject *remoteObject = nullptr; - if (current != nullptr) { - remoteObject = current->QueryObject(current->MakeHandleDescriptor(flat->handle)); - } - if (remoteObject != nullptr) { - remoteObject->IncStrongRef(cookie); - } - break; - } - case BINDER_TYPE_FD: - flat->handle = static_cast(dup(flat->handle)); - flat->cookie = 1; - break; - default: - ZLOGE(LOG_LABEL, "binder object type is invalid."); - break; - } - } - MessageParcel::MessageParcel() : Parcel(), writeRawDataFd_(-1), @@ -100,444 +40,101 @@ namespace OHOS { MessageParcel::~MessageParcel() { - if (kernelMappedWrite_ != nullptr) { - ::munmap(kernelMappedWrite_, rawDataSize_); - kernelMappedWrite_ = nullptr; - } - if (kernelMappedRead_ != nullptr) { - ::munmap(kernelMappedRead_, rawDataSize_); - kernelMappedRead_ = nullptr; - } - - if (readRawDataFd_ > 0) { - ::close(readRawDataFd_); - readRawDataFd_ = -1; - } - if (writeRawDataFd_ > 0) { - ::close(writeRawDataFd_); - writeRawDataFd_ = -1; - } - - ClearFileDescriptor(); - - rawData_ = nullptr; - rawDataSize_ = 0; } #ifndef CONFIG_IPC_SINGLE bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) { - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - if (current == nullptr) { - ZLOGE(LOG_LABEL, "current is nullptr"); - return false; - } - std::shared_ptr sessionOfPeer = current->ProxyQueryDBinderSession(handle); - if (sessionOfPeer == nullptr) { - ZLOGE(LOG_LABEL, "sessionOfPeer is null, handle: %{public}u, stubIndex: %{public}" PRIu64, handle, stubIndex); - return false; - } - std::string peerName = sessionOfPeer->GetServiceName(); - std::string peerId = sessionOfPeer->GetDeviceId(); - std::string localId = current->GetLocalDeviceID(); - uint32_t tokenId = sessionOfPeer->GetTokenId(); - - sptr fakeStub = current->QueryDBinderCallbackStub(object); - if (fakeStub == nullptr) { - // note that cannot use this proxy's descriptor, this stub is now stored and strong refered - // and need to be erased in an approprite time - fakeStub = new (std::nothrow) DBinderCallbackStub(peerName, peerId, localId, sessionOfPeer->GetStubIndex(), - handle, tokenId); - if (fakeStub == nullptr) { - ZLOGE(LOG_LABEL, "create DBinderCallbackStub object failed"); - return false; - } - if (!current->AttachDBinderCallbackStub(object, fakeStub)) { - ZLOGE(LOG_LABEL, "save callback of fake stub failed"); - return false; - } - } - return WriteRemoteObject(fakeStub); + (void)object; + (void)handle; + (void)stubIndex; + return false; } #endif bool MessageParcel::WriteRemoteObject(const sptr &object) { - if (object == nullptr) { - return false; - } - // Increase object's refcount temporarily in case of premature deallocation, - // object's refcount will be decreased when this MessageParcel destroyed. - holders_.push_back(object); -#ifndef CONFIG_IPC_SINGLE - if (object->IsProxyObject()) { - const IPCObjectProxy *proxy = reinterpret_cast(object.GetRefPtr()); - const uint32_t handle = proxy ? proxy->GetHandle() : 0; - if (IPCProcessSkeleton::IsHandleMadeByUser(handle)) { - /* this is a fake proxy which handle get by MakeRemoteHandle(), Not binder driver of kernel */ - ZLOGI(LOG_LABEL, "send a dbinder proxy to another process in this device"); - return WriteDBinderProxy(object, handle, 0); - } - } -#endif - auto result = WriteObject(object); - if (result == false) { - return result; - } - return result; + (void)object; + return false; } sptr MessageParcel::ReadRemoteObject() { - sptr temp = ReadObject(); -#ifndef CONFIG_IPC_SINGLE - if (temp != nullptr && !temp->IsProxyObject()) { - // if this stub is a DBinderCallbackStub, return corresponding proxy - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - if (current != nullptr) { - sptr proxy = current->QueryDBinderCallbackProxy(temp); - if (proxy != nullptr) { - temp = proxy; - } - } - } -#endif - return temp; + return nullptr; } bool MessageParcel::WriteFileDescriptor(int fd) { - if (fd < 0) { - return false; - } - int dupFd = dup(fd); - if (dupFd < 0) { - return false; - } - sptr descriptor = new (std::nothrow) IPCFileDescriptor(dupFd); - if (descriptor == nullptr) { - ZLOGE(LOG_LABEL, "create IPCFileDescriptor object failed"); - return false; - } - return WriteObject(descriptor); + return false; } int MessageParcel::ReadFileDescriptor() { - sptr descriptor = ReadObject(); - if (descriptor == nullptr) { - return -1; - } - int fd = descriptor->GetFd(); - if (fd < 0) { - return -1; - } - return dup(fd); + return -1; } void MessageParcel::ClearFileDescriptor() { - size_t dataOffset = 0; - binder_size_t *object = nullptr; - const flat_binder_object *flat = nullptr; - for (size_t i = 0; i < GetOffsetsSize(); i++) { - object = reinterpret_cast(GetObjectOffsets()); - if (object == nullptr) { - ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); - break; - } - // offset + size - dataOffset = object[i] + sizeof(flat_binder_object); - if (dataOffset > GetDataSize()) { - ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", - dataOffset, GetDataSize()); - break; - } - uintptr_t data = GetData(); - if (data == 0) { - ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); - break; - } - flat = reinterpret_cast(data + object[i]); - if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) { - ::close(flat->handle); - } - } } bool MessageParcel::ContainFileDescriptors() const { - size_t dataOffset = 0; - binder_size_t *object = nullptr; - const flat_binder_object *flat = nullptr; - for (size_t i = 0; i < GetOffsetsSize(); i++) { - object = reinterpret_cast(GetObjectOffsets()); - if (object == nullptr) { - ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); - break; - } - // offset + size - dataOffset = object[i] + sizeof(flat_binder_object); - if (dataOffset > GetDataSize()) { - ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", - dataOffset, GetDataSize()); - break; - } - uintptr_t data = GetData(); - if (data == 0) { - ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); - break; - } - flat = reinterpret_cast(data + object[i]); - if (flat->hdr.type == BINDER_TYPE_FD) { - return true; - } - } - return false; } bool MessageParcel::WriteInterfaceToken(std::u16string name) { - constexpr int strictModePolicy = 0x100; - constexpr int workSource = 0; - size_t rewindPos = GetWritePosition(); - if (!WriteInt32(strictModePolicy)) { - return false; - } - - if (!WriteInt32(workSource)) { - if (!RewindWrite(rewindPos)) { - FlushBuffer(); - } - return false; - } - - return WriteString16(name); + (void)name; + return false; } std::u16string MessageParcel::ReadInterfaceToken() { - [[maybe_unused]] int32_t strictModePolicy = ReadInt32(); - [[maybe_unused]] int32_t workSource = ReadInt32(); - return ReadString16(); + return u""; } bool MessageParcel::WriteRawData(const void *data, size_t size) { - if (data == nullptr || size > MAX_RAWDATA_SIZE || size == 0) { - ZLOGE(LOG_LABEL, "data is null or size:%{public}zu not ok", size); - return false; - } - if (kernelMappedWrite_ != nullptr) { - return false; - } - if (!WriteInt32(size)) { - return false; - } - if (size <= MIN_RAWDATA_SIZE) { - rawDataSize_ = size; - return WriteUnpadBuffer(data, size); - } - int fd = AshmemCreate("Parcel RawData", size); - if (fd < 0) { - return false; - } - writeRawDataFd_ = fd; - - int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); - if (result < 0) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return false; - } - void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return false; - } - if (!WriteFileDescriptor(fd)) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ::munmap(ptr, size); - return false; - } - if (memcpy_s(ptr, size, data, size) != EOK) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ::munmap(ptr, size); - return false; - } - kernelMappedWrite_ = ptr; - rawDataSize_ = size; - return true; + (void)data; + (void)size; + return false; } bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) { - if (rawData_ != nullptr || rawData == nullptr) { - return false; - } - rawData_ = rawData; - rawDataSize_ = size; - writeRawDataFd_ = 0; - return true; + (void)rawData; + (void)size; + return false; } const void *MessageParcel::ReadRawData(size_t size) { - if (size == 0) { - ZLOGE(LOG_LABEL, "the parameter size is 0"); - return nullptr; - } - size_t bufferSize = static_cast(ReadInt32()); - if (bufferSize != size) { - ZLOGE(LOG_LABEL, "ReadRawData: the buffersize %{public}zu not equal the parameter size %{public}zu", - bufferSize, size); - return nullptr; - } - if (bufferSize <= MIN_RAWDATA_SIZE) { - rawDataSize_ = size; - return ReadUnpadBuffer(size); - } - - /* if rawDataFd_ == 0 means rawData is received from remote */ - if (rawData_ != nullptr && writeRawDataFd_ == 0) { - /* should read fd for move readCursor of parcel */ - if (ReadFileDescriptor()) { - // do nothing - } - if (rawDataSize_ != size) { - ZLOGE(LOG_LABEL, "rawData is received from remote, the rawDataSize_ %{public}zu" - " not equal size %{public}zu", rawDataSize_, size); - return nullptr; - } - return rawData_.get(); - } - int fd = ReadFileDescriptor(); - if (fd < 0) { - return nullptr; - } - readRawDataFd_ = fd; - - int ashmemSize = AshmemGetSize(fd); - if (ashmemSize < 0 || size_t(ashmemSize) < size) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ZLOGE(LOG_LABEL, "ashmemSize %{public}d less than size %{public}zu", - ashmemSize, size); - return nullptr; - } - void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return nullptr; - } - kernelMappedRead_ = ptr; - rawDataSize_ = size; - return ptr; + (void)size; + return nullptr; } const void *MessageParcel::GetRawData() const { - if (rawData_ != nullptr) { - return rawData_.get(); - } - if (kernelMappedWrite_ != nullptr) { - return kernelMappedWrite_; - } - if (kernelMappedRead_ != nullptr) { - return kernelMappedRead_; - } return nullptr; } size_t MessageParcel::GetRawDataSize() const { - return rawDataSize_; + return -1; } size_t MessageParcel::GetRawDataCapacity() const { - return MAX_RAWDATA_SIZE; + return -1; } void MessageParcel::WriteNoException() { - WriteInt32(0); } int32_t MessageParcel::ReadException() { - int32_t errorCode = ReadInt32(); - if (errorCode != 0) { - ReadString16(); - } - return errorCode; - } - - bool MessageParcel::WriteAshmem(sptr ashmem) - { - int fd = ashmem->GetAshmemFd(); - int32_t size = ashmem->GetAshmemSize(); - if (fd < 0 || size <= 0) { - return false; - } - if (!WriteFileDescriptor(fd) || !WriteInt32(size)) { - return false; - } - return true; - } - - sptr MessageParcel::ReadAshmem() - { - int fd = ReadFileDescriptor(); - if (fd < 0) { - return nullptr; - } - - int32_t size = ReadInt32(); - if (size <= 0) { - ::close(fd); - return nullptr; - } - return new (std::nothrow) Ashmem(fd, size); - } - - bool MessageParcel::Append(MessageParcel &data) - { - size_t dataSize = data.GetDataSize(); - if (dataSize == 0) { - ZLOGE(LOG_LABEL, "no data to append"); - return true; - } - uintptr_t dataPtr = data.GetData(); - size_t writeCursorOld = this->GetWritePosition(); - if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { - ZLOGE(LOG_LABEL, "failed to append data with writebuffer."); - return false; - } - size_t objectSize = data.GetOffsetsSize(); - if (objectSize == 0) { - return true; - } - binder_size_t objectOffsets = data.GetObjectOffsets(); - auto *newObjectOffsets = reinterpret_cast(objectOffsets); - for (size_t index = 0; index < objectSize; index++) { - if (EnsureObjectsCapacity()) { - size_t offset = writeCursorOld + newObjectOffsets[index]; - if (!WriteObjectOffset(offset)) { - ZLOGE(LOG_LABEL, "failed to write object offset"); - return false; - } - flat_binder_object *flat = reinterpret_cast(this->GetData() + offset); - if (flat == nullptr) { - ZLOGE(LOG_LABEL, "flat binder object is nullptr"); - return false; - } - AcquireObject(flat, this); - } else { - ZLOGE(LOG_LABEL, "Failed to ensure parcel capacity"); - return false; - } - } - return true; + return -1; } } // namespace OHOS diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h new file mode 100644 index 0000000..6765a73 --- /dev/null +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_IPC_SYS_BINDER_H +#define OHOS_IPC_SYS_BINDER_H + +#include + +#ifndef _UAPI_LINUX_BINDER_H +#define _UAPI_LINUX_BINDER_H + +#include +#include + +#ifndef B_PACK_CHARS +#define B_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4)) +#endif + +#define B_TYPE_LARGE 0x85 +enum { + BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), + BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), + BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), + BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE), + BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), +}; +enum { + FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, + FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, +}; +#ifdef BINDER_IPC_32BIT +typedef __u32 binder_size_t; +typedef __u32 binder_uintptr_t; +#else +typedef __u64 binder_size_t; +typedef __u64 binder_uintptr_t; +#endif +struct binder_object_header { + __u32 type; +}; +struct flat_binder_object { + struct binder_object_header hdr; + __u32 flags; + union { + binder_uintptr_t binder; + __u32 handle; + }; + binder_uintptr_t cookie; +}; + +struct binder_fd_object { + struct binder_object_header hdr; + __u32 pad_flags; + union { + binder_uintptr_t pad_binder; + __u32 fd; + }; + binder_uintptr_t cookie; +}; +struct binder_buffer_object { + struct binder_object_header hdr; + __u32 flags; + binder_uintptr_t buffer; + binder_size_t length; + binder_size_t parent; + binder_size_t parent_offset; +}; +enum { + BINDER_BUFFER_FLAG_HAS_PARENT = 0x01, +}; +struct binder_fd_array_object { + struct binder_object_header hdr; + __u32 pad; + binder_size_t num_fds; + binder_size_t parent; + binder_size_t parent_offset; +}; +struct binder_write_read { + binder_size_t write_size; + binder_size_t write_consumed; + binder_uintptr_t write_buffer; + binder_size_t read_size; + binder_size_t read_consumed; + binder_uintptr_t read_buffer; +}; +struct binder_version { + __s32 protocol_version; +}; +#ifdef BINDER_IPC_32BIT +#define BINDER_CURRENT_PROTOCOL_VERSION 7 +#else +#define BINDER_CURRENT_PROTOCOL_VERSION 8 +#endif +struct binder_node_debug_info { + binder_uintptr_t ptr; + binder_uintptr_t cookie; + __u32 has_strong_ref; + __u32 has_weak_ref; +}; + +struct binder_node_info_for_ref { + __u32 handle; + __u32 strong_count; + __u32 weak_count; + __u32 reserved1; + __u32 reserved2; + __u32 reserved3; +}; + +#define ACCESS_TOKENID_GET_TOKENID _IOR('A', 1, unsigned long long) +#define ACCESS_TOKENID_GET_FTOKENID _IOR('A', 3, unsigned long long) +#define ACCESS_TOKEN_FAETURE_MASK (1 << 0) + +struct binder_feature_set { + __u64 feature_set; +}; + +struct access_token { + __u64 sender_tokenid; + __u64 first_tokenid; + __u64 reserved[2]; +}; + +#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) +#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) +#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) +#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) +#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) +#define BINDER_THREAD_EXIT _IOW('b', 8, __s32) +#define BINDER_VERSION _IOWR('b', 9, struct binder_version) +#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) +#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) +#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) +#define BINDER_FEATURE_SET _IOWR('b', 30, struct binder_feature_set) +#define BINDER_GET_ACCESS_TOKEN _IOWR('b', 31, struct access_token) + +enum transaction_flags { + TF_ONE_WAY = 0x01, + TF_ROOT_OBJECT = 0x04, + TF_STATUS_CODE = 0x08, + TF_ACCEPT_FDS = 0x10, + TF_HITRACE = 0x80, // add flag for hitrace +}; +struct binder_transaction_data { + union { + __u32 handle; + binder_uintptr_t ptr; + } target; + binder_uintptr_t cookie; + __u32 code; + __u32 flags; + pid_t sender_pid; + uid_t sender_euid; + binder_size_t data_size; + binder_size_t offsets_size; + union { + struct { + binder_uintptr_t buffer; + binder_uintptr_t offsets; + } ptr; + __u8 buf[8]; + } data; +}; + +struct binder_transaction_data_secctx { + struct binder_transaction_data transaction_data; + binder_uintptr_t secctx; +}; + +struct binder_transaction_data_sg { + struct binder_transaction_data transaction_data; + binder_size_t buffers_size; +}; + +struct binder_ptr_cookie { + binder_uintptr_t ptr; + binder_uintptr_t cookie; +}; +struct binder_handle_cookie { + __u32 handle; + binder_uintptr_t cookie; +} __attribute__((__packed__)); +struct binder_pri_desc { + __s32 priority; + __u32 desc; +}; +struct binder_pri_ptr_cookie { + __s32 priority; + binder_uintptr_t ptr; + binder_uintptr_t cookie; +}; +enum binder_driver_return_protocol { + BR_ERROR = _IOR('r', 0, __s32), + BR_OK = _IO('r', 1), + BR_TRANSACTION_SEC_CTX = _IOR('r', 2, struct binder_transaction_data_secctx), + BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), + BR_REPLY = _IOR('r', 3, struct binder_transaction_data), + BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), + BR_DEAD_REPLY = _IO('r', 5), + BR_TRANSACTION_COMPLETE = _IO('r', 6), + BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), + BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), + BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), + BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), + BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), + BR_NOOP = _IO('r', 12), + BR_SPAWN_LOOPER = _IO('r', 13), + BR_FINISHED = _IO('r', 14), + BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), + BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), + BR_FAILED_REPLY = _IO('r', 17), + BR_RELEASE_NODE = _IO('r', 18), + BR_TRANSLATION_COMPLETE = _IOR('r', 20, __u32), +}; +enum binder_driver_command_protocol { + BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), + BC_REPLY = _IOW('c', 1, struct binder_transaction_data), + BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), + BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), + BC_INCREFS = _IOW('c', 4, __u32), + BC_ACQUIRE = _IOW('c', 5, __u32), + BC_RELEASE = _IOW('c', 6, __u32), + BC_DECREFS = _IOW('c', 7, __u32), + BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), + BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), + BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), + BC_REGISTER_LOOPER = _IO('c', 11), + BC_ENTER_LOOPER = _IO('c', 12), + BC_EXIT_LOOPER = _IO('c', 13), + BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), + BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), + BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), + BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg), + BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg), + BC_SEND_RAWDATA = _IOW('c', 20, __u32), + BC_TRANSLATION = _IOW('c', 21, struct flat_binder_object), +}; +#endif /* * _UAPI_LINUX_BINDER_H * */ + +static const uint32_t DBINDER_MAGICWORD = 0X4442494E; +static const uint32_t ENCRYPT_HEAD_LEN = 28; +static const uint32_t DEVICEID_LENGTH = 64; +static const uint32_t PID_LEN = 32; +static const uint32_t RPC_DEFAULT_VERSION_NUM = 1; +static const uint32_t SUPPORT_TOKENID_VERSION_NUM = 2; +static const uint32_t TOKENID_MAGIC = 0X544F4B49; + +enum { + BINDER_TYPE_REMOTE_BINDER = B_PACK_CHARS('r', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_REMOTE_HANDLE = B_PACK_CHARS('r', 'h', '*', B_TYPE_LARGE), + ZBINDER_TYPE_REMOTE_NODE = B_PACK_CHARS('r', 'n', '*', B_TYPE_LARGE), + ZBINDER_TYPE_NODE = B_PACK_CHARS('s', 'n', '*', B_TYPE_LARGE), + BINDER_TYPE_FDR = B_PACK_CHARS('f', 'd', 'r', B_TYPE_LARGE), + BINDER_TYPE_INVALID_HANDLE = B_PACK_CHARS('r', 'h', 'e', B_TYPE_LARGE), + BINDER_TYPE_INVALID_BINDER = B_PACK_CHARS('r', 'b', 'e', B_TYPE_LARGE), +}; + +struct binder_ptr_count { + binder_uintptr_t ptr; + uint32_t count; +}; + +struct dbinder_transaction_data { + __u32 sizeOfSelf; + __u32 magic; + __u32 version; + int cmd; + __u32 code; + __u32 flags; + __u64 cookie; + __u64 seqNumber; + binder_size_t buffer_size; + binder_size_t offsets_size; + binder_uintptr_t offsets; + unsigned char buffer[0]; +}; +#endif // OHOS_IPC_SYS_BINDER_H diff --git a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp index 2998791..c734859 100644 --- a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp +++ b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp @@ -61,221 +61,6 @@ void CopyFormatDataMap(const Format::FormatDataMap &from, Format::FormatDataMap } } -Format::~Format() -{ - for (auto it = formatMap_.begin(); it != formatMap_.end(); ++it) { - if (it->second.type == FORMAT_TYPE_ADDR && it->second.addr != nullptr) { - free(it->second.addr); - it->second.addr = nullptr; - } - } -} - -Format::Format(const Format &rhs) -{ - if (&rhs == this) { - return; - } - - CopyFormatDataMap(rhs.formatMap_, formatMap_); -} - -Format::Format(Format &&rhs) noexcept -{ - std::swap(formatMap_, rhs.formatMap_); -} - -Format &Format::operator=(const Format &rhs) -{ - if (&rhs == this) { - return *this; - } - - CopyFormatDataMap(rhs.formatMap_, this->formatMap_); - return *this; -} - -Format &Format::operator=(Format &&rhs) noexcept -{ - if (&rhs == this) { - return *this; - } - std::swap(this->formatMap_, rhs.formatMap_); - return *this; -} - -bool Format::PutIntValue(const std::string_view &key, int32_t value) -{ - FormatData data; - data.type = FORMAT_TYPE_INT32; - data.val.int32Val = value; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); // cgd: fix windows compile error - return ret.second; -} - -bool Format::PutLongValue(const std::string_view &key, int64_t value) -{ - FormatData data; - data.type = FORMAT_TYPE_INT64; - data.val.int64Val = value; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); - return ret.second; -} - -bool Format::PutFloatValue(const std::string_view &key, float value) -{ - FormatData data; - data.type = FORMAT_TYPE_FLOAT; - data.val.floatVal = value; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); - return ret.second; -} - -bool Format::PutDoubleValue(const std::string_view &key, double value) -{ - FormatData data; - data.type = FORMAT_TYPE_DOUBLE; - data.val.doubleVal = value; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); - return ret.second; -} - -bool Format::PutStringValue(const std::string_view &key, const std::string_view &value) -{ - FormatData data; - data.type = FORMAT_TYPE_STRING; - data.stringVal = value; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); - return ret.second; -} - -bool Format::GetStringValue(const std::string_view &key, std::string &value) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_STRING) { - printf("Format::GetFormat failed. Key: %{public}s", key.data()); - return false; - } - value = iter->second.stringVal; - return true; -} - -bool Format::GetIntValue(const std::string_view &key, int32_t &value) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_INT32) { - printf("Format::GetFormat failed. Key: %{public}s", key.data()); - return false; - } - value = iter->second.val.int32Val; - return true; -} - -bool Format::GetLongValue(const std::string_view &key, int64_t &value) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_INT64) { - printf("Format::GetFormat failed. Key: %{public}s", key.data()); - return false; - } - value = iter->second.val.int64Val; - return true; -} - -bool Format::GetFloatValue(const std::string_view &key, float &value) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_FLOAT) { - printf("Format::GetFormat failed. Key: %{public}s", key.data()); - return false; - } - value = iter->second.val.floatVal; - return true; -} - -bool Format::GetDoubleValue(const std::string_view &key, double &value) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_DOUBLE) { - printf("Format::GetFormat failed. Key: %{public}s", key.data()); - return false; - } - value = iter->second.val.doubleVal; - return true; -} - -bool Format::PutBuffer(const std::string_view &key, const uint8_t *addr, size_t size) -{ - const size_t sizeMax = 1 * 1024 * 1024; - if (size > sizeMax) { - printf("PutBuffer input size failed. Key: %{public}s", key.data()); - return false; - } - - FormatData data; - data.type = FORMAT_TYPE_ADDR; - data.addr = reinterpret_cast(malloc(size)); - auto err = memcpy_s(reinterpret_cast(data.addr), size, reinterpret_cast(addr), size); - if (err != EOK) { - printf("PutBuffer memcpy addr failed. Key: %{public}s", key.data()); - return false; - } - - RemoveKey(key); - - data.size = size; - auto ret = formatMap_.insert(std::make_pair(key.data(), data)); - return ret.second; -} - -bool Format::GetBuffer(const std::string_view &key, uint8_t **addr, size_t &size) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end() || iter->second.type != FORMAT_TYPE_ADDR) { - printf("Format::GetBuffer failed. Key: %{public}s", key.data()); - return false; - } - *addr = iter->second.addr; - size = iter->second.size; - return true; -} - -bool Format::ContainKey(const std::string_view &key) const -{ - auto iter = formatMap_.find(key); - if (iter != formatMap_.end()) { - return true; - } - - return false; -} - -FormatDataType Format::GetValueType(const std::string_view &key) const -{ - auto iter = formatMap_.find(key); - if (iter == formatMap_.end()) { - return FORMAT_TYPE_NONE; - } - - return iter->second.type; -} - -void Format::RemoveKey(const std::string_view &key) -{ - auto iter = formatMap_.find(key); - if (iter != formatMap_.end()) { - if (iter->second.type == FORMAT_TYPE_ADDR && iter->second.addr != nullptr) { - free(iter->second.addr); - iter->second.addr = nullptr; - } - formatMap_.erase(iter); - } -} - -const Format::FormatDataMap &Format::GetFormatMap() const -{ - return formatMap_; -} } } \ No newline at end of file diff --git a/adapter/linux/types.h b/adapter/linux/types.h new file mode 100644 index 0000000..e69de29 diff --git a/adapter/windows/sys/mman.h b/adapter/windows/sys/mman.h new file mode 100644 index 0000000..e69de29 -- Gitee From ec38b519fef2a71ea45bd947455e12d1f7b39600 Mon Sep 17 00:00:00 2001 From: Chen Guodong Date: Wed, 29 Nov 2023 16:01:07 +0800 Subject: [PATCH 3/5] Fix windows compile error. Signed-off-by: Chen Guodong (cherry picked from commit 74af6db82e79f6b7fb83f83cd6a022d1bce64d85) # Conflicts: # 3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp --- .../media_standard/services/utils/format.cpp | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp diff --git a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp deleted file mode 100644 index c734859..0000000 --- a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/format.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// ########################## this file is modified with removing media_log.h #################################### -#include "format.h" -#include "securec.h" -//#include "media_log.h" -#include "media_errors.h" - -namespace { -//constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "Format"}; -} - -namespace OHOS { -namespace Media { -void CopyFormatDataMap(const Format::FormatDataMap &from, Format::FormatDataMap &to) -{ - for (auto it = to.begin(); it != to.end(); ++it) { - if (it->second.type == FORMAT_TYPE_ADDR && it->second.addr != nullptr) { - free(it->second.addr); - it->second.addr = nullptr; - } - } - - to = from; - - for (auto it = to.begin(); it != to.end();) { - if (it->second.type != FORMAT_TYPE_ADDR || it->second.addr == nullptr) { - ++it; - continue; - } - - it->second.addr = reinterpret_cast(malloc(it->second.size)); - if (it->second.addr == nullptr) { - printf("malloc addr failed. Key: %{public}s", it->first.c_str()); - it = to.erase(it); - continue; - } - - auto err = memcpy_s(reinterpret_cast(it->second.addr), - it->second.size, reinterpret_cast(from.at(it->first).addr), it->second.size); - if (err != EOK) { - printf("memcpy addr failed. Key: %{public}s", it->first.c_str()); - free(it->second.addr); - it = to.erase(it); - continue; - } - ++it; - } -} - - -} -} \ No newline at end of file -- Gitee From 652802ec46079cd686e3fb82cbb72f79d576a43a Mon Sep 17 00:00:00 2001 From: liyang Date: Sat, 25 Nov 2023 18:18:54 +0800 Subject: [PATCH 4/5] update gtest for windows unittest Signed-off-by: liyang --- .../gtest/include/gtest/gtest-death-test.h | 45 +- 3rdparty/gtest/include/gtest/gtest-matchers.h | 416 ++- 3rdparty/gtest/include/gtest/gtest-message.h | 7 +- .../gtest/include/gtest/gtest-param-test.h | 30 +- 3rdparty/gtest/include/gtest/gtest-printers.h | 665 ++-- 3rdparty/gtest/include/gtest/gtest-spi.h | 6 +- .../gtest/include/gtest/gtest-test-part.h | 6 +- .../gtest/include/gtest/gtest-typed-test.h | 69 +- 3rdparty/gtest/include/gtest/gtest.h | 119 +- .../gtest/include/gtest/gtest_pred_impl.h | 6 +- 3rdparty/gtest/include/gtest/gtest_prod.h | 6 +- .../gtest/include/gtest/hwext/gtest-ext.h | 83 + .../gtest/include/gtest/hwext/gtest-filter.h | 48 + .../include/gtest/hwext/gtest-multithread.h | 117 + .../gtest/include/gtest/hwext/gtest-tag.h | 115 + .../gtest/include/gtest/hwext/gtest-utils.h | 21 + .../gtest/internal/custom/gtest-port.h | 6 +- .../gtest/internal/custom/gtest-printers.h | 6 +- .../include/gtest/internal/custom/gtest.h | 6 +- .../internal/gtest-death-test-internal.h | 6 +- .../include/gtest/internal/gtest-filepath.h | 8 +- .../include/gtest/internal/gtest-internal.h | 380 +- .../include/gtest/internal/gtest-param-util.h | 94 +- .../include/gtest/internal/gtest-port-arch.h | 13 +- .../gtest/include/gtest/internal/gtest-port.h | 334 +- .../include/gtest/internal/gtest-string.h | 12 +- .../include/gtest/internal/gtest-type-util.h | 3282 +---------------- .../mingw64/src/gtest/src/hwext/gtest-ext.cc | 220 ++ .../src/gtest/src/hwext/gtest-filter.cc | 226 ++ .../src/gtest/src/hwext/gtest-multithread.cpp | 96 + .../mingw64/src/gtest/src/hwext/gtest-tag.cc | 197 + .../src/gtest/src/hwext/gtest-utils.cc | 81 + .../ipc_core/include/message_parcel.h | 230 +- .../native/src/core/source/message_parcel.cpp | 635 +++- .../services/utils/media_data_source.cpp | 23 +- .../ohos/utils/native/base/include/parcel.h | 533 +-- .../ohos/utils/native/base/src/parcel.cpp | 951 ++++- 37 files changed, 4662 insertions(+), 4436 deletions(-) create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-ext.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-filter.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-multithread.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-tag.h create mode 100644 3rdparty/gtest/include/gtest/hwext/gtest-utils.h create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc create mode 100644 3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc diff --git a/3rdparty/gtest/include/gtest/gtest-death-test.h b/3rdparty/gtest/include/gtest/gtest-death-test.h index dc878ff..9b4d4d1 100644 --- a/3rdparty/gtest/include/gtest/gtest-death-test.h +++ b/3rdparty/gtest/include/gtest/gtest-death-test.h @@ -35,8 +35,8 @@ // directly. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ #include "gtest/internal/gtest-death-test-internal.h" @@ -97,6 +97,10 @@ GTEST_API_ bool InDeathTestChild(); // // ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!"); // +// The final parameter to each of these macros is a matcher applied to any data +// the sub-process wrote to stderr. For compatibility with existing tests, a +// bare string is interpreted as a regular expression matcher. +// // On the regular expressions used in death tests: // // GOOGLETEST_CM0005 DO NOT DELETE @@ -162,27 +166,27 @@ GTEST_API_ bool InDeathTestChild(); // directory in PATH. // -// Asserts that a given statement causes the program to exit, with an -// integer exit status that satisfies predicate, and emitting error output -// that matches regex. -# define ASSERT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_) +// Asserts that a given `statement` causes the program to exit, with an +// integer exit status that satisfies `predicate`, and emitting error output +// that matches `matcher`. +# define ASSERT_EXIT(statement, predicate, matcher) \ + GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_FATAL_FAILURE_) -// Like ASSERT_EXIT, but continues on to successive tests in the +// Like `ASSERT_EXIT`, but continues on to successive tests in the // test suite, if any: -# define EXPECT_EXIT(statement, predicate, regex) \ - GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_) +# define EXPECT_EXIT(statement, predicate, matcher) \ + GTEST_DEATH_TEST_(statement, predicate, matcher, GTEST_NONFATAL_FAILURE_) -// Asserts that a given statement causes the program to exit, either by +// Asserts that a given `statement` causes the program to exit, either by // explicitly exiting with a nonzero exit code or being killed by a -// signal, and emitting error output that matches regex. -# define ASSERT_DEATH(statement, regex) \ - ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) +// signal, and emitting error output that matches `matcher`. +# define ASSERT_DEATH(statement, matcher) \ + ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher) -// Like ASSERT_DEATH, but continues on to successive tests in the +// Like `ASSERT_DEATH`, but continues on to successive tests in the // test suite, if any: -# define EXPECT_DEATH(statement, regex) \ - EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex) +# define EXPECT_DEATH(statement, matcher) \ + EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, matcher) // Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*: @@ -190,11 +194,10 @@ GTEST_API_ bool InDeathTestChild(); class GTEST_API_ ExitedWithCode { public: explicit ExitedWithCode(int exit_code); + ExitedWithCode(const ExitedWithCode&) = default; + void operator=(const ExitedWithCode& other) = delete; bool operator()(int exit_status) const; private: - // No implementation - assignment is unsupported. - void operator=(const ExitedWithCode& other); - const int exit_code_; }; @@ -340,4 +343,4 @@ class GTEST_API_ KilledBySignal { } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-matchers.h b/3rdparty/gtest/include/gtest/gtest-matchers.h index 9de6c2e..9fa34a0 100644 --- a/3rdparty/gtest/include/gtest/gtest-matchers.h +++ b/3rdparty/gtest/include/gtest/gtest-matchers.h @@ -32,13 +32,10 @@ // This file implements just enough of the matcher interface to allow // EXPECT_DEATH and friends to accept a matcher argument. -// IWYU pragma: private, include "testing/base/public/gunit.h" -// IWYU pragma: friend third_party/googletest/googlemock/.* -// IWYU pragma: friend third_party/googletest/googletest/.* - -#ifndef GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#include #include #include #include @@ -63,20 +60,16 @@ GTEST_DISABLE_MSC_WARNINGS_PUSH_( namespace testing { // To implement a matcher Foo for type T, define: -// 1. a class FooMatcherImpl that implements the -// MatcherInterface interface, and -// 2. a factory function that creates a Matcher object from a -// FooMatcherImpl*. -// -// The two-level delegation design makes it possible to allow a user -// to write "v" instead of "Eq(v)" where a Matcher is expected, which -// is impossible if we pass matchers by pointers. It also eases -// ownership management as Matcher objects can now be copied like -// plain values. - -// MatchResultListener is an abstract class. Its << operator can be -// used by a matcher to explain why a value matches or doesn't match. +// 1. a class FooMatcherMatcher that implements the matcher interface: +// using is_gtest_matcher = void; +// bool MatchAndExplain(const T&, std::ostream*); +// (MatchResultListener* can also be used instead of std::ostream*) +// void DescribeTo(std::ostream*); +// void DescribeNegationTo(std::ostream*); // +// 2. a factory function that creates a Matcher object from a +// FooMatcherMatcher. + class MatchResultListener { public: // Creates a listener object with the given underlying ostream. The @@ -113,7 +106,7 @@ inline MatchResultListener::~MatchResultListener() { // An instance of a subclass of this knows how to describe itself as a // matcher. -class MatcherDescriberInterface { +class GTEST_API_ MatcherDescriberInterface { public: virtual ~MatcherDescriberInterface() {} @@ -181,31 +174,6 @@ class MatcherInterface : public MatcherDescriberInterface { namespace internal { -// Converts a MatcherInterface to a MatcherInterface. -template -class MatcherInterfaceAdapter : public MatcherInterface { - public: - explicit MatcherInterfaceAdapter(const MatcherInterface* impl) - : impl_(impl) {} - ~MatcherInterfaceAdapter() override { delete impl_; } - - void DescribeTo(::std::ostream* os) const override { impl_->DescribeTo(os); } - - void DescribeNegationTo(::std::ostream* os) const override { - impl_->DescribeNegationTo(os); - } - - bool MatchAndExplain(const T& x, - MatchResultListener* listener) const override { - return impl_->MatchAndExplain(x, listener); - } - - private: - const MatcherInterface* const impl_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MatcherInterfaceAdapter); -}; - struct AnyEq { template bool operator()(const A& a, const B& b) const { return a == b; } @@ -252,16 +220,35 @@ class StreamMatchResultListener : public MatchResultListener { GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); }; +struct SharedPayloadBase { + std::atomic ref{1}; + void Ref() { ref.fetch_add(1, std::memory_order_relaxed); } + bool Unref() { return ref.fetch_sub(1, std::memory_order_acq_rel) == 1; } +}; + +template +struct SharedPayload : SharedPayloadBase { + explicit SharedPayload(const T& v) : value(v) {} + explicit SharedPayload(T&& v) : value(std::move(v)) {} + + static void Destroy(SharedPayloadBase* shared) { + delete static_cast(shared); + } + + T value; +}; + // An internal class for implementing Matcher, which will derive // from it. We put functionalities common to all Matcher // specializations here to avoid code duplication. template -class MatcherBase { +class MatcherBase : private MatcherDescriberInterface { public: // Returns true if and only if the matcher matches x; also explains the // match result to 'listener'. bool MatchAndExplain(const T& x, MatchResultListener* listener) const { - return impl_->MatchAndExplain(x, listener); + GTEST_CHECK_(vtable_ != nullptr); + return vtable_->match_and_explain(*this, x, listener); } // Returns true if and only if this matcher matches x. @@ -271,11 +258,15 @@ class MatcherBase { } // Describes this matcher to an ostream. - void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } + void DescribeTo(::std::ostream* os) const final { + GTEST_CHECK_(vtable_ != nullptr); + vtable_->describe(*this, os, false); + } // Describes the negation of this matcher to an ostream. - void DescribeNegationTo(::std::ostream* os) const { - impl_->DescribeNegationTo(os); + void DescribeNegationTo(::std::ostream* os) const final { + GTEST_CHECK_(vtable_ != nullptr); + vtable_->describe(*this, os, true); } // Explains why x matches, or doesn't match, the matcher. @@ -288,31 +279,194 @@ class MatcherBase { // of the describer, which is only guaranteed to be alive when // this matcher object is alive. const MatcherDescriberInterface* GetDescriber() const { - return impl_.get(); + if (vtable_ == nullptr) return nullptr; + return vtable_->get_describer(*this); } protected: - MatcherBase() {} + MatcherBase() : vtable_(nullptr) {} // Constructs a matcher from its implementation. - explicit MatcherBase(const MatcherInterface* impl) : impl_(impl) {} - template - explicit MatcherBase( - const MatcherInterface* impl, - typename std::enable_if::value>::type* = - nullptr) - : impl_(new internal::MatcherInterfaceAdapter(impl)) {} + explicit MatcherBase(const MatcherInterface* impl) { + Init(impl); + } + + template ::type::is_gtest_matcher> + MatcherBase(M&& m) { // NOLINT + Init(std::forward(m)); + } + + MatcherBase(const MatcherBase& other) + : vtable_(other.vtable_), buffer_(other.buffer_) { + if (IsShared()) buffer_.shared->Ref(); + } + + MatcherBase& operator=(const MatcherBase& other) { + if (this == &other) return *this; + Destroy(); + vtable_ = other.vtable_; + buffer_ = other.buffer_; + if (IsShared()) buffer_.shared->Ref(); + return *this; + } - MatcherBase(const MatcherBase&) = default; - MatcherBase& operator=(const MatcherBase&) = default; - MatcherBase(MatcherBase&&) = default; - MatcherBase& operator=(MatcherBase&&) = default; + MatcherBase(MatcherBase&& other) + : vtable_(other.vtable_), buffer_(other.buffer_) { + other.vtable_ = nullptr; + } + + MatcherBase& operator=(MatcherBase&& other) { + if (this == &other) return *this; + Destroy(); + vtable_ = other.vtable_; + buffer_ = other.buffer_; + other.vtable_ = nullptr; + return *this; + } - virtual ~MatcherBase() {} + ~MatcherBase() override { Destroy(); } private: - std::shared_ptr> impl_; + struct VTable { + bool (*match_and_explain)(const MatcherBase&, const T&, + MatchResultListener*); + void (*describe)(const MatcherBase&, std::ostream*, bool negation); + // Returns the captured object if it implements the interface, otherwise + // returns the MatcherBase itself. + const MatcherDescriberInterface* (*get_describer)(const MatcherBase&); + // Called on shared instances when the reference count reaches 0. + void (*shared_destroy)(SharedPayloadBase*); + }; + + bool IsShared() const { + return vtable_ != nullptr && vtable_->shared_destroy != nullptr; + } + + // If the implementation uses a listener, call that. + template + static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, + MatchResultListener* listener) + -> decltype(P::Get(m).MatchAndExplain(value, listener->stream())) { + return P::Get(m).MatchAndExplain(value, listener->stream()); + } + + template + static auto MatchAndExplainImpl(const MatcherBase& m, const T& value, + MatchResultListener* listener) + -> decltype(P::Get(m).MatchAndExplain(value, listener)) { + return P::Get(m).MatchAndExplain(value, listener); + } + + template + static void DescribeImpl(const MatcherBase& m, std::ostream* os, + bool negation) { + if (negation) { + P::Get(m).DescribeNegationTo(os); + } else { + P::Get(m).DescribeTo(os); + } + } + + template + static const MatcherDescriberInterface* GetDescriberImpl( + const MatcherBase& m) { + // If the impl is a MatcherDescriberInterface, then return it. + // Otherwise use MatcherBase itself. + // This allows us to implement the GetDescriber() function without support + // from the impl, but some users really want to get their impl back when + // they call GetDescriber(). + // We use std::get on a tuple as a workaround of not having `if constexpr`. + return std::get<( + std::is_convertible::value + ? 1 + : 0)>(std::make_tuple(&m, &P::Get(m))); + } + + template + const VTable* GetVTable() { + static constexpr VTable kVTable = {&MatchAndExplainImpl

, + &DescribeImpl

, &GetDescriberImpl

, + P::shared_destroy}; + return &kVTable; + } + + union Buffer { + // Add some types to give Buffer some common alignment/size use cases. + void* ptr; + double d; + int64_t i; + // And add one for the out-of-line cases. + SharedPayloadBase* shared; + }; + + void Destroy() { + if (IsShared() && buffer_.shared->Unref()) { + vtable_->shared_destroy(buffer_.shared); + } + } + + template + static constexpr bool IsInlined() { + return sizeof(M) <= sizeof(Buffer) && alignof(M) <= alignof(Buffer) && + std::is_trivially_copy_constructible::value && + std::is_trivially_destructible::value; + } + + template ()> + struct ValuePolicy { + static const M& Get(const MatcherBase& m) { + // When inlined along with Init, need to be explicit to avoid violating + // strict aliasing rules. + const M *ptr = static_cast( + static_cast(&m.buffer_)); + return *ptr; + } + static void Init(MatcherBase& m, M impl) { + ::new (static_cast(&m.buffer_)) M(impl); + } + static constexpr auto shared_destroy = nullptr; + }; + + template + struct ValuePolicy { + using Shared = SharedPayload; + static const M& Get(const MatcherBase& m) { + return static_cast(m.buffer_.shared)->value; + } + template + static void Init(MatcherBase& m, Arg&& arg) { + m.buffer_.shared = new Shared(std::forward(arg)); + } + static constexpr auto shared_destroy = &Shared::Destroy; + }; + + template + struct ValuePolicy*, B> { + using M = const MatcherInterface; + using Shared = SharedPayload>; + static const M& Get(const MatcherBase& m) { + return *static_cast(m.buffer_.shared)->value; + } + static void Init(MatcherBase& m, M* impl) { + m.buffer_.shared = new Shared(std::unique_ptr(impl)); + } + + static constexpr auto shared_destroy = &Shared::Destroy; + }; + + template + void Init(M&& m) { + using MM = typename std::decay::type; + using Policy = ValuePolicy; + vtable_ = GetVTable(); + Policy::Init(*this, std::forward(m)); + } + + const VTable* vtable_; + Buffer buffer_; }; } // namespace internal @@ -340,6 +494,10 @@ class Matcher : public internal::MatcherBase { nullptr) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) : internal::MatcherBase(std::forward(m)) {} // NOLINT + // Implicit constructor here allows people to write // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes Matcher(T value); // NOLINT @@ -357,6 +515,11 @@ class GTEST_API_ Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} + // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. Matcher(const std::string& s); // NOLINT @@ -376,6 +539,11 @@ class GTEST_API_ Matcher explicit Matcher(const MatcherInterface* impl) : internal::MatcherBase(impl) {} + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} + // Allows the user to write str instead of Eq(str) sometimes, where // str is a string object. Matcher(const std::string& s); // NOLINT @@ -384,18 +552,24 @@ class GTEST_API_ Matcher Matcher(const char* s); // NOLINT }; -#if GTEST_HAS_ABSL +#if GTEST_INTERNAL_HAS_STRING_VIEW // The following two specializations allow the user to write str // instead of Eq(str) and "foo" instead of Eq("foo") when a absl::string_view // matcher is expected. template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { +class GTEST_API_ Matcher + : public internal::MatcherBase { public: Matcher() {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) { + } // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. @@ -404,20 +578,25 @@ class GTEST_API_ Matcher // Allows the user to write "foo" instead of Eq("foo") sometimes. Matcher(const char* s); // NOLINT - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT + // Allows the user to pass absl::string_views or std::string_views directly. + Matcher(internal::StringView s); // NOLINT }; template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { +class GTEST_API_ Matcher + : public internal::MatcherBase { public: Matcher() {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + explicit Matcher(const MatcherInterface* impl) + : internal::MatcherBase(impl) {} + + template ::type::is_gtest_matcher> + Matcher(M&& m) // NOLINT + : internal::MatcherBase(std::forward(m)) {} // Allows the user to write str instead of Eq(str) sometimes, where // str is a std::string object. @@ -426,10 +605,10 @@ class GTEST_API_ Matcher // Allows the user to write "foo" instead of Eq("foo") sometimes. Matcher(const char* s); // NOLINT - // Allows the user to pass absl::string_views directly. - Matcher(absl::string_view s); // NOLINT + // Allows the user to pass absl::string_views or std::string_views directly. + Matcher(internal::StringView s); // NOLINT }; -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Prints a matcher in a human-readable format. template @@ -474,13 +653,13 @@ class PolymorphicMatcher { public: explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); } + void DescribeTo(::std::ostream* os) const override { impl_.DescribeTo(os); } - virtual void DescribeNegationTo(::std::ostream* os) const { + void DescribeNegationTo(::std::ostream* os) const override { impl_.DescribeNegationTo(os); } - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { + bool MatchAndExplain(T x, MatchResultListener* listener) const override { return impl_.MatchAndExplain(x, listener); } @@ -529,37 +708,32 @@ template class ComparisonBase { public: explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} + + using is_gtest_matcher = void; + template - operator Matcher() const { - return Matcher(new Impl(rhs_)); + bool MatchAndExplain(const Lhs& lhs, std::ostream*) const { + return Op()(lhs, Unwrap(rhs_)); + } + void DescribeTo(std::ostream* os) const { + *os << D::Desc() << " "; + UniversalPrint(Unwrap(rhs_), os); + } + void DescribeNegationTo(std::ostream* os) const { + *os << D::NegatedDesc() << " "; + UniversalPrint(Unwrap(rhs_), os); } private: template - static const T& Unwrap(const T& v) { return v; } + static const T& Unwrap(const T& v) { + return v; + } template - static const T& Unwrap(std::reference_wrapper v) { return v; } - - template - class Impl : public MatcherInterface { - public: - explicit Impl(const Rhs& rhs) : rhs_(rhs) {} - bool MatchAndExplain(Lhs lhs, - MatchResultListener* /* listener */) const override { - return Op()(lhs, Unwrap(rhs_)); - } - void DescribeTo(::std::ostream* os) const override { - *os << D::Desc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } - void DescribeNegationTo(::std::ostream* os) const override { - *os << D::NegatedDesc() << " "; - UniversalPrint(Unwrap(rhs_), os); - } + static const T& Unwrap(std::reference_wrapper v) { + return v; + } - private: - Rhs rhs_; - }; Rhs rhs_; }; @@ -612,6 +786,10 @@ class GeMatcher : public ComparisonBase, Rhs, AnyGe> { static const char* NegatedDesc() { return "isn't >="; } }; +template ::value>::type> +using StringLike = T; + // Implements polymorphic matchers MatchesRegex(regex) and // ContainsRegex(regex), which can be used as a Matcher as long as // T can be converted to a string. @@ -620,12 +798,12 @@ class MatchesRegexMatcher { MatchesRegexMatcher(const RE* regex, bool full_match) : regex_(regex), full_match_(full_match) {} -#if GTEST_HAS_ABSL - bool MatchAndExplain(const absl::string_view& s, +#if GTEST_INTERNAL_HAS_STRING_VIEW + bool MatchAndExplain(const internal::StringView& s, MatchResultListener* listener) const { return MatchAndExplain(std::string(s), listener); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW // Accepts pointer types, particularly: // const char* @@ -672,9 +850,10 @@ inline PolymorphicMatcher MatchesRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true)); } -inline PolymorphicMatcher MatchesRegex( - const std::string& regex) { - return MatchesRegex(new internal::RE(regex)); +template +PolymorphicMatcher MatchesRegex( + const internal::StringLike& regex) { + return MatchesRegex(new internal::RE(std::string(regex))); } // Matches a string that contains regular expression 'regex'. @@ -683,9 +862,10 @@ inline PolymorphicMatcher ContainsRegex( const internal::RE* regex) { return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false)); } -inline PolymorphicMatcher ContainsRegex( - const std::string& regex) { - return ContainsRegex(new internal::RE(regex)); +template +PolymorphicMatcher ContainsRegex( + const internal::StringLike& regex) { + return ContainsRegex(new internal::RE(std::string(regex))); } // Creates a polymorphic matcher that matches anything equal to x. @@ -747,4 +927,4 @@ inline internal::NeMatcher Ne(Rhs x) { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 -#endif // GTEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MATCHERS_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-message.h b/3rdparty/gtest/include/gtest/gtest-message.h index 4a80e11..becfd49 100644 --- a/3rdparty/gtest/include/gtest/gtest-message.h +++ b/3rdparty/gtest/include/gtest/gtest-message.h @@ -44,11 +44,12 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ -#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ #include #include +#include #include "gtest/internal/gtest-port.h" @@ -215,4 +216,4 @@ std::string StreamableToString(const T& streamable) { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_MESSAGE_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-param-test.h b/3rdparty/gtest/include/gtest/gtest-param-test.h index c2e6eae..804e702 100644 --- a/3rdparty/gtest/include/gtest/gtest-param-test.h +++ b/3rdparty/gtest/include/gtest/gtest-param-test.h @@ -30,12 +30,9 @@ // Macros and functions for implementing parameterized tests // in Google C++ Testing and Mocking Framework (Google Test) // -// This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ - +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ // Value-parameterized tests allow you to test your code with different // parameters without writing multiple copies of the same test. @@ -371,8 +368,6 @@ inline internal::ParamGenerator Bool() { // std::tuple where T1, T2, ..., TN are the types // of elements from sequences produces by gen1, gen2, ..., genN. // -// Combine can have up to 10 arguments. -// // Example: // // This will instantiate tests in test suite AnimalTest each one with @@ -416,19 +411,20 @@ internal::CartesianProductHolder Combine(const Generator&... g) { : public test_suite_name { \ public: \ GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ - virtual void TestBody(); \ + void TestBody() override; \ \ private: \ static int AddToRegistry() { \ ::testing::UnitTest::GetInstance() \ ->parameterized_test_registry() \ .GetTestSuitePatternHolder( \ - #test_suite_name, \ + GTEST_STRINGIFY_(test_suite_name), \ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ ->AddTestPattern( \ GTEST_STRINGIFY_(test_suite_name), GTEST_STRINGIFY_(test_name), \ new ::testing::internal::TestMetaFactory()); \ + test_suite_name, test_name)>(), \ + ::testing::internal::CodeLocation(__FILE__, __LINE__)); \ return 0; \ } \ static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \ @@ -483,13 +479,21 @@ internal::CartesianProductHolder Combine(const Generator&... g) { ::testing::UnitTest::GetInstance() \ ->parameterized_test_registry() \ .GetTestSuitePatternHolder( \ - #test_suite_name, \ + GTEST_STRINGIFY_(test_suite_name), \ ::testing::internal::CodeLocation(__FILE__, __LINE__)) \ ->AddTestSuiteInstantiation( \ - #prefix, >est_##prefix##test_suite_name##_EvalGenerator_, \ + GTEST_STRINGIFY_(prefix), \ + >est_##prefix##test_suite_name##_EvalGenerator_, \ >est_##prefix##test_suite_name##_EvalGenerateName_, \ __FILE__, __LINE__) + +// Allow Marking a Parameterized test class as not needing to be instantiated. +#define GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(T) \ + namespace gtest_do_not_use_outside_namespace_scope {} \ + static const ::testing::internal::MarkAsIgnored gtest_allow_ignore_##T( \ + GTEST_STRINGIFY_(T)) + // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #define INSTANTIATE_TEST_CASE_P \ @@ -500,4 +504,4 @@ internal::CartesianProductHolder Combine(const Generator&... g) { } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-printers.h b/3rdparty/gtest/include/gtest/gtest-printers.h index 56a0545..076c9de 100644 --- a/3rdparty/gtest/include/gtest/gtest-printers.h +++ b/3rdparty/gtest/include/gtest/gtest-printers.h @@ -97,10 +97,11 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #include +#include #include // NOLINT #include #include @@ -108,64 +109,124 @@ #include #include #include + #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" -#if GTEST_HAS_ABSL -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" -#include "absl/types/variant.h" -#endif // GTEST_HAS_ABSL - namespace testing { -// Definitions in the 'internal' and 'internal2' name spaces are -// subject to change without notice. DO NOT USE THEM IN USER CODE! -namespace internal2 { +// Definitions in the internal* namespaces are subject to change without notice. +// DO NOT USE THEM IN USER CODE! +namespace internal { -// Prints the given number of bytes in the given object to the given -// ostream. -GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, - size_t count, - ::std::ostream* os); +template +void UniversalPrint(const T& value, ::std::ostream* os); -// For selecting which printer to use when a given type has neither << -// nor PrintTo(). -enum TypeKind { - kProtobuf, // a protobuf type - kConvertibleToInteger, // a type implicitly convertible to BiggestInt - // (e.g. a named or unnamed enum type) -#if GTEST_HAS_ABSL - kConvertibleToStringView, // a type implicitly convertible to - // absl::string_view -#endif - kOtherType // anything else +// Used to print an STL-style container when the user doesn't define +// a PrintTo() for it. +struct ContainerPrinter { + template (0)) == sizeof(IsContainer)) && + !IsRecursiveContainer::value>::type> + static void PrintValue(const T& container, std::ostream* os) { + const size_t kMaxCount = 32; // The maximum number of elements to print. + *os << '{'; + size_t count = 0; + for (auto&& elem : container) { + if (count > 0) { + *os << ','; + if (count == kMaxCount) { // Enough has been printed. + *os << " ..."; + break; + } + } + *os << ' '; + // We cannot call PrintTo(elem, os) here as PrintTo() doesn't + // handle `elem` being a native array. + internal::UniversalPrint(elem, os); + ++count; + } + + if (count > 0) { + *os << ' '; + } + *os << '}'; + } }; -// TypeWithoutFormatter::PrintValue(value, os) is called -// by the universal printer to print a value of type T when neither -// operator<< nor PrintTo() is defined for T, where kTypeKind is the -// "kind" of T as defined by enum TypeKind. -template -class TypeWithoutFormatter { - public: - // This default version is called when kTypeKind is kOtherType. +// Used to print a pointer that is neither a char pointer nor a member +// pointer, when the user doesn't define PrintTo() for it. (A member +// variable pointer or member function pointer doesn't really point to +// a location in the address space. Their representation is +// implementation-defined. Therefore they will be printed as raw +// bytes.) +struct FunctionPointerPrinter { + template ::value>::type> + static void PrintValue(T* p, ::std::ostream* os) { + if (p == nullptr) { + *os << "NULL"; + } else { + // T is a function type, so '*os << p' doesn't do what we want + // (it just prints p as bool). We want to print p as a const + // void*. + *os << reinterpret_cast(p); + } + } +}; + +struct PointerPrinter { + template + static void PrintValue(T* p, ::std::ostream* os) { + if (p == nullptr) { + *os << "NULL"; + } else { + // T is not a function type. We just call << to print p, + // relying on ADL to pick up user-defined << for their pointer + // types, if any. + *os << p; + } + } +}; + +namespace internal_stream_operator_without_lexical_name_lookup { + +// The presence of an operator<< here will terminate lexical scope lookup +// straight away (even though it cannot be a match because of its argument +// types). Thus, the two operator<< calls in StreamPrinter will find only ADL +// candidates. +struct LookupBlocker {}; +void operator<<(LookupBlocker, LookupBlocker); + +struct StreamPrinter { + template ::value>::type, + // Only accept types for which we can find a streaming operator via + // ADL (possibly involving implicit conversions). + typename = decltype(std::declval() + << std::declval())> static void PrintValue(const T& value, ::std::ostream* os) { - PrintBytesInObjectTo( - static_cast( - reinterpret_cast(std::addressof(value))), - sizeof(value), os); + // Call streaming operator found by ADL, possibly with implicit conversions + // of the arguments. + *os << value; } }; -// We print a protobuf using its ShortDebugString() when the string -// doesn't exceed this many characters; otherwise we print it using -// DebugString() for better readability. -const size_t kProtobufOneLinerMaxLength = 50; +} // namespace internal_stream_operator_without_lexical_name_lookup -template -class TypeWithoutFormatter { - public: +struct ProtobufPrinter { + // We print a protobuf using its ShortDebugString() when the string + // doesn't exceed this many characters; otherwise we print it using + // DebugString() for better readability. + static const size_t kProtobufOneLinerMaxLength = 50; + + template ::value>::type> static void PrintValue(const T& value, ::std::ostream* os) { std::string pretty_str = value.ShortDebugString(); if (pretty_str.length() > kProtobufOneLinerMaxLength) { @@ -175,9 +236,7 @@ class TypeWithoutFormatter { } }; -template -class TypeWithoutFormatter { - public: +struct ConvertibleToIntegerPrinter { // Since T has no << operator or PrintTo() but can be implicitly // converted to BiggestInt, we print it as a BiggestInt. // @@ -185,112 +244,73 @@ class TypeWithoutFormatter { // case printing it as an integer is the desired behavior. In case // T is not an enum, printing it as an integer is the best we can do // given that it has no user-defined printer. - static void PrintValue(const T& value, ::std::ostream* os) { - const internal::BiggestInt kBigInt = value; - *os << kBigInt; + static void PrintValue(internal::BiggestInt value, ::std::ostream* os) { + *os << value; } }; -#if GTEST_HAS_ABSL -template -class TypeWithoutFormatter { - public: - // Since T has neither operator<< nor PrintTo() but can be implicitly - // converted to absl::string_view, we print it as a absl::string_view. - // - // Note: the implementation is further below, as it depends on - // internal::PrintTo symbol which is defined later in the file. - static void PrintValue(const T& value, ::std::ostream* os); -}; -#endif - -// Prints the given value to the given ostream. If the value is a -// protocol message, its debug string is printed; if it's an enum or -// of a type implicitly convertible to BiggestInt, it's printed as an -// integer; otherwise the bytes in the value are printed. This is -// what UniversalPrinter::Print() does when it knows nothing about -// type T and T has neither << operator nor PrintTo(). -// -// A user can override this behavior for a class type Foo by defining -// a << operator in the namespace where Foo is defined. -// -// We put this operator in namespace 'internal2' instead of 'internal' -// to simplify the implementation, as much code in 'internal' needs to -// use << in STL, which would conflict with our own << were it defined -// in 'internal'. -// -// Note that this operator<< takes a generic std::basic_ostream type instead of the more restricted std::ostream. If -// we define it to take an std::ostream instead, we'll get an -// "ambiguous overloads" compiler error when trying to print a type -// Foo that supports streaming to std::basic_ostream, as the compiler cannot tell whether -// operator<<(std::ostream&, const T&) or -// operator<<(std::basic_stream, const Foo&) is more -// specific. -template -::std::basic_ostream& operator<<( - ::std::basic_ostream& os, const T& x) { - TypeWithoutFormatter::value - ? kProtobuf - : std::is_convertible< - const T&, internal::BiggestInt>::value - ? kConvertibleToInteger - : -#if GTEST_HAS_ABSL - std::is_convertible< - const T&, absl::string_view>::value - ? kConvertibleToStringView - : +struct ConvertibleToStringViewPrinter { +#if GTEST_INTERNAL_HAS_STRING_VIEW + static void PrintValue(internal::StringView value, ::std::ostream* os) { + internal::UniversalPrint(value, os); + } #endif - kOtherType)>::PrintValue(x, &os); - return os; -} +}; -} // namespace internal2 -} // namespace testing -// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up -// magic needed for implementing UniversalPrinter won't work. -namespace testing_internal { +// Prints the given number of bytes in the given object to the given +// ostream. +GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes, + size_t count, + ::std::ostream* os); +struct RawBytesPrinter { + // SFINAE on `sizeof` to make sure we have a complete type. + template + static void PrintValue(const T& value, ::std::ostream* os) { + PrintBytesInObjectTo( + static_cast( + // Load bearing cast to void* to support iOS + reinterpret_cast(std::addressof(value))), + sizeof(value), os); + } +}; -// Used to print a value that is not an STL-style container when the -// user doesn't define PrintTo() for it. -template -void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) { - // With the following statement, during unqualified name lookup, - // testing::internal2::operator<< appears as if it was declared in - // the nearest enclosing namespace that contains both - // ::testing_internal and ::testing::internal2, i.e. the global - // namespace. For more details, refer to the C++ Standard section - // 7.3.4-1 [namespace.udir]. This allows us to fall back onto - // testing::internal2::operator<< in case T doesn't come with a << - // operator. - // - // We cannot write 'using ::testing::internal2::operator<<;', which - // gcc 3.3 fails to compile due to a compiler bug. - using namespace ::testing::internal2; // NOLINT +struct FallbackPrinter { + template + static void PrintValue(const T&, ::std::ostream* os) { + *os << "(incomplete type)"; + } +}; - // Assuming T is defined in namespace foo, in the next statement, - // the compiler will consider all of: - // - // 1. foo::operator<< (thanks to Koenig look-up), - // 2. ::operator<< (as the current namespace is enclosed in ::), - // 3. testing::internal2::operator<< (thanks to the using statement above). - // - // The operator<< whose type matches T best will be picked. - // - // We deliberately allow #2 to be a candidate, as sometimes it's - // impossible to define #1 (e.g. when foo is ::std, defining - // anything in it is undefined behavior unless you are a compiler - // vendor.). - *os << value; -} +// Try every printer in order and return the first one that works. +template +struct FindFirstPrinter : FindFirstPrinter {}; -} // namespace testing_internal +template +struct FindFirstPrinter< + T, decltype(Printer::PrintValue(std::declval(), nullptr)), + Printer, Printers...> { + using type = Printer; +}; -namespace testing { -namespace internal { +// Select the best printer in the following order: +// - Print containers (they have begin/end/etc). +// - Print function pointers. +// - Print object pointers. +// - Use the stream operator, if available. +// - Print protocol buffers. +// - Print types convertible to BiggestInt. +// - Print types convertible to StringView, if available. +// - Fallback to printing the raw bytes of the object. +template +void PrintWithFallback(const T& value, ::std::ostream* os) { + using Printer = typename FindFirstPrinter< + T, void, ContainerPrinter, FunctionPointerPrinter, PointerPrinter, + internal_stream_operator_without_lexical_name_lookup::StreamPrinter, + ProtobufPrinter, ConvertibleToIntegerPrinter, + ConvertibleToStringViewPrinter, RawBytesPrinter, FallbackPrinter>::type; + Printer::PrintValue(value, os); +} // FormatForComparison::Format(value) formats a // value of type ToPrint that is an operand of a comparison assertion @@ -340,6 +360,14 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); +#ifdef __cpp_char8_t +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char8_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char8_t); +#endif +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char16_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char16_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char32_t); +GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char32_t); #undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_ @@ -357,6 +385,14 @@ GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string); GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string); +#ifdef __cpp_char8_t +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char8_t, ::std::u8string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char8_t, ::std::u8string); +#endif +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char16_t, ::std::u16string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char16_t, ::std::u16string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char32_t, ::std::u32string); +GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char32_t, ::std::u32string); #if GTEST_HAS_STD_WSTRING GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring); @@ -389,85 +425,6 @@ std::string FormatForComparisonFailureMessage( template class UniversalPrinter; -template -void UniversalPrint(const T& value, ::std::ostream* os); - -enum DefaultPrinterType { - kPrintContainer, - kPrintPointer, - kPrintFunctionPointer, - kPrintOther, -}; -template struct WrapPrinterType {}; - -// Used to print an STL-style container when the user doesn't define -// a PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const C& container, ::std::ostream* os) { - const size_t kMaxCount = 32; // The maximum number of elements to print. - *os << '{'; - size_t count = 0; - for (typename C::const_iterator it = container.begin(); - it != container.end(); ++it, ++count) { - if (count > 0) { - *os << ','; - if (count == kMaxCount) { // Enough has been printed. - *os << " ..."; - break; - } - } - *os << ' '; - // We cannot call PrintTo(*it, os) here as PrintTo() doesn't - // handle *it being a native array. - internal::UniversalPrint(*it, os); - } - - if (count > 0) { - *os << ' '; - } - *os << '}'; -} - -// Used to print a pointer that is neither a char pointer nor a member -// pointer, when the user doesn't define PrintTo() for it. (A member -// variable pointer or member function pointer doesn't really point to -// a location in the address space. Their representation is -// implementation-defined. Therefore they will be printed as raw -// bytes.) -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is not a function type. We just call << to print p, - // relying on ADL to pick up user-defined << for their pointer - // types, if any. - *os << p; - } -} -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - T* p, ::std::ostream* os) { - if (p == nullptr) { - *os << "NULL"; - } else { - // T is a function type, so '*os << p' doesn't do what we want - // (it just prints p as bool). We want to print p as a const - // void*. - *os << reinterpret_cast(p); - } -} - -// Used to print a non-container, non-pointer value when the user -// doesn't define PrintTo() for it. -template -void DefaultPrintTo(WrapPrinterType /* dummy */, - const T& value, ::std::ostream* os) { - ::testing_internal::DefaultPrintNonContainerTo(value, os); -} - // Prints the given value using the << operator if it has one; // otherwise prints the bytes in it. This is what // UniversalPrinter::Print() does when PrintTo() is not specialized @@ -481,36 +438,7 @@ void DefaultPrintTo(WrapPrinterType /* dummy */, // wants). template void PrintTo(const T& value, ::std::ostream* os) { - // DefaultPrintTo() is overloaded. The type of its first argument - // determines which version will be picked. - // - // Note that we check for container types here, prior to we check - // for protocol message types in our operator<<. The rationale is: - // - // For protocol messages, we want to give people a chance to - // override Google Mock's format by defining a PrintTo() or - // operator<<. For STL containers, other formats can be - // incompatible with Google Mock's format for the container - // elements; therefore we check for container types here to ensure - // that our format is used. - // - // Note that MSVC and clang-cl do allow an implicit conversion from - // pointer-to-function to pointer-to-object, but clang-cl warns on it. - // So don't use ImplicitlyConvertible if it can be helped since it will - // cause this warning, and use a separate overload of DefaultPrintTo for - // function pointers so that the `*os << p` in the object pointer overload - // doesn't cause that warning either. - DefaultPrintTo( - WrapPrinterType < - (sizeof(IsContainerTest(0)) == sizeof(IsContainer)) && - !IsRecursiveContainer::value - ? kPrintContainer - : !std::is_pointer::value - ? kPrintOther - : std::is_function::type>::value - ? kPrintFunctionPointer - : kPrintPointer > (), - value, os); + internal::PrintWithFallback(value, os); } // The following list of PrintTo() overloads tells @@ -541,6 +469,16 @@ inline void PrintTo(bool x, ::std::ostream* os) { // is implemented as an unsigned type. GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os); +GTEST_API_ void PrintTo(char32_t c, ::std::ostream* os); +inline void PrintTo(char16_t c, ::std::ostream* os) { + PrintTo(ImplicitCast_(c), os); +} +#ifdef __cpp_char8_t +inline void PrintTo(char8_t c, ::std::ostream* os) { + PrintTo(ImplicitCast_(c), os); +} +#endif + // Overloads for C strings. GTEST_API_ void PrintTo(const char* s, ::std::ostream* os); inline void PrintTo(char* s, ::std::ostream* os) { @@ -561,6 +499,23 @@ inline void PrintTo(const unsigned char* s, ::std::ostream* os) { inline void PrintTo(unsigned char* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } +#ifdef __cpp_char8_t +// Overloads for u8 strings. +GTEST_API_ void PrintTo(const char8_t* s, ::std::ostream* os); +inline void PrintTo(char8_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +#endif +// Overloads for u16 strings. +GTEST_API_ void PrintTo(const char16_t* s, ::std::ostream* os); +inline void PrintTo(char16_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} +// Overloads for u32 strings. +GTEST_API_ void PrintTo(const char32_t* s, ::std::ostream* os); +inline void PrintTo(char32_t* s, ::std::ostream* os) { + PrintTo(ImplicitCast_(s), os); +} // MSVC can be configured to define wchar_t as a typedef of unsigned // short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native @@ -595,6 +550,26 @@ inline void PrintTo(const ::std::string& s, ::std::ostream* os) { PrintStringTo(s, os); } +// Overloads for ::std::u8string +#ifdef __cpp_char8_t +GTEST_API_ void PrintU8StringTo(const ::std::u8string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u8string& s, ::std::ostream* os) { + PrintU8StringTo(s, os); +} +#endif + +// Overloads for ::std::u16string +GTEST_API_ void PrintU16StringTo(const ::std::u16string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u16string& s, ::std::ostream* os) { + PrintU16StringTo(s, os); +} + +// Overloads for ::std::u32string +GTEST_API_ void PrintU32StringTo(const ::std::u32string& s, ::std::ostream* os); +inline void PrintTo(const ::std::u32string& s, ::std::ostream* os) { + PrintU32StringTo(s, os); +} + // Overloads for ::std::wstring. #if GTEST_HAS_STD_WSTRING GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os); @@ -603,12 +578,12 @@ inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) { } #endif // GTEST_HAS_STD_WSTRING -#if GTEST_HAS_ABSL -// Overload for absl::string_view. -inline void PrintTo(absl::string_view sp, ::std::ostream* os) { +#if GTEST_INTERNAL_HAS_STRING_VIEW +// Overload for internal::StringView. +inline void PrintTo(internal::StringView sp, ::std::ostream* os) { PrintTo(::std::string(sp), os); } -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_STRING_VIEW inline void PrintTo(std::nullptr_t, ::std::ostream* os) { *os << "(nullptr)"; } @@ -617,6 +592,43 @@ void PrintTo(std::reference_wrapper ref, ::std::ostream* os) { UniversalPrinter::Print(ref.get(), os); } +inline const void* VoidifyPointer(const void* p) { return p; } +inline const void* VoidifyPointer(volatile const void* p) { + return const_cast(p); +} + +template +void PrintSmartPointer(const Ptr& ptr, std::ostream* os, char) { + if (ptr == nullptr) { + *os << "(nullptr)"; + } else { + // We can't print the value. Just print the pointer.. + *os << "(" << (VoidifyPointer)(ptr.get()) << ")"; + } +} +template ::value && + !std::is_array::value>::type> +void PrintSmartPointer(const Ptr& ptr, std::ostream* os, int) { + if (ptr == nullptr) { + *os << "(nullptr)"; + } else { + *os << "(ptr = " << (VoidifyPointer)(ptr.get()) << ", value = "; + UniversalPrinter::Print(*ptr, os); + *os << ")"; + } +} + +template +void PrintTo(const std::unique_ptr& ptr, std::ostream* os) { + (PrintSmartPointer)(ptr, os, 0); +} + +template +void PrintTo(const std::shared_ptr& ptr, std::ostream* os) { + (PrintSmartPointer)(ptr, os, 0); +} + // Helper function for printing a tuple. T must be instantiated with // a tuple type. template @@ -682,14 +694,46 @@ class UniversalPrinter { GTEST_DISABLE_MSC_WARNINGS_POP_() }; -#if GTEST_HAS_ABSL +// Remove any const-qualifiers before passing a type to UniversalPrinter. +template +class UniversalPrinter : public UniversalPrinter {}; + +#if GTEST_INTERNAL_HAS_ANY + +// Printer for std::any / absl::any -// Printer for absl::optional +template <> +class UniversalPrinter { + public: + static void Print(const Any& value, ::std::ostream* os) { + if (value.has_value()) { + *os << "value of type " << GetTypeName(value); + } else { + *os << "no value"; + } + } + + private: + static std::string GetTypeName(const Any& value) { +#if GTEST_HAS_RTTI + return internal::GetTypeName(value.type()); +#else + static_cast(value); // possibly unused + return ""; +#endif // GTEST_HAS_RTTI + } +}; + +#endif // GTEST_INTERNAL_HAS_ANY + +#if GTEST_INTERNAL_HAS_OPTIONAL + +// Printer for std::optional / absl::optional template -class UniversalPrinter<::absl::optional> { +class UniversalPrinter> { public: - static void Print(const ::absl::optional& value, ::std::ostream* os) { + static void Print(const Optional& value, ::std::ostream* os) { *os << '('; if (!value) { *os << "nullopt"; @@ -700,14 +744,22 @@ class UniversalPrinter<::absl::optional> { } }; -// Printer for absl::variant +#endif // GTEST_INTERNAL_HAS_OPTIONAL + +#if GTEST_INTERNAL_HAS_VARIANT + +// Printer for std::variant / absl::variant template -class UniversalPrinter<::absl::variant> { +class UniversalPrinter> { public: - static void Print(const ::absl::variant& value, ::std::ostream* os) { + static void Print(const Variant& value, ::std::ostream* os) { *os << '('; - absl::visit(Visitor{os}, value); +#if GTEST_HAS_ABSL + absl::visit(Visitor{os, value.index()}, value); +#else + std::visit(Visitor{os, value.index()}, value); +#endif // GTEST_HAS_ABSL *os << ')'; } @@ -715,14 +767,16 @@ class UniversalPrinter<::absl::variant> { struct Visitor { template void operator()(const U& u) const { - *os << "'" << GetTypeName() << "' with value "; + *os << "'" << GetTypeName() << "(index = " << index + << ")' with value "; UniversalPrint(u, os); } ::std::ostream* os; + std::size_t index; }; }; -#endif // GTEST_HAS_ABSL +#endif // GTEST_INTERNAL_HAS_VARIANT // UniversalPrintArray(begin, len, os) prints an array of 'len' // elements, starting at address 'begin'. @@ -751,6 +805,20 @@ void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) { GTEST_API_ void UniversalPrintArray( const char* begin, size_t len, ::std::ostream* os); +#ifdef __cpp_char8_t +// This overload prints a (const) char8_t array compactly. +GTEST_API_ void UniversalPrintArray(const char8_t* begin, size_t len, + ::std::ostream* os); +#endif + +// This overload prints a (const) char16_t array compactly. +GTEST_API_ void UniversalPrintArray(const char16_t* begin, size_t len, + ::std::ostream* os); + +// This overload prints a (const) char32_t array compactly. +GTEST_API_ void UniversalPrintArray(const char32_t* begin, size_t len, + ::std::ostream* os); + // This overload prints a (const) wchar_t array compactly. GTEST_API_ void UniversalPrintArray( const wchar_t* begin, size_t len, ::std::ostream* os); @@ -823,12 +891,55 @@ class UniversalTersePrinter { } }; template <> -class UniversalTersePrinter { +class UniversalTersePrinter : public UniversalTersePrinter { +}; + +#ifdef __cpp_char8_t +template <> +class UniversalTersePrinter { public: - static void Print(char* str, ::std::ostream* os) { - UniversalTersePrinter::Print(str, os); + static void Print(const char8_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u8string(str), os); + } } }; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; +#endif + +template <> +class UniversalTersePrinter { + public: + static void Print(const char16_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u16string(str), os); + } + } +}; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; + +template <> +class UniversalTersePrinter { + public: + static void Print(const char32_t* str, ::std::ostream* os) { + if (str == nullptr) { + *os << "NULL"; + } else { + UniversalPrint(::std::u32string(str), os); + } + } +}; +template <> +class UniversalTersePrinter + : public UniversalTersePrinter {}; #if GTEST_HAS_STD_WSTRING template <> @@ -901,16 +1012,6 @@ Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) { } // namespace internal -#if GTEST_HAS_ABSL -namespace internal2 { -template -void TypeWithoutFormatter::PrintValue( - const T& value, ::std::ostream* os) { - internal::PrintTo(absl::string_view(value), os); -} -} // namespace internal2 -#endif - template ::std::string PrintToString(const T& value) { ::std::stringstream ss; @@ -925,4 +1026,4 @@ template // declarations from this file. #include "gtest/internal/custom/gtest-printers.h" -#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-spi.h b/3rdparty/gtest/include/gtest/gtest-spi.h index aa38870..eacef44 100644 --- a/3rdparty/gtest/include/gtest/gtest-spi.h +++ b/3rdparty/gtest/include/gtest/gtest-spi.h @@ -33,8 +33,8 @@ // GOOGLETEST_CM0004 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_ -#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ #include "gtest/gtest.h" @@ -235,4 +235,4 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 }\ } while (::testing::internal::AlwaysFalse()) -#endif // GTEST_INCLUDE_GTEST_GTEST_SPI_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_SPI_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-test-part.h b/3rdparty/gtest/include/gtest/gtest-test-part.h index 05a7985..203fdf9 100644 --- a/3rdparty/gtest/include/gtest/gtest-test-part.h +++ b/3rdparty/gtest/include/gtest/gtest-test-part.h @@ -29,8 +29,8 @@ // // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ #include #include @@ -181,4 +181,4 @@ class GTEST_API_ HasNewFatalFailureHelper GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TEST_PART_H_ diff --git a/3rdparty/gtest/include/gtest/gtest-typed-test.h b/3rdparty/gtest/include/gtest/gtest-typed-test.h index 095ce05..9fdc6be 100644 --- a/3rdparty/gtest/include/gtest/gtest-typed-test.h +++ b/3rdparty/gtest/include/gtest/gtest-typed-test.h @@ -27,11 +27,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ // This header implements typed tests and type-parameterized tests. @@ -170,13 +169,12 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #endif // 0 +#include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-type-util.h" // Implements typed tests. -#if GTEST_HAS_TYPED_TEST - // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the name of the typedef for the type parameters of the @@ -188,24 +186,25 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #define GTEST_NAME_GENERATOR_(TestSuiteName) \ gtest_type_params_##TestSuiteName##_NameGenerator -#define TYPED_TEST_SUITE(CaseName, Types, ...) \ - typedef ::testing::internal::TypeList::type GTEST_TYPE_PARAMS_( \ - CaseName); \ - typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ +#define TYPED_TEST_SUITE(CaseName, Types, ...) \ + typedef ::testing::internal::GenerateTypeList::type \ + GTEST_TYPE_PARAMS_(CaseName); \ + typedef ::testing::internal::NameGeneratorSelector<__VA_ARGS__>::type \ GTEST_NAME_GENERATOR_(CaseName) -# define TYPED_TEST(CaseName, TestName) \ +#define TYPED_TEST(CaseName, TestName) \ + static_assert(sizeof(GTEST_STRINGIFY_(TestName)) > 1, \ + "test-name must not be empty"); \ template \ class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \ : public CaseName { \ private: \ typedef CaseName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ + void TestBody() override; \ }; \ static bool gtest_##CaseName##_##TestName##_registered_ \ - GTEST_ATTRIBUTE_UNUSED_ = \ - ::testing::internal::TypeParameterizedTest< \ + GTEST_ATTRIBUTE_UNUSED_ = ::testing::internal::TypeParameterizedTest< \ CaseName, \ ::testing::internal::TemplateSel, \ @@ -213,7 +212,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); CaseName)>::Register("", \ ::testing::internal::CodeLocation( \ __FILE__, __LINE__), \ - #CaseName, #TestName, 0, \ + GTEST_STRINGIFY_(CaseName), \ + GTEST_STRINGIFY_(TestName), 0, \ ::testing::internal::GenerateNames< \ GTEST_NAME_GENERATOR_(CaseName), \ GTEST_TYPE_PARAMS_(CaseName)>()); \ @@ -228,12 +228,8 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); TYPED_TEST_SUITE #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#endif // GTEST_HAS_TYPED_TEST - // Implements type-parameterized tests. -#if GTEST_HAS_TYPED_TEST_P - // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // Expands to the namespace name that the type-parameterized tests for @@ -276,24 +272,26 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); private: \ typedef SuiteName TestFixture; \ typedef gtest_TypeParam_ TypeParam; \ - virtual void TestBody(); \ + void TestBody() override; \ }; \ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \ GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).AddTestName( \ - __FILE__, __LINE__, #SuiteName, #TestName); \ + __FILE__, __LINE__, GTEST_STRINGIFY_(SuiteName), \ + GTEST_STRINGIFY_(TestName)); \ } \ template \ void GTEST_SUITE_NAMESPACE_( \ SuiteName)::TestName::TestBody() -#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ - namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ - typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ - } \ - static const char* const GTEST_REGISTERED_TEST_NAMES_( \ - SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ - GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ - __FILE__, __LINE__, #__VA_ARGS__) +// Note: this won't work correctly if the trailing arguments are macros. +#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) \ + namespace GTEST_SUITE_NAMESPACE_(SuiteName) { \ + typedef ::testing::internal::Templates<__VA_ARGS__> gtest_AllTests_; \ + } \ + static const char* const GTEST_REGISTERED_TEST_NAMES_( \ + SuiteName) GTEST_ATTRIBUTE_UNUSED_ = \ + GTEST_TYPED_TEST_SUITE_P_STATE_(SuiteName).VerifyRegisteredTestNames( \ + GTEST_STRINGIFY_(SuiteName), __FILE__, __LINE__, #__VA_ARGS__) // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ @@ -304,18 +302,21 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ #define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) \ + static_assert(sizeof(GTEST_STRINGIFY_(Prefix)) > 1, \ + "test-suit-prefix must not be empty"); \ static bool gtest_##Prefix##_##SuiteName GTEST_ATTRIBUTE_UNUSED_ = \ ::testing::internal::TypeParameterizedTestSuite< \ SuiteName, GTEST_SUITE_NAMESPACE_(SuiteName)::gtest_AllTests_, \ - ::testing::internal::TypeList::type>:: \ - Register(#Prefix, \ + ::testing::internal::GenerateTypeList::type>:: \ + Register(GTEST_STRINGIFY_(Prefix), \ ::testing::internal::CodeLocation(__FILE__, __LINE__), \ - >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), #SuiteName, \ + >EST_TYPED_TEST_SUITE_P_STATE_(SuiteName), \ + GTEST_STRINGIFY_(SuiteName), \ GTEST_REGISTERED_TEST_NAMES_(SuiteName), \ ::testing::internal::GenerateNames< \ ::testing::internal::NameGeneratorSelector< \ __VA_ARGS__>::type, \ - ::testing::internal::TypeList::type>()) + ::testing::internal::GenerateTypeList::type>()) // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ @@ -325,6 +326,4 @@ INSTANTIATE_TYPED_TEST_SUITE_P(My, FooTest, MyTypes); INSTANTIATE_TYPED_TEST_SUITE_P #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_ -#endif // GTEST_HAS_TYPED_TEST_P - -#endif // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest.h b/3rdparty/gtest/include/gtest/gtest.h index dbe5b1c..74a28dd 100644 --- a/3rdparty/gtest/include/gtest/gtest.h +++ b/3rdparty/gtest/include/gtest/gtest.h @@ -49,8 +49,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_H_ -#define GTEST_INCLUDE_GTEST_GTEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_H_ #include #include @@ -70,6 +70,10 @@ #include "gtest/gtest-test-part.h" #include "gtest/gtest-typed-test.h" +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-ext.h" +#include "gtest/hwext/gtest-filter.h" + GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ /* class A needs to have dll-interface to be used by clients of class B */) @@ -101,6 +105,10 @@ GTEST_DECLARE_bool_(catch_exceptions); // to let Google Test decide. GTEST_DECLARE_string_(color); +// This flag controls whether the test runner should continue execution past +// first failure. +GTEST_DECLARE_bool_(fail_fast); + // This flag sets up the filter to select by name using a glob pattern // the tests to run. If the filter is not given all tests are executed. GTEST_DECLARE_string_(filter); @@ -117,6 +125,9 @@ GTEST_DECLARE_bool_(list_tests); // in addition to its normal textual output. GTEST_DECLARE_string_(output); +// This flags control whether Google Test prints only test failures. +GTEST_DECLARE_bool_(brief); + // This flags control whether Google Test prints the elapsed time for each // test. GTEST_DECLARE_bool_(print_time); @@ -177,6 +188,7 @@ class FuchsiaDeathTest; class UnitTestImpl* GetUnitTestImpl(); void ReportFailureInUnknownLocation(TestPartResult::Type result_type, const std::string& message); +std::set* GetIgnoredParameterizedTestSuites(); } // namespace internal @@ -278,7 +290,11 @@ class GTEST_API_ AssertionResult { // Used in EXPECT_TRUE/FALSE(assertion_result). AssertionResult(const AssertionResult& other); -#if defined(_MSC_VER) && _MSC_VER < 1910 +// C4800 is a level 3 warning in Visual Studio 2015 and earlier. +// This warning is not emitted in Visual Studio 2017. +// This warning is off by default starting in Visual Studio 2019 but can be +// enabled with command-line options. +#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920) GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */) #endif @@ -298,7 +314,7 @@ class GTEST_API_ AssertionResult { = nullptr) : success_(success) {} -#if defined(_MSC_VER) && _MSC_VER < 1910 +#if defined(_MSC_VER) && (_MSC_VER < 1910 || _MSC_VER >= 1920) GTEST_DISABLE_MSC_WARNINGS_POP_() #endif @@ -406,27 +422,24 @@ class GTEST_API_ Test { // The d'tor is virtual as we intend to inherit from Test. virtual ~Test(); - // Sets up the stuff shared by all tests in this test case. + // Sets up the stuff shared by all tests in this test suite. // // Google Test will call Foo::SetUpTestSuite() before running the first - // test in test case Foo. Hence a sub-class can define its own + // test in test suite Foo. Hence a sub-class can define its own // SetUpTestSuite() method to shadow the one defined in the super // class. - // Failures that happen during SetUpTestSuite are logged but otherwise - // ignored. static void SetUpTestSuite() {} // Tears down the stuff shared by all tests in this test suite. // // Google Test will call Foo::TearDownTestSuite() after running the last - // test in test case Foo. Hence a sub-class can define its own + // test in test suite Foo. Hence a sub-class can define its own // TearDownTestSuite() method to shadow the one defined in the super // class. - // Failures that happen during TearDownTestSuite are logged but otherwise - // ignored. static void TearDownTestSuite() {} - // Legacy API is deprecated but still available + // Legacy API is deprecated but still available. Use SetUpTestSuite and + // TearDownTestSuite instead. #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ static void TearDownTestCase() {} static void SetUpTestCase() {} @@ -664,7 +677,7 @@ class GTEST_API_ TestResult { // Protects mutable state of the property vector and of owned // properties, whose values may be updated. - internal::Mutex test_properites_mutex_; + internal::Mutex test_properties_mutex_; // The vector of TestPartResults std::vector test_part_results_; @@ -794,6 +807,9 @@ class GTEST_API_ TestInfo { // deletes it. void Run(); + // Skip and records the test result for this object. + void Skip(); + static void ClearTestResult(TestInfo* test_info) { test_info->result_.Clear(); } @@ -889,7 +905,9 @@ class GTEST_API_ TestSuite { bool Passed() const { return !Failed(); } // Returns true if and only if the test suite failed. - bool Failed() const { return failed_test_count() > 0; } + bool Failed() const { + return failed_test_count() > 0 || ad_hoc_test_result().Failed(); + } // Returns the elapsed time, in milliseconds. TimeInMillis elapsed_time() const { return elapsed_time_; } @@ -940,6 +958,9 @@ class GTEST_API_ TestSuite { // Runs every test in this TestSuite. void Run(); + // Skips the execution of tests under this TestSuite + void Skip(); + // Runs SetUpTestSuite() for this TestSuite. This wrapper is needed // for catching exceptions thrown from SetUpTestSuite(). void RunSetUpTestSuite() { @@ -1420,6 +1441,7 @@ class GTEST_API_ UnitTest { friend class internal::StreamingListenerTest; friend class internal::UnitTestRecordPropertyTestHelper; friend Environment* AddGlobalTestEnvironment(Environment* env); + friend std::set* internal::GetIgnoredParameterizedTestSuites(); friend internal::UnitTestImpl* internal::GetUnitTestImpl(); friend void internal::ReportFailureInUnknownLocation( TestPartResult::Type result_type, @@ -1531,14 +1553,6 @@ AssertionResult CmpHelperEQ(const char* lhs_expression, return CmpHelperEQFailure(lhs_expression, rhs_expression, lhs, rhs); } -// With this overloaded version, we allow anonymous enums to be used -// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums -// can be implicitly cast to BiggestInt. -GTEST_API_ AssertionResult CmpHelperEQ(const char* lhs_expression, - const char* rhs_expression, - BiggestInt lhs, - BiggestInt rhs); - class EqHelper { public: // This templatized version is for the general case. @@ -1595,11 +1609,6 @@ AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2, // ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste // of similar code. // -// For each templatized helper function, we also define an overloaded -// version for BiggestInt in order to reduce code bloat and allow -// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled -// with gcc 4. -// // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. #define GTEST_IMPL_CMP_HELPER_(op_name, op)\ @@ -1611,22 +1620,20 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ } else {\ return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\ }\ -}\ -GTEST_API_ AssertionResult CmpHelper##op_name(\ - const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2) +} // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // Implements the helper function for {ASSERT|EXPECT}_NE -GTEST_IMPL_CMP_HELPER_(NE, !=); +GTEST_IMPL_CMP_HELPER_(NE, !=) // Implements the helper function for {ASSERT|EXPECT}_LE -GTEST_IMPL_CMP_HELPER_(LE, <=); +GTEST_IMPL_CMP_HELPER_(LE, <=) // Implements the helper function for {ASSERT|EXPECT}_LT -GTEST_IMPL_CMP_HELPER_(LT, <); +GTEST_IMPL_CMP_HELPER_(LT, <) // Implements the helper function for {ASSERT|EXPECT}_GE -GTEST_IMPL_CMP_HELPER_(GE, >=); +GTEST_IMPL_CMP_HELPER_(GE, >=) // Implements the helper function for {ASSERT|EXPECT}_GT -GTEST_IMPL_CMP_HELPER_(GT, >); +GTEST_IMPL_CMP_HELPER_(GT, >) #undef GTEST_IMPL_CMP_HELPER_ @@ -1803,12 +1810,6 @@ class GTEST_API_ AssertHelper { GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper); }; -enum GTestColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; - -GTEST_API_ GTEST_ATTRIBUTE_PRINTF_(2, 3) void ColoredPrintf(GTestColor color, - const char* fmt, - ...); - } // namespace internal // The pure interface class that all value-parameterized tests inherit from. @@ -1889,7 +1890,7 @@ class TestWithParam : public Test, public WithParamInterface { // Skips test in runtime. // Skipping test aborts current function. // Skipped tests are neither successful nor failed. -#define GTEST_SKIP() GTEST_SKIP_("Skipped") +#define GTEST_SKIP() GTEST_SKIP_("") // ADD_FAILURE unconditionally adds a failure to the current test. // SUCCEED generates a success - it doesn't automatically make the @@ -1965,19 +1966,38 @@ class TestWithParam : public Test, public WithParamInterface { // Boolean assertions. Condition can be either a Boolean expression or an // AssertionResult. For more information on how to use AssertionResult with // these macros see comments on that class. -#define EXPECT_TRUE(condition) \ +#define GTEST_EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) -#define EXPECT_FALSE(condition) \ +#define GTEST_EXPECT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_NONFATAL_FAILURE_) -#define ASSERT_TRUE(condition) \ +#define GTEST_ASSERT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_FATAL_FAILURE_) -#define ASSERT_FALSE(condition) \ +#define GTEST_ASSERT_FALSE(condition) \ GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \ GTEST_FATAL_FAILURE_) +// Define these macros to 1 to omit the definition of the corresponding +// EXPECT or ASSERT, which clashes with some users' own code. + +#if !GTEST_DONT_DEFINE_EXPECT_TRUE +#define EXPECT_TRUE(condition) GTEST_EXPECT_TRUE(condition) +#endif + +#if !GTEST_DONT_DEFINE_EXPECT_FALSE +#define EXPECT_FALSE(condition) GTEST_EXPECT_FALSE(condition) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_TRUE +#define ASSERT_TRUE(condition) GTEST_ASSERT_TRUE(condition) +#endif + +#if !GTEST_DONT_DEFINE_ASSERT_FALSE +#define ASSERT_FALSE(condition) GTEST_ASSERT_FALSE(condition) +#endif + // Macros for testing equalities and inequalities. // // * {ASSERT|EXPECT}_EQ(v1, v2): Tests that v1 == v2 @@ -2298,8 +2318,7 @@ class GTEST_API_ ScopedTrace { // to cause a compiler error. template constexpr bool StaticAssertTypeEq() noexcept { - static_assert(std::is_same::value, - "type1 and type2 are not the same type"); + static_assert(std::is_same::value, "T1 and T2 are not the same type"); return true; } @@ -2365,9 +2384,11 @@ constexpr bool StaticAssertTypeEq() noexcept { // } // // GOOGLETEST_CM0011 DO NOT DELETE +#if !GTEST_DONT_DEFINE_TEST #define TEST_F(test_fixture, test_name)\ GTEST_TEST_(test_fixture, test_name, test_fixture, \ ::testing::internal::GetTypeId()) +#endif // !GTEST_DONT_DEFINE_TEST // Returns a path to temporary directory. // Tries to determine an appropriate directory for the platform. @@ -2475,4 +2496,4 @@ inline int RUN_ALL_TESTS() { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_GTEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_H_ diff --git a/3rdparty/gtest/include/gtest/gtest_pred_impl.h b/3rdparty/gtest/include/gtest/gtest_pred_impl.h index d514255..5029a9b 100644 --- a/3rdparty/gtest/include/gtest/gtest_pred_impl.h +++ b/3rdparty/gtest/include/gtest/gtest_pred_impl.h @@ -33,8 +33,8 @@ // Implements a family of generic predicate assertion macros. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ #include "gtest/gtest.h" @@ -356,4 +356,4 @@ AssertionResult AssertPred5Helper(const char* pred_text, } // namespace testing -#endif // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_ diff --git a/3rdparty/gtest/include/gtest/gtest_prod.h b/3rdparty/gtest/include/gtest/gtest_prod.h index e651671..38b9d85 100644 --- a/3rdparty/gtest/include/gtest/gtest_prod.h +++ b/3rdparty/gtest/include/gtest/gtest_prod.h @@ -31,8 +31,8 @@ // Google C++ Testing and Mocking Framework definitions useful in production code. // GOOGLETEST_CM0003 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ -#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ +#define GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ // When you need to test the private or protected members of a class, // use the FRIEND_TEST macro to declare your tests as friends of the @@ -58,4 +58,4 @@ #define FRIEND_TEST(test_case_name, test_name)\ friend class test_case_name##_##test_name##_Test -#endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_GTEST_PROD_H_ diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-ext.h b/3rdparty/gtest/include/gtest/hwext/gtest-ext.h new file mode 100644 index 0000000..e44b3bb --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-ext.h @@ -0,0 +1,83 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_EXT_H_ +#define GTEST_INCLUDE_GTEST_GTEST_EXT_H_ + +#include +#include "gtest/gtest.h" + +namespace testing { + namespace ext { + + // helper macro to create unique variable name + #define GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, file_line) \ + test_case_name##_##test_name##_##file_line + + // 1. define a extended TEST supporting test flags registing + #if !GTEST_DONT_DEFINE_TEST + # define HWTEST(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Plain);\ + TEST(test_case_name, test_name) + #endif + + // 2. define a extended TEST_F supporting test flags registing + # define HWTEST_F(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Fixtured);\ + TEST_F(test_case_name, test_name) + + // 3. define a extended TYPED_TEST supporting test flags registing + # define HWTYPED_TEST(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Typed);\ + TYPED_TEST(test_case_name, test_name) + + // 4. define a extended TYPED_TEST_P supporting test flags registing + # define HWTYPED_TEST_P(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::PatternTyped);\ + TYPED_TEST_P(test_case_name, test_name) + + // 5. define a extended TEST_P supporting test flags registing + # define HWTEST_P(test_case_name, test_name, test_flags) \ + bool GTEST_TEST_UNIQUE_ID_(test_case_name, test_name, __LINE__) = testing::ext::TestDefManager::instance()->regist(#test_case_name, #test_name, test_flags, testing::ext::Parameterized);\ + TEST_P(test_case_name, test_name) + + // test definition types + enum TestDefType { + Plain, Fixtured, Typed, PatternTyped, Parameterized + }; + // case_name/test_name matchNaming pattern + enum NamingMatchType { + AEqualsB, AStartsWithB, AContainsB, AEndsWithB + }; + + // information of a test difinition + class TestDefInfo { + public: + friend class TestDefManager; + private: + const static char kNamingSepchar = '/'; + const char* const test_case_name; + const char* const name; + const int flags; + const TestDefType def_type; + TestDefInfo(const char* tcn, const char* n, int fs, TestDefType tdf); + }; + + class TestDefManager { + private: + TestDefManager() {}; + std::vector testDefInfos; + const TestDefInfo* findDefFor(const TestInfo* test) const; + bool matchNaming(const char* const a, const char* const b, NamingMatchType mt) const; + public: + static TestDefManager* instance(); + static const TestDefManager* cinstance(); + bool regist(const char* test_case_name, const char* test_name, int test_flags, TestDefType tdf); + int queryFlagsFor(const TestInfo* test, int def_value) const; + int getLevel(const std::string testcasename, const std::string testname) const; + int* getTestFlags(const std::string testcasename, const std::string testname) const; + }; + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_EXT_H_ \ No newline at end of file diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-filter.h b/3rdparty/gtest/include/gtest/hwext/gtest-filter.h new file mode 100644 index 0000000..3be4481 --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-filter.h @@ -0,0 +1,48 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ +#define GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ + +#include +#include +#include + +namespace testing { + namespace ext { + + using ::std::string; + using ::std::map; + using ::std::vector; + + class TestFilter { + public: + map& getAllFilterFlagsKv(); + void printHelp() const; + bool postParsingArguments(); + bool accept(int flags) const; + void reset(); + static TestFilter* instance(); + + private: + TestFilter() {}; + static const char* const kStrictFilter; + int requiredFlags; + // strcit filter requires the entirely same test flags and require no + bool strictMode; + bool flag_kvs_inited; // teels iff the filter kvs has been parsed + bool ready; // teels iff the filter are ready to be used + void postSetType(vector vectemp); + void postSetSize(vector vectemp); + void postSetRank(vector vectemp); + map filterFlagsKv; + vector vecTestLevel; + vector vecType; + vector vecSize; + vector vecRank; + }; + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_FILTER_H_ + diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h b/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h new file mode 100644 index 0000000..e7254e6 --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-multithread.h @@ -0,0 +1,117 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +* Description:多线程测试框架(GTEST-MULTITHREAD)库接口声明 +* Author: +* Create:2023/2/24 +*/ + +#ifndef __MULTI_THREAD_TEST_H__ +#define __MULTI_THREAD_TEST_H__ + +#include +#include +#include +#include +#include "gtest/gtest.h" + +using ::testing::TestPartResult; + +namespace testing{ + namespace mt { + using PF = void(*)(); + using uint = unsigned int; + const uint RANDOM_THREAD_ID = 0x3f3f3f3f; //线程ID常量 + static uint g_thread_count = 10 ; //全局变量,默认线程数是10 + inline void setThreadNum(uint num) + { + g_thread_count = num; + } + class TestTask { + public: + TestTask() = default; + TestTask(std::string ts, std::string tc, PF func) : m_testsuite(ts), m_testcase(tc), m_func(func){} + std::string m_testsuite; + std::string m_testcase; + PF m_func; + }; + class ThreadTaskEntry { + public: + ThreadTaskEntry(std::vector v_task) : funcList(v_task) {} + std::thread *thread; + std::vector funcList; + }; + class MultiThreadTest { + private: + std::vector> threadTasks; + std::vector threadTestEntryList; + std::map> randomTasks; + + public: + void doTest(); + void run(); + MultiThreadTest() {} + unsigned m_threadNum; + MultiThreadTest(unsigned int t_cnt) : m_threadNum(t_cnt) {} + uint runTask(unsigned thread_num, PF func, std::string testsuite, std::string testcase); + void appendTaskToList(unsigned thread_id, PF func, std::string testsuite, std::string testcase); + }; + + static MultiThreadTest testInstance; + static MultiThreadTest *getMTestSingleton() + { + return &testInstance; + } + + inline void getMTest() + { + auto ret = getMTestSingleton(); + if (ret == nullptr) { + return; + } + } + + class MultiThreadFailCaseListener : public EmptyTestEventListener { + private: + MultiThreadTest *testInstance; + public: + MultiThreadFailCaseListener(MultiThreadTest *ins) + { + this->testInstance = ins; + } + }; + + inline void addPostTest(unsigned thread_id, PF func, std::string testsuite = "NA", std::string testcase = "NA") + { + for (unsigned int i = 0; i < g_thread_count; i++) { + testInstance.appendTaskToList(thread_id, func, testsuite, testcase); + } + } + + #define MTEST_ADD_TASK(thread_id, func) addPostTest(thread_id, func) + + #define MTEST_POST_RUN() \ + do { \ + getMTestSingleton()->run(); \ + } while (0) + + #define SET_THREAD_NUM(n) setThreadNum(n) + #define MTEST_FUNC_NAME(x, y) TC_##x_##y + #define GTEST_RUN_TASK(hook) \ + do { \ + MultiThreadTest _test(g_thread_count); \ + _test.runTask(_test.m_threadNum, hook, this->test_info_->test_case_name(), this->test_info_->name()); \ + } while (0) + + #define MTEST_TYPE(x, y, z, n) \ + void MTEST_FUNC_NAME(x, y)(); \ + z(x, y) \ + { \ + SET_THREAD_NUM(n); \ + GTEST_RUN_TASK(MTEST_FUNC_NAME(x, y)); \ + } \ + void MTEST_FUNC_NAME(x, y)() + #define HWMTEST(x, y, w, n) MTEST_TYPE(x, y, TEST, n) + #define HWMTEST_F(x, y, w, n) MTEST_TYPE(x, y, TEST_F, n) + } +} +#endif /* __MULTI_THREAD_TEST_H__ */ \ No newline at end of file diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-tag.h b/3rdparty/gtest/include/gtest/hwext/gtest-tag.h new file mode 100644 index 0000000..e9b9f4d --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-tag.h @@ -0,0 +1,115 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_GTEST_TAG_H_ +#define GTEST_INCLUDE_GTEST_GTEST_TAG_H_ + +#include +#include +#include +#include + +namespace testing { + namespace ext { + + using ::std::string; + using ::std::map; + using ::std::pair; + using ::std::vector; + + enum TestTypeFlag { + Function = 1 << 8, Performance = 2 << 8, Power = 3 << 8, Reliability = 4 << 8, + Security = 5 << 8, Global = 6 << 8, Compatibility = 7 << 8, User = 8 << 8, + Standard = 9 << 8, Safety = 10 << 8, Resilience = 11 << 8 + }; + + enum TestSizeFlag { + SmallTest = 1 << 4, MediumTest = 2 << 4, LargeTest = 3 << 4 + }; + + enum TestRankFlag { + Level0 = 1, Level1 = 2, Level2 = 3, Level3 = 4, Level4 = 5 + }; + + // base class of tag flag::bitwise integers + class TestFlag { + public: + static const int None = 0; + + private: + const char* const name; + const char* const desc; + const int mask; + map elementMap; + int eleCount; + protected: + TestFlag(const char* n, const char* d, int m); + void element(const char* desc, int hex); + public: + bool verify(const int hex, char* err) const; + const char* naming() const { return name; } + const char* description() const { return desc; } + bool eleForName(const char* name, int& result) const; + void printHelp(const char** indents) const; + }; + + // test size scope + class TestSizeSet : public TestFlag { + public: + TestSizeSet(); + static const int Level0 = 1 << 24; + static const int Level1 = 2 << 24; + static const int Level2 = 4 << 24; + static const int Level3 = 8 << 24; + static const int Level4 = 16 << 24; + }; + + extern const TestSizeSet TestSize; + + // test type scope + class TypeSet : public TestFlag { + public: + TypeSet(); + static const int function = Function; + static const int performance = Performance; + static const int power = Power; + static const int reliability = Reliability; + static const int security = Security; + static const int global = Global; + static const int compatibility = Compatibility; + static const int user = User; + static const int standard = Standard; + static const int safety = Safety; + static const int resilience = Resilience; + }; + + // test size scope + class SizeSet : public TestFlag { + public: + SizeSet(); + static const int smallTest = SmallTest; + static const int mediumTest = MediumTest; + static const int largeTest = LargeTest; + }; + + // test rank scope + class RankSet : public TestFlag { + public: + RankSet(); + static const int level0 = Level0; + static const int level1 = Level1; + static const int level2 = Level2; + static const int level3 = Level3; + static const int level4 = Level4; + }; + + // get each instance of all the TestFlag implementions + const vector& AllHextTagSets(); + // verify the test flagset, returns false if the flagset is illegal + bool CheckFlagsLegality(int flags); + // convert name string to test flag value + bool flagForName(const char* set_name, const char* ele_name, int& result); + + } // namespace ext +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_GTEST_TAG_H_ diff --git a/3rdparty/gtest/include/gtest/hwext/gtest-utils.h b/3rdparty/gtest/include/gtest/hwext/gtest-utils.h new file mode 100644 index 0000000..676bc9d --- /dev/null +++ b/3rdparty/gtest/include/gtest/hwext/gtest-utils.h @@ -0,0 +1,21 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#ifndef GTEST_INCLUDE_GTEST_UTILS_H_ +#define GTEST_INCLUDE_GTEST_UTILS_H_ + +#include +#include +#include + +namespace testing { + + using ::std::string; + using ::std::vector; + + bool compareStringsByIgnoreCase(const char* one, const char* two); + bool IsElementInVector(vector vec, int element); + vector SplitString(const string& str, const string& delim); + +} // namespace testing + +#endif // GTEST_INCLUDE_GTEST_UTILS_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h b/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h index cd85d95..db02881 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest-port.h @@ -31,7 +31,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h b/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h index eb4467a..b9495d8 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest-printers.h @@ -36,7 +36,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_ diff --git a/3rdparty/gtest/include/gtest/internal/custom/gtest.h b/3rdparty/gtest/include/gtest/internal/custom/gtest.h index 4c8e07b..afaaf17 100644 --- a/3rdparty/gtest/include/gtest/internal/custom/gtest.h +++ b/3rdparty/gtest/include/gtest/internal/custom/gtest.h @@ -31,7 +31,7 @@ // // ** Custom implementation starts here ** -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h b/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h index 68bd353..490296d 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-death-test-internal.h @@ -33,8 +33,8 @@ // death tests. They are subject to change without notice. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ #include "gtest/gtest-matchers.h" #include "gtest/internal/gtest-internal.h" @@ -301,4 +301,4 @@ InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag(); } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-filepath.h b/3rdparty/gtest/include/gtest/internal/gtest-filepath.h index c11b101..0c033ab 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-filepath.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-filepath.h @@ -37,8 +37,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ #include "gtest/internal/gtest-string.h" @@ -195,7 +195,7 @@ class GTEST_API_ FilePath { void Normalize(); - // Returns a pointer to the last occurence of a valid path separator in + // Returns a pointer to the last occurrence of a valid path separator in // the FilePath. On Windows, for example, both '/' and '\' are valid path // separators. Returns NULL if no path separator was found. const char* FindLastPathSeparator() const; @@ -208,4 +208,4 @@ class GTEST_API_ FilePath { GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-internal.h b/3rdparty/gtest/include/gtest/internal/gtest-internal.h index 94c816a..f8cbdbd 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-internal.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-internal.h @@ -34,8 +34,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #include "gtest/internal/gtest-port.h" @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -78,9 +79,20 @@ #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar // Stringifies its argument. -#define GTEST_STRINGIFY_(name) #name +// Work around a bug in visual studio which doesn't accept code like this: +// +// #define GTEST_STRINGIFY_(name) #name +// #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ... +// MACRO(, x, y) +// +// Complaining about the argument to GTEST_STRINGIFY_ being empty. +// This is allowed by the spec. +#define GTEST_STRINGIFY_HELPER_(name, ...) #name +#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, ) -namespace proto2 { class Message; } +namespace proto2 { +class MessageLite; +} namespace testing { @@ -275,7 +287,7 @@ class FloatingPoint { // // See the following article for more details on ULP: // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - static const size_t kMaxUlps = 4; + static const uint32_t kMaxUlps = 4; // Constructs a FloatingPoint from a raw floating-point number. // @@ -508,6 +520,7 @@ struct SuiteApiResolver : T { static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, int line_num) { +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ SetUpTearDownSuiteFuncType test_case_fp = GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); SetUpTearDownSuiteFuncType test_suite_fp = @@ -519,10 +532,16 @@ struct SuiteApiResolver : T { << filename << ":" << line_num; return test_case_fp != nullptr ? test_case_fp : test_suite_fp; +#else + (void)(filename); + (void)(line_num); + return &T::SetUpTestSuite; +#endif } static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, int line_num) { +#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ SetUpTearDownSuiteFuncType test_case_fp = GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); SetUpTearDownSuiteFuncType test_suite_fp = @@ -534,6 +553,11 @@ struct SuiteApiResolver : T { << filename << ":" << line_num; return test_case_fp != nullptr ? test_case_fp : test_suite_fp; +#else + (void)(filename); + (void)(line_num); + return &T::TearDownTestSuite; +#endif } }; @@ -542,11 +566,11 @@ struct SuiteApiResolver : T { // // Arguments: // -// test_suite_name: name of the test suite +// test_suite_name: name of the test suite // name: name of the test -// type_param the name of the test's type parameter, or NULL if +// type_param: the name of the test's type parameter, or NULL if // this is not a typed or a type-parameterized test. -// value_param text representation of the test's value parameter, +// value_param: text representation of the test's value parameter, // or NULL if this is not a type-parameterized test. // code_location: code location where the test is defined // fixture_class_id: ID of the test fixture class @@ -566,8 +590,6 @@ GTEST_API_ TestInfo* MakeAndRegisterTestInfo( // and returns false. None of pstr, *pstr, and prefix can be NULL. GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ /* class A needs to have dll-interface to be used by clients of class B */) @@ -607,8 +629,9 @@ class GTEST_API_ TypedTestSuitePState { // Verifies that registered_tests match the test names in // defined_test_names_; returns registered_tests if successful, or // aborts the program otherwise. - const char* VerifyRegisteredTestNames( - const char* file, int line, const char* registered_tests); + const char* VerifyRegisteredTestNames(const char* test_suite_name, + const char* file, int line, + const char* registered_tests); private: typedef ::std::map RegisteredTestsMap; @@ -662,7 +685,7 @@ struct NameGeneratorSelector { }; template -void GenerateNamesRecursively(Types0, std::vector*, int) {} +void GenerateNamesRecursively(internal::None, std::vector*, int) {} template void GenerateNamesRecursively(Types, std::vector* result, int i) { @@ -729,7 +752,7 @@ class TypeParameterizedTest { // The base case for the compile time recursion. template -class TypeParameterizedTest { +class TypeParameterizedTest { public: static bool Register(const char* /*prefix*/, const CodeLocation&, const char* /*case_name*/, const char* /*test_names*/, @@ -740,6 +763,11 @@ class TypeParameterizedTest { } }; +GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name, + CodeLocation code_location); +GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation( + const char* case_name); + // TypeParameterizedTestSuite::Register() // registers *all combinations* of 'Tests' and 'Types' with Google // Test. The return value is insignificant - we just need to return @@ -752,6 +780,7 @@ class TypeParameterizedTestSuite { const char* test_names, const std::vector& type_names = GenerateNames()) { + RegisterTypeParameterizedTestSuiteInstantiation(case_name); std::string test_name = StripTrailingSpaces( GetPrefixUntilComma(test_names)); if (!state->TestExists(test_name)) { @@ -781,7 +810,7 @@ class TypeParameterizedTestSuite { // The base case for the compile time recursion. template -class TypeParameterizedTestSuite { +class TypeParameterizedTestSuite { public: static bool Register(const char* /*prefix*/, const CodeLocation&, const TypedTestSuitePState* /*state*/, @@ -792,8 +821,6 @@ class TypeParameterizedTestSuite { } }; -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - // Returns the current OS stack trace as an std::string. // // The maximum number of stack frames to be included is specified by @@ -825,6 +852,16 @@ struct GTEST_API_ ConstCharPtr { const char* value; }; +// Helper for declaring std::string within 'if' statement +// in pre C++17 build environment. +struct TrueWithString { + TrueWithString() = default; + explicit TrueWithString(const char* str) : value(str) {} + explicit TrueWithString(const std::string& str) : value(str) {} + explicit operator bool() const { return true; } + std::string value; +}; + // A simple Linear Congruential Generator for generating random // numbers with a uniform distribution. Unlike rand() and srand(), it // doesn't use global state (and therefore can't interfere with user @@ -832,18 +869,18 @@ struct GTEST_API_ ConstCharPtr { // but it's good enough for our purposes. class GTEST_API_ Random { public: - static const UInt32 kMaxRange = 1u << 31; + static const uint32_t kMaxRange = 1u << 31; - explicit Random(UInt32 seed) : state_(seed) {} + explicit Random(uint32_t seed) : state_(seed) {} - void Reseed(UInt32 seed) { state_ = seed; } + void Reseed(uint32_t seed) { state_ = seed; } // Generates a random number from [0, range). Crashes if 'range' is // 0 or greater than kMaxRange. - UInt32 Generate(UInt32 range); + uint32_t Generate(uint32_t range); private: - UInt32 state_; + uint32_t state_; GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); }; @@ -851,12 +888,34 @@ class GTEST_API_ Random { #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ typename std::remove_const::type>::type -// IsAProtocolMessage::value is a compile-time bool constant that's -// true if and only if T is type proto2::Message or a subclass of it. +// HasDebugStringAndShortDebugString::value is a compile-time bool constant +// that's true if and only if T has methods DebugString() and ShortDebugString() +// that return std::string. template -struct IsAProtocolMessage - : public bool_constant< - std::is_convertible::value> {}; +class HasDebugStringAndShortDebugString { + private: + template + static auto CheckDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().DebugString())>::type; + template + static std::false_type CheckDebugString(...); + + template + static auto CheckShortDebugString(C*) -> typename std::is_same< + std::string, decltype(std::declval().ShortDebugString())>::type; + template + static std::false_type CheckShortDebugString(...); + + using HasDebugStringType = decltype(CheckDebugString(nullptr)); + using HasShortDebugStringType = decltype(CheckShortDebugString(nullptr)); + + public: + static constexpr bool value = + HasDebugStringType::value && HasShortDebugStringType::value; +}; + +template +constexpr bool HasDebugStringAndShortDebugString::value; // When the compiler sees expression IsContainerTest(0), if C is an // STL-style container class, the first overload of IsContainerTest @@ -1092,8 +1151,6 @@ class NativeArray { const Element* array_; size_t size_; void (NativeArray::*clone_)(const Element*, size_t); - - GTEST_DISALLOW_ASSIGN_(NativeArray); }; // Backport of std::index_sequence. @@ -1117,32 +1174,44 @@ struct DoubleSequence, sizeofT> { // Backport of std::make_index_sequence. // It uses O(ln(N)) instantiation depth. template -struct MakeIndexSequence - : DoubleSequence::type, +struct MakeIndexSequenceImpl + : DoubleSequence::type, N / 2>::type {}; template <> -struct MakeIndexSequence<0> : IndexSequence<> {}; +struct MakeIndexSequenceImpl<0> : IndexSequence<> {}; + +template +using MakeIndexSequence = typename MakeIndexSequenceImpl::type; -// FIXME: This implementation of ElemFromList is O(1) in instantiation depth, -// but it is O(N^2) in total instantiations. Not sure if this is the best -// tradeoff, as it will make it somewhat slow to compile. -template -struct ElemFromListImpl {}; +template +using IndexSequenceFor = typename MakeIndexSequence::type; + +template +struct Ignore { + Ignore(...); // NOLINT +}; -template -struct ElemFromListImpl { - using type = T; +template +struct ElemFromListImpl; +template +struct ElemFromListImpl> { + // We make Ignore a template to solve a problem with MSVC. + // A non-template Ignore would work fine with `decltype(Ignore(I))...`, but + // MSVC doesn't understand how to deal with that pack expansion. + // Use `0 * I` to have a single instantiation of Ignore. + template + static R Apply(Ignore<0 * I>..., R (*)(), ...); }; -// Get the Nth element from T... -// It uses O(1) instantiation depth. -template -struct ElemFromList; +template +struct ElemFromList { + using type = + decltype(ElemFromListImpl::type>::Apply( + static_cast(nullptr)...)); +}; -template -struct ElemFromList, T...> - : ElemFromListImpl... {}; +struct FlatTupleConstructTag {}; template class FlatTuple; @@ -1152,11 +1221,11 @@ struct FlatTupleElemBase; template struct FlatTupleElemBase, I> { - using value_type = - typename ElemFromList::type, - T...>::type; + using value_type = typename ElemFromList::type; FlatTupleElemBase() = default; - explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} + template + explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t) + : value(std::forward(t)) {} value_type value; }; @@ -1168,13 +1237,35 @@ struct FlatTupleBase, IndexSequence> : FlatTupleElemBase, Idx>... { using Indices = IndexSequence; FlatTupleBase() = default; - explicit FlatTupleBase(T... t) - : FlatTupleElemBase, Idx>(std::move(t))... {} + template + explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args) + : FlatTupleElemBase, Idx>(FlatTupleConstructTag{}, + std::forward(args))... {} + + template + const typename ElemFromList::type& Get() const { + return FlatTupleElemBase, I>::value; + } + + template + typename ElemFromList::type& Get() { + return FlatTupleElemBase, I>::value; + } + + template + auto Apply(F&& f) -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } + + template + auto Apply(F&& f) const -> decltype(std::forward(f)(this->Get()...)) { + return std::forward(f)(Get()...); + } }; // Analog to std::tuple but with different tradeoffs. // This class minimizes the template instantiation depth, thus allowing more -// elements that std::tuple would. std::tuple has been seen to require an +// elements than std::tuple would. std::tuple has been seen to require an // instantiation depth of more than 10x the number of elements in some // implementations. // FlatTuple and ElemFromList are not recursive and have a fixed depth @@ -1185,21 +1276,17 @@ template class FlatTuple : private FlatTupleBase, typename MakeIndexSequence::type> { - using Indices = typename FlatTuple::FlatTupleBase::Indices; + using Indices = typename FlatTupleBase< + FlatTuple, typename MakeIndexSequence::type>::Indices; public: FlatTuple() = default; - explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} - - template - const typename ElemFromList::type& Get() const { - return static_cast*>(this)->value; - } + template + explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args) + : FlatTuple::FlatTupleBase(tag, std::forward(args)...) {} - template - typename ElemFromList::type& Get() { - return static_cast*>(this)->value; - } + using FlatTuple::FlatTupleBase::Apply; + using FlatTuple::FlatTupleBase::Get; }; // Utility functions to be called with static_assert to induce deprecation @@ -1232,6 +1319,22 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } } // namespace internal } // namespace testing +namespace std { +// Some standard library implementations use `struct tuple_size` and some use +// `class tuple_size`. Clang warns about the mismatch. +// https://reviews.llvm.org/D55466 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +struct tuple_size> + : std::integral_constant {}; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif +} // namespace std + #define GTEST_MESSAGE_AT_(file, line, message, result_type) \ ::testing::internal::AssertHelper(result_type, file, line, message) \ = ::testing::Message() @@ -1254,48 +1357,122 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } // Suppress MSVC warning 4072 (unreachable code) for the code following // statement if it returns or throws (or doesn't return or throw in some // situations). +// NOTE: The "else" is important to keep this expansion to prevent a top-level +// "else" from attaching to our "if". #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ - if (::testing::internal::AlwaysTrue()) { statement; } + if (::testing::internal::AlwaysTrue()) { \ + statement; \ + } else /* NOLINT */ \ + static_assert(true, "") // User must have a semicolon after expansion. -#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ - GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::ConstCharPtr gtest_msg = "") { \ - bool gtest_caught_expected = false; \ - try { \ - GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ - } \ - catch (expected_exception const&) { \ - gtest_caught_expected = true; \ - } \ - catch (...) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws a different type."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - if (!gtest_caught_expected) { \ - gtest_msg.value = \ - "Expected: " #statement " throws an exception of type " \ - #expected_exception ".\n Actual: it throws nothing."; \ - goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ - } \ - } else \ - GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ - fail(gtest_msg.value) +#if GTEST_HAS_EXCEPTIONS + +namespace testing { +namespace internal { + +class NeverThrown { + public: + const char* what() const noexcept { + return "this exception should never be thrown"; + } +}; + +} // namespace internal +} // namespace testing + +#if GTEST_HAS_RTTI + +#define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e)) + +#else // GTEST_HAS_RTTI + +#define GTEST_EXCEPTION_TYPE_(e) \ + std::string { "an std::exception-derived error" } + +#endif // GTEST_HAS_RTTI + +#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ + catch (typename std::conditional< \ + std::is_same::type>::type, \ + std::exception>::value, \ + const ::testing::internal::NeverThrown&, const std::exception&>::type \ + e) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws "; \ + gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ + gtest_msg.value += " with description \""; \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) + +#endif // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ + GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ + bool gtest_caught_expected = false; \ + try { \ + GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ + } catch (expected_exception const&) { \ + gtest_caught_expected = true; \ + } \ + GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ + catch (...) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws a different type."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + if (!gtest_caught_expected) { \ + gtest_msg.value = "Expected: " #statement \ + " throws an exception of type " #expected_exception \ + ".\n Actual: it throws nothing."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ + } \ + } else /*NOLINT*/ \ + GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \ + : fail(gtest_msg.value.c_str()) + +#if GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ + catch (std::exception const& e) { \ + gtest_msg.value = "it throws "; \ + gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ + gtest_msg.value += " with description \""; \ + gtest_msg.value += e.what(); \ + gtest_msg.value += "\"."; \ + goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ + } + +#else // GTEST_HAS_EXCEPTIONS + +#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() + +#endif // GTEST_HAS_EXCEPTIONS #define GTEST_TEST_NO_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ - if (::testing::internal::AlwaysTrue()) { \ + if (::testing::internal::TrueWithString gtest_msg{}) { \ try { \ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ } \ + GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ catch (...) { \ + gtest_msg.value = "it throws."; \ goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ } \ } else \ GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ - fail("Expected: " #statement " doesn't throw an exception.\n" \ - " Actual: it throws.") + fail(("Expected: " #statement " doesn't throw an exception.\n" \ + " Actual: " + gtest_msg.value).c_str()) #define GTEST_TEST_ANY_THROW_(statement, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ @@ -1318,7 +1495,7 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } // Implements Boolean test assertions such as EXPECT_TRUE. expression can be // either a boolean expression or an AssertionResult. text is a textual -// represenation of expression as it was passed into the EXPECT_TRUE. +// representation of expression as it was passed into the EXPECT_TRUE. #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const ::testing::AssertionResult gtest_ar_ = \ @@ -1355,13 +1532,16 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ : public parent_class { \ public: \ - GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ + GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \ + ~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \ + GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ + GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ + test_name)); \ \ private: \ - virtual void TestBody(); \ + void TestBody() override; \ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ - GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ - test_name)); \ }; \ \ ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ @@ -1377,4 +1557,4 @@ constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } test_suite_name, test_name)>); \ void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-param-util.h b/3rdparty/gtest/include/gtest/internal/gtest-param-util.h index 9753399..c2ef6e3 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-param-util.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-param-util.h @@ -32,8 +32,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ #include @@ -42,12 +42,14 @@ #include #include #include +#include #include #include #include "gtest/internal/gtest-internal.h" #include "gtest/internal/gtest-port.h" #include "gtest/gtest-printers.h" +#include "gtest/gtest-test-part.h" namespace testing { // Input to a parameterized test name generator, describing a test parameter. @@ -457,7 +459,7 @@ class ParameterizedTestSuiteInfoBase { // Base part of test suite name for display purposes. virtual const std::string& GetTestSuiteName() const = 0; - // Test case id to verify identity. + // Test suite id to verify identity. virtual TypeId GetTestSuiteTypeId() const = 0; // UnitTest class invokes this method to register tests in this // test suite right before running them in RUN_ALL_TESTS macro. @@ -472,6 +474,17 @@ class ParameterizedTestSuiteInfoBase { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteInfoBase); }; +// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. +// +// Report a the name of a test_suit as safe to ignore +// as the side effect of construction of this type. +struct GTEST_API_ MarkAsIgnored { + explicit MarkAsIgnored(const char* test_suite); +}; + +GTEST_API_ void InsertSyntheticTestCase(const std::string& name, + CodeLocation location, bool has_test_p); + // INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE. // // ParameterizedTestSuiteInfo accumulates tests obtained from TEST_P @@ -494,11 +507,11 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { CodeLocation code_location) : test_suite_name_(name), code_location_(code_location) {} - // Test case base name for display purposes. + // Test suite base name for display purposes. const std::string& GetTestSuiteName() const override { return test_suite_name_; } - // Test case id to verify identity. + // Test suite id to verify identity. TypeId GetTestSuiteTypeId() const override { return GetTypeId(); } // TEST_P macro uses AddTestPattern() to record information // about a single test in a LocalTestInfo structure. @@ -507,9 +520,10 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is // test suite base name and DoBar is test base name. void AddTestPattern(const char* test_suite_name, const char* test_base_name, - TestMetaFactoryBase* meta_factory) { - tests_.push_back(std::shared_ptr( - new TestInfo(test_suite_name, test_base_name, meta_factory))); + TestMetaFactoryBase* meta_factory, + CodeLocation code_location) { + tests_.push_back(std::shared_ptr(new TestInfo( + test_suite_name, test_base_name, meta_factory, code_location))); } // INSTANTIATE_TEST_SUITE_P macro uses AddGenerator() to record information // about a generator. @@ -522,11 +536,13 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { return 0; // Return value used only to run this method in namespace scope. } // UnitTest class invokes this method to register tests in this test suite - // test suites right before running tests in RUN_ALL_TESTS macro. + // right before running tests in RUN_ALL_TESTS macro. // This method should not be called more than once on any single // instance of a ParameterizedTestSuiteInfoBase derived class. // UnitTest has a guard to prevent from calling this method more than once. void RegisterTests() override { + bool generated_instantiations = false; + for (typename TestInfoContainer::iterator test_it = tests_.begin(); test_it != tests_.end(); ++test_it) { std::shared_ptr test_info = *test_it; @@ -549,6 +565,8 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { for (typename ParamGenerator::iterator param_it = generator.begin(); param_it != generator.end(); ++param_it, ++i) { + generated_instantiations = true; + Message test_name_stream; std::string param_name = name_func( @@ -572,7 +590,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { MakeAndRegisterTestInfo( test_suite_name.c_str(), test_name_stream.GetString().c_str(), nullptr, // No type parameter. - PrintToString(*param_it).c_str(), code_location_, + PrintToString(*param_it).c_str(), test_info->code_location, GetTestSuiteTypeId(), SuiteApiResolver::GetSetUpCaseOrSuite(file, line), SuiteApiResolver::GetTearDownCaseOrSuite(file, line), @@ -580,6 +598,12 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { } // for param_it } // for gen_it } // for test_it + + if (!generated_instantiations) { + // There are no generaotrs, or they all generate nothing ... + InsertSyntheticTestCase(GetTestSuiteName(), code_location_, + !tests_.empty()); + } } // RegisterTests private: @@ -587,14 +611,17 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // with TEST_P macro. struct TestInfo { TestInfo(const char* a_test_suite_base_name, const char* a_test_base_name, - TestMetaFactoryBase* a_test_meta_factory) + TestMetaFactoryBase* a_test_meta_factory, + CodeLocation a_code_location) : test_suite_base_name(a_test_suite_base_name), test_base_name(a_test_base_name), - test_meta_factory(a_test_meta_factory) {} + test_meta_factory(a_test_meta_factory), + code_location(a_code_location) {} const std::string test_suite_base_name; const std::string test_base_name; const std::unique_ptr > test_meta_factory; + const CodeLocation code_location; }; using TestInfoContainer = ::std::vector >; // Records data received from INSTANTIATE_TEST_SUITE_P macros: @@ -627,7 +654,7 @@ class ParameterizedTestSuiteInfo : public ParameterizedTestSuiteInfoBase { // Check for invalid characters for (std::string::size_type index = 0; index < name.size(); ++index) { - if (!isalnum(name[index]) && name[index] != '_') + if (!IsAlNum(name[index]) && name[index] != '_') return false; } @@ -717,6 +744,34 @@ class ParameterizedTestSuiteRegistry { GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestSuiteRegistry); }; +// Keep track of what type-parameterized test suite are defined and +// where as well as which are intatiated. This allows susequently +// identifying suits that are defined but never used. +class TypeParameterizedTestSuiteRegistry { + public: + // Add a suite definition + void RegisterTestSuite(const char* test_suite_name, + CodeLocation code_location); + + // Add an instantiation of a suit. + void RegisterInstantiation(const char* test_suite_name); + + // For each suit repored as defined but not reported as instantiation, + // emit a test that reports that fact (configurably, as an error). + void CheckForInstantiations(); + + private: + struct TypeParameterizedTestSuiteInfo { + explicit TypeParameterizedTestSuiteInfo(CodeLocation c) + : code_location(c), instantiated(false) {} + + CodeLocation code_location; + bool instantiated; + }; + + std::map suites_; +}; + } // namespace internal // Forward declarations of ValuesIn(), which is implemented in @@ -728,10 +783,15 @@ internal::ParamGenerator ValuesIn( namespace internal { // Used in the Values() function to provide polymorphic capabilities. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + template class ValueArray { public: - ValueArray(Ts... v) : v_{std::move(v)...} {} + explicit ValueArray(Ts... v) : v_(FlatTupleConstructTag{}, std::move(v)...) {} template operator ParamGenerator() const { // NOLINT @@ -747,6 +807,10 @@ class ValueArray { FlatTuple v_; }; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + template class CartesianProductGenerator : public ParamGeneratorInterface<::std::tuple> { @@ -880,4 +944,4 @@ class CartesianProductHolder { } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h b/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h index cece93d..dd84591 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-port-arch.h @@ -32,8 +32,8 @@ // This header file defines the GTEST_OS_* macro. // It is separate from gtest-port.h so that custom/gtest-port.h can include it. -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ // Determines the platform on which Google Test is compiled. #ifdef __CYGWIN__ @@ -68,6 +68,7 @@ # define GTEST_OS_OS2 1 #elif defined __APPLE__ # define GTEST_OS_MAC 1 +# include # if TARGET_OS_IPHONE # define GTEST_OS_IOS 1 # endif @@ -102,6 +103,12 @@ # define GTEST_OS_QNX 1 #elif defined(__HAIKU__) #define GTEST_OS_HAIKU 1 +#elif defined ESP8266 +#define GTEST_OS_ESP8266 1 +#elif defined ESP32 +#define GTEST_OS_ESP32 1 +#elif defined(__XTENSA__) +#define GTEST_OS_XTENSA 1 #endif // __CYGWIN__ -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-port.h b/3rdparty/gtest/include/gtest/internal/gtest-port.h index 063fcb1..0953a78 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-port.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-port.h @@ -40,8 +40,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ // Environment-describing macros // ----------------------------- @@ -190,13 +190,27 @@ // GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning. // GTEST_ATTRIBUTE_UNUSED_ - declares that a class' instances or a // variable don't have to be used. -// GTEST_DISALLOW_ASSIGN_ - disables operator=. +// GTEST_DISALLOW_ASSIGN_ - disables copy operator=. // GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=. +// GTEST_DISALLOW_MOVE_ASSIGN_ - disables move operator=. +// GTEST_DISALLOW_MOVE_AND_ASSIGN_ - disables move ctor and operator=. // GTEST_MUST_USE_RESULT_ - declares that a function's result must be used. // GTEST_INTENTIONAL_CONST_COND_PUSH_ - start code section where MSVC C4127 is // suppressed (constant conditional). // GTEST_INTENTIONAL_CONST_COND_POP_ - finish code section where MSVC C4127 // is suppressed. +// GTEST_INTERNAL_HAS_ANY - for enabling UniversalPrinter or +// UniversalPrinter specializations. +// GTEST_INTERNAL_HAS_OPTIONAL - for enabling UniversalPrinter +// or +// UniversalPrinter +// specializations. +// GTEST_INTERNAL_HAS_STRING_VIEW - for enabling Matcher or +// Matcher +// specializations. +// GTEST_INTERNAL_HAS_VARIANT - for enabling UniversalPrinter or +// UniversalPrinter +// specializations. // // Synchronization: // Mutex, MutexLock, ThreadLocal, GetThreadCount() @@ -223,8 +237,7 @@ // // Integer types: // TypeWithSize - maps an integer to a int type. -// Int32, UInt32, Int64, UInt64, TimeInMillis -// - integers of known sizes. +// TimeInMillis - integers of known sizes. // BiggestInt - the biggest signed integer type. // // Command-line utilities: @@ -235,7 +248,7 @@ // Environment variable utilities: // GetEnv() - gets the value of an environment variable. // BoolFromGTestEnv() - parses a bool environment variable. -// Int32FromGTestEnv() - parses an Int32 environment variable. +// Int32FromGTestEnv() - parses an int32_t environment variable. // StringFromGTestEnv() - parses a string environment variable. // // Deprecation warnings: @@ -248,7 +261,10 @@ #include #include #include -#include + +#include +#include +#include #include #ifndef _WIN32_WCE @@ -261,16 +277,15 @@ # include #endif -#include // NOLINT -#include // NOLINT -#include // NOLINT -#include // NOLINT +#include // NOLINT +#include +#include +#include // NOLINT #include -#include #include // NOLINT -#include "gtest/internal/gtest-port-arch.h" #include "gtest/internal/custom/gtest-port.h" +#include "gtest/internal/gtest-port-arch.h" #if !defined(GTEST_DEV_EMAIL_) # define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com" @@ -344,6 +359,10 @@ typedef struct _CRITICAL_SECTION GTEST_CRITICAL_SECTION; // WindowsTypesTest.CRITICAL_SECTIONIs_RTL_CRITICAL_SECTION. typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #endif +#elif GTEST_OS_XTENSA +#include +// Xtensa toolchains define strcasecmp in the string.h header instead of +// strings.h. string.h is already included. #else // This assumes that non-Windows OSes provide unistd.h. For OSes where this // is not the case, we need to include headers that provide the functions @@ -364,7 +383,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // On Android, is only available starting with Gingerbread. # define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9) # else -# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS) +#define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS && !GTEST_OS_XTENSA) # endif #endif @@ -441,15 +460,6 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; # endif // defined(_MSC_VER) || defined(__BORLANDC__) #endif // GTEST_HAS_EXCEPTIONS -#if !defined(GTEST_HAS_STD_STRING) -// Even though we don't use this macro any longer, we keep it in case -// some clients still depend on it. -# define GTEST_HAS_STD_STRING 1 -#elif !GTEST_HAS_STD_STRING -// The user told us that ::std::string isn't available. -# error "::std::string isn't available." -#endif // !defined(GTEST_HAS_STD_STRING) - #ifndef GTEST_HAS_STD_WSTRING // The user didn't tell us whether ::std::wstring is available, so we need // to figure it out. @@ -458,7 +468,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; // no support for it at least as recent as Froyo (2.2). #define GTEST_HAS_STD_WSTRING \ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ - GTEST_OS_HAIKU)) + GTEST_OS_HAIKU || GTEST_OS_ESP32 || GTEST_OS_ESP8266 || GTEST_OS_XTENSA)) #endif // GTEST_HAS_STD_WSTRING @@ -582,7 +592,8 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #ifndef GTEST_HAS_STREAM_REDIRECTION // By default, we assume that stream redirection is supported on all // platforms except known mobile ones. -# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA # define GTEST_HAS_STREAM_REDIRECTION 0 # else # define GTEST_HAS_STREAM_REDIRECTION 1 @@ -676,16 +687,27 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #endif -// A macro to disallow operator= +// A macro to disallow copy operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_ASSIGN_(type) \ - void operator=(type const &) = delete + type& operator=(type const &) = delete // A macro to disallow copy constructor and operator= // This should be used in the private: declarations for a class. #define GTEST_DISALLOW_COPY_AND_ASSIGN_(type) \ - type(type const &) = delete; \ - GTEST_DISALLOW_ASSIGN_(type) + type(type const&) = delete; \ + type& operator=(type const&) = delete + +// A macro to disallow move operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_MOVE_ASSIGN_(type) \ + type& operator=(type &&) noexcept = delete + +// A macro to disallow move constructor and operator= +// This should be used in the private: declarations for a class. +#define GTEST_DISALLOW_MOVE_AND_ASSIGN_(type) \ + type(type&&) noexcept = delete; \ + type& operator=(type&&) noexcept = delete // Tell the compiler to warn about unused return values for functions declared // with this macro. The macro should be used on function declarations @@ -856,9 +878,6 @@ class Secret; // expression is false, compiler will issue an error containing this identifier. #define GTEST_COMPILE_ASSERT_(expr, msg) static_assert(expr, #msg) -// Evaluates to the number of elements in 'array'. -#define GTEST_ARRAY_SIZE_(array) (sizeof(array) / sizeof(array[0])) - // A helper for suppressing warnings on constant condition. It just // returns 'condition'. GTEST_API_ bool IsTrue(bool condition); @@ -915,8 +934,6 @@ class GTEST_API_ RE { const char* full_pattern_; // For FullMatch(); # endif - - GTEST_DISALLOW_ASSIGN_(RE); }; #endif // GTEST_USES_PCRE @@ -1599,7 +1616,7 @@ class ThreadLocal : public ThreadLocalBase { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -1608,7 +1625,7 @@ class ThreadLocal : public ThreadLocalBase { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -1808,7 +1825,7 @@ class GTEST_API_ ThreadLocal { class DefaultValueHolderFactory : public ValueHolderFactory { public: DefaultValueHolderFactory() {} - virtual ValueHolder* MakeNewHolder() const { return new ValueHolder(); } + ValueHolder* MakeNewHolder() const override { return new ValueHolder(); } private: GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultValueHolderFactory); @@ -1817,7 +1834,7 @@ class GTEST_API_ ThreadLocal { class InstanceValueHolderFactory : public ValueHolderFactory { public: explicit InstanceValueHolderFactory(const T& value) : value_(value) {} - virtual ValueHolder* MakeNewHolder() const { + ValueHolder* MakeNewHolder() const override { return new ValueHolder(value_); } @@ -1887,18 +1904,12 @@ class GTEST_API_ ThreadLocal { // we cannot detect it. GTEST_API_ size_t GetThreadCount(); -template -using bool_constant = std::integral_constant; - #if GTEST_OS_WINDOWS # define GTEST_PATH_SEP_ "\\" # define GTEST_HAS_ALT_PATH_SEP_ 1 -// The biggest signed integer type the compiler supports. -typedef __int64 BiggestInt; #else # define GTEST_PATH_SEP_ "/" # define GTEST_HAS_ALT_PATH_SEP_ 0 -typedef long long BiggestInt; // NOLINT #endif // GTEST_OS_WINDOWS // Utilities for char. @@ -1929,6 +1940,19 @@ inline bool IsUpper(char ch) { inline bool IsXDigit(char ch) { return isxdigit(static_cast(ch)) != 0; } +#ifdef __cpp_char8_t +inline bool IsXDigit(char8_t ch) { + return isxdigit(static_cast(ch)) != 0; +} +#endif +inline bool IsXDigit(char16_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} +inline bool IsXDigit(char32_t ch) { + const unsigned char low_byte = static_cast(ch); + return ch == low_byte && isxdigit(low_byte) != 0; +} inline bool IsXDigit(wchar_t ch) { const unsigned char low_byte = static_cast(ch); return ch == low_byte && isxdigit(low_byte) != 0; @@ -1963,16 +1987,16 @@ namespace posix { typedef struct _stat StatStruct; # ifdef __BORLANDC__ -inline int IsATTY(int fd) { return isatty(fd); } +inline int DoIsATTY(int fd) { return isatty(fd); } inline int StrCaseCmp(const char* s1, const char* s2) { return stricmp(s1, s2); } inline char* StrDup(const char* src) { return strdup(src); } # else // !__BORLANDC__ # if GTEST_OS_WINDOWS_MOBILE -inline int IsATTY(int /* fd */) { return 0; } +inline int DoIsATTY(int /* fd */) { return 0; } # else -inline int IsATTY(int fd) { return _isatty(fd); } +inline int DoIsATTY(int fd) { return _isatty(fd); } # endif // GTEST_OS_WINDOWS_MOBILE inline int StrCaseCmp(const char* s1, const char* s2) { return _stricmp(s1, s2); @@ -1993,12 +2017,28 @@ inline bool IsDir(const StatStruct& st) { } # endif // GTEST_OS_WINDOWS_MOBILE +#elif GTEST_OS_ESP8266 +typedef struct stat StatStruct; + +inline int FileNo(FILE* file) { return fileno(file); } +inline int DoIsATTY(int fd) { return isatty(fd); } +inline int Stat(const char* path, StatStruct* buf) { + // stat function not implemented on ESP8266 + return 0; +} +inline int StrCaseCmp(const char* s1, const char* s2) { + return strcasecmp(s1, s2); +} +inline char* StrDup(const char* src) { return strdup(src); } +inline int RmDir(const char* dir) { return rmdir(dir); } +inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } + #else typedef struct stat StatStruct; inline int FileNo(FILE* file) { return fileno(file); } -inline int IsATTY(int fd) { return isatty(fd); } +inline int DoIsATTY(int fd) { return isatty(fd); } inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); } inline int StrCaseCmp(const char* s1, const char* s2) { return strcasecmp(s1, s2); @@ -2009,23 +2049,39 @@ inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); } #endif // GTEST_OS_WINDOWS +inline int IsATTY(int fd) { + // DoIsATTY might change errno (for example ENOTTY in case you redirect stdout + // to a file on Linux), which is unexpected, so save the previous value, and + // restore it after the call. + int savedErrno = errno; + int isAttyValue = DoIsATTY(fd); + errno = savedErrno; + + return isAttyValue; +} + // Functions deprecated by MSVC 8.0. GTEST_DISABLE_MSC_DEPRECATED_PUSH_() -inline const char* StrNCpy(char* dest, const char* src, size_t n) { - return strncpy(dest, src, n); -} - // ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and // StrError() aren't needed on Windows CE at this time and thus not // defined there. -#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT +#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && \ + !GTEST_OS_WINDOWS_RT && !GTEST_OS_ESP8266 && !GTEST_OS_XTENSA inline int ChDir(const char* dir) { return chdir(dir); } #endif inline FILE* FOpen(const char* path, const char* mode) { +#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW + struct wchar_codecvt : public std::codecvt {}; + std::wstring_convert converter; + std::wstring wide_path = converter.from_bytes(path); + std::wstring wide_mode = converter.from_bytes(mode); + return _wfopen(wide_path.c_str(), wide_mode.c_str()); +#else // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW return fopen(path, mode); +#endif // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MINGW } #if !GTEST_OS_WINDOWS_MOBILE inline FILE *FReopen(const char* path, const char* mode, FILE* stream) { @@ -2045,8 +2101,9 @@ inline int Close(int fd) { return close(fd); } inline const char* StrError(int errnum) { return strerror(errnum); } #endif inline const char* GetEnv(const char* name) { -#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT - // We are on Windows CE, which has no environment variables. +#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || \ + GTEST_OS_WINDOWS_RT || GTEST_OS_ESP8266 || GTEST_OS_XTENSA + // We are on an embedded platform, which has no environment variables. static_cast(name); // To prevent 'unused argument' warning. return nullptr; #elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9) @@ -2088,15 +2145,13 @@ GTEST_DISABLE_MSC_DEPRECATED_POP_() # define GTEST_SNPRINTF_ snprintf #endif -// The maximum number a BiggestInt can represent. This definition -// works no matter BiggestInt is represented in one's complement or -// two's complement. +// The biggest signed integer type the compiler supports. // -// We cannot rely on numeric_limits in STL, as __int64 and long long -// are not part of standard C++ and numeric_limits doesn't need to be -// defined for them. -const BiggestInt kMaxBiggestInt = - ~(static_cast(1) << (8*sizeof(BiggestInt) - 1)); +// long long is guaranteed to be at least 64-bits in C++11. +using BiggestInt = long long; // NOLINT + +// The maximum number a BiggestInt can represent. +constexpr BiggestInt kMaxBiggestInt = (std::numeric_limits::max)(); // This template class serves as a compile-time function from size to // type. It maps a size in bytes to a primitive type with that @@ -2121,40 +2176,27 @@ class TypeWithSize { public: // This prevents the user from using TypeWithSize with incorrect // values of N. - typedef void UInt; + using UInt = void; }; // The specialization for size 4. template <> class TypeWithSize<4> { public: - // unsigned int has size 4 in both gcc and MSVC. - // - // As base/basictypes.h doesn't compile on Windows, we cannot use - // uint32, uint64, and etc here. - typedef int Int; - typedef unsigned int UInt; + using Int = std::int32_t; + using UInt = std::uint32_t; }; // The specialization for size 8. template <> class TypeWithSize<8> { public: -#if GTEST_OS_WINDOWS - typedef __int64 Int; - typedef unsigned __int64 UInt; -#else - typedef long long Int; // NOLINT - typedef unsigned long long UInt; // NOLINT -#endif // GTEST_OS_WINDOWS + using Int = std::int64_t; + using UInt = std::uint64_t; }; // Integer types of known sizes. -typedef TypeWithSize<4>::Int Int32; -typedef TypeWithSize<4>::UInt UInt32; -typedef TypeWithSize<8>::Int Int64; -typedef TypeWithSize<8>::UInt UInt64; -typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. +using TimeInMillis = int64_t; // Represents time in milliseconds. // Utilities for command line flags and environment variables. @@ -2173,7 +2215,7 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Macros for declaring flags. # define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name) # define GTEST_DECLARE_int32_(name) \ - GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name) + GTEST_API_ extern std::int32_t GTEST_FLAG(name) # define GTEST_DECLARE_string_(name) \ GTEST_API_ extern ::std::string GTEST_FLAG(name) @@ -2181,7 +2223,7 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. # define GTEST_DEFINE_bool_(name, default_val, doc) \ GTEST_API_ bool GTEST_FLAG(name) = (default_val) # define GTEST_DEFINE_int32_(name, default_val, doc) \ - GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val) + GTEST_API_ std::int32_t GTEST_FLAG(name) = (default_val) # define GTEST_DEFINE_string_(name, default_val, doc) \ GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val) @@ -2196,12 +2238,13 @@ typedef TypeWithSize<8>::Int TimeInMillis; // Represents time in milliseconds. // Parses 'str' for a 32-bit signed integer. If successful, writes the result // to *value and returns true; otherwise leaves *value unchanged and returns // false. -bool ParseInt32(const Message& src_text, const char* str, Int32* value); +GTEST_API_ bool ParseInt32(const Message& src_text, const char* str, + int32_t* value); -// Parses a bool/Int32/string from the environment variable +// Parses a bool/int32_t/string from the environment variable // corresponding to the given Google Test flag. bool BoolFromGTestEnv(const char* flag, bool default_val); -GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val); +GTEST_API_ int32_t Int32FromGTestEnv(const char* flag, int32_t default_val); std::string OutputFlagAlsoCheckEnvVar(); const char* StringFromGTestEnv(const char* flag, const char* default_val); @@ -2228,4 +2271,119 @@ const char* StringFromGTestEnv(const char* flag, const char* default_val); #endif // !defined(GTEST_INTERNAL_DEPRECATED) -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ +#if GTEST_HAS_ABSL +// Always use absl::any for UniversalPrinter<> specializations if googletest +// is built with absl support. +#define GTEST_INTERNAL_HAS_ANY 1 +#include "absl/types/any.h" +namespace testing { +namespace internal { +using Any = ::absl::any; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::any for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_ANY 1 +#include +namespace testing { +namespace internal { +using Any = ::std::any; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::any is not +// supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::optional for UniversalPrinter<> specializations if +// googletest is built with absl support. +#define GTEST_INTERNAL_HAS_OPTIONAL 1 +#include "absl/types/optional.h" +namespace testing { +namespace internal { +template +using Optional = ::absl::optional; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::optional for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_OPTIONAL 1 +#include +namespace testing { +namespace internal { +template +using Optional = ::std::optional; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::optional is not +// supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::string_view for Matcher<> specializations if googletest +// is built with absl support. +# define GTEST_INTERNAL_HAS_STRING_VIEW 1 +#include "absl/strings/string_view.h" +namespace testing { +namespace internal { +using StringView = ::absl::string_view; +} // namespace internal +} // namespace testing +#else +# ifdef __has_include +# if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::string_view for Matcher<> +// specializations. +# define GTEST_INTERNAL_HAS_STRING_VIEW 1 +#include +namespace testing { +namespace internal { +using StringView = ::std::string_view; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::string_view is not +// supported. +# endif // __has_include() && __cplusplus >= 201703L +# endif // __has_include +#endif // GTEST_HAS_ABSL + +#if GTEST_HAS_ABSL +// Always use absl::variant for UniversalPrinter<> specializations if googletest +// is built with absl support. +#define GTEST_INTERNAL_HAS_VARIANT 1 +#include "absl/types/variant.h" +namespace testing { +namespace internal { +template +using Variant = ::absl::variant; +} // namespace internal +} // namespace testing +#else +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +// Otherwise for C++17 and higher use std::variant for UniversalPrinter<> +// specializations. +#define GTEST_INTERNAL_HAS_VARIANT 1 +#include +namespace testing { +namespace internal { +template +using Variant = ::std::variant; +} // namespace internal +} // namespace testing +// The case where absl is configured NOT to alias std::variant is not supported. +#endif // __has_include() && __cplusplus >= 201703L +#endif // __has_include +#endif // GTEST_HAS_ABSL + +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-string.h b/3rdparty/gtest/include/gtest/internal/gtest-string.h index 82aaa63..10f774f 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-string.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-string.h @@ -38,8 +38,8 @@ // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ #ifdef __BORLANDC__ // string.h is not guaranteed to provide strcpy on C++ Builder. @@ -47,6 +47,7 @@ #endif #include +#include #include #include "gtest/internal/gtest-port.h" @@ -148,11 +149,14 @@ class GTEST_API_ String { // Formats an int value as "%02d". static std::string FormatIntWidth2(int value); // "%02d" for width == 2 + // Formats an int value to given width with leading zeros. + static std::string FormatIntWidthN(int value, int width); + // Formats an int value as "%X". static std::string FormatHexInt(int value); // Formats an int value as "%X". - static std::string FormatHexUInt32(UInt32 value); + static std::string FormatHexUInt32(uint32_t value); // Formats a byte as "%02X". static std::string FormatByte(unsigned char value); @@ -168,4 +172,4 @@ GTEST_API_ std::string StringStreamToString(::std::stringstream* stream); } // namespace internal } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_ diff --git a/3rdparty/gtest/include/gtest/internal/gtest-type-util.h b/3rdparty/gtest/include/gtest/internal/gtest-type-util.h index 3d7542d..b87a2e2 100644 --- a/3rdparty/gtest/include/gtest/internal/gtest-type-util.h +++ b/3rdparty/gtest/include/gtest/internal/gtest-type-util.h @@ -1,7 +1,3 @@ -// This file was GENERATED by command: -// pump.py gtest-type-util.h.pump -// DO NOT EDIT BY HAND!!! - // Copyright 2008 Google Inc. // All Rights Reserved. // @@ -32,17 +28,12 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Type utilities needed for implementing typed and type-parameterized -// tests. This file is generated by a SCRIPT. DO NOT EDIT BY HAND! -// -// Currently we support at most 50 types in a list, and at most 50 -// type-parameterized tests in one type-parameterized test suite. -// Please contact googletestframework@googlegroups.com if you need -// more. +// tests. // GOOGLETEST_CM0001 DO NOT DELETE -#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ -#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ #include "gtest/internal/gtest-port.h" @@ -73,1556 +64,43 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) { return s; } -// GetTypeName() returns a human-readable name of type T. -// NB: This function is also used in Google Mock, so don't move it inside of -// the typed-test-only section below. -template -std::string GetTypeName() { -# if GTEST_HAS_RTTI - - const char* const name = typeid(T).name(); -# if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) +#if GTEST_HAS_RTTI +// GetTypeName(const std::type_info&) returns a human-readable name of type T. +inline std::string GetTypeName(const std::type_info& type) { + const char* const name = type.name(); +#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) int status = 0; // gcc's implementation of typeid(T).name() mangles the type name, // so we have to demangle it. -# if GTEST_HAS_CXXABI_H_ +#if GTEST_HAS_CXXABI_H_ using abi::__cxa_demangle; -# endif // GTEST_HAS_CXXABI_H_ +#endif // GTEST_HAS_CXXABI_H_ char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); const std::string name_str(status == 0 ? readable_name : name); free(readable_name); return CanonicalizeForStdLibVersioning(name_str); -# else +#else return name; -# endif // GTEST_HAS_CXXABI_H_ || __HP_aCC - -# else +#endif // GTEST_HAS_CXXABI_H_ || __HP_aCC +} +#endif // GTEST_HAS_RTTI +// GetTypeName() returns a human-readable name of type T if and only if +// RTTI is enabled, otherwise it returns a dummy type name. +// NB: This function is also used in Google Mock, so don't move it inside of +// the typed-test-only section below. +template +std::string GetTypeName() { +#if GTEST_HAS_RTTI + return GetTypeName(typeid(T)); +#else return ""; - -# endif // GTEST_HAS_RTTI +#endif // GTEST_HAS_RTTI } -#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - -// A unique type used as the default value for the arguments of class -// template Types. This allows us to simulate variadic templates -// (e.g. Types, Type, and etc), which C++ doesn't -// support directly. +// A unique type indicating an empty node struct None {}; -// The following family of struct and struct templates are used to -// represent type lists. In particular, TypesN -// represents a type list with N types (T1, T2, ..., and TN) in it. -// Except for Types0, every struct in the family has two member types: -// Head for the first type in the list, and Tail for the rest of the -// list. - -// The empty type list. -struct Types0 {}; - -// Type lists of length 1, 2, 3, and so on. - -template -struct Types1 { - typedef T1 Head; - typedef Types0 Tail; -}; -template -struct Types2 { - typedef T1 Head; - typedef Types1 Tail; -}; - -template -struct Types3 { - typedef T1 Head; - typedef Types2 Tail; -}; - -template -struct Types4 { - typedef T1 Head; - typedef Types3 Tail; -}; - -template -struct Types5 { - typedef T1 Head; - typedef Types4 Tail; -}; - -template -struct Types6 { - typedef T1 Head; - typedef Types5 Tail; -}; - -template -struct Types7 { - typedef T1 Head; - typedef Types6 Tail; -}; - -template -struct Types8 { - typedef T1 Head; - typedef Types7 Tail; -}; - -template -struct Types9 { - typedef T1 Head; - typedef Types8 Tail; -}; - -template -struct Types10 { - typedef T1 Head; - typedef Types9 Tail; -}; - -template -struct Types11 { - typedef T1 Head; - typedef Types10 Tail; -}; - -template -struct Types12 { - typedef T1 Head; - typedef Types11 Tail; -}; - -template -struct Types13 { - typedef T1 Head; - typedef Types12 Tail; -}; - -template -struct Types14 { - typedef T1 Head; - typedef Types13 Tail; -}; - -template -struct Types15 { - typedef T1 Head; - typedef Types14 Tail; -}; - -template -struct Types16 { - typedef T1 Head; - typedef Types15 Tail; -}; - -template -struct Types17 { - typedef T1 Head; - typedef Types16 Tail; -}; - -template -struct Types18 { - typedef T1 Head; - typedef Types17 Tail; -}; - -template -struct Types19 { - typedef T1 Head; - typedef Types18 Tail; -}; - -template -struct Types20 { - typedef T1 Head; - typedef Types19 Tail; -}; - -template -struct Types21 { - typedef T1 Head; - typedef Types20 Tail; -}; - -template -struct Types22 { - typedef T1 Head; - typedef Types21 Tail; -}; - -template -struct Types23 { - typedef T1 Head; - typedef Types22 Tail; -}; - -template -struct Types24 { - typedef T1 Head; - typedef Types23 Tail; -}; - -template -struct Types25 { - typedef T1 Head; - typedef Types24 Tail; -}; - -template -struct Types26 { - typedef T1 Head; - typedef Types25 Tail; -}; - -template -struct Types27 { - typedef T1 Head; - typedef Types26 Tail; -}; - -template -struct Types28 { - typedef T1 Head; - typedef Types27 Tail; -}; - -template -struct Types29 { - typedef T1 Head; - typedef Types28 Tail; -}; - -template -struct Types30 { - typedef T1 Head; - typedef Types29 Tail; -}; - -template -struct Types31 { - typedef T1 Head; - typedef Types30 Tail; -}; - -template -struct Types32 { - typedef T1 Head; - typedef Types31 Tail; -}; - -template -struct Types33 { - typedef T1 Head; - typedef Types32 Tail; -}; - -template -struct Types34 { - typedef T1 Head; - typedef Types33 Tail; -}; - -template -struct Types35 { - typedef T1 Head; - typedef Types34 Tail; -}; - -template -struct Types36 { - typedef T1 Head; - typedef Types35 Tail; -}; - -template -struct Types37 { - typedef T1 Head; - typedef Types36 Tail; -}; - -template -struct Types38 { - typedef T1 Head; - typedef Types37 Tail; -}; - -template -struct Types39 { - typedef T1 Head; - typedef Types38 Tail; -}; - -template -struct Types40 { - typedef T1 Head; - typedef Types39 Tail; -}; - -template -struct Types41 { - typedef T1 Head; - typedef Types40 Tail; -}; - -template -struct Types42 { - typedef T1 Head; - typedef Types41 Tail; -}; - -template -struct Types43 { - typedef T1 Head; - typedef Types42 Tail; -}; - -template -struct Types44 { - typedef T1 Head; - typedef Types43 Tail; -}; - -template -struct Types45 { - typedef T1 Head; - typedef Types44 Tail; -}; - -template -struct Types46 { - typedef T1 Head; - typedef Types45 Tail; -}; - -template -struct Types47 { - typedef T1 Head; - typedef Types46 Tail; -}; - -template -struct Types48 { - typedef T1 Head; - typedef Types47 Tail; -}; - -template -struct Types49 { - typedef T1 Head; - typedef Types48 Tail; -}; - -template -struct Types50 { - typedef T1 Head; - typedef Types49 Tail; -}; - - -} // namespace internal - -// We don't want to require the users to write TypesN<...> directly, -// as that would require them to count the length. Types<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Types -// will appear as Types in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Types, and Google Test will translate -// that to TypesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Types template. -template -struct Types { - typedef internal::Types50 type; -}; - -template <> -struct Types { - typedef internal::Types0 type; -}; -template -struct Types { - typedef internal::Types1 type; -}; -template -struct Types { - typedef internal::Types2 type; -}; -template -struct Types { - typedef internal::Types3 type; -}; -template -struct Types { - typedef internal::Types4 type; -}; -template -struct Types { - typedef internal::Types5 type; -}; -template -struct Types { - typedef internal::Types6 type; -}; -template -struct Types { - typedef internal::Types7 type; -}; -template -struct Types { - typedef internal::Types8 type; -}; -template -struct Types { - typedef internal::Types9 type; -}; -template -struct Types { - typedef internal::Types10 type; -}; -template -struct Types { - typedef internal::Types11 type; -}; -template -struct Types { - typedef internal::Types12 type; -}; -template -struct Types { - typedef internal::Types13 type; -}; -template -struct Types { - typedef internal::Types14 type; -}; -template -struct Types { - typedef internal::Types15 type; -}; -template -struct Types { - typedef internal::Types16 type; -}; -template -struct Types { - typedef internal::Types17 type; -}; -template -struct Types { - typedef internal::Types18 type; -}; -template -struct Types { - typedef internal::Types19 type; -}; -template -struct Types { - typedef internal::Types20 type; -}; -template -struct Types { - typedef internal::Types21 type; -}; -template -struct Types { - typedef internal::Types22 type; -}; -template -struct Types { - typedef internal::Types23 type; -}; -template -struct Types { - typedef internal::Types24 type; -}; -template -struct Types { - typedef internal::Types25 type; -}; -template -struct Types { - typedef internal::Types26 type; -}; -template -struct Types { - typedef internal::Types27 type; -}; -template -struct Types { - typedef internal::Types28 type; -}; -template -struct Types { - typedef internal::Types29 type; -}; -template -struct Types { - typedef internal::Types30 type; -}; -template -struct Types { - typedef internal::Types31 type; -}; -template -struct Types { - typedef internal::Types32 type; -}; -template -struct Types { - typedef internal::Types33 type; -}; -template -struct Types { - typedef internal::Types34 type; -}; -template -struct Types { - typedef internal::Types35 type; -}; -template -struct Types { - typedef internal::Types36 type; -}; -template -struct Types { - typedef internal::Types37 type; -}; -template -struct Types { - typedef internal::Types38 type; -}; -template -struct Types { - typedef internal::Types39 type; -}; -template -struct Types { - typedef internal::Types40 type; -}; -template -struct Types { - typedef internal::Types41 type; -}; -template -struct Types { - typedef internal::Types42 type; -}; -template -struct Types { - typedef internal::Types43 type; -}; -template -struct Types { - typedef internal::Types44 type; -}; -template -struct Types { - typedef internal::Types45 type; -}; -template -struct Types { - typedef internal::Types46 type; -}; -template -struct Types { - typedef internal::Types47 type; -}; -template -struct Types { - typedef internal::Types48 type; -}; -template -struct Types { - typedef internal::Types49 type; -}; - -namespace internal { - # define GTEST_TEMPLATE_ template class // The template "selector" struct TemplateSel is used to @@ -1644,1692 +122,62 @@ struct TemplateSel { # define GTEST_BIND_(TmplSel, T) \ TmplSel::template Bind::type -// A unique struct template used as the default value for the -// arguments of class template Templates. This allows us to simulate -// variadic templates (e.g. Templates, Templates, -// and etc), which C++ doesn't support directly. -template -struct NoneT {}; - -// The following family of struct and struct templates are used to -// represent template lists. In particular, TemplatesN represents a list of N templates (T1, T2, ..., and TN). Except -// for Templates0, every struct in the family has two member types: -// Head for the selector of the first template in the list, and Tail -// for the rest of the list. - -// The empty template list. -struct Templates0 {}; - -// Template lists of length 1, 2, 3, and so on. - -template -struct Templates1 { - typedef TemplateSel Head; - typedef Templates0 Tail; -}; -template -struct Templates2 { - typedef TemplateSel Head; - typedef Templates1 Tail; -}; - -template -struct Templates3 { - typedef TemplateSel Head; - typedef Templates2 Tail; -}; - -template -struct Templates4 { - typedef TemplateSel Head; - typedef Templates3 Tail; -}; - -template -struct Templates5 { - typedef TemplateSel Head; - typedef Templates4 Tail; -}; - -template -struct Templates6 { - typedef TemplateSel Head; - typedef Templates5 Tail; -}; - -template -struct Templates7 { - typedef TemplateSel Head; - typedef Templates6 Tail; -}; - -template -struct Templates8 { - typedef TemplateSel Head; - typedef Templates7 Tail; -}; - -template -struct Templates9 { - typedef TemplateSel Head; - typedef Templates8 Tail; -}; - -template -struct Templates10 { - typedef TemplateSel Head; - typedef Templates9 Tail; -}; - -template -struct Templates11 { - typedef TemplateSel Head; - typedef Templates10 Tail; -}; - -template -struct Templates12 { - typedef TemplateSel Head; - typedef Templates11 Tail; -}; - -template -struct Templates13 { - typedef TemplateSel Head; - typedef Templates12 Tail; -}; - -template -struct Templates14 { - typedef TemplateSel Head; - typedef Templates13 Tail; -}; - -template -struct Templates15 { - typedef TemplateSel Head; - typedef Templates14 Tail; -}; - -template -struct Templates16 { - typedef TemplateSel Head; - typedef Templates15 Tail; -}; - -template -struct Templates17 { - typedef TemplateSel Head; - typedef Templates16 Tail; -}; - -template -struct Templates18 { - typedef TemplateSel Head; - typedef Templates17 Tail; -}; - -template -struct Templates19 { - typedef TemplateSel Head; - typedef Templates18 Tail; -}; - -template -struct Templates20 { - typedef TemplateSel Head; - typedef Templates19 Tail; -}; - -template -struct Templates21 { - typedef TemplateSel Head; - typedef Templates20 Tail; -}; - -template -struct Templates22 { - typedef TemplateSel Head; - typedef Templates21 Tail; -}; - -template -struct Templates23 { - typedef TemplateSel Head; - typedef Templates22 Tail; -}; - -template -struct Templates24 { - typedef TemplateSel Head; - typedef Templates23 Tail; -}; - -template -struct Templates25 { - typedef TemplateSel Head; - typedef Templates24 Tail; -}; - -template -struct Templates26 { - typedef TemplateSel Head; - typedef Templates25 Tail; -}; - -template -struct Templates27 { - typedef TemplateSel Head; - typedef Templates26 Tail; -}; - -template -struct Templates28 { - typedef TemplateSel Head; - typedef Templates27 Tail; -}; - -template -struct Templates29 { - typedef TemplateSel Head; - typedef Templates28 Tail; -}; - -template -struct Templates30 { - typedef TemplateSel Head; - typedef Templates29 Tail; -}; - -template -struct Templates31 { - typedef TemplateSel Head; - typedef Templates30 Tail; -}; - -template -struct Templates32 { - typedef TemplateSel Head; - typedef Templates31 Tail; -}; - -template -struct Templates33 { - typedef TemplateSel Head; - typedef Templates32 Tail; -}; - -template -struct Templates34 { - typedef TemplateSel Head; - typedef Templates33 Tail; -}; - -template -struct Templates35 { - typedef TemplateSel Head; - typedef Templates34 Tail; -}; - -template -struct Templates36 { - typedef TemplateSel Head; - typedef Templates35 Tail; -}; - -template -struct Templates37 { - typedef TemplateSel Head; - typedef Templates36 Tail; -}; - -template -struct Templates38 { - typedef TemplateSel Head; - typedef Templates37 Tail; -}; - -template -struct Templates39 { - typedef TemplateSel Head; - typedef Templates38 Tail; -}; - -template -struct Templates40 { - typedef TemplateSel Head; - typedef Templates39 Tail; -}; - -template -struct Templates41 { - typedef TemplateSel Head; - typedef Templates40 Tail; -}; - -template -struct Templates42 { - typedef TemplateSel Head; - typedef Templates41 Tail; -}; - -template -struct Templates43 { - typedef TemplateSel Head; - typedef Templates42 Tail; -}; - -template -struct Templates44 { - typedef TemplateSel Head; - typedef Templates43 Tail; -}; - -template -struct Templates45 { - typedef TemplateSel Head; - typedef Templates44 Tail; -}; - -template -struct Templates46 { - typedef TemplateSel Head; - typedef Templates45 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = Templates; }; -template -struct Templates47 { - typedef TemplateSel Head; - typedef Templates46 Tail; +template +struct Templates { + using Head = TemplateSel; + using Tail = None; }; -template -struct Templates48 { - typedef TemplateSel Head; - typedef Templates47 Tail; +// Tuple-like type lists +template +struct Types { + using Head = Head_; + using Tail = Types; }; -template -struct Templates49 { - typedef TemplateSel Head; - typedef Templates48 Tail; +template +struct Types { + using Head = Head_; + using Tail = None; }; -template -struct Templates50 { - typedef TemplateSel Head; - typedef Templates49 Tail; +// Helper metafunctions to tell apart a single type from types +// generated by ::testing::Types +template +struct ProxyTypeList { + using type = Types; }; +template +struct is_proxy_type_list : std::false_type {}; -// We don't want to require the users to write TemplatesN<...> directly, -// as that would require them to count the length. Templates<...> is much -// easier to write, but generates horrible messages when there is a -// compiler error, as gcc insists on printing out each template -// argument, even if it has the default value (this means Templates -// will appear as Templates in the compiler -// errors). -// -// Our solution is to combine the best part of the two approaches: a -// user would write Templates, and Google Test will translate -// that to TemplatesN internally to make error messages -// readable. The translation is done by the 'type' member of the -// Templates template. -template -struct Templates { - typedef Templates50 type; -}; - -template <> -struct Templates { - typedef Templates0 type; -}; -template -struct Templates { - typedef Templates1 type; -}; -template -struct Templates { - typedef Templates2 type; -}; -template -struct Templates { - typedef Templates3 type; -}; -template -struct Templates { - typedef Templates4 type; -}; -template -struct Templates { - typedef Templates5 type; -}; -template -struct Templates { - typedef Templates6 type; -}; -template -struct Templates { - typedef Templates7 type; -}; -template -struct Templates { - typedef Templates8 type; -}; -template -struct Templates { - typedef Templates9 type; -}; -template -struct Templates { - typedef Templates10 type; -}; -template -struct Templates { - typedef Templates11 type; -}; -template -struct Templates { - typedef Templates12 type; -}; -template -struct Templates { - typedef Templates13 type; -}; -template -struct Templates { - typedef Templates14 type; -}; -template -struct Templates { - typedef Templates15 type; -}; -template -struct Templates { - typedef Templates16 type; -}; -template -struct Templates { - typedef Templates17 type; -}; -template -struct Templates { - typedef Templates18 type; -}; -template -struct Templates { - typedef Templates19 type; -}; -template -struct Templates { - typedef Templates20 type; -}; -template -struct Templates { - typedef Templates21 type; -}; -template -struct Templates { - typedef Templates22 type; -}; -template -struct Templates { - typedef Templates23 type; -}; -template -struct Templates { - typedef Templates24 type; -}; -template -struct Templates { - typedef Templates25 type; -}; -template -struct Templates { - typedef Templates26 type; -}; -template -struct Templates { - typedef Templates27 type; -}; -template -struct Templates { - typedef Templates28 type; -}; -template -struct Templates { - typedef Templates29 type; -}; -template -struct Templates { - typedef Templates30 type; -}; -template -struct Templates { - typedef Templates31 type; -}; -template -struct Templates { - typedef Templates32 type; -}; -template -struct Templates { - typedef Templates33 type; -}; -template -struct Templates { - typedef Templates34 type; -}; -template -struct Templates { - typedef Templates35 type; -}; -template -struct Templates { - typedef Templates36 type; -}; -template -struct Templates { - typedef Templates37 type; -}; -template -struct Templates { - typedef Templates38 type; -}; -template -struct Templates { - typedef Templates39 type; -}; -template -struct Templates { - typedef Templates40 type; -}; -template -struct Templates { - typedef Templates41 type; -}; -template -struct Templates { - typedef Templates42 type; -}; -template -struct Templates { - typedef Templates43 type; -}; -template -struct Templates { - typedef Templates44 type; -}; -template -struct Templates { - typedef Templates45 type; -}; -template -struct Templates { - typedef Templates46 type; -}; -template -struct Templates { - typedef Templates47 type; -}; -template -struct Templates { - typedef Templates48 type; -}; -template -struct Templates { - typedef Templates49 type; -}; - -// The TypeList template makes it possible to use either a single type -// or a Types<...> list in TYPED_TEST_SUITE() and -// INSTANTIATE_TYPED_TEST_SUITE_P(). +template +struct is_proxy_type_list> : std::true_type {}; +// Generator which conditionally creates type lists. +// It recognizes if a requested type list should be created +// and prevents creating a new type list nested within another one. template -struct TypeList { - typedef Types1 type; -}; +struct GenerateTypeList { + private: + using proxy = typename std::conditional::value, T, + ProxyTypeList>::type; -template -struct TypeList > { - typedef typename Types::type type; + public: + using type = typename proxy::type; }; -#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P - } // namespace internal + +template +using Types = internal::ProxyTypeList; + } // namespace testing -#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ +#endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc new file mode 100644 index 0000000..12d383b --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-ext.cc @@ -0,0 +1,220 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: CPPTest框架中ext入口 + */ + +#include +#include +#include +#include +#include "gtest/hwext/gtest-ext.h" + + +namespace testing { + namespace ext { + #define GTEST_EXT_DEBUG 0 + + TestDefManager* TestDefManager::instance() + { + static TestDefManager* instance_ = NULL; + if (instance_ == NULL) { + instance_ = new TestDefManager(); + } + return instance_; + } + + const TestDefManager* TestDefManager::cinstance() + { + return instance(); + } + + // c'tor, all members immutable + TestDefInfo::TestDefInfo(const char* tcn, const char* n, int fs, TestDefType tdf) :\ + test_case_name(tcn), name(n), flags(fs), def_type(tdf) {}; + + bool TestDefManager::regist(const char* test_case_name, const char* test_name, int test_flags, TestDefType tdf) + { + TestDefManager::testDefInfos.push_back(new TestDefInfo(test_case_name, test_name, test_flags, tdf)); + return true; + } + + int TestDefManager::queryFlagsFor(const TestInfo* test, int def_value) const + { + const TestDefInfo* def = findDefFor(test); + return def == NULL ? def_value : def->flags; + } + + const TestDefInfo* TestDefManager::findDefFor(const TestInfo* test) const + { + // search by matching test definition information + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) + { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(test->test_case_name(), info->test_case_name, case_name_mt) + && matchNaming(test->name(), info->name, test_name_mt); + if (matched) { + return info; + } + } + + #if GTEST_EXT_DEBUG + printf("cannot find test definition for: %s.%s\n", test->test_case_name(), test->name()); + #endif + return NULL; + } + + bool TestDefManager::matchNaming(const char * const a, const char * const b, NamingMatchType mt) const + { + const char sep = TestDefInfo::kNamingSepchar; + const int len_a = strlen(a); + const int len_b = strlen(b); + int i; + switch (mt) { + case AEqualsB: + // a=b + return strcmp(a, b) == 0; + case AStartsWithB: + // a=b/xxx + return strstr(a, b) == a && a[len_b] == sep; + case AContainsB: + // a=xxx/b/yyy + for (i = 1; i < len_a - len_b; i++) { + if (a[i - 1] == sep&&a[i + len_b] == sep&&strstr(a + i, b) == a + i) { + return true; + } + } + return false; + case AEndsWithB: + // a=xxx/b + return len_a > len_b&&a[len_a - len_b - 1] == sep&&strcmp(a + len_a - len_b, b) == 0; + default: + fprintf(stderr, "Illegal NamingMatchType: %d", mt); + return false; + } + } + + int TestDefManager::getLevel(const std::string testcasename, const std::string testname) const + { + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + int levelShift = 24; + int levelList[5] = {1, 2, 4, 8, 16}; + enum indexEnum {I0 = 0, I1, I2, I3, I4}; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(testcasename.c_str(), info->test_case_name, case_name_mt) + && matchNaming(testname.c_str(), info->name, test_name_mt); + if (matched) { + int level = (info->flags >> levelShift); + if (level == levelList[I0]) return I0; + if (level == levelList[I1]) return I1; + if (level == levelList[I2]) return I2; + if (level == levelList[I3]) return I3; + if (level == levelList[I4]) return I4; + } + } + return -1; + } + + int* TestDefManager::getTestFlags (const std::string testcasename, const std::string testname) const + { + NamingMatchType case_name_mt = AEqualsB; + NamingMatchType test_name_mt = AEqualsB; + static int flagList[3] = {-1, -1, -1}; + int posType = 8; + int posSize = 4; + int indexType = 0; + int indexSize = 1; + int indexRank = 2; + + for (unsigned int i = 0; i < testDefInfos.size(); i++) { + const TestDefInfo* info = testDefInfos.at(i); + switch (info->def_type) { + case Plain: + case Fixtured: + case_name_mt = AEqualsB; + test_name_mt = AEqualsB; + break; + case Typed: + case_name_mt = AStartsWithB; + test_name_mt = AEqualsB; + break; + case PatternTyped: + case_name_mt = AContainsB; + test_name_mt = AEqualsB; + break; + case Parameterized: + case_name_mt = AEndsWithB; + test_name_mt = AStartsWithB; + break; + default: + break; + } + + const bool matched = matchNaming(testcasename.c_str(), info->test_case_name, case_name_mt) + && matchNaming(testname.c_str(), info->name, test_name_mt); + if (matched) { + // get the three flag + int type = (info->flags >> posType); + int size = (info->flags >> posSize); + int rank = info->flags; + + // add three flag value in the flag list + flagList[indexType] = type; + flagList[indexSize] = size; + flagList[indexRank] = rank; + } + } + return flagList; + } + + } //namespace ext +} //namespace testing diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc new file mode 100644 index 0000000..d7bfc6c --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-filter.cc @@ -0,0 +1,226 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: CPPTest框架中通过Flag标识实现用例过滤 + */ + +#include "gtest/hwext/gtest-filter.h" +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + namespace ext { + + const char* const TestFilter::kStrictFilter = "strict_tags"; + enum IndexEnum {A = 1, B, C, D, E, F, G, H, I, J, K}; + + TestFilter* TestFilter::instance() + { + static TestFilter* instance_ = NULL; + if (instance_ == NULL) { + instance_ = new TestFilter(); + instance_->reset(); + } + return instance_; + } + + void TestFilter::printHelp() const + { + printf("\nTest Filtering:\n"); + const std::vector& sets = AllHextTagSets(); + // help message line indents + const char* indents[] = { " ", " " }; + + for (unsigned int i = 0; i < sets.size(); i++) { + sets.at(i)->printHelp(indents); + } + + printf("%sSelect tests by test level, may be a list seperated by ',' or ';'.\n", indents[1]); + } + + map& TestFilter::getAllFilterFlagsKv() + { + // no need to consider concurrence so for, because we do + // this before running tests + if (flag_kvs_inited) { + return filterFlagsKv; + } + + flag_kvs_inited = true; + const std::vector& sets = AllHextTagSets(); + for (unsigned int i = 0; i < sets.size(); i++) { + filterFlagsKv.insert(pair(sets.at(i)->naming(), new string(""))); + } + + // strict mode + filterFlagsKv.insert(pair(kStrictFilter, new string("false"))); + return filterFlagsKv; + } + + void TestFilter::postSetType (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Function") { + vecType.push_back(A); + } else if (curr == "Performance") { + vecType.push_back(B); + } else if (curr == "Power") { + vecType.push_back(C); + } else if (curr == "Reliability") { + vecType.push_back(D); + } else if (curr == "Security") { + vecType.push_back(E); + } else if (curr == "Global") { + vecType.push_back(F); + } else if (curr == "Compatibility") { + vecType.push_back(G); + } else if (curr == "User") { + vecType.push_back(H); + } else if (curr == "Standard") { + vecType.push_back(I); + } else if (curr == "Safety") { + vecType.push_back(J); + } else if (curr == "Resilience") { + vecType.push_back(K); + } + } + } + + void TestFilter::postSetSize (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "SmallTest") { + vecSize.push_back(A); + } else if (curr == "MediumTest") { + vecSize.push_back(B); + } else if (curr == "LargeTest") { + vecSize.push_back(C); + } + } + } + + void TestFilter::postSetRank (vector vectemp) + { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Level0") { + vecRank.push_back(A); + } else if (curr == "Level1") { + vecRank.push_back(B); + } else if (curr == "Level2") { + vecRank.push_back(C); + } else if (curr == "Level3") { + vecRank.push_back(D); + } else if (curr == "Level4") { + vecRank.push_back(E); + } + } + } + + bool TestFilter::postParsingArguments() + { + if (ready || !flag_kvs_inited) { + // only run setup logic once + return true; + } + + const char *kCandidateSeps = ",;|/"; + ready = true; + bool error = false; + map::iterator iter; + + for (iter = filterFlagsKv.begin(); iter != filterFlagsKv.end(); iter++) { + const char *kstr = iter->first; + const char *vstr = iter->second->c_str(); + int flag = TestFlag::None; + + if (compareStringsByIgnoreCase(kStrictFilter, kstr)) { + strictMode = compareStringsByIgnoreCase("true", vstr) || compareStringsByIgnoreCase("t", vstr); + } else if (flagForName(kstr, vstr, flag)) { + string strname = string(kstr); + string strval = string(vstr); + vector vectemp = SplitString(strval, kCandidateSeps); + + if (strname == "testsize") { + for (size_t i = 0; i < vectemp.size(); i++) { + string curr = vectemp[i]; + if (curr == "Level0") { + vecTestLevel.push_back(1); + } else if (curr == "Level1") { + vecTestLevel.push_back(2); + } else if (curr == "Level2") { + vecTestLevel.push_back(4); + } else if (curr == "Level3") { + vecTestLevel.push_back(8); + } else if (curr == "Level4") { + vecTestLevel.push_back(16); + } + } + } else if (strname == "type") { + this->postSetType(vectemp); + } else if (strname == "size") { + this->postSetSize(vectemp); + } else if (strname == "rank") { + this->postSetRank(vectemp); + } + } else { + // illegal arguments + error = true; + } + // free the newed strings + delete iter->second; + } + + filterFlagsKv.clear(); + return !error; + } + + bool TestFilter::accept(int flags) const + { + // both of flags and req_no should be accepted + if (!ready) { + return true; + } + + int posType = 8; + int posSize = 4; + int level = (flags >> 24); + int type = (flags >> posType); + int size = (flags >> posSize); + int rank = flags; + bool flags_type = false; + bool flags_size = false; + bool flags_rank = false; + bool flags_level = false; + bool flags_accepted = false; + + if (!strictMode) { + flags_type = IsElementInVector(vecType, type); + flags_size = IsElementInVector(vecSize, size); + flags_rank = IsElementInVector(vecRank, rank); + flags_level = IsElementInVector(vecTestLevel, level); + flags_accepted = (flags_type & flags_size & flags_rank) | (flags_level); + } + else { + flags_accepted = ((flags&requiredFlags) == requiredFlags); + } + + if (!flags_accepted) { + return false; + } + + return true; + } + + void TestFilter::reset() + { + filterFlagsKv.clear(); + requiredFlags = TestFlag::None; + flag_kvs_inited = false; + strictMode = false; + ready = false; + } + + } // namespace ext +} // namespace testing \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp new file mode 100644 index 0000000..2ca22fa --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-multithread.cpp @@ -0,0 +1,96 @@ +/* +* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +* Description:多线程测试框架(GTEST-MULTITHREAD)库,源码移植自CDK +* Author: +* Create:2023/2/24 +*/ + +#include "gtest/hwext/gtest-multithread.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace testing{ + namespace mt { + static inline void doThreadTestTask(ThreadTaskEntry *task) + { + for (const auto &f : task->funcList){ + f.m_func(); + } + } + + void MultiThreadTest::run() + { + int i = 0; + for (const auto &_ : randomTasks) { + for (const auto &val : _.second) { + auto pid = rand() % 100 + i; + appendTaskToList(pid, val.m_func, val.m_testsuite, val.m_testcase); + } + i++; + } + doTest(); + } + + void MultiThreadTest::doTest() + { + threadTestEntryList.clear(); + for (const auto &task : threadTasks){ + threadTestEntryList.push_back(ThreadTaskEntry(task)); + } + for (auto &test : threadTestEntryList){ + test.thread = new std::thread(doThreadTestTask, &test); + } + auto check = [&](ThreadTaskEntry &t) -> void { + if (t.thread){ + t.thread->join(); + delete t.thread; + t.thread = nullptr; + } + }; + std::for_each(threadTestEntryList.begin(), threadTestEntryList.end(), check); + } + + unsigned MultiThreadTest::runTask(unsigned thread_num, PF func, std::string testsuite, std::string testcase) + { + MultiThreadFailCaseListener *listener = new MultiThreadFailCaseListener(this); + testing::UnitTest::GetInstance()->listeners().Append(listener); + if (thread_num == 0){ + func(); + } + unsigned i = 0; + for(; i < thread_num; i++){ + appendTaskToList(i, func, testsuite, testcase); + } + i = 0; + for (const auto &_ : randomTasks){ + for (const auto &val : _.second){ + auto pid = rand() % 100 + i; + appendTaskToList(pid, val.m_func, val.m_testsuite, val.m_testcase); + } + i++; + } + doTest(); + testing::UnitTest::GetInstance()->listeners().Release(listener); + return 0; + } + + void MultiThreadTest::appendTaskToList(unsigned thread_id, PF func, std::string testsuite, std::string testcase) + { + TestTask task(testsuite, testcase, func); + if (thread_id == RANDOM_THREAD_ID){ + randomTasks[testsuite].emplace_back(task); + return; + } + while (thread_id >= threadTasks.size()){ + threadTasks.push_back(std::vector()); + } + threadTasks[thread_id].push_back(task); + } + } +} \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc new file mode 100644 index 0000000..e21a117 --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-tag.cc @@ -0,0 +1,197 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. + * Description: 实现CPPTest的flag标识设置 + */ + +#include "gtest/hwext/gtest-tag.h" +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + namespace ext { + + const TestSizeSet TestSize; + const TypeSet G_TYPE; + const SizeSet G_SIZE; + const RankSet G_RANK; + const int G_TESTSIZESHIFT = 24; + const int G_TYPESHIFT = 8; + const int G_SIZESHIFT = 4; + + TestFlag::TestFlag(const char* n, const char* d, int m) : name(n), desc(d), mask(m) + { + eleCount = 0; + } + + void TestFlag::element(const char* desc, int hex) + { + elementMap.insert(pair(hex, desc)); + } + + void TestFlag::printHelp(const char** indents) const + { + map::const_iterator c_iter; + int i = 0; + printf("%s--gtest_%s=(", indents[0], naming()); + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + printf("%s%s", (i > 0) ? "|" : "", c_iter->second); + i++; + } + printf(")\n"); + printf("%s%s\n", indents[1], description()); + } + + bool TestFlag::verify(int hex, char* err) const + { + // wipe bits not belong to this set + int masked = hex&mask; + + map::const_iterator c_iter; + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + // wipe each bit defined in this set + masked &= ~c_iter->first; + } + + // masked!=0 means find undefined bit(s) + const bool nice = masked == 0; + if (!nice&&err != NULL) { + sprintf(err, "Illegal %s value '0x%08x'\n", naming(), hex); + } + + return nice; + } + + bool TestFlag::eleForName(const char* name, int& result) const + { + if (name == NULL) { + // NOTE:: strlen(NULL) will cause seg fault + return false; + } + + const int result_raw = result; + // must set to 0 here, because we will do bit-OR arithmetic later + result = 0; + // the parameter 'name' may contatin more than one element + const char* kCandidateSeps = ",;|/"; + char name_cpoy[256]; + memset(name_cpoy, 0, 256); + memcpy(name_cpoy, name, strlen(name)); + + char * pch; + pch = strtok(name_cpoy, kCandidateSeps); + while (pch != NULL) + { + map::const_iterator c_iter; + bool matched = false; + // try to matchNaming all the elements + for (c_iter = elementMap.begin(); c_iter != elementMap.end(); c_iter++) { + const char* ele_name = c_iter->second; + const string ele_full_name_string = string(naming()) + "." + ele_name; + if (compareStringsByIgnoreCase(pch, ele_name) || compareStringsByIgnoreCase(pch, ele_full_name_string.c_str())) { + // set this bit + result |= c_iter->first; + matched = true; + break; + } + } + if (!matched) { + fprintf(stderr, "Unrecognized %s value '%s'\n", naming(), pch); + // abort the matching, recover result to raw value + result = result_raw; + return false; + } + pch = strtok(NULL, kCandidateSeps); + } + return true; + } + + TestSizeSet::TestSizeSet() : TestFlag ("testsize", "Select tests by test level hint.", 0xff << G_TESTSIZESHIFT) + { + element("Level0", Level0); + element("Level1", Level1); + element("Level2", Level2); + element("Level3", Level3); + element("Level4", Level4); + } + + TypeSet::TypeSet() : TestFlag ("type", "Select testcase by type hint.", 0x0f << G_TYPESHIFT) + { + element("Function", function); + element("Performance", performance); + element("Power", power); + element("Reliability", reliability); + element("Security", security); + element("Global", global); + element("Compatibility", compatibility); + element("User", user); + element("Standard", standard); + element("Safety", safety); + element("Resilience", resilience); + } + + + SizeSet::SizeSet() : TestFlag ("size", "Select testcase by size hint.", 0x0f << G_SIZESHIFT) + { + element("SmallTest", smallTest); + element("MediumTest", mediumTest); + element("LargeTest", largeTest); + } + + + RankSet::RankSet() : TestFlag("rank", "Select testcase by rank hint.", 0x0f) + { + element("Level0", level0); + element("Level1", level1); + element("Level2", level2); + element("Level3", level3); + element("Level4", level4); + } + + static std::vector sets; + + static void ensureSetsInit() { + if (sets.size() > 0) { + return; + } + sets.push_back(&TestSize); + sets.push_back(&G_TYPE); + sets.push_back(&G_SIZE); + sets.push_back(&G_RANK); + } + + const std::vector& AllHextTagSets() + { + ensureSetsInit(); + return sets; + } + + bool CheckFlagsLegality(int flags) + { + ensureSetsInit(); + char buf[256]; + for (unsigned int i = 0; i < sets.size(); i++) + { + const TestFlag* set = sets.at(i); + memset(buf, 0, 256); + if (!set->verify(flags, buf)) { + return false; + } + } + return true; + } + + bool flagForName(const char* set_name, const char* ele_name, int& result) { + ensureSetsInit(); + for (unsigned int i = 0; i < sets.size(); i++) + { + const TestFlag* set = sets.at(i); + if (!compareStringsByIgnoreCase(set_name, set->naming())) { + continue; + } + return set->eleForName(ele_name, result); + } + fprintf(stderr, "Unrecognized flagset '%s'\n", set_name); + return false; + } + + } // namespace ext +} // namespace testing \ No newline at end of file diff --git a/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc new file mode 100644 index 0000000..416b88d --- /dev/null +++ b/3rdparty/gtest/mingw64/src/gtest/src/hwext/gtest-utils.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2018. Huawei Technologies Co., Ltd. All rights reserved. + +#include +#include +#include "gtest/hwext/gtest-utils.h" + +namespace testing { + + /* + * Function: compareStringsByIgnoreCase + * Description: Ignore case to compare two strings + * Input: one: first string + * two: second string + * Output: N/A + * Return: true(equal),flase(not equal) + * Others: N/A + */ + bool compareStringsByIgnoreCase(const char* one, const char* two) { + if (one == NULL && two == NULL) { + return true; + } + + if (one == NULL || two == NULL) { + return false; + } + + if (strcmp(one, two) == 0) { + return true; + } + + const int len_one = strlen(one); + const int len_two = strlen(two); + + if (len_one != len_two) { + return false; + } + + if (len_one == 0 && len_two == 0) { + return true; + } + + for (int i = 0; i < len_one; i++) { + if (tolower(one[i]) != tolower(two[i])) { + return false; + } + } + + return true; + } + + bool IsElementInVector(vector vec, int element){ + vector::iterator it = find(vec.begin(), vec.end(), element); + if (it != vec.end()) { + return true; + } + return false; + } + + vector SplitString(const string& str, const string& delim) { + vector result; + if (str != "") { + int len = str.length(); + char *src = new char[len + 1]; + memset(src, 0, len + 1); + strcpy(src, str.c_str()); + src[len] = '\0'; + + char *tokenptr = strtok(src, delim.c_str()); + while (tokenptr != NULL) + { + string tk = tokenptr; + result.emplace_back(tk); + tokenptr = strtok(NULL, delim.c_str()); + } + delete[] src; + } + + return result; + } + +} // namespace testing diff --git a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h index c28b6e9..c154b5e 100755 --- a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h +++ b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,57 +16,195 @@ #ifndef OHOS_IPC_MESSAGE_PARCEL_H #define OHOS_IPC_MESSAGE_PARCEL_H -#include -#include +#include #include "parcel.h" #include "refbase.h" -#include +#include namespace OHOS { -class IRemoteObject; -class MessageParcel : public Parcel { -public: - MessageParcel(); - ~MessageParcel(); - explicit MessageParcel(Allocator *allocator); - bool WriteRemoteObject(const sptr &object); - sptr ReadRemoteObject(); - bool WriteFileDescriptor(int fd); - int ReadFileDescriptor(); - bool ContainFileDescriptors() const; - bool WriteInterfaceToken(std::u16string name); - std::u16string ReadInterfaceToken(); - bool WriteRawData(const void *data, size_t size); - const void *ReadRawData(size_t size); - bool RestoreRawData(std::shared_ptr rawData, size_t size); - const void *GetRawData() const; - size_t GetRawDataSize() const; - size_t GetRawDataCapacity() const; - void WriteNoException(); - int32_t ReadException(); - bool WriteAshmem(sptr ashmem); - sptr ReadAshmem(); - void ClearFileDescriptor(); - bool Append(MessageParcel &parcel) { return false; }; - void SetClearFdFlag() - { - needCloseFd_ = true; - }; + class IRemoteObject; + class MessageParcel : public Parcel { + public: + MessageParcel(); + ~MessageParcel(); + explicit MessageParcel(Allocator *allocator); + + /** + * @brief Serializes the remote object and writes it. + * @param object Indicates the remote object to serialize. + * @return Returns true if it is successful; returns false otherwise. + * @since 9 + */ + bool WriteRemoteObject(const sptr &object); + + /** + * @brief Reads a remote object. + * @return Returns the IRemoteObject pointer object. + * @since 9 + */ + sptr ReadRemoteObject(); + + /** + * @brief Writes an file descriptor into the object. + * @param fd Indicates file descriptor to write. + * @return Returns true if the write succeeds; return false otherwise. + * @since 9 + */ + bool WriteFileDescriptor(int fd); + + /** + * @brief Reads an file descriptor from the object. + * @return Returns the corresponding descriptor If the read is successful; returns {@code -1} otherwise. + * @since 9 + */ + int ReadFileDescriptor(); + + /** + * @brief Check whether the file descriptor is included. + * @return Returns true if checking for inclusion; returns false Otherwise. + * @since 9 + */ + bool ContainFileDescriptors() const; + + /** + * @brief Writes an interface token into the object. + * @param name Indicates the string type name. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteInterfaceToken(std::u16string name); + + /** + * @brief Reads an interface token from the object. + * @return Returns a string value. + * @since 9 + */ + std::u16string ReadInterfaceToken(); + + /** + * @brief Writes raw data to the object. + * @param data Indicates the original data written. + * @param size Indicates the size of the raw data sent. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteRawData(const void *data, size_t size); + + /** + * @brief Reads raw data from the object. + * @param size Indicates the size of the raw data to read. + * @return void + * @since 9 + */ + const void *ReadRawData(size_t size); -private: + /** + * @brief Restore raw data. + * @param rawData Indicates the original data to be recovered. + * @param size Indicates the size of the raw data to read. + * @return Returns true if recovery is successful; returns false Otherwise. + * @since 9 + */ + bool RestoreRawData(std::shared_ptr rawData, size_t size); + + /** + * @brief Obtains raw data from the object. + * @return void + * @since 9 + */ + const void *GetRawData() const; + + /** + * @brief Gets the raw data size. + * @return Returns the resulting raw data size. + * @since 9 + */ + size_t GetRawDataSize() const; + + /** + * @brief Get raw data capacity. + * @return Returns the maximum value of the raw data capacity. + * @since 9 + */ + size_t GetRawDataCapacity() const; + + /** + * @brief writes information to the object indicating that no exception occurred. + * @return void + * @since 9 + */ + void WriteNoException(); + + /** + * @brief Reads the exception information from the object. + * @return Returns the read error code. + * @since 9 + */ + int32_t ReadException(); + + /** + * @brief Writes an anonymous shared memory object to the object. + * @param ashmem Indicates anonymous shared memory object to wrote. + * @return Returns true if the write succeeds; returns false otherwise. + * @since 9 + */ + bool WriteAshmem(sptr ashmem); + + /** + * @brief Reads the anonymous shared memory object from the object. + * @return Returns anonymous share object obtained. + * @since 9 + */ + sptr ReadAshmem(); + + /** + * @brief Clear the file descriptor. + * @return void + * @since 9 + */ + void ClearFileDescriptor(); + + /** + * @brief Sets the Clear specified file descriptor flag. + * @return void + * @since 9 + */ + void SetClearFdFlag() + { + needCloseFd_ = true; + }; + + /** + * @brief Append a MessageParcel object to the end of the current MessageParcel. + * @param data Indicates the data to append. + * @return Returns true if append succeeds; returns false Otherwise. + * @since 9 + */ + bool Append(MessageParcel &data); + + private: #ifndef CONFIG_IPC_SINGLE - bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); + + /** + * @brief Write to the DBinder proxy object. + * @param object Indicates an IRemoteObject type object. + * @param handle Indicates the handle to write. + * @param stubIndex Indicates the stub index to write to. + * @return Returns true if the write succeeds; returns false otherwise. + * @since + */ + bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); #endif - static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M - static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k - bool needCloseFd_ = false; - std::vector> holders_; - int writeRawDataFd_; - int readRawDataFd_; - void *kernelMappedWrite_; - void *kernelMappedRead_; - std::shared_ptr rawData_; - size_t rawDataSize_; -}; + static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M + static constexpr size_t MIN_RAWDATA_SIZE = 32 * 1024; // 32k + bool needCloseFd_ = false; + std::vector> holders_; + int writeRawDataFd_; + int readRawDataFd_; + void *kernelMappedWrite_; + void *kernelMappedRead_; + std::shared_ptr rawData_; + size_t rawDataSize_; + }; } // namespace OHOS #endif // OHOS_IPC_MESSAGE_PARCEL_H diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp index e6a879e..b226d2c 100644 --- a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp @@ -1,10 +1,10 @@ /* - * Copyright (C) 2023 Huawei Device Co., Ltd. + * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -15,126 +15,529 @@ #include "message_parcel.h" +#include +#include +#include +#include + +#include "ashmem.h" +#include "hilog/log_c.h" +#include "hilog/log_cpp.h" +#include "ipc_file_descriptor.h" +#include "ipc_process_skeleton.h" +#include "iremote_invoker.h" #include "iremote_object.h" +#include "log_tags.h" +#include "memory" +#include "new" +#include "parcel.h" +#include "refbase.h" +#include "securec.h" +#include "string" +#include "sys_binder.h" +#include "vector" +#include "ipc_debug.h" + +#ifndef CONFIG_IPC_SINGLE +#include "dbinder_callback_stub.h" +#include "dbinder_session_object.h" +#endif namespace OHOS { -MessageParcel::MessageParcel() - : Parcel(), - writeRawDataFd_(-1), - readRawDataFd_(-1), - kernelMappedWrite_(nullptr), - kernelMappedRead_(nullptr), - rawData_(nullptr), - rawDataSize_(0) -{} - -MessageParcel::MessageParcel(Allocator *allocator) - : Parcel(allocator), - writeRawDataFd_(-1), - readRawDataFd_(-1), - kernelMappedWrite_(nullptr), - kernelMappedRead_(nullptr), - rawData_(nullptr), - rawDataSize_(0) -{} - -MessageParcel::~MessageParcel() -{ -} +#ifdef CONFIG_IPC_SINGLE + using namespace IPC_SINGLE; +#endif + static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "MessageParcel" }; + + void AcquireObject(flat_binder_object *flat, const void *cookie) + { + switch (flat->hdr.type) { + case BINDER_TYPE_BINDER: + if (flat->binder) { + reinterpret_cast(flat->cookie)->IncStrongRef(cookie); + } + break; + case BINDER_TYPE_HANDLE: { + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + IRemoteObject *remoteObject = nullptr; + if (current != nullptr) { + remoteObject = current->QueryObject(current->MakeHandleDescriptor(flat->handle)); + } + if (remoteObject != nullptr) { + remoteObject->IncStrongRef(cookie); + } + break; + } + case BINDER_TYPE_FD: + flat->handle = static_cast(dup(flat->handle)); + flat->cookie = 1; + break; + default: + ZLOGE(LOG_LABEL, "binder object type is invalid."); + break; + } + } + + MessageParcel::MessageParcel() + : Parcel(), + writeRawDataFd_(-1), + readRawDataFd_(-1), + kernelMappedWrite_(nullptr), + kernelMappedRead_(nullptr), + rawData_(nullptr), + rawDataSize_(0) + {} + + MessageParcel::MessageParcel(Allocator *allocator) + : Parcel(allocator), + writeRawDataFd_(-1), + readRawDataFd_(-1), + kernelMappedWrite_(nullptr), + kernelMappedRead_(nullptr), + rawData_(nullptr), + rawDataSize_(0) + {} + + MessageParcel::~MessageParcel() + { + if (kernelMappedWrite_ != nullptr) { + ::munmap(kernelMappedWrite_, rawDataSize_); + kernelMappedWrite_ = nullptr; + } + if (kernelMappedRead_ != nullptr) { + ::munmap(kernelMappedRead_, rawDataSize_); + kernelMappedRead_ = nullptr; + } + + if (readRawDataFd_ > 0) { + ::close(readRawDataFd_); + readRawDataFd_ = -1; + } + if (writeRawDataFd_ > 0) { + ::close(writeRawDataFd_); + writeRawDataFd_ = -1; + } + + ClearFileDescriptor(); + rawData_ = nullptr; + rawDataSize_ = 0; + } + +#ifndef CONFIG_IPC_SINGLE + bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) + { + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + if (current == nullptr) { + ZLOGE(LOG_LABEL, "current is nullptr"); + return false; + } + std::shared_ptr sessionOfPeer = current->ProxyQueryDBinderSession(handle); + if (sessionOfPeer == nullptr) { + ZLOGE(LOG_LABEL, "sessionOfPeer is null, handle: %{public}u, stubIndex: %{public}" PRIu64, handle, stubIndex); + return false; + } + std::string peerName = sessionOfPeer->GetServiceName(); + std::string peerId = sessionOfPeer->GetDeviceId(); + std::string localId = current->GetLocalDeviceID(); + uint32_t tokenId = sessionOfPeer->GetTokenId(); + + sptr fakeStub = current->QueryDBinderCallbackStub(object); + if (fakeStub == nullptr) { + // note that cannot use this proxy's descriptor, this stub is now stored and strong refered + // and need to be erased in an approprite time + fakeStub = new (std::nothrow) DBinderCallbackStub(peerName, peerId, localId, sessionOfPeer->GetStubIndex(), + handle, tokenId); + if (fakeStub == nullptr) { + ZLOGE(LOG_LABEL, "create DBinderCallbackStub object failed"); + return false; + } + if (!current->AttachDBinderCallbackStub(object, fakeStub)) { + ZLOGE(LOG_LABEL, "save callback of fake stub failed"); + return false; + } + } + return WriteRemoteObject(fakeStub); + } +#endif + + bool MessageParcel::WriteRemoteObject(const sptr &object) + { + if (object == nullptr) { + return false; + } + // Increase object's refcount temporarily in case of premature deallocation, + // object's refcount will be decreased when this MessageParcel destroyed. + holders_.push_back(object); #ifndef CONFIG_IPC_SINGLE -bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) -{ - (void)object; - (void)handle; - (void)stubIndex; - return false; -} + if (object->IsProxyObject()) { + const IPCObjectProxy *proxy = reinterpret_cast(object.GetRefPtr()); + const uint32_t handle = proxy ? proxy->GetHandle() : 0; + if (IPCProcessSkeleton::IsHandleMadeByUser(handle)) { + /* this is a fake proxy which handle get by MakeRemoteHandle(), Not binder driver of kernel */ + ZLOGI(LOG_LABEL, "send a dbinder proxy to another process in this device"); + return WriteDBinderProxy(object, handle, 0); + } + } #endif + auto result = WriteObject(object); + if (result == false) { + return result; + } + return result; + } + + sptr MessageParcel::ReadRemoteObject() + { + sptr temp = ReadObject(); +#ifndef CONFIG_IPC_SINGLE + if (temp != nullptr && !temp->IsProxyObject()) { + // if this stub is a DBinderCallbackStub, return corresponding proxy + IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); + if (current != nullptr) { + sptr proxy = current->QueryDBinderCallbackProxy(temp); + if (proxy != nullptr) { + temp = proxy; + } + } + } +#endif + return temp; + } + + bool MessageParcel::WriteFileDescriptor(int fd) + { + if (fd < 0) { + return false; + } + int dupFd = dup(fd); + if (dupFd < 0) { + return false; + } + sptr descriptor = new (std::nothrow) IPCFileDescriptor(dupFd); + if (descriptor == nullptr) { + ZLOGE(LOG_LABEL, "create IPCFileDescriptor object failed"); + return false; + } + return WriteObject(descriptor); + } + + int MessageParcel::ReadFileDescriptor() + { + sptr descriptor = ReadObject(); + if (descriptor == nullptr) { + return -1; + } + int fd = descriptor->GetFd(); + if (fd < 0) { + return -1; + } + return dup(fd); + } + + void MessageParcel::ClearFileDescriptor() + { + size_t dataOffset = 0; + binder_size_t *object = nullptr; + const flat_binder_object *flat = nullptr; + for (size_t i = 0; i < GetOffsetsSize(); i++) { + object = reinterpret_cast(GetObjectOffsets()); + if (object == nullptr) { + ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); + break; + } + // offset + size + dataOffset = object[i] + sizeof(flat_binder_object); + if (dataOffset > GetDataSize()) { + ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", + dataOffset, GetDataSize()); + break; + } + uintptr_t data = GetData(); + if (data == 0) { + ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); + break; + } + flat = reinterpret_cast(data + object[i]); + if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) { + ::close(flat->handle); + } + } + } + + bool MessageParcel::ContainFileDescriptors() const + { + size_t dataOffset = 0; + binder_size_t *object = nullptr; + const flat_binder_object *flat = nullptr; + for (size_t i = 0; i < GetOffsetsSize(); i++) { + object = reinterpret_cast(GetObjectOffsets()); + if (object == nullptr) { + ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); + break; + } + // offset + size + dataOffset = object[i] + sizeof(flat_binder_object); + if (dataOffset > GetDataSize()) { + ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", + dataOffset, GetDataSize()); + break; + } + uintptr_t data = GetData(); + if (data == 0) { + ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); + break; + } + flat = reinterpret_cast(data + object[i]); + if (flat->hdr.type == BINDER_TYPE_FD) { + return true; + } + } + + return false; + } + + bool MessageParcel::WriteInterfaceToken(std::u16string name) + { + constexpr int strictModePolicy = 0x100; + constexpr int workSource = 0; + size_t rewindPos = GetWritePosition(); + if (!WriteInt32(strictModePolicy)) { + return false; + } + + if (!WriteInt32(workSource)) { + if (!RewindWrite(rewindPos)) { + FlushBuffer(); + } + return false; + } + + return WriteString16(name); + } + + std::u16string MessageParcel::ReadInterfaceToken() + { + [[maybe_unused]] int32_t strictModePolicy = ReadInt32(); + [[maybe_unused]] int32_t workSource = ReadInt32(); + return ReadString16(); + } + + bool MessageParcel::WriteRawData(const void *data, size_t size) + { + if (data == nullptr || size > MAX_RAWDATA_SIZE || size == 0) { + ZLOGE(LOG_LABEL, "data is null or size:%{public}zu not ok", size); + return false; + } + if (kernelMappedWrite_ != nullptr) { + return false; + } + if (!WriteInt32(size)) { + return false; + } + if (size <= MIN_RAWDATA_SIZE) { + rawDataSize_ = size; + return WriteUnpadBuffer(data, size); + } + int fd = AshmemCreate("Parcel RawData", size); + if (fd < 0) { + return false; + } + writeRawDataFd_ = fd; + + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + if (result < 0) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return false; + } + void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return false; + } + if (!WriteFileDescriptor(fd)) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ::munmap(ptr, size); + return false; + } + if (memcpy_s(ptr, size, data, size) != EOK) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ::munmap(ptr, size); + return false; + } + kernelMappedWrite_ = ptr; + rawDataSize_ = size; + return true; + } + + bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) + { + if (rawData_ != nullptr || rawData == nullptr) { + return false; + } + rawData_ = rawData; + rawDataSize_ = size; + writeRawDataFd_ = 0; + return true; + } + + const void *MessageParcel::ReadRawData(size_t size) + { + if (size == 0) { + ZLOGE(LOG_LABEL, "the parameter size is 0"); + return nullptr; + } + size_t bufferSize = static_cast(ReadInt32()); + if (bufferSize != size) { + ZLOGE(LOG_LABEL, "ReadRawData: the buffersize %{public}zu not equal the parameter size %{public}zu", + bufferSize, size); + return nullptr; + } + if (bufferSize <= MIN_RAWDATA_SIZE) { + rawDataSize_ = size; + return ReadUnpadBuffer(size); + } + + /* if rawDataFd_ == 0 means rawData is received from remote */ + if (rawData_ != nullptr && writeRawDataFd_ == 0) { + /* should read fd for move readCursor of parcel */ + if (ReadFileDescriptor()) { + // do nothing + } + if (rawDataSize_ != size) { + ZLOGE(LOG_LABEL, "rawData is received from remote, the rawDataSize_ %{public}zu" + " not equal size %{public}zu", rawDataSize_, size); + return nullptr; + } + return rawData_.get(); + } + int fd = ReadFileDescriptor(); + if (fd < 0) { + return nullptr; + } + readRawDataFd_ = fd; + + int ashmemSize = AshmemGetSize(fd); + if (ashmemSize < 0 || size_t(ashmemSize) < size) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + ZLOGE(LOG_LABEL, "ashmemSize %{public}d less than size %{public}zu", + ashmemSize, size); + return nullptr; + } + void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); + if (ptr == MAP_FAILED) { + // Do not close fd here, which will be closed in MessageParcel's destructor. + return nullptr; + } + kernelMappedRead_ = ptr; + rawDataSize_ = size; + return ptr; + } + + const void *MessageParcel::GetRawData() const + { + if (rawData_ != nullptr) { + return rawData_.get(); + } + if (kernelMappedWrite_ != nullptr) { + return kernelMappedWrite_; + } + if (kernelMappedRead_ != nullptr) { + return kernelMappedRead_; + } + return nullptr; + } + + size_t MessageParcel::GetRawDataSize() const + { + return rawDataSize_; + } + + size_t MessageParcel::GetRawDataCapacity() const + { + return MAX_RAWDATA_SIZE; + } + + void MessageParcel::WriteNoException() + { + WriteInt32(0); + } + + int32_t MessageParcel::ReadException() + { + int32_t errorCode = ReadInt32(); + if (errorCode != 0) { + ReadString16(); + } + return errorCode; + } + + bool MessageParcel::WriteAshmem(sptr ashmem) + { + int fd = ashmem->GetAshmemFd(); + int32_t size = ashmem->GetAshmemSize(); + if (fd < 0 || size <= 0) { + return false; + } + if (!WriteFileDescriptor(fd) || !WriteInt32(size)) { + return false; + } + return true; + } + + sptr MessageParcel::ReadAshmem() + { + int fd = ReadFileDescriptor(); + if (fd < 0) { + return nullptr; + } + + int32_t size = ReadInt32(); + if (size <= 0) { + ::close(fd); + return nullptr; + } + return new (std::nothrow) Ashmem(fd, size); + } -bool MessageParcel::WriteRemoteObject(const sptr &object) -{ - (void)object; - return false; -} - -sptr MessageParcel::ReadRemoteObject() -{ - return nullptr; -} - -bool MessageParcel::WriteFileDescriptor(int fd) -{ - return false; -} - -int MessageParcel::ReadFileDescriptor() -{ - return -1; -} - -void MessageParcel::ClearFileDescriptor() -{ -} - -bool MessageParcel::ContainFileDescriptors() const -{ - return false; -} - -bool MessageParcel::WriteInterfaceToken(std::u16string name) -{ - (void)name; - return false; -} - -std::u16string MessageParcel::ReadInterfaceToken() -{ - return u""; -} - -bool MessageParcel::WriteRawData(const void *data, size_t size) -{ - (void)data; - (void)size; - return false; -} - -bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) -{ - (void)rawData; - (void)size; - return false; -} - -const void *MessageParcel::ReadRawData(size_t size) -{ - (void)size; - return nullptr; -} - -const void *MessageParcel::GetRawData() const -{ - return nullptr; -} - -size_t MessageParcel::GetRawDataSize() const -{ - return -1; -} - -size_t MessageParcel::GetRawDataCapacity() const -{ - return -1; -} - -void MessageParcel::WriteNoException() -{ -} - -int32_t MessageParcel::ReadException() -{ - return -1; -} + bool MessageParcel::Append(MessageParcel &data) + { + size_t dataSize = data.GetDataSize(); + if (dataSize == 0) { + ZLOGE(LOG_LABEL, "no data to append"); + return true; + } + uintptr_t dataPtr = data.GetData(); + size_t writeCursorOld = this->GetWritePosition(); + if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { + ZLOGE(LOG_LABEL, "failed to append data with writebuffer."); + return false; + } + size_t objectSize = data.GetOffsetsSize(); + if (objectSize == 0) { + return true; + } + binder_size_t objectOffsets = data.GetObjectOffsets(); + auto *newObjectOffsets = reinterpret_cast(objectOffsets); + for (size_t index = 0; index < objectSize; index++) { + if (EnsureObjectsCapacity()) { + size_t offset = writeCursorOld + newObjectOffsets[index]; + if (!WriteObjectOffset(offset)) { + ZLOGE(LOG_LABEL, "failed to write object offset"); + return false; + } + flat_binder_object *flat = reinterpret_cast(this->GetData() + offset); + if (flat == nullptr) { + ZLOGE(LOG_LABEL, "flat binder object is nullptr"); + return false; + } + AcquireObject(flat, this); + } else { + ZLOGE(LOG_LABEL, "Failed to ensure parcel capacity"); + return false; + } + } + return true; + } } // namespace OHOS diff --git a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp index ca21d77..81b71fe 100644 --- a/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp +++ b/3rdparty/ohos/foundation/multimedia/media_standard/services/utils/media_data_source.cpp @@ -26,6 +26,7 @@ #else #include "inner_api/osal/utils/util.h" #endif +#include namespace OHOS { namespace Media { @@ -43,10 +44,30 @@ namespace Media { return GetDataFromSource(mem, length); } + char *realpath(const char *__restrict name, char *__restrict resolved) + { + return _fullpath(resolved, name, PATH_MAX); + } + + bool ConvertFullPath(const std::string& partialPath, std::string& fullPath) + { + if (partialPath.empty() || partialPath.length() >= PATH_MAX) { + return false; + } + char tmpPath[PATH_MAX] = {0}; + if (realpath(partialPath.c_str(), tmpPath) == nullptr) { + return false; + } + if (access(tmpPath, F_OK) || access(tmpPath, R_OK)) { + return false; + } + fullPath = tmpPath; + return true; + } int IMediaDataSourceImpl::ReadDataFromFile() { std::string dataFullPath; - if (OHOS::Media::OSAL::ConvertFullPath(url_, dataFullPath) && !dataFullPath.empty()) { + if (ConvertFullPath(url_, dataFullPath) && !dataFullPath.empty()) { url_ = dataFullPath; } std::fstream fs(url_); diff --git a/3rdparty/ohos/utils/native/base/include/parcel.h b/3rdparty/ohos/utils/native/base/include/parcel.h index 774f4ad..08453bb 100755 --- a/3rdparty/ohos/utils/native/base/include/parcel.h +++ b/3rdparty/ohos/utils/native/base/include/parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,9 +16,10 @@ /** * @file parcel.h * - * @brief Provide classes for data container implemented in c_utils. + * @brief Provides classes for the data container implemented in c_utils. * - * Including class Parcel, Parcelable and related memory Allocator. + * The Parcel and Parcelable classes and the related memory + * allocator are provided. */ #ifndef OHOS_UTILS_PARCEL_H @@ -35,10 +36,10 @@ namespace OHOS { class Parcel; /** - * @brief Interface for class whose Instance can be written into a Parcel. + * @brief Defines a class for which the instance can be written into a parcel. * - * @note If this object is remote, its position intends to - * use in kernel data transaction. + * @note If this object is remote, its position will be used in + * kernel data transaction. */ class Parcelable : public virtual RefBase { public: @@ -46,39 +47,41 @@ public: Parcelable(); /** - * @brief Construct a new Parcelable object. + * @brief Creates a `Parcelable` object. * - * @param asRemote Specifies whether this object is remote. + * @param asRemote Specifies whether the object is remote. */ explicit Parcelable(bool asRemote); /** - * @brief Write a parcelable object to the given parcel. + * @brief Writes a `Parcelable` object into a parcel. * - * @param parcel Target parcel to write to. - * @return Return true being written on success or false if any error occur. - * @note If this object is remote, its position will be saved in the parcel. - * @note A static Unmarshalling function must also be implemented, so that - * you can get data from the given parcel into this parcelable object. + * @param parcel Indicates the parcel. + * @return Returns `true` if the operation is successful; returns `false` + * otherwise. + * @note If the `Parcelable` object is remote, its position will be saved + * in the parcel. + * @note You must implement a static Unmarshalling function to + * fetch data from the given parcel into this `Parcelable` object. * See `static TestParcelable *Unmarshalling(Parcel &parcel)` as an example. */ virtual bool Marshalling(Parcel &parcel) const = 0; /** - * @brief Enum flag to describe behaviors of the Parcelable object. + * @brief Enumerates the behavior types of a `Parcelable` object. * - * @var IPC Indicate the object can be used in IPC. - * @var RPC Indicate the object can be used in RPC. - * @var HOLD_OBJECT Indicate the object will ensure - * alive during data transaction. + * @var IPC Indicate an object that can be used in IPC. + * @var RPC Indicate an object that can be used in RPC. + * @var HOLD_OBJECT Indicate an object that will be always alive + * during data transaction. * */ enum BehaviorFlag { IPC = 0x01, RPC = 0x02, HOLD_OBJECT = 0x10 }; /** - * @brief Enable specified behavior. + * @brief Enables the specified behavior. * - * @param b Specific flag value. + * @param b Indicates the behavior. * @see BehaviorFlag. */ inline void SetBehavior(BehaviorFlag b) const @@ -87,9 +90,10 @@ public: } /** - * @brief Disable specified behavior. + * @brief Disables the specified behavior. * - * @param b Specific flag value. See BehaviorFlag. + * @param b Indicates the behavior. + * @see BehaviorFlag. */ inline void ClearBehavior(BehaviorFlag b) const { @@ -97,9 +101,12 @@ public: } /** - * @brief Check whether specified behavior is enabled. + * @brief Checks whether the specified behavior is enabled. * - * @param b Specific flag value. + * @param b Indicates the behavior. + + * @return Returns `true` if the behavior is enabled; returns `false` + * otherwise. * @see BehaviorFlag. */ inline bool TestBehavior(BehaviorFlag b) const @@ -108,12 +115,12 @@ public: } public: - bool asRemote_; // if the object is remote - mutable uint8_t behavior_; // value of flag of behaviors + bool asRemote_; // If the object is remote. + mutable uint8_t behavior_; // Behavior of the object. }; /** - * @brief Interface for memory allocator of the data in Parcel. + * @brief Defines a memory allocator for data in `Parcel`. */ class Allocator { public: @@ -127,144 +134,150 @@ public: }; /** - * @brief Default implement of Allocator. + * @brief Provides the default implementation for a memory allocator. * - * @note Allocator defined by user for a parcel need be specified manually. + * @note A non-default allocator for a parcel must be specified manually. */ class DefaultAllocator : public Allocator { public: /** - * @brief Use `malloc()` to allocate memory for a parcel. + * @brief Allocates memory for this parcel. * - * @param size Size of desired memory region. - * @return Void-type pointer to the memory region. + * @param size Indicates the size of the memory to allocate. + * @return Returns the void pointer to the memory region. */ void *Alloc(size_t size) override; /** - * @brief Use `free()` to deallocate memory for a parcel. + * @brief Deallocates memory for this parcel. * - * @param data Void-type pointer to the memory region. + * @param data Indicates the void pointer to the memory region. */ void Dealloc(void *data) override; private: /** - * @brief Use `realloc()` to reallocate memory for a parcel. + * @brief Reallocates memory for this parcel. * - * @param data Void-type pointer to the existed memory region. - * @param newSize New desired size of memory region. - * @return Void-type pointer to the new memory region. + * @param data Indicates the void pointer to the existing memory region. + * @param newSize Indicates the size of the memory to reallocate. + * @return Returns the void pointer to the new memory region. */ void *Realloc(void *data, size_t newSize) override; }; /** - * @brief A data/message container. + * @brief Provides a data/message container. * - * Contains interfaces for writing and reading data of various types, - * including primitives, Parcelable objects etc. + * This class provides methods for writing and reading data of various types, + * including primitives and parcelable objects. * - * @note Usually used in IPC, RPC. + * @note This class is usually used in IPC and RPC scenarios. */ class Parcel { public: Parcel(); /** - * @brief Construct a new Parcel object with specified Allocator. + * @brief Creates a `Parcel` object with the specified memory allocator. * - * @param allocator Specified Allocator. + * @param allocator Indicates the memory allocator. */ explicit Parcel(Allocator *allocator); virtual ~Parcel(); /** - * @brief Get total size of existed data in this parcel. + * @brief Obtains the total size of existing data in this parcel. * - * @return Value of the size in bytes. + * @return Returns the size, in bytes. */ size_t GetDataSize() const; /** - * @brief Get the pointer to the beginning of data in this parcel. + * @brief Obtains the pointer to the beginning of data in this parcel. * - * @return `uintptr_t`-type pointer. + * @return Returns a pointer of the `uintptr_t` type. */ uintptr_t GetData() const; /** - * @brief Get position of every object written in this parcel. + * @brief Obtains the position (offset) of every object written + * in this parcel. * - * @return `binder_size_t`-type pointer to + * @return Returns a pointer of the `binder_size_t` type to * the first slot of the position array. * @see flat_obj.h */ binder_size_t GetObjectOffsets() const; /** - * @brief Get total size of all of the current positions. + * @brief Obtains the size of the position array. * - * @return Value of the size in bytes. + * @return Returns the size, in bytes. */ size_t GetOffsetsSize() const; /** - * @brief Get total availiable bytes to write to this parcel. + * @brief Obtains the total number of available bytes to write + * into this parcel. * - * @return Amount of the availiable bytes. + * @return Returns the number of available bytes. */ size_t GetWritableBytes() const; /** - * @brief Get total availiable bytes to read from this parcel. + * @brief Obtains the total number of available bytes to read + * from this parcel. * - * @return Amount of the availiable bytes. + * @return Returns the number of available bytes. */ size_t GetReadableBytes() const; /** - * @brief Get total capacity of this parcel, - * i.e. size of current data region in parcel. + * @brief Obtains the total capacity of this parcel, that is, the size of + * the current data region in the parcel. * - * @return Value of the capacity in bytes. + * @return Returns the capacity, in bytes. */ size_t GetDataCapacity() const; /** - * @brief Get maximum capacity of this parcel. + * @brief Obtains the maximum capacity of this parcel. * - * @return Value of the capacity in bytes. + * @return Returns the capacity, in bytes. */ size_t GetMaxCapacity() const; /** - * @brief Set capacity of this parcel, - * i.e. size of current data region in parcel. + * @brief Sets the capacity for this parcel, that is, the size of the + * current data region in the parcel. * - * @param newCapacity Desired new capacity. - * @return Return True on success, or false if any error occur. - * @note Corresponding Allocator will try to reallocate - * the data region with new capacity. + * @param newCapacity Indicates the capacity to set. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note The memory allocator will try to reallocate the data region + * with the new capacity. * */ bool SetDataCapacity(size_t newCapacity); /** - * @brief Set total size of existed data in this parcel. + * @brief Sets the total size of existing data in this parcel. * - * @param dataSize Desired value of size in bytes. - * @return Return True on success, or false if any error occur. - * @note Avoid using it independently, otherwise it may not - * represents the correct size of existed data. + * @param dataSize Indicates the size, in bytes. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note Do not call this function independently; otherwise, it may fail to + * return the correct data size. */ bool SetDataSize(size_t dataSize); /** - * @brief Set maximux capacity of this parcel. + * @brief Sets the maximum capacity for this parcel. * - * @param maxCapacity Desired value of maximum capacity. - * @return Return True on success, or false if any error occur. + * @param maxCapacity Indicates the maximum capacity to set. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool SetMaxCapacity(size_t maxCapacity); @@ -283,150 +296,166 @@ public: bool WritePointer(uintptr_t value); /** - * @brief Write a data region(buffer) to this parcel. + * @brief Writes a data region (buffer) to this parcel. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteBuffer(const void *data, size_t size); /** - * @brief Write a data region(buffer) to this parcel - * in alignment and with terminator replaced. + * @brief Writes a data region (buffer) to this parcel in alignment + * and with the terminator replaced. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @param typeSize Size of the terminator. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @param typeSize Indicates the size of the terminator. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. * @note The last several bytes specified by `typeSize` of the aligned data - * will be deemed as a terminator, and then will be replaced by - * '0b00000000'. + * will be treated as a terminator and replaced by '0b00000000'. */ bool WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize); /** - * @brief Write a data region(buffer) to this parcel without padding. + * @brief Writes a data region (buffer) to this parcel. + * + * Currently, this function provides the same capability as `WriteBuffer()`. * - * @param data Void-type pointer to the buffer. - * @param size Size of the buffer to be written. - * @return Return True on success, or false if any error occur. + * @param data Indicates the void pointer to the buffer. + * @param size Indicates the size of the buffer. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteUnpadBuffer(const void *data, size_t size); /** - * @brief Write a C-style string to this parcel. + * @brief Writes a C-style string to this parcel. * - * Default terminator `\0` of C-style string will also write. + * The default terminator `\0` of the C-style string will also be written. * - * @param value A C-style string, i.e. char-type pointer. - * @return Return True on success, or false if any error occur. + * @param value Indicates a pointer of the char type to a C-style string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteCString(const char *value); /** - * @brief Write a C++ string(`std::u16string`) to this parcel. + * @brief Writes a C++ string (`std::string`) to this parcel. * - * The exact length of the string will write first, then the string itself - * with an appended terminator `\0` will write. + * The exact length of the string will be written first, and then the string + * itself with the appended terminator `\0` will be written. * - * @param value An `std::string` object passed by reference. - * @return Return True on success, or false if any error occur. + * @param value Indicates the reference to an `std::string` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString(const std::string &value); /** - * @brief Write a C++ UTF-16 encoded string(`std::string`) to this parcel. + * @brief Writes a C++ UTF-16 encoded string (`std::u16string`) + * to this parcel. * - * The exact length of the string will write first, then the string itself - * with an appended terminator `\0` will write. + * The exact length of the string will be written first, and then the string + * itself with the appended terminator `\0` will be written. * - * @param value An `std::u16string` object passed by reference. - * @return Return True on success, or false if any error occur. + * @param value Indicates the reference to an `std::u16string` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString16(const std::u16string &value); /** - * @brief Write a UTF-16 encoded string - * with specified length to this parcel. + * @brief Writes a UTF-16 encoded string with the specified length + * to this parcel. * - * An `std::u16string` object will be constructed by input `char16_t*` + * An `std::u16string` object will be constructed based on the `char16_t*` * pointer and the length `len` first. Then the input length and the string - * data in `u16string` object with an appended terminator `\0` will write. + * data in the `u16string` object with the appended terminator `\0` will + * be written. * - * @param value Pointer to the UTF-16 encoded string. - * @param len Exact length of the input string. - * @return Return True on success, or false if any error occur. + * @param value Indicates the pointer to a UTF-16 encoded string. + * @param len Indicates the exact length of the input string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString16WithLength(const char16_t *value, size_t len); /** - * @brief Write a UTF-8 encoded string - * with specified length to this parcel. + * @brief Writes a UTF-8 encoded string with the specified length + * to this parcel. * - * The input length `len` and the string data - * with an appended terminator `\0` will write. + * The input length `len` and the string itself + * with the appended terminator `\0` will be written. * - * @param value Pointer to the UTF-8 encoded string. - * @param len Exact length of the input string. - * @return Return True on success, or false if any error occur. + * @param value Indicates the pointer to a UTF-8 encoded string. + * @param len Indicates the exact length of the input string. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteString8WithLength(const char *value, size_t len); /** - * @brief Write a Parcelable object to this parcel. + * @brief Writes a `Parcelable` object to this parcel. * - * Remote object will be written by `WriteRemoteObject(const Parcelable *)`. - * Non-remote object will be written by its own - * `Marshalling(Parcel &parcel)`. + * Call `WriteRemoteObject(const Parcelable *)` to write a remote object. + * Call `Marshalling(Parcel &parcel)` to write a non-remote object. * - * @param object Pointer to the input Parcelable object. - * @return Return True on success, or false if any error occur. - * @note '0' of `Int32_t` will write if input pointer is `nullptr`. + * @param object Indicates the pointer to a `Parcelable` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note The value '0' of `Int32_t` will be written if a null pointer + * is passed in. */ bool WriteParcelable(const Parcelable *object); /** - * @brief Write a Parcelable object to this parcel, - * and enable its behavior of `HOLD_OBJECT`. + * @brief Writes a `Parcelable` object to this parcel, and enables its + * behavior of `HOLD_OBJECT`. * - * @param object Smart pointer to the input parcelable object. - * @return Return True on success, or false if any error occur. + * @param object Indicates the smart pointer to a `Parcelable` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteStrongParcelable(const sptr &object); /** - * @brief Write a remote object to this parcel. + * @brief Writes a remote object to this parcel. * - * @param object Pointer to a remote object. - * @return Return True on success, or false if any error occur. - * @note If `HOLD_OBJECT` is enabled for the input object, it will stay + * @param object Indicates the pointer to a remote object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note If `HOLD_OBJECT` is enabled for the remote object, it will stay * alive as long as this parcel is alive. * */ bool WriteRemoteObject(const Parcelable *object); /** - * @brief Write an object to this parcel. + * @brief Writes an object to this parcel. * - * Use its own `Marshalling(Parcel &parcel)` when `nullptr` as input, - * otherwise use `WriteRemoteObject(const Parcelable *)`. + * Use its own `Marshalling(Parcel &parcel)` when a null pointer is passed + * in; in other scenarios, use `WriteRemoteObject(const Parcelable *)`. * - * @tparam T Specific class type of the input object. - * @param object Smart pointer to the input object. - * @return Return True on success, or false if any error occur. + * @tparam T Indicates the class type of the object. + * @param object Indicates the smart pointer to the object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool WriteObject(const sptr &object); /** - * @brief Parse input data by this parcel. + * @brief Parses input data by this parcel. * - * @param data Pointer to input data. - * @param size Size of input data(Bytes). - * @return Return True on success, or false if any error occur. - * @note Only read operation from this parcel is permitted after successful - * calling this method. + * @param data Indicates the pointer to input data. + * @param size Indicates the size of the input data, in bytes. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. + * @note Only the read operation from this parcel is allowed after + * successful calling of this method. */ bool ParseFrom(uintptr_t data, size_t size); @@ -477,200 +506,212 @@ public: bool ReadDouble(double &value); /** - * @brief Read a block of data(buffer data) from this parcel. + * @brief Reads a block of data (buffer data) from this parcel. * - * @param length Size of the buffer(Bytes). - * @return A `uint8_t` pointer to the buffer. + * @param length Indicates the size of the buffer, in bytes. + * @return Returns a pointer of the `uint8_t` type to the buffer. */ const uint8_t *ReadBuffer(size_t length); /** - * @brief Read a block of data(buffer data) without padding(alignment) from - * this parcel. + * @brief Reads a block of data (buffer data) without padding (alignment) + * from this parcel. * - * This method will read the effective data whose length specified by - * `length` and discard bytes for padding. + * This method will read the effective data with the specified + * `length` and discard the bytes used for padding. * - * @param length Effective size of the buffer(Bytes). - * @return A `uint8_t` pointer to the buffer. + * @param length Indicates the effective size of the buffer, in bytes. + * @return Returns a pointer of the `uint8_t` type to the buffer. * */ const uint8_t *ReadUnpadBuffer(size_t length); /** - * @brief Skip the next several bytes specifed by `bytes` in read process. + * @brief Skips the next several bytes specified by `bytes` in the read + * operation. * - * @param bytes Skipped number of bytes. + * @param bytes Indicates the number of bytes to skip. */ void SkipBytes(size_t bytes); /** - * @brief Read a C-style string from this parcel. + * @brief Reads a C-style string from this parcel. * - * @return A C-style string, which is represented by a `char`-type pointer. + * @return Returns a pointer of the `char` type to the C-style string. */ const char *ReadCString(); /** - * @brief Read a C++ string(`std::string`) object from this parcel. + * @brief Reads a C++ string (`std::string`) object from this parcel. * - * @return An `std::string` object. + * @return Returns a pointer of the `std::string` type to the C-style + * string. */ const std::string ReadString(); /** - * @brief Read a C++ string(`std::string`) object from this parcel to input - * object. + * @brief Reads a C++ string (`std::string`) object from this parcel to + * an object. * - * @param value Target receiver `std::string` object. - * @return Return True on success, or false if any error occur. + * @param value Indicates the `std::string` object to hold the data read. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool ReadString(std::string &value); /** - * @brief Read a C++ UTF-16 encoded string(`std::string`) object from this - * parcel. + * @brief Reads a C++ UTF-16 encoded string (`std::u16string`) object + * from this parcel. * - * @return An `std::u16string` object. + * @return Returns a pointer of the `std::u16string` type to the C-style + * string. */ const std::u16string ReadString16(); /** - * @brief Read a C++ UTF-16 string(`std::u16string`) object from this - * parcel to input object. + * @brief Reads a C++ UTF-16 string (`std::u16string`) object from this + * parcel to an object. * - * @param value Target receiver `std::string` object. - * @return Return True on success, or false if any error occur. + * @param value Indicates the `std::u16string` object to hold the data read. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool ReadString16(std::u16string &value); /** - * @brief Read a C++ UTF-16 string(`std::u16string`) object and its length + * @brief Reads a C++ UTF-16 string (`std::u16string`) object and its length * from this parcel. * - * @param len `int32_t`-type variable passed by reference to receive the - * length. - * @return An output `std::u16string` object. + * @param len Indicates the reference to a variable of the `int32_t` type + * to receive the length. + * @return Returns an `std::u16string` object. */ const std::u16string ReadString16WithLength(int32_t &len); /** - * @brief Read a C++ string(`std::string`) object and its length from this - * parcel. + * @brief Reads a C++ string (`std::string`) object and its length from + * this parcel. * - * @param len `int32_t`-type variable passed by reference to receive the - * length. - * @return An output `std::u8string` object. + * @param len Indicates the reference to a variable of the `int32_t` type + * to receive the length. + * @return Returns an `std::string` object. */ const std::string ReadString8WithLength(int32_t &len); /** - * @brief Set the read cursor to specified position. + * @brief Sets the read cursor to the specified position. * - * @param newPosition Specified position represented by offsets relative to - * the beginning of the data region. - * @return Return True on success, or false if any error occur. + * @param newPosition Indicates the position, represented by the offset + * (in bytes) from the beginning of the data region. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool RewindRead(size_t newPosition); /** - * @brief Set the write cursor to specified position. + * @brief Sets the write cursor to the specified position. * - * @param offsets Specified position represented by offsets(Bytes) relative - * to the beginning of the data region. - * @return Return True on success, or false if any error occur. + * @param offsets Indicates the position, represented by the offset + * (in bytes) from the beginning of the data region. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool RewindWrite(size_t offsets); /** - * @brief Get current position of read cursor. + * @brief Obtains the current position of the read cursor. * - * @return Position represented by offsets(Bytes) relative to the beginning - * of the data region. + * @return Returns the position, represented by the offset (in bytes) + * from the beginning of the data region. */ size_t GetReadPosition(); /** - * @brief Get current position of write cursor. + * @brief Obtains the current position of the write cursor. * - * @return Position represented by offsets(Bytes) relative to the beginning - * of the data region. + * @return Returns the position, represented by the offset (in bytes) + * from the beginning of the data region. */ size_t GetWritePosition(); /** - * @brief Read a Parcelable(and its subclass) object from this parcel. + * @brief Reads a `Parcelable` object and its child class objects + * from this parcel. * - * @tparam T Specific class type of the output object. - * @return Object of specific class. - * @note `nullptr` will return if a '0' is read. + * @tparam T Indicates the class type of the output object. + * @return Returns the object read. + * @note A null pointer will be returned if '0' is read. */ template T *ReadParcelable(); /** - * @brief Read a Parcelable object from this parcel, and manage it by a + * @brief Reads a `Parcelable` object from this parcel and manages it by a * smart pointer. * - * @tparam T Specific class type of the output object. - * @return Object managed by a smart pointer. - * @note `nullptr` will return if a '0' is read. + * @tparam T Indicates the class type of the output object. + * @return Returns the object managed by a smart pointer. + * @note A null pointer will be returned if '0' is read. */ template sptr ReadStrongParcelable(); /** - * @brief Check if it is valid to read an object from current cursor. + * @brief Checks whether it is valid to read an object from the current + * cursor. * - * @return Return true if valid, otherwise return false. + * @return Returns `true` if valid; returns `false` otherwise. */ bool CheckOffsets(); /** - * @brief Read an object from this parcel. + * @brief Reads an object from this parcel. * - * `CheckOffsets()` will call first to check whether it is valid to read an + * Call `CheckOffsets()` first to check whether it is valid to read an * object. * - * @tparam T Specific class type of the output object. - * @return A smart pointer to the object. - * @note `nullptr` will return if `CheckOffsets()` fail. + * @tparam T Indicates the class type of the output object. + * @return Returns the smart pointer to the object. + * @note A null pointer will be returned if `CheckOffsets()` fails + * to be called. */ template sptr ReadObject(); /** - * @brief Set the Allocator object of this parcel. + * @brief Sets a memory allocator for this parcel. * - * New Allocator will reallocate the data region to which has been written. + * The new allocator will reallocate the data region that has been written. * - * @param allocator Specified Allocator object. - * @return Return True on success, or false if any error occur. + * @param allocator Indicates the pointer to an `Allocator` object. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool SetAllocator(Allocator *allocator); /** - * @brief Record an array of offsets of the object. + * @brief Records an array of positions of this parcel. * - * @param offsets A pointer to the input array. - * @param offsetSize Size of the input array. - * @note It will return directly if fail. + * @param offsets Indicates the pointer to the position array. + * @param offsetSize Indicates the size of the position array. + * @note The method returns directly if the call fail. */ void InjectOffsets(binder_size_t offsets, size_t offsetSize); /** - * @brief Deallocate the data region, and reset this parcel. + * @brief Deallocates the data region and resets this parcel. */ void FlushBuffer(); /** - * @brief Write an `std::vector` object to this parcel. + * @brief Writes an `std::vector` object to this parcel. * - * @tparam T1 Specific class type for input vector. - * @tparam T2 Specific class type for write method of this parcel. - * @param val Input vector object passed by reference. - * @param Write Specific `Parcel::Write(T2 value)` method. - * @return Return True on success, or false if any error occur. + * @tparam T1 Indicates the class type for the vector. + * @tparam T2 Indicates the class type for the write method of this parcel. + * @param val Indicates the reference to the vector. + * @param Write Indicates the `Parcel::Write(T2 value)` method. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool WriteVector(const std::vector &val, bool (Parcel::*Write)(T2)); @@ -689,13 +730,14 @@ public: bool WriteString16Vector(const std::vector &val); /** - * @brief Read an `std::vector` object from this parcel. + * @brief Reads an `std::vector` object from this parcel. * - * @tparam T1 Specific class type for output vector. - * @tparam T2 Specific class type for read method of this parcel. - * @param val Pointer to the output vector object. - * @param Write Specific `Parcel::Read(T2 value)` method. - * @return Return True on success, or false if any error occur. + * @tparam T1 Indicates the class type for the vector. + * @tparam T2 Indicates the class type for the read method of this parcel. + * @param val Indicates the pointer to the vector. + * @param Write Indicates the `Parcel::Read(T2 value)` method. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ template bool ReadVector(std::vector *val, bool (Parcel::*Read)(T &)); @@ -728,21 +770,23 @@ public: protected: /** - * @brief Record position of the written object, which are represented by - * offset from the beginning of the data region. + * @brief Records the position of the written object, which is represented + * by the offset from the beginning of the data region. * - * @param offset Specific position. - * @return Return True on success, or false if any error occur. + * @param offset Indicates the position. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool WriteObjectOffset(binder_size_t offset); /** - * @brief Ensure number of the written objects is lower than the capacity of - * objects. + * @brief Ensures that the number of written objects is less than + * the capacity of objects. * - * If it is full, the capacity will be expanded. + * If the data region is full, the capacity will be expanded. * - * @return Return True on success, or false if any error occur. + * @return Returns `true` if the operation is successful; + * returns `false` otherwise. */ bool EnsureObjectsCapacity(); @@ -776,6 +820,12 @@ private: bool WriteParcelableOffset(size_t offset); + const uint8_t *BasicReadBuffer(size_t length); + + bool ValidateReadData(size_t upperBound); + + void ClearObjects(); + private: uint8_t *data_; size_t readCursor_; @@ -784,6 +834,7 @@ private: size_t dataCapacity_; size_t maxDataCapacity_; binder_size_t *objectOffsets_; + size_t nextObjectIdx_; size_t objectCursor_; size_t objectsCapacity_; Allocator *allocator_; @@ -821,7 +872,7 @@ T *Parcel::ReadParcelable() return T::Unmarshalling(*this); } -// Read data from the given parcel into this parcelable object, return sptr. +// Read data from the given parcel into this parcelable object, and return sptr. template sptr Parcel::ReadStrongParcelable() { diff --git a/3rdparty/ohos/utils/native/base/src/parcel.cpp b/3rdparty/ohos/utils/native/base/src/parcel.cpp index 4d3038c..86f0215 100644 --- a/3rdparty/ohos/utils/native/base/src/parcel.cpp +++ b/3rdparty/ohos/utils/native/base/src/parcel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -14,20 +14,43 @@ */ #include "parcel.h" -#include +#include "securec.h" #include "utils_log.h" namespace OHOS { +static const size_t DEFAULT_CPACITY = 204800; // 200K +static const size_t CAPACITY_THRESHOLD = 4096; // 4k + Parcelable::Parcelable() : Parcelable(false) {} Parcelable::Parcelable(bool asRemote) { + asRemote_ = asRemote; + behavior_ = 0; } Parcel::Parcel(Allocator *allocator) { + if (allocator != nullptr) { + allocator_ = allocator; + } else { + allocator_ = new DefaultAllocator(); + } + + writeCursor_ = 0; + readCursor_ = 0; + + data_ = nullptr; + dataSize_ = 0; + dataCapacity_ = 0; + + maxDataCapacity_ = DEFAULT_CPACITY; + objectOffsets_ = nullptr; + nextObjectIdx_ = 0; + objectCursor_ = 0; + objectsCapacity_ = 0; } Parcel::Parcel() : Parcel(new DefaultAllocator()) @@ -35,119 +58,386 @@ Parcel::Parcel() : Parcel(new DefaultAllocator()) Parcel::~Parcel() { + FlushBuffer(); + delete allocator_; + allocator_ = nullptr; } size_t Parcel::GetWritableBytes() const { - return {}; + if (dataCapacity_ > writeCursor_) { + return dataCapacity_ - writeCursor_; + } + + return 0; } size_t Parcel::GetReadableBytes() const { - return {}; + if (dataSize_ > readCursor_) { + return dataSize_ - readCursor_; + } + + return 0; } size_t Parcel::CalcNewCapacity(size_t minNewCapacity) { - return {}; + size_t threshold = CAPACITY_THRESHOLD; + + if (minNewCapacity == threshold) { + return threshold; + } + + // If over threshold, step by threshold. + if (minNewCapacity > threshold) { + size_t newCapacity = minNewCapacity / threshold * threshold; + + if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_ - threshold)) { + newCapacity = maxDataCapacity_; + } else { + newCapacity += threshold; + } + + return newCapacity; + } + + // Not over threshold. Double it. + size_t newCapacity = 64; + + while (newCapacity < minNewCapacity) { + newCapacity = newCapacity * 2; + } + + if ((maxDataCapacity_ > 0) && (newCapacity > maxDataCapacity_)) { + newCapacity = maxDataCapacity_; + } + + return newCapacity; } bool Parcel::EnsureWritableCapacity(size_t desireCapacity) { - return {}; + if (!writable_) { + UTILS_LOGW("this parcel data is alloc by driver, which is can not be writen"); + return false; + } + if (desireCapacity <= GetWritableBytes()) { + return true; + } + + size_t minNewCapacity = desireCapacity + writeCursor_; + size_t newCapacity = CalcNewCapacity(minNewCapacity); + if ((newCapacity <= dataCapacity_) || (newCapacity < minNewCapacity)) { + UTILS_LOGW("Failed to ensure parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu, " + "minNewCapacity = %{public}zu", + newCapacity, dataCapacity_, minNewCapacity); + return false; + } + + if (allocator_ != nullptr) { + void *newData = allocator_->Realloc(data_, newCapacity); + if (newData != nullptr) { + data_ = reinterpret_cast(newData); + dataCapacity_ = newCapacity; + return true; + } + UTILS_LOGW("Failed to realloc parcel capacity, newCapacity = %{public}zu, dataCapacity_ = %{public}zu", + newCapacity, dataCapacity_); + } + + return false; +} + +// ValidateReadData only works in basic type read. It doesn't work when read remote object. +// And read/write remote object has no effect on "nextObjectIdx_". +bool Parcel::ValidateReadData([[maybe_unused]]size_t upperBound) +{ +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_ == nullptr || objectCursor_ == 0) { + return true; + } + size_t readPos = readCursor_; + size_t objSize = objectCursor_; + binder_size_t *objects = objectOffsets_; + if (nextObjectIdx_ < objSize && upperBound > objects[nextObjectIdx_]) { + size_t nextObj = nextObjectIdx_; + do { + if (readPos < objects[nextObj] + sizeof(parcel_flat_binder_object)) { + UTILS_LOGE("Non-object Read object data, readPos = %{public}zu, upperBound = %{public}zu", + readPos, upperBound); + return false; + } + nextObj++; + } while (nextObj < objSize && upperBound > objects[nextObj]); + nextObjectIdx_ = nextObj; + } +#endif + return true; } size_t Parcel::GetDataSize() const { - return {}; + return dataSize_; } uintptr_t Parcel::GetData() const { - return {}; + return reinterpret_cast(data_); } binder_size_t Parcel::GetObjectOffsets() const { - return {}; + return reinterpret_cast(objectOffsets_); } size_t Parcel::GetOffsetsSize() const { - return {}; + return objectCursor_; } size_t Parcel::GetDataCapacity() const { - return {}; + return dataCapacity_; } size_t Parcel::GetMaxCapacity() const { - return {}; + return maxDataCapacity_; } bool Parcel::SetMaxCapacity(size_t maxCapacity) { - return {}; + if (maxCapacity > maxDataCapacity_) { + maxDataCapacity_ = maxCapacity; + return true; + } + + return false; } bool Parcel::SetAllocator(Allocator *allocator) { - return {}; + if ((allocator == nullptr) || (allocator_ == allocator)) { + return false; + } + + if ((data_ != nullptr) && (dataSize_ > 0)) { + if (allocator_ == nullptr) { + return false; + } + + void *newData = allocator->Alloc(dataSize_); + if (newData == nullptr) { + UTILS_LOGE("Failed to alloc parcel size, dataSize_ = %{public}zu", dataSize_); + return false; + } + + if (memcpy_s(newData, dataSize_, data_, dataSize_) != EOK) { + allocator->Dealloc(newData); + return false; + } + allocator_->Dealloc(data_); + data_ = reinterpret_cast(newData); + dataCapacity_ = dataSize_; + } + + delete allocator_; + allocator_ = allocator; + return true; } bool Parcel::CheckOffsets() { - return {}; + size_t readPos = readCursor_; + if ((readPos + sizeof(parcel_flat_binder_object)) > dataSize_) { + UTILS_LOGW("CheckOffsets Invalid obj, obj size overflow. objSize:%{public}zu, dataSize:%{public}zu", + readPos + sizeof(parcel_flat_binder_object), dataSize_); + return false; + } + + size_t objSize = objectCursor_; + binder_size_t *objects = objectOffsets_; + size_t objCount = 0; + while (objCount < objSize) { + if (objects[objCount] == readPos) { + return true; + } + objCount++; + } + UTILS_LOGW("CheckOffsets Invalid obj: obj not found."); + return false; } void Parcel::InjectOffsets(binder_size_t offsets, size_t offsetSize) { + if (offsetSize <= 0) { + return; + } + + auto *newObjectOffsets = reinterpret_cast(offsets); + for (size_t index = 0; index < offsetSize; index++) { + if (EnsureObjectsCapacity()) { + WriteObjectOffset(newObjectOffsets[index]); + } + } +} + +void Parcel::ClearObjects() +{ + objectHolder_.clear(); + free(objectOffsets_); + nextObjectIdx_ = 0; + objectCursor_ = 0; + objectOffsets_ = nullptr; + objectsCapacity_ = 0; } void Parcel::FlushBuffer() { + if (allocator_ == nullptr) { + return; + } + + if (data_ != nullptr) { + allocator_->Dealloc(data_); + dataSize_ = 0; + writeCursor_ = 0; + readCursor_ = 0; + dataCapacity_ = 0; + data_ = nullptr; + } + + if (objectOffsets_) { + ClearObjects(); + } } bool Parcel::SetDataCapacity(size_t newCapacity) { - return {}; + if (allocator_ == nullptr || dataSize_ >= newCapacity) { + return false; + } + + void *newData = allocator_->Realloc(data_, newCapacity); + if (newData != nullptr) { + data_ = reinterpret_cast(newData); + dataCapacity_ = newCapacity; + return true; + } + return false; } bool Parcel::SetDataSize(size_t dataSize) { - return {}; + if (dataSize > dataCapacity_) { + return false; + } + + dataSize_ = dataSize; + return true; } bool Parcel::WriteDataBytes(const void *data, size_t size) { - return {}; + void *dest = data_ + writeCursor_; + size_t writableBytes = GetWritableBytes(); + if (memcpy_s(dest, writableBytes, data, size) != EOK) { + return false; + } + writeCursor_ += size; + dataSize_ += size; + return true; } void Parcel::WritePadBytes(size_t padSize) { + uint8_t *dest = data_ + writeCursor_; + static const int MAX_MASK_NUM = 4; +#if __BYTE_ORDER == __LITTLE_ENDIAN + static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0x00ffffff, 0x0000ffff, 0x000000ff }; +#else + static const size_t mask[MAX_MASK_NUM] = { 0xFFFFFFFF, 0xffffff00, 0xffff0000, 0xff000000 }; +#endif + *reinterpret_cast(dest + padSize - MAX_MASK_NUM) &= mask[padSize]; + writeCursor_ += padSize; + dataSize_ += padSize; } bool Parcel::WriteBuffer(const void *data, size_t size) { - return {}; + if (data == nullptr || size == 0) { + return false; + } + + size_t padSize = GetPadSize(size); + size_t desireCapacity = size + padSize; + + // in case of desireCapacity overflow + if (desireCapacity < size || desireCapacity < padSize) { + return false; + } + + if (EnsureWritableCapacity(desireCapacity)) { + if (!WriteDataBytes(data, size)) { + return false; + } + WritePadBytes(padSize); + return true; + } + + return false; } bool Parcel::WriteBufferAddTerminator(const void *data, size_t size, size_t typeSize) { - return {}; + if (data == nullptr || size < typeSize) { + return false; + } + + size_t padSize = GetPadSize(size); + size_t desireCapacity = size + padSize; + + // in case of desireCapacity overflow + if (desireCapacity < size || desireCapacity < padSize) { + return false; + } + + if (EnsureWritableCapacity(desireCapacity)) { + if (!WriteDataBytes(data, size - typeSize)) { + return false; + } + + // Reserved for 32 bits + const char terminator[] = {0, 0, 0, 0}; + if (!WriteDataBytes(terminator, typeSize)) { + return false; + } + WritePadBytes(padSize); + return true; + } + + return false; } bool Parcel::WriteUnpadBuffer(const void *data, size_t size) { - return {}; + return WriteBuffer(data, size); } template bool Parcel::Write(T value) { - return {}; + size_t desireCapacity = sizeof(T); + + if (EnsureWritableCapacity(desireCapacity)) { + *reinterpret_cast(data_ + writeCursor_) = value; + writeCursor_ += desireCapacity; + dataSize_ += desireCapacity; + return true; + } + + return false; } bool Parcel::WriteBool(bool value) @@ -237,103 +527,352 @@ bool Parcel::WritePointer(uintptr_t value) bool Parcel::WriteCString(const char *value) { - return {}; + if (value == nullptr) { + return false; + } + int32_t dataLength = strlen(value); + int32_t desireCapacity = (dataLength + 1) * sizeof(char); + return WriteBuffer(value, desireCapacity); } bool Parcel::WriteString(const std::string &value) { - return {}; + if (value.data() == nullptr) { + return WriteInt32(-1); + } + + int32_t dataLength = value.length(); + int32_t typeSize = sizeof(char); + int32_t desireCapacity = dataLength + typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16(const std::u16string &value) { - return {}; + if (value.data() == nullptr) { + return WriteInt32(-1); + } + + int32_t dataLength = value.length(); + int32_t typeSize = sizeof(char16_t); + int32_t desireCapacity = (dataLength + 1) * typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value.data(), desireCapacity, typeSize); } bool Parcel::WriteString16WithLength(const char16_t *value, size_t len) { - return {}; + if (!value) { + return WriteInt32(-1); + } + + int32_t dataLength = len; + int32_t typeSize = sizeof(char16_t); + int32_t desireCapacity = (dataLength + 1) * typeSize; + std::u16string u16str(reinterpret_cast(value), len); + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(u16str.data(), desireCapacity, typeSize); } bool Parcel::WriteString8WithLength(const char *value, size_t len) { - return {}; + if (!value) { + return WriteInt32(-1); + } + + int32_t dataLength = len; + int32_t typeSize = sizeof(char); + int32_t desireCapacity = (dataLength + 1) * typeSize; + + if (!Write(dataLength)) { + return false; + } + + return WriteBufferAddTerminator(value, desireCapacity, typeSize); } bool Parcel::EnsureObjectsCapacity() { - return {}; + if ((objectsCapacity_ - objectCursor_) >= 1) { + return true; + } + + if (allocator_ == nullptr) { + return false; + } + + const int NEW_CAPACITY_ADD = 2; + const int NEW_CAPACITY_MULTI = 3; + const int NEW_CAPACITY_DIV = 2; + size_t newCapacity = ((objectsCapacity_ + NEW_CAPACITY_ADD) * NEW_CAPACITY_MULTI) / NEW_CAPACITY_DIV; + size_t newBytes = newCapacity * sizeof(binder_size_t); + + void *newOffsets = realloc(objectOffsets_, newBytes); + if (newOffsets == nullptr) { + return false; + } + + objectOffsets_ = reinterpret_cast(newOffsets); + objectsCapacity_ = newCapacity; + return true; } bool Parcel::WriteObjectOffset(binder_size_t offset) { - return {}; + if (offset > dataSize_) { + return false; + } + + for (size_t index = 0; index < objectCursor_; index++) { + if (objectOffsets_[index] == offset) { + return false; + } + } + + objectOffsets_[objectCursor_] = offset; + objectCursor_++; + return true; } bool Parcel::WriteRemoteObject(const Parcelable *object) { - return {}; + size_t placeholder = writeCursor_; + // Parcelable is nullptr + if ((object == nullptr) || (!object->asRemote_)) { + return false; + } + + if (!EnsureObjectsCapacity()) { + return false; + } + + if (!object->Marshalling(*this)) { + return false; + } + + WriteObjectOffset(placeholder); + + if (object->TestBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT)) { + sptr tmp(const_cast(object)); + objectHolder_.push_back(tmp); + } + + return true; } bool Parcel::WriteParcelable(const Parcelable *object) { - return {}; + size_t placeholder = writeCursor_; + size_t restorSize = dataSize_; + + // Parcelable is nullptr + if (object == nullptr) { + // write the meta data to indicate pass an null object. + return WriteInt32(0); + } + + if (!object->asRemote_) { + // meta data indicate we have an parcelable object. + if (!WriteInt32(1)) { + return false; + } + + return object->Marshalling(*this); + } + + // Write the remote object flag + if (!WriteInt32(1)) { + return false; + } + + if (WriteRemoteObject(const_cast(object))) { + return true; + } + + // rollback the write position. + writeCursor_ = placeholder; + dataSize_ = restorSize; + return false; } bool Parcel::WriteStrongParcelable(const sptr &object) { - return {}; + if (object == nullptr) { + WriteInt32(0); + return true; + } + + object->SetBehavior(Parcelable::BehaviorFlag::HOLD_OBJECT); + return WriteParcelable(object.GetRefPtr()); } template bool Parcel::Read(T &value) { - return {}; + size_t desireCapacity = sizeof(T); + + if (desireCapacity <= GetReadableBytes()) { + const void *data = data_ + readCursor_; +#ifdef PARCEL_OBJECT_CHECK + size_t upperBound = readCursor_ + desireCapacity; + if (!ValidateReadData(upperBound)) { + readCursor_ += desireCapacity; + return false; + } +#endif + readCursor_ += desireCapacity; + value = *reinterpret_cast(data); + return true; + } + + return false; } template T Parcel::Read() { - return {}; + T lvalue {}; + return Read(lvalue) ? lvalue : 0; } bool Parcel::ParseFrom(uintptr_t data, size_t size) { - return {}; + if (data_ != nullptr) { + return false; + } + + data_ = reinterpret_cast(data); + dataCapacity_ = size; + dataSize_ = size; + /* data is alloc by driver, can not write again */ + writable_ = false; +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_) { + ClearObjects(); + } +#endif + return true; } const uint8_t *Parcel::ReadBuffer(size_t length) { - return {}; + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + readCursor_ += length; + return buffer; + } + + return nullptr; +} + +const uint8_t *Parcel::BasicReadBuffer([[maybe_unused]]size_t length) +{ +#ifdef PARCEL_OBJECT_CHECK + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + size_t upperBound = readCursor_ + length; + if (!ValidateReadData(upperBound)) { + readCursor_ += length; + return nullptr; + } + readCursor_ += length; + return buffer; + } +#endif + return nullptr; } const uint8_t *Parcel::ReadUnpadBuffer(size_t length) { - return {}; + if (GetReadableBytes() >= length) { + uint8_t *buffer = data_ + readCursor_; + readCursor_ += length; + SkipBytes(GetPadSize(length)); + return buffer; + } + + return nullptr; } void Parcel::SkipBytes(size_t bytes) { + if (GetReadableBytes() >= bytes) { + readCursor_ += bytes; + } else if (readCursor_ < dataCapacity_) { + readCursor_ = dataCapacity_; + } } size_t Parcel::GetReadPosition() { - return {}; + return readCursor_; } bool Parcel::RewindRead(size_t newPosition) { - return {}; + if (newPosition > dataSize_) { + return false; + } + readCursor_ = newPosition; + nextObjectIdx_ = 0; + return true; } size_t Parcel::GetWritePosition() { - return {}; + return writeCursor_; } bool Parcel::RewindWrite(size_t newPosition) { - return {}; + if (newPosition > dataSize_) { + return false; + } + writeCursor_ = newPosition; + dataSize_ = newPosition; +#ifdef PARCEL_OBJECT_CHECK + if (objectOffsets_ == nullptr || objectCursor_ == 0) { + return true; + } + size_t objectSize = objectCursor_; + if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) > newPosition) { + while (objectSize > 0) { + if (objectOffsets_[objectSize - 1] + sizeof(parcel_flat_binder_object) <= newPosition) { + break; + } + objectSize--; + } + if (objectSize == 0) { + ClearObjects(); + return true; + } + size_t newBytes = objectSize * sizeof(binder_size_t); + void *newOffsets = realloc(objectOffsets_, newBytes); + if (newOffsets == nullptr) { + return false; + } + objectOffsets_ = reinterpret_cast(newOffsets); + objectCursor_ = objectSize; + objectsCapacity_ = objectCursor_; + objectHolder_.resize(objectSize); + nextObjectIdx_ = 0; + return true; + } +#endif + return true; } bool Parcel::ReadBool() @@ -404,7 +943,13 @@ double Parcel::ReadDouble() template bool Parcel::ReadPadded(T &value) { - return {}; + int32_t temp; + bool result = Read(temp); + if (result) { + value = static_cast(temp); + } + + return result; } bool Parcel::ReadBool(bool &value) @@ -489,42 +1034,216 @@ uintptr_t Parcel::ReadPointer() const char *Parcel::ReadCString() { - return {}; + size_t oldCursor = readCursor_; + const size_t avail = GetReadableBytes(); + const char* cstr = reinterpret_cast(data_ + readCursor_); + // is the string's trailing NUL within the parcel's valid bounds? + const char* eos = reinterpret_cast(memchr(cstr, 0, avail)); + if (eos != nullptr) { + const size_t dataLength = eos - cstr; + readCursor_ += (dataLength + 1); + SkipBytes(GetPadSize(dataLength + 1)); + return cstr; + } + readCursor_ = oldCursor; + return nullptr; } const std::string Parcel::ReadString() { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + return std::string(); + } + + size_t readCapacity = static_cast(dataLength) + 1; + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *dest = BasicReadBuffer(readCapacity); +#else + const uint8_t *dest = ReadBuffer(readCapacity); +#endif + if (dest != nullptr) { + const auto *str = reinterpret_cast(dest); + SkipBytes(GetPadSize(readCapacity)); + if (str[dataLength] == 0) { + return std::string(str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::string(); } bool Parcel::ReadString(std::string &value) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + value = std::string(); + return false; + } + + size_t readCapacity = static_cast(dataLength) + 1; + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *dest = BasicReadBuffer(readCapacity); +#else + const uint8_t *dest = ReadBuffer(readCapacity); +#endif + if (dest != nullptr) { + const auto *str = reinterpret_cast(dest); + SkipBytes(GetPadSize(readCapacity)); + if (str[dataLength] == 0) { + value = std::string(str, dataLength); + return true; + } + } + } + + readCursor_ = oldCursor; + value = std::string(); + return false; } const std::u16string Parcel::ReadString16() { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + return std::u16string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + return std::u16string(u16Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::u16string(); } bool Parcel::ReadString16(std::u16string &value) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength) || dataLength < 0 || dataLength >= INT32_MAX) { + value = std::u16string(); + return false; + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + value = std::u16string(u16Str, dataLength); + return true; + } + } + } + + readCursor_ = oldCursor; + value = std::u16string(); + return false; } const std::u16string Parcel::ReadString16WithLength(int32_t &readLength) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength)) { + return std::u16string(); + } + + if (dataLength < 0 || dataLength >= INT32_MAX) { + readLength = dataLength; + return std::u16string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char16_t); + if ((readCapacity > (static_cast(dataLength))) && (readCapacity <= GetReadableBytes())) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u16Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u16Str[dataLength] == 0) { + readLength = dataLength; + return std::u16string(u16Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::u16string(); } const std::string Parcel::ReadString8WithLength(int32_t &readLength) { - return {}; + int32_t dataLength = 0; + size_t oldCursor = readCursor_; + + if (!Read(dataLength)) { + return std::string(); + } + + if (dataLength < 0 || dataLength >= INT32_MAX) { + readLength = dataLength; + return std::string(); + } + + size_t readCapacity = (static_cast(dataLength) + 1) * sizeof(char); + if (readCapacity <= GetReadableBytes()) { +#ifdef PARCEL_OBJECT_CHECK + const uint8_t *str = BasicReadBuffer(readCapacity); +#else + const uint8_t *str = ReadBuffer(readCapacity); +#endif + if (str != nullptr) { + const auto *u8Str = reinterpret_cast(str); + SkipBytes(GetPadSize(readCapacity)); + if (u8Str[dataLength] == 0) { + readLength = dataLength; + return std::string(u8Str, dataLength); + } + } + } + + readCursor_ = oldCursor; + return std::string(); } void *DefaultAllocator::Alloc(size_t size) { - return nullptr; + return malloc(size); } void DefaultAllocator::Dealloc(void *data) @@ -536,13 +1255,29 @@ void DefaultAllocator::Dealloc(void *data) void *DefaultAllocator::Realloc(void *data, size_t newSize) { - return nullptr; + return realloc(data, newSize); } template bool Parcel::WriteVector(const std::vector &val, bool (Parcel::*Write)(T2)) { - return {}; + if (val.size() > INT_MAX) { + return false; + } + + if (!this->WriteInt32(static_cast(val.size()))) { + return false; + } + + for (const auto &v : val) { + if (!(this->*Write)(v)) { + return false; + } + } + + size_t padSize = this->GetPadSize(val.size() * sizeof(T1)); + this->WritePadBytes(padSize); + return true; } bool Parcel::WriteBoolVector(const std::vector &val) @@ -613,12 +1348,66 @@ bool Parcel::WriteString16Vector(const std::vector &val) template bool Parcel::ReadVector(std::vector *val, bool (Parcel::*Read)(T &)) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes() / sizeof(T); + size_t size = static_cast(len); + if ((size > readAbleSize) || (size > val->max_size())) { + UTILS_LOGE("Failed to read vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + if (!(this->*Read)(v)) { + return false; + } + } + + size_t padSize = this->GetPadSize(size * sizeof(T)); + this->SkipBytes(padSize); + return true; } bool Parcel::ReadBoolVector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read bool vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (size_t i = 0; i < size; ++i) { + (*val)[i] = ReadBool(); + } + + size_t padSize = this->GetPadSize(size * sizeof(bool)); + this->SkipBytes(padSize); + return true; } bool Parcel::ReadInt8Vector(std::vector *val) @@ -673,11 +1462,61 @@ bool Parcel::ReadDoubleVector(std::vector *val) bool Parcel::ReadStringVector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read string vector, size = %{public}zu, readAbleSize = %{public}zu", size, readAbleSize); + return false; + } + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + v = ReadString(); + } + + return true; } bool Parcel::ReadString16Vector(std::vector *val) { - return {}; + if (val == nullptr) { + return false; + } + + int32_t len = this->ReadInt32(); + if (len < 0) { + return false; + } + + size_t readAbleSize = this->GetReadableBytes(); + size_t size = static_cast(len); + if ((size > readAbleSize) || (val->max_size() < size)) { + UTILS_LOGE("Failed to read u16string vector, size = %{public}zu, readAbleSize = %{public}zu", + size, readAbleSize); + return false; + } + + val->resize(size); + if (val->size() < size) { + return false; + } + + for (auto &v : *val) { + v = ReadString16(); + } + + return true; } } // namespace OHOS -- Gitee From d7ad93d0fa203fe8556c9f94f1fa7e03d15c80ca Mon Sep 17 00:00:00 2001 From: liyang Date: Wed, 6 Dec 2023 17:21:20 +0800 Subject: [PATCH 5/5] update gtest for windows unittest Signed-off-by: liyang --- .../ipc_core/include/message_parcel.h | 178 ++----- .../native/src/core/source/message_parcel.cpp | 453 +----------------- .../ipc/native/src/mock/include/sys_binder.h | 292 +++++++++++ adapter/linux/types.h | 0 4 files changed, 352 insertions(+), 571 deletions(-) create mode 100644 3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h create mode 100644 adapter/linux/types.h diff --git a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h index c154b5e..cffffca 100755 --- a/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h +++ b/3rdparty/ohos/foundation/communication/ipc/interfaces/innerkits/ipc_core/include/message_parcel.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021-2023 Huawei Device Co., Ltd. + * Copyright (C) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,10 +16,11 @@ #ifndef OHOS_IPC_MESSAGE_PARCEL_H #define OHOS_IPC_MESSAGE_PARCEL_H -#include +#include +#include #include "parcel.h" #include "refbase.h" -#include +#include namespace OHOS { class IRemoteObject; @@ -28,171 +29,62 @@ namespace OHOS { MessageParcel(); ~MessageParcel(); explicit MessageParcel(Allocator *allocator); - - /** - * @brief Serializes the remote object and writes it. - * @param object Indicates the remote object to serialize. - * @return Returns true if it is successful; returns false otherwise. - * @since 9 - */ bool WriteRemoteObject(const sptr &object); - - /** - * @brief Reads a remote object. - * @return Returns the IRemoteObject pointer object. - * @since 9 - */ sptr ReadRemoteObject(); - - /** - * @brief Writes an file descriptor into the object. - * @param fd Indicates file descriptor to write. - * @return Returns true if the write succeeds; return false otherwise. - * @since 9 - */ bool WriteFileDescriptor(int fd); - - /** - * @brief Reads an file descriptor from the object. - * @return Returns the corresponding descriptor If the read is successful; returns {@code -1} otherwise. - * @since 9 - */ int ReadFileDescriptor(); - - /** - * @brief Check whether the file descriptor is included. - * @return Returns true if checking for inclusion; returns false Otherwise. - * @since 9 - */ bool ContainFileDescriptors() const; - - /** - * @brief Writes an interface token into the object. - * @param name Indicates the string type name. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteInterfaceToken(std::u16string name); - - /** - * @brief Reads an interface token from the object. - * @return Returns a string value. - * @since 9 - */ std::u16string ReadInterfaceToken(); - - /** - * @brief Writes raw data to the object. - * @param data Indicates the original data written. - * @param size Indicates the size of the raw data sent. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteRawData(const void *data, size_t size); - - /** - * @brief Reads raw data from the object. - * @param size Indicates the size of the raw data to read. - * @return void - * @since 9 - */ const void *ReadRawData(size_t size); - - /** - * @brief Restore raw data. - * @param rawData Indicates the original data to be recovered. - * @param size Indicates the size of the raw data to read. - * @return Returns true if recovery is successful; returns false Otherwise. - * @since 9 - */ bool RestoreRawData(std::shared_ptr rawData, size_t size); - - /** - * @brief Obtains raw data from the object. - * @return void - * @since 9 - */ const void *GetRawData() const; - - /** - * @brief Gets the raw data size. - * @return Returns the resulting raw data size. - * @since 9 - */ size_t GetRawDataSize() const; - - /** - * @brief Get raw data capacity. - * @return Returns the maximum value of the raw data capacity. - * @since 9 - */ size_t GetRawDataCapacity() const; - - /** - * @brief writes information to the object indicating that no exception occurred. - * @return void - * @since 9 - */ void WriteNoException(); - - /** - * @brief Reads the exception information from the object. - * @return Returns the read error code. - * @since 9 - */ int32_t ReadException(); - - /** - * @brief Writes an anonymous shared memory object to the object. - * @param ashmem Indicates anonymous shared memory object to wrote. - * @return Returns true if the write succeeds; returns false otherwise. - * @since 9 - */ bool WriteAshmem(sptr ashmem); - - /** - * @brief Reads the anonymous shared memory object from the object. - * @return Returns anonymous share object obtained. - * @since 9 - */ sptr ReadAshmem(); - - /** - * @brief Clear the file descriptor. - * @return void - * @since 9 - */ void ClearFileDescriptor(); - - /** - * @brief Sets the Clear specified file descriptor flag. - * @return void - * @since 9 - */ + std::vector vectorParcel; + bool Append(MessageParcel &data) + { + size_t dataSize = data.GetDataSize(); + if (dataSize == 0) { + return true; + } + uintptr_t dataPtr = data.GetData(); + size_t writeCursorOld = this->GetWritePosition(); + if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { + return false; + } + size_t objectSize = data.GetOffsetsSize(); + if (objectSize == 0) { + return true; + } + binder_size_t objectOffsets = data.GetObjectOffsets(); + auto *newObjectOffsets = reinterpret_cast(objectOffsets); + for (size_t index = 0; index < objectSize; index++) { + if (EnsureObjectsCapacity()) { + size_t offset = writeCursorOld + newObjectOffsets[index]; + if (!WriteObjectOffset(offset)) { + return false; + } + + } else { + return false; + } + } + return true; + }; void SetClearFdFlag() { needCloseFd_ = true; }; - /** - * @brief Append a MessageParcel object to the end of the current MessageParcel. - * @param data Indicates the data to append. - * @return Returns true if append succeeds; returns false Otherwise. - * @since 9 - */ - bool Append(MessageParcel &data); - private: #ifndef CONFIG_IPC_SINGLE - - /** - * @brief Write to the DBinder proxy object. - * @param object Indicates an IRemoteObject type object. - * @param handle Indicates the handle to write. - * @param stubIndex Indicates the stub index to write to. - * @return Returns true if the write succeeds; returns false otherwise. - * @since - */ bool WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex); #endif static constexpr size_t MAX_RAWDATA_SIZE = 128 * 1024 * 1024; // 128M diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp index b226d2c..4eac1e3 100644 --- a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/core/source/message_parcel.cpp @@ -1,10 +1,10 @@ /* - * Copyright (C) 2021 Huawei Device Co., Ltd. + * Copyright (C) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -15,69 +15,9 @@ #include "message_parcel.h" -#include -#include -#include -#include - -#include "ashmem.h" -#include "hilog/log_c.h" -#include "hilog/log_cpp.h" -#include "ipc_file_descriptor.h" -#include "ipc_process_skeleton.h" -#include "iremote_invoker.h" #include "iremote_object.h" -#include "log_tags.h" -#include "memory" -#include "new" -#include "parcel.h" -#include "refbase.h" -#include "securec.h" -#include "string" -#include "sys_binder.h" -#include "vector" -#include "ipc_debug.h" - -#ifndef CONFIG_IPC_SINGLE -#include "dbinder_callback_stub.h" -#include "dbinder_session_object.h" -#endif namespace OHOS { -#ifdef CONFIG_IPC_SINGLE - using namespace IPC_SINGLE; -#endif - static constexpr OHOS::HiviewDFX::HiLogLabel LOG_LABEL = { LOG_CORE, LOG_ID_RPC, "MessageParcel" }; - - void AcquireObject(flat_binder_object *flat, const void *cookie) - { - switch (flat->hdr.type) { - case BINDER_TYPE_BINDER: - if (flat->binder) { - reinterpret_cast(flat->cookie)->IncStrongRef(cookie); - } - break; - case BINDER_TYPE_HANDLE: { - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - IRemoteObject *remoteObject = nullptr; - if (current != nullptr) { - remoteObject = current->QueryObject(current->MakeHandleDescriptor(flat->handle)); - } - if (remoteObject != nullptr) { - remoteObject->IncStrongRef(cookie); - } - break; - } - case BINDER_TYPE_FD: - flat->handle = static_cast(dup(flat->handle)); - flat->cookie = 1; - break; - default: - ZLOGE(LOG_LABEL, "binder object type is invalid."); - break; - } - } - MessageParcel::MessageParcel() : Parcel(), writeRawDataFd_(-1), @@ -100,444 +40,101 @@ namespace OHOS { MessageParcel::~MessageParcel() { - if (kernelMappedWrite_ != nullptr) { - ::munmap(kernelMappedWrite_, rawDataSize_); - kernelMappedWrite_ = nullptr; - } - if (kernelMappedRead_ != nullptr) { - ::munmap(kernelMappedRead_, rawDataSize_); - kernelMappedRead_ = nullptr; - } - - if (readRawDataFd_ > 0) { - ::close(readRawDataFd_); - readRawDataFd_ = -1; - } - if (writeRawDataFd_ > 0) { - ::close(writeRawDataFd_); - writeRawDataFd_ = -1; - } - - ClearFileDescriptor(); - - rawData_ = nullptr; - rawDataSize_ = 0; } #ifndef CONFIG_IPC_SINGLE bool MessageParcel::WriteDBinderProxy(const sptr &object, uint32_t handle, uint64_t stubIndex) { - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - if (current == nullptr) { - ZLOGE(LOG_LABEL, "current is nullptr"); - return false; - } - std::shared_ptr sessionOfPeer = current->ProxyQueryDBinderSession(handle); - if (sessionOfPeer == nullptr) { - ZLOGE(LOG_LABEL, "sessionOfPeer is null, handle: %{public}u, stubIndex: %{public}" PRIu64, handle, stubIndex); - return false; - } - std::string peerName = sessionOfPeer->GetServiceName(); - std::string peerId = sessionOfPeer->GetDeviceId(); - std::string localId = current->GetLocalDeviceID(); - uint32_t tokenId = sessionOfPeer->GetTokenId(); - - sptr fakeStub = current->QueryDBinderCallbackStub(object); - if (fakeStub == nullptr) { - // note that cannot use this proxy's descriptor, this stub is now stored and strong refered - // and need to be erased in an approprite time - fakeStub = new (std::nothrow) DBinderCallbackStub(peerName, peerId, localId, sessionOfPeer->GetStubIndex(), - handle, tokenId); - if (fakeStub == nullptr) { - ZLOGE(LOG_LABEL, "create DBinderCallbackStub object failed"); - return false; - } - if (!current->AttachDBinderCallbackStub(object, fakeStub)) { - ZLOGE(LOG_LABEL, "save callback of fake stub failed"); - return false; - } - } - return WriteRemoteObject(fakeStub); + (void)object; + (void)handle; + (void)stubIndex; + return false; } #endif bool MessageParcel::WriteRemoteObject(const sptr &object) { - if (object == nullptr) { - return false; - } - // Increase object's refcount temporarily in case of premature deallocation, - // object's refcount will be decreased when this MessageParcel destroyed. - holders_.push_back(object); -#ifndef CONFIG_IPC_SINGLE - if (object->IsProxyObject()) { - const IPCObjectProxy *proxy = reinterpret_cast(object.GetRefPtr()); - const uint32_t handle = proxy ? proxy->GetHandle() : 0; - if (IPCProcessSkeleton::IsHandleMadeByUser(handle)) { - /* this is a fake proxy which handle get by MakeRemoteHandle(), Not binder driver of kernel */ - ZLOGI(LOG_LABEL, "send a dbinder proxy to another process in this device"); - return WriteDBinderProxy(object, handle, 0); - } - } -#endif - auto result = WriteObject(object); - if (result == false) { - return result; - } - return result; + (void)object; + return false; } sptr MessageParcel::ReadRemoteObject() { - sptr temp = ReadObject(); -#ifndef CONFIG_IPC_SINGLE - if (temp != nullptr && !temp->IsProxyObject()) { - // if this stub is a DBinderCallbackStub, return corresponding proxy - IPCProcessSkeleton *current = IPCProcessSkeleton::GetCurrent(); - if (current != nullptr) { - sptr proxy = current->QueryDBinderCallbackProxy(temp); - if (proxy != nullptr) { - temp = proxy; - } - } - } -#endif - return temp; + return nullptr; } bool MessageParcel::WriteFileDescriptor(int fd) { - if (fd < 0) { - return false; - } - int dupFd = dup(fd); - if (dupFd < 0) { - return false; - } - sptr descriptor = new (std::nothrow) IPCFileDescriptor(dupFd); - if (descriptor == nullptr) { - ZLOGE(LOG_LABEL, "create IPCFileDescriptor object failed"); - return false; - } - return WriteObject(descriptor); + return false; } int MessageParcel::ReadFileDescriptor() { - sptr descriptor = ReadObject(); - if (descriptor == nullptr) { - return -1; - } - int fd = descriptor->GetFd(); - if (fd < 0) { - return -1; - } - return dup(fd); + return -1; } void MessageParcel::ClearFileDescriptor() { - size_t dataOffset = 0; - binder_size_t *object = nullptr; - const flat_binder_object *flat = nullptr; - for (size_t i = 0; i < GetOffsetsSize(); i++) { - object = reinterpret_cast(GetObjectOffsets()); - if (object == nullptr) { - ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); - break; - } - // offset + size - dataOffset = object[i] + sizeof(flat_binder_object); - if (dataOffset > GetDataSize()) { - ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", - dataOffset, GetDataSize()); - break; - } - uintptr_t data = GetData(); - if (data == 0) { - ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); - break; - } - flat = reinterpret_cast(data + object[i]); - if (flat->hdr.type == BINDER_TYPE_FD && flat->handle > 0) { - ::close(flat->handle); - } - } } bool MessageParcel::ContainFileDescriptors() const { - size_t dataOffset = 0; - binder_size_t *object = nullptr; - const flat_binder_object *flat = nullptr; - for (size_t i = 0; i < GetOffsetsSize(); i++) { - object = reinterpret_cast(GetObjectOffsets()); - if (object == nullptr) { - ZLOGE(LOG_LABEL, "object get by GetObjectOffsets() is nullptr"); - break; - } - // offset + size - dataOffset = object[i] + sizeof(flat_binder_object); - if (dataOffset > GetDataSize()) { - ZLOGE(LOG_LABEL, "object offset is overflow, dataOffset:%{public}zu, dataSize:%{public}zu", - dataOffset, GetDataSize()); - break; - } - uintptr_t data = GetData(); - if (data == 0) { - ZLOGE(LOG_LABEL, "data get by GetData() is invalid"); - break; - } - flat = reinterpret_cast(data + object[i]); - if (flat->hdr.type == BINDER_TYPE_FD) { - return true; - } - } - return false; } bool MessageParcel::WriteInterfaceToken(std::u16string name) { - constexpr int strictModePolicy = 0x100; - constexpr int workSource = 0; - size_t rewindPos = GetWritePosition(); - if (!WriteInt32(strictModePolicy)) { - return false; - } - - if (!WriteInt32(workSource)) { - if (!RewindWrite(rewindPos)) { - FlushBuffer(); - } - return false; - } - - return WriteString16(name); + (void)name; + return false; } std::u16string MessageParcel::ReadInterfaceToken() { - [[maybe_unused]] int32_t strictModePolicy = ReadInt32(); - [[maybe_unused]] int32_t workSource = ReadInt32(); - return ReadString16(); + return u""; } bool MessageParcel::WriteRawData(const void *data, size_t size) { - if (data == nullptr || size > MAX_RAWDATA_SIZE || size == 0) { - ZLOGE(LOG_LABEL, "data is null or size:%{public}zu not ok", size); - return false; - } - if (kernelMappedWrite_ != nullptr) { - return false; - } - if (!WriteInt32(size)) { - return false; - } - if (size <= MIN_RAWDATA_SIZE) { - rawDataSize_ = size; - return WriteUnpadBuffer(data, size); - } - int fd = AshmemCreate("Parcel RawData", size); - if (fd < 0) { - return false; - } - writeRawDataFd_ = fd; - - int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); - if (result < 0) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return false; - } - void *ptr = ::mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return false; - } - if (!WriteFileDescriptor(fd)) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ::munmap(ptr, size); - return false; - } - if (memcpy_s(ptr, size, data, size) != EOK) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ::munmap(ptr, size); - return false; - } - kernelMappedWrite_ = ptr; - rawDataSize_ = size; - return true; + (void)data; + (void)size; + return false; } bool MessageParcel::RestoreRawData(std::shared_ptr rawData, size_t size) { - if (rawData_ != nullptr || rawData == nullptr) { - return false; - } - rawData_ = rawData; - rawDataSize_ = size; - writeRawDataFd_ = 0; - return true; + (void)rawData; + (void)size; + return false; } const void *MessageParcel::ReadRawData(size_t size) { - if (size == 0) { - ZLOGE(LOG_LABEL, "the parameter size is 0"); - return nullptr; - } - size_t bufferSize = static_cast(ReadInt32()); - if (bufferSize != size) { - ZLOGE(LOG_LABEL, "ReadRawData: the buffersize %{public}zu not equal the parameter size %{public}zu", - bufferSize, size); - return nullptr; - } - if (bufferSize <= MIN_RAWDATA_SIZE) { - rawDataSize_ = size; - return ReadUnpadBuffer(size); - } - - /* if rawDataFd_ == 0 means rawData is received from remote */ - if (rawData_ != nullptr && writeRawDataFd_ == 0) { - /* should read fd for move readCursor of parcel */ - if (ReadFileDescriptor()) { - // do nothing - } - if (rawDataSize_ != size) { - ZLOGE(LOG_LABEL, "rawData is received from remote, the rawDataSize_ %{public}zu" - " not equal size %{public}zu", rawDataSize_, size); - return nullptr; - } - return rawData_.get(); - } - int fd = ReadFileDescriptor(); - if (fd < 0) { - return nullptr; - } - readRawDataFd_ = fd; - - int ashmemSize = AshmemGetSize(fd); - if (ashmemSize < 0 || size_t(ashmemSize) < size) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - ZLOGE(LOG_LABEL, "ashmemSize %{public}d less than size %{public}zu", - ashmemSize, size); - return nullptr; - } - void *ptr = ::mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); - if (ptr == MAP_FAILED) { - // Do not close fd here, which will be closed in MessageParcel's destructor. - return nullptr; - } - kernelMappedRead_ = ptr; - rawDataSize_ = size; - return ptr; + (void)size; + return nullptr; } const void *MessageParcel::GetRawData() const { - if (rawData_ != nullptr) { - return rawData_.get(); - } - if (kernelMappedWrite_ != nullptr) { - return kernelMappedWrite_; - } - if (kernelMappedRead_ != nullptr) { - return kernelMappedRead_; - } return nullptr; } size_t MessageParcel::GetRawDataSize() const { - return rawDataSize_; + return -1; } size_t MessageParcel::GetRawDataCapacity() const { - return MAX_RAWDATA_SIZE; + return -1; } void MessageParcel::WriteNoException() { - WriteInt32(0); } int32_t MessageParcel::ReadException() { - int32_t errorCode = ReadInt32(); - if (errorCode != 0) { - ReadString16(); - } - return errorCode; - } - - bool MessageParcel::WriteAshmem(sptr ashmem) - { - int fd = ashmem->GetAshmemFd(); - int32_t size = ashmem->GetAshmemSize(); - if (fd < 0 || size <= 0) { - return false; - } - if (!WriteFileDescriptor(fd) || !WriteInt32(size)) { - return false; - } - return true; - } - - sptr MessageParcel::ReadAshmem() - { - int fd = ReadFileDescriptor(); - if (fd < 0) { - return nullptr; - } - - int32_t size = ReadInt32(); - if (size <= 0) { - ::close(fd); - return nullptr; - } - return new (std::nothrow) Ashmem(fd, size); - } - - bool MessageParcel::Append(MessageParcel &data) - { - size_t dataSize = data.GetDataSize(); - if (dataSize == 0) { - ZLOGE(LOG_LABEL, "no data to append"); - return true; - } - uintptr_t dataPtr = data.GetData(); - size_t writeCursorOld = this->GetWritePosition(); - if (!WriteBuffer(reinterpret_cast(dataPtr), dataSize)) { - ZLOGE(LOG_LABEL, "failed to append data with writebuffer."); - return false; - } - size_t objectSize = data.GetOffsetsSize(); - if (objectSize == 0) { - return true; - } - binder_size_t objectOffsets = data.GetObjectOffsets(); - auto *newObjectOffsets = reinterpret_cast(objectOffsets); - for (size_t index = 0; index < objectSize; index++) { - if (EnsureObjectsCapacity()) { - size_t offset = writeCursorOld + newObjectOffsets[index]; - if (!WriteObjectOffset(offset)) { - ZLOGE(LOG_LABEL, "failed to write object offset"); - return false; - } - flat_binder_object *flat = reinterpret_cast(this->GetData() + offset); - if (flat == nullptr) { - ZLOGE(LOG_LABEL, "flat binder object is nullptr"); - return false; - } - AcquireObject(flat, this); - } else { - ZLOGE(LOG_LABEL, "Failed to ensure parcel capacity"); - return false; - } - } - return true; + return -1; } } // namespace OHOS diff --git a/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h new file mode 100644 index 0000000..6765a73 --- /dev/null +++ b/3rdparty/ohos/foundation/communication/ipc/ipc/native/src/mock/include/sys_binder.h @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_IPC_SYS_BINDER_H +#define OHOS_IPC_SYS_BINDER_H + +#include + +#ifndef _UAPI_LINUX_BINDER_H +#define _UAPI_LINUX_BINDER_H + +#include +#include + +#ifndef B_PACK_CHARS +#define B_PACK_CHARS(c1, c2, c3, c4) ((((c1) << 24)) | (((c2) << 16)) | (((c3) << 8)) | (c4)) +#endif + +#define B_TYPE_LARGE 0x85 +enum { + BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), + BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), + BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), + BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE), + BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), +}; +enum { + FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff, + FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100, + FLAT_BINDER_FLAG_TXN_SECURITY_CTX = 0x1000, +}; +#ifdef BINDER_IPC_32BIT +typedef __u32 binder_size_t; +typedef __u32 binder_uintptr_t; +#else +typedef __u64 binder_size_t; +typedef __u64 binder_uintptr_t; +#endif +struct binder_object_header { + __u32 type; +}; +struct flat_binder_object { + struct binder_object_header hdr; + __u32 flags; + union { + binder_uintptr_t binder; + __u32 handle; + }; + binder_uintptr_t cookie; +}; + +struct binder_fd_object { + struct binder_object_header hdr; + __u32 pad_flags; + union { + binder_uintptr_t pad_binder; + __u32 fd; + }; + binder_uintptr_t cookie; +}; +struct binder_buffer_object { + struct binder_object_header hdr; + __u32 flags; + binder_uintptr_t buffer; + binder_size_t length; + binder_size_t parent; + binder_size_t parent_offset; +}; +enum { + BINDER_BUFFER_FLAG_HAS_PARENT = 0x01, +}; +struct binder_fd_array_object { + struct binder_object_header hdr; + __u32 pad; + binder_size_t num_fds; + binder_size_t parent; + binder_size_t parent_offset; +}; +struct binder_write_read { + binder_size_t write_size; + binder_size_t write_consumed; + binder_uintptr_t write_buffer; + binder_size_t read_size; + binder_size_t read_consumed; + binder_uintptr_t read_buffer; +}; +struct binder_version { + __s32 protocol_version; +}; +#ifdef BINDER_IPC_32BIT +#define BINDER_CURRENT_PROTOCOL_VERSION 7 +#else +#define BINDER_CURRENT_PROTOCOL_VERSION 8 +#endif +struct binder_node_debug_info { + binder_uintptr_t ptr; + binder_uintptr_t cookie; + __u32 has_strong_ref; + __u32 has_weak_ref; +}; + +struct binder_node_info_for_ref { + __u32 handle; + __u32 strong_count; + __u32 weak_count; + __u32 reserved1; + __u32 reserved2; + __u32 reserved3; +}; + +#define ACCESS_TOKENID_GET_TOKENID _IOR('A', 1, unsigned long long) +#define ACCESS_TOKENID_GET_FTOKENID _IOR('A', 3, unsigned long long) +#define ACCESS_TOKEN_FAETURE_MASK (1 << 0) + +struct binder_feature_set { + __u64 feature_set; +}; + +struct access_token { + __u64 sender_tokenid; + __u64 first_tokenid; + __u64 reserved[2]; +}; + +#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) +#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64) +#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32) +#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, __s32) +#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, __s32) +#define BINDER_THREAD_EXIT _IOW('b', 8, __s32) +#define BINDER_VERSION _IOWR('b', 9, struct binder_version) +#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info) +#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref) +#define BINDER_SET_CONTEXT_MGR_EXT _IOW('b', 13, struct flat_binder_object) +#define BINDER_FEATURE_SET _IOWR('b', 30, struct binder_feature_set) +#define BINDER_GET_ACCESS_TOKEN _IOWR('b', 31, struct access_token) + +enum transaction_flags { + TF_ONE_WAY = 0x01, + TF_ROOT_OBJECT = 0x04, + TF_STATUS_CODE = 0x08, + TF_ACCEPT_FDS = 0x10, + TF_HITRACE = 0x80, // add flag for hitrace +}; +struct binder_transaction_data { + union { + __u32 handle; + binder_uintptr_t ptr; + } target; + binder_uintptr_t cookie; + __u32 code; + __u32 flags; + pid_t sender_pid; + uid_t sender_euid; + binder_size_t data_size; + binder_size_t offsets_size; + union { + struct { + binder_uintptr_t buffer; + binder_uintptr_t offsets; + } ptr; + __u8 buf[8]; + } data; +}; + +struct binder_transaction_data_secctx { + struct binder_transaction_data transaction_data; + binder_uintptr_t secctx; +}; + +struct binder_transaction_data_sg { + struct binder_transaction_data transaction_data; + binder_size_t buffers_size; +}; + +struct binder_ptr_cookie { + binder_uintptr_t ptr; + binder_uintptr_t cookie; +}; +struct binder_handle_cookie { + __u32 handle; + binder_uintptr_t cookie; +} __attribute__((__packed__)); +struct binder_pri_desc { + __s32 priority; + __u32 desc; +}; +struct binder_pri_ptr_cookie { + __s32 priority; + binder_uintptr_t ptr; + binder_uintptr_t cookie; +}; +enum binder_driver_return_protocol { + BR_ERROR = _IOR('r', 0, __s32), + BR_OK = _IO('r', 1), + BR_TRANSACTION_SEC_CTX = _IOR('r', 2, struct binder_transaction_data_secctx), + BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), + BR_REPLY = _IOR('r', 3, struct binder_transaction_data), + BR_ACQUIRE_RESULT = _IOR('r', 4, __s32), + BR_DEAD_REPLY = _IO('r', 5), + BR_TRANSACTION_COMPLETE = _IO('r', 6), + BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), + BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), + BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), + BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), + BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), + BR_NOOP = _IO('r', 12), + BR_SPAWN_LOOPER = _IO('r', 13), + BR_FINISHED = _IO('r', 14), + BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t), + BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), + BR_FAILED_REPLY = _IO('r', 17), + BR_RELEASE_NODE = _IO('r', 18), + BR_TRANSLATION_COMPLETE = _IOR('r', 20, __u32), +}; +enum binder_driver_command_protocol { + BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), + BC_REPLY = _IOW('c', 1, struct binder_transaction_data), + BC_ACQUIRE_RESULT = _IOW('c', 2, __s32), + BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t), + BC_INCREFS = _IOW('c', 4, __u32), + BC_ACQUIRE = _IOW('c', 5, __u32), + BC_RELEASE = _IOW('c', 6, __u32), + BC_DECREFS = _IOW('c', 7, __u32), + BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), + BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), + BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), + BC_REGISTER_LOOPER = _IO('c', 11), + BC_ENTER_LOOPER = _IO('c', 12), + BC_EXIT_LOOPER = _IO('c', 13), + BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_handle_cookie), + BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie), + BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t), + BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg), + BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg), + BC_SEND_RAWDATA = _IOW('c', 20, __u32), + BC_TRANSLATION = _IOW('c', 21, struct flat_binder_object), +}; +#endif /* * _UAPI_LINUX_BINDER_H * */ + +static const uint32_t DBINDER_MAGICWORD = 0X4442494E; +static const uint32_t ENCRYPT_HEAD_LEN = 28; +static const uint32_t DEVICEID_LENGTH = 64; +static const uint32_t PID_LEN = 32; +static const uint32_t RPC_DEFAULT_VERSION_NUM = 1; +static const uint32_t SUPPORT_TOKENID_VERSION_NUM = 2; +static const uint32_t TOKENID_MAGIC = 0X544F4B49; + +enum { + BINDER_TYPE_REMOTE_BINDER = B_PACK_CHARS('r', 'b', '*', B_TYPE_LARGE), + BINDER_TYPE_REMOTE_HANDLE = B_PACK_CHARS('r', 'h', '*', B_TYPE_LARGE), + ZBINDER_TYPE_REMOTE_NODE = B_PACK_CHARS('r', 'n', '*', B_TYPE_LARGE), + ZBINDER_TYPE_NODE = B_PACK_CHARS('s', 'n', '*', B_TYPE_LARGE), + BINDER_TYPE_FDR = B_PACK_CHARS('f', 'd', 'r', B_TYPE_LARGE), + BINDER_TYPE_INVALID_HANDLE = B_PACK_CHARS('r', 'h', 'e', B_TYPE_LARGE), + BINDER_TYPE_INVALID_BINDER = B_PACK_CHARS('r', 'b', 'e', B_TYPE_LARGE), +}; + +struct binder_ptr_count { + binder_uintptr_t ptr; + uint32_t count; +}; + +struct dbinder_transaction_data { + __u32 sizeOfSelf; + __u32 magic; + __u32 version; + int cmd; + __u32 code; + __u32 flags; + __u64 cookie; + __u64 seqNumber; + binder_size_t buffer_size; + binder_size_t offsets_size; + binder_uintptr_t offsets; + unsigned char buffer[0]; +}; +#endif // OHOS_IPC_SYS_BINDER_H diff --git a/adapter/linux/types.h b/adapter/linux/types.h new file mode 100644 index 0000000..e69de29 -- Gitee