aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp
diff options
context:
space:
mode:
authorMaxim Yurchuk <maxim-yurchuk@ydb.tech>2024-12-16 13:10:39 +0000
committerGitHub <noreply@github.com>2024-12-16 13:10:39 +0000
commit35acee00dc0737e31cb52949f4d234df6440dac8 (patch)
tree19c92c26539d52c0d1f9472da874fb6c264320bd /library/cpp
parent5ab41b68a8fc4451c81db0ff0ba6ed129e4cf3da (diff)
parent9688b270dcf40ca0a66b591cbc2a3ffb6a875c04 (diff)
downloadydb-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.cpp10
-rw-r--r--library/cpp/cgiparam/cgiparam.h7
-rw-r--r--library/cpp/cgiparam/cgiparam_ut.cpp2
-rw-r--r--library/cpp/testing/gtest_protobuf/matcher.h132
-rw-r--r--library/cpp/yt/misc/static_initializer.h19
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