diff options
author | Maxim Yurchuk <maxim-yurchuk@ydb.tech> | 2024-12-16 13:10:39 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-16 13:10:39 +0000 |
commit | 35acee00dc0737e31cb52949f4d234df6440dac8 (patch) | |
tree | 19c92c26539d52c0d1f9472da874fb6c264320bd /library/cpp | |
parent | 5ab41b68a8fc4451c81db0ff0ba6ed129e4cf3da (diff) | |
parent | 9688b270dcf40ca0a66b591cbc2a3ffb6a875c04 (diff) | |
download | ydb-35acee00dc0737e31cb52949f4d234df6440dac8.tar.gz |
Merge pull request #12632 from ydb-platform/mergelibs-241216-0851
Library import 241216-0851
Diffstat (limited to 'library/cpp')
-rw-r--r-- | library/cpp/cgiparam/cgiparam.cpp | 10 | ||||
-rw-r--r-- | library/cpp/cgiparam/cgiparam.h | 7 | ||||
-rw-r--r-- | library/cpp/cgiparam/cgiparam_ut.cpp | 2 | ||||
-rw-r--r-- | library/cpp/testing/gtest_protobuf/matcher.h | 132 | ||||
-rw-r--r-- | library/cpp/yt/misc/static_initializer.h | 19 |
5 files changed, 170 insertions, 0 deletions
diff --git a/library/cpp/cgiparam/cgiparam.cpp b/library/cpp/cgiparam/cgiparam.cpp index 397e23407ff..5f3be8705f0 100644 --- a/library/cpp/cgiparam/cgiparam.cpp +++ b/library/cpp/cgiparam/cgiparam.cpp @@ -17,6 +17,16 @@ const TString& TCgiParameters::Get(const TStringBuf name, size_t numOfValue) con return end() == it ? Default<TString>() : it->second; } +const TString& TCgiParameters::GetLast(const TStringBuf name) const noexcept { + if (auto it = this->upper_bound(name); it != this->begin()) { + --it; + if (it->first == name) { + return it->second; + } + } + return Default<TString>(); +} + bool TCgiParameters::Erase(const TStringBuf name, size_t pos) { const auto pair = equal_range(name); diff --git a/library/cpp/cgiparam/cgiparam.h b/library/cpp/cgiparam/cgiparam.h index 465940be677..c30a8ac7948 100644 --- a/library/cpp/cgiparam/cgiparam.h +++ b/library/cpp/cgiparam/cgiparam.h @@ -78,6 +78,13 @@ public: Y_PURE_FUNCTION const TString& Get(const TStringBuf name, size_t numOfValue = 0) const noexcept Y_LIFETIME_BOUND; + /// Returns the last value by name + /** + * @note The returned value is CGI-unescaped. + */ + Y_PURE_FUNCTION + const TString& GetLast(const TStringBuf name) const noexcept Y_LIFETIME_BOUND; + void InsertEscaped(const TStringBuf name, const TStringBuf value); #if !defined(__GLIBCXX__) diff --git a/library/cpp/cgiparam/cgiparam_ut.cpp b/library/cpp/cgiparam/cgiparam_ut.cpp index de6d23882dc..c82f0344d2a 100644 --- a/library/cpp/cgiparam/cgiparam_ut.cpp +++ b/library/cpp/cgiparam/cgiparam_ut.cpp @@ -210,8 +210,10 @@ Y_UNIT_TEST_SUITE(TCgiParametersTest) { UNIT_ASSERT_VALUES_EQUAL(c.NumOfValues("b"), 1u); UNIT_ASSERT_VALUES_EQUAL(c.Get("b"), "b1"); + UNIT_ASSERT_VALUES_EQUAL(c.GetLast("b"), "b1"); UNIT_ASSERT_VALUES_EQUAL(c.Get("a", 0), "a1"); UNIT_ASSERT_VALUES_EQUAL(c.Get("a", 1), "a2"); + UNIT_ASSERT_VALUES_EQUAL(c.GetLast("a"), "a2"); UNIT_ASSERT_VALUES_EQUAL(c.Print(), "a=a1&a=a2&b=b1"); } diff --git a/library/cpp/testing/gtest_protobuf/matcher.h b/library/cpp/testing/gtest_protobuf/matcher.h new file mode 100644 index 00000000000..006e56ee3da --- /dev/null +++ b/library/cpp/testing/gtest_protobuf/matcher.h @@ -0,0 +1,132 @@ +#pragma once + +#include <google/protobuf/util/message_differencer.h> +#include <util/generic/string.h> + +#include <gmock/gmock.h> + +#include <ostream> + +namespace NGTest { + // Protobuf message compare options + struct TProtoCompareOptions { + using EScope = google::protobuf::util::MessageDifferencer::Scope; + using EMessageFieldComparison = google::protobuf::util::MessageDifferencer::MessageFieldComparison; + using ERepeatedFieldComparison = google::protobuf::util::MessageDifferencer::RepeatedFieldComparison; + using EFloatComparison = google::protobuf::util::DefaultFieldComparator::FloatComparison; + + // Sets the scope of the comparison + EScope Scope = EScope::FULL; + // Unset fields comparison method + EMessageFieldComparison MessageFieldComparison = EMessageFieldComparison::EQUIVALENT; + // Sets the type of comparison for repeated field + ERepeatedFieldComparison RepeatedFieldComparison = ERepeatedFieldComparison::AS_LIST; + // Floats and doubles are comparison method + EFloatComparison FloatComparison = EFloatComparison::EXACT; + // if true comparator will treat to float or double fields are equal when both are NaN + bool TreatNanAsEqual = true; + }; + + // Implements the protobuf message equality matcher, which matches two messages using MessageDifferencer. + template <typename T> + class TEqualsProtoMatcher { + public: + TEqualsProtoMatcher(T expected, const TProtoCompareOptions& options) + : Expected_(expected) + , Options_(options) + { + } + TEqualsProtoMatcher(const TEqualsProtoMatcher& other) = default; + TEqualsProtoMatcher(TEqualsProtoMatcher&& other) = default; + + TEqualsProtoMatcher& operator=(const TEqualsProtoMatcher& other) = delete; + TEqualsProtoMatcher& operator=(TEqualsProtoMatcher&& other) = delete; + + template <class X> + operator ::testing::Matcher<X>() const { + return ::testing::MakeMatcher(new TImpl<X>(Expected_, Options_)); + } + + private: + // Implements the protobuf message equality matcher as a Matcher<X>. + template <class X> + class TImpl : public ::testing::MatcherInterface<X> { + public: + TImpl(T expected, const TProtoCompareOptions& options) + : Expected_(expected) + , Options_(options) + { + } + + bool MatchAndExplain(X actual, ::testing::MatchResultListener* listener) const override { + google::protobuf::util::DefaultFieldComparator cmp; + cmp.set_float_comparison(Options_.FloatComparison); + cmp.set_treat_nan_as_equal(Options_.TreatNanAsEqual); + + google::protobuf::util::MessageDifferencer md; + md.set_scope(Options_.Scope); + md.set_message_field_comparison(Options_.MessageFieldComparison); + md.set_repeated_field_comparison(Options_.RepeatedFieldComparison); + md.set_field_comparator(&cmp); + + TString diff; + md.ReportDifferencesToString(&diff); + + if (!md.Compare(actual, ::testing::internal::Unwrap(Expected_))) { + if (listener->IsInterested()) { + *listener << diff.c_str(); + } + return false; + } else { + if (listener->IsInterested()) { + *listener << "is equal."; + } + return true; + } + } + + void DescribeTo(::std::ostream* os) const override { + *os << "message is equal to "; + ::testing::internal::UniversalPrint(::testing::internal::Unwrap(Expected_), os); + } + + void DescribeNegationTo(::std::ostream* os) const override { + *os << "message isn't equal to "; + ::testing::internal::UniversalPrint(::testing::internal::Unwrap(Expected_), os); + } + + private: + const T Expected_; + const TProtoCompareOptions Options_; + }; + + private: + const T Expected_; + const TProtoCompareOptions Options_; + }; + + /** + * Matcher that checks that protobuf messages are equal. + * + * Example: + * + * ```c++ + * EXPECT_THAT(actualMessage, EqualsProto(std::ref(expectedMessage)); + * ``` + * NOTE: according to the documentation there is a similar matcher in the internal gtest implementation of Google + * and it may appear in the opensource in course of this `https://github.com/google/googletest/issues/1761` + */ + + template <class T> + TEqualsProtoMatcher<T> EqualsProto(T expected, const TProtoCompareOptions& options = {}) { + return {expected, options}; + } + + template <typename T> + TEqualsProtoMatcher<T> EqualsProtoStrict(T expected) { + return EqualsProto(expected, TProtoCompareOptions{ + // Either both fields must be present, or none of them (unset != default value) + .MessageFieldComparison = TProtoCompareOptions::EMessageFieldComparison::EQUAL, + }); + } +} diff --git a/library/cpp/yt/misc/static_initializer.h b/library/cpp/yt/misc/static_initializer.h new file mode 100644 index 00000000000..ebaa35a1a24 --- /dev/null +++ b/library/cpp/yt/misc/static_initializer.h @@ -0,0 +1,19 @@ +#pragma once + +#include "preprocessor.h" + +namespace NYT { + +//////////////////////////////////////////////////////////////////////////////// + +//! Static initializer will be invoked prior to entering |main|. +//! The exact order of these invocations is, of course, undefined. +#define YT_STATIC_INITIALIZER(...) \ + [[maybe_unused]] static inline const void* PP_ANONYMOUS_VARIABLE(StaticInitializer) = [] { \ + __VA_ARGS__; \ + return nullptr; \ + } () + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT |