diff options
author | Grigory Reznikov <gritukan@nebius.com> | 2023-12-07 11:03:02 +0300 |
---|---|---|
committer | robot-piglet <robot-piglet@yandex-team.com> | 2023-12-07 11:28:00 +0300 |
commit | c9acd0d0c5306c53f3e81a780f2217870946be4d (patch) | |
tree | 8d80679e68531970bd449057ba23a44d2a2c9ece | |
parent | 87a9197de16375faef3babefc7d511be2b45f39a (diff) | |
download | ydb-c9acd0d0c5306c53f3e81a780f2217870946be4d.tar.gz |
Avoid duplication of "original_error_depth" attribute during deep error reserialization
I hereby agree to the terms of the CLA available at: https://yandex.ru/legal/cla/?lang=en
---
Pull Request resolved: https://github.com/ytsaurus/ytsaurus/pull/218
-rw-r--r-- | yt/yt/core/misc/error.cpp | 8 | ||||
-rw-r--r-- | yt/yt/core/misc/unittests/error_ut.cpp | 44 |
2 files changed, 50 insertions, 2 deletions
diff --git a/yt/yt/core/misc/error.cpp b/yt/yt/core/misc/error.cpp index 33f5372356..17cf40583b 100644 --- a/yt/yt/core/misc/error.cpp +++ b/yt/yt/core/misc/error.cpp @@ -39,6 +39,10 @@ using NYT::ToProto; //////////////////////////////////////////////////////////////////////////////// +constexpr TStringBuf OriginalErrorDepthAttribute = "original_error_depth"; + +//////////////////////////////////////////////////////////////////////////////// + void TErrorCode::Save(TStreamSaveContext& context) const { NYT::Save(context, Value_); @@ -1155,9 +1159,9 @@ void Serialize( .Item("trace_id").Value(error.GetTraceId()) .Item("span_id").Value(error.GetSpanId()); } - if (depth > ErrorSerializationDepthLimit) { + if (depth > ErrorSerializationDepthLimit && !error.Attributes().Contains(OriginalErrorDepthAttribute)) { fluent - .Item("original_error_depth").Value(depth); + .Item(OriginalErrorDepthAttribute).Value(depth); } for (const auto& [key, value] : error.Attributes().ListPairs()) { fluent diff --git a/yt/yt/core/misc/unittests/error_ut.cpp b/yt/yt/core/misc/unittests/error_ut.cpp index d2db8ff56c..905a35d414 100644 --- a/yt/yt/core/misc/unittests/error_ut.cpp +++ b/yt/yt/core/misc/unittests/error_ut.cpp @@ -421,6 +421,50 @@ TEST(TErrorTest, SerializationDepthLimit) } } +TEST(TErrorTest, DoNotDuplicateOriginalErrorDepth) +{ + constexpr int Depth = 20; + ASSERT_GE(Depth, ErrorSerializationDepthLimit); + + auto error = TError(TErrorCode(Depth), "error"); + for (int i = Depth; i >= 2; --i) { + error = TError(TErrorCode(i), "error") << std::move(error); + } + + auto errorYson = ConvertToYsonString(error); + error = ConvertTo<TError>(errorYson); + + // Due to reserialization, error already contains "original_error_depth" attribute. + // It should not be duplicated after the next serialization. + error = TError(TErrorCode(1), "error") << std::move(error); + + // Use intermediate conversion to test YSON parser depth limit simultaneously. + errorYson = ConvertToYsonString(error); + auto errorNode = ConvertTo<IMapNodePtr>(errorYson); + + error = ConvertTo<TError>(errorYson); + for (int index = 0; index < ErrorSerializationDepthLimit - 1; ++index) { + ASSERT_FALSE(error.Attributes().Contains("original_error_depth")); + error = error.InnerErrors()[0]; + } + + const auto& children = error.InnerErrors(); + ASSERT_EQ(std::ssize(children), Depth - ErrorSerializationDepthLimit + 1); + for (int index = 0; index < std::ssize(children); ++index) { + const auto& child = children[index]; + if (index == 0) { + ASSERT_FALSE(child.Attributes().Contains("original_error_depth")); + } else { + ASSERT_TRUE(child.Attributes().Contains("original_error_depth")); + if (index == 1) { + ASSERT_EQ(child.Attributes().Get<i64>("original_error_depth"), index + ErrorSerializationDepthLimit); + } else { + ASSERT_EQ(child.Attributes().Get<i64>("original_error_depth"), index + ErrorSerializationDepthLimit - 1); + } + } + } +} + TEST(TErrorTest, ErrorSkeletonStubImplementation) { TError error("foo"); |