summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrenadeen <[email protected]>2025-08-28 16:41:01 +0300
committerrenadeen <[email protected]>2025-08-28 17:07:56 +0300
commit9be8744bb96ab00cbf25afb60ab54db5cbad95dc (patch)
tree963b8d209cb1799bea0ed0aa62d90665d29b33f9
parent64ca6c1c9b620c076cefb3594764cc8205e636b8 (diff)
YT-26037: Fix empty polymorphic yson struct
commit_hash:918f0da0ab743372aebb95a69ed93cc6dad32df2
-rw-r--r--yt/yt/core/ytree/polymorphic_yson_struct-inl.h15
-rw-r--r--yt/yt/core/ytree/polymorphic_yson_struct.h2
-rw-r--r--yt/yt/core/ytree/unittests/yson_struct_ut.cpp39
3 files changed, 47 insertions, 9 deletions
diff --git a/yt/yt/core/ytree/polymorphic_yson_struct-inl.h b/yt/yt/core/ytree/polymorphic_yson_struct-inl.h
index ed0352c2438..382742609bf 100644
--- a/yt/yt/core/ytree/polymorphic_yson_struct-inl.h
+++ b/yt/yt/core/ytree/polymorphic_yson_struct-inl.h
@@ -46,6 +46,16 @@ CreateInstance(TEnum value)
////////////////////////////////////////////////////////////////////////////////
template <CPolymorphicEnumMapping TMapping>
+TPolymorphicYsonStruct<TMapping>::TPolymorphicYsonStruct()
+{
+ if constexpr (DefaultType_) {
+ HeldType_ = *DefaultType_;
+ } else {
+ HeldType_ = {};
+ }
+}
+
+template <CPolymorphicEnumMapping TMapping>
TPolymorphicYsonStruct<TMapping>::TPolymorphicYsonStruct(TKey key)
: TPolymorphicYsonStruct(key, TMapping::CreateInstance(key))
{ }
@@ -77,11 +87,6 @@ void TPolymorphicYsonStruct<TMapping>::Load(
SerializedStorage_ = TTraits::AsNode(source);
IMapNodePtr map = SerializedStorage_->AsMap();
- if (!map || map->GetChildCount() == 0) {
- // Empty struct.
- return;
- }
-
auto key = map->FindChildValue<TKey>("type");
THROW_ERROR_EXCEPTION_UNLESS(
key.has_value() || DefaultType_,
diff --git a/yt/yt/core/ytree/polymorphic_yson_struct.h b/yt/yt/core/ytree/polymorphic_yson_struct.h
index 50c4b206380..effc27ae034 100644
--- a/yt/yt/core/ytree/polymorphic_yson_struct.h
+++ b/yt/yt/core/ytree/polymorphic_yson_struct.h
@@ -160,7 +160,7 @@ class TPolymorphicYsonStruct
public:
using TImplementsYsonStructField = void;
- TPolymorphicYsonStruct() = default;
+ TPolymorphicYsonStruct();
explicit TPolymorphicYsonStruct(TKey key);
TPolymorphicYsonStruct(TKey key, TIntrusivePtr<TBase> ptr) noexcept;
diff --git a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
index 31217b26b2f..792c5636c76 100644
--- a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
+++ b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
@@ -3478,6 +3478,18 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefault)
{
TMyPolyDefault poly;
+ auto empty = BuildYsonNodeFluently()
+ .BeginMap()
+ .EndMap();
+
+ Deserialize(poly, empty->AsMap());
+ EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv1);
+
+ auto drv1Ptr = poly.TryGetConcrete<TPolyDerived1>();
+ EXPECT_TRUE(drv1Ptr.operator bool());
+
+ ///////////////
+
auto node = BuildYsonNodeFluently()
.BeginMap()
.Item("base_field").Value(11)
@@ -3487,11 +3499,13 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefault)
Deserialize(poly, node->AsMap());
EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv1);
- auto drv1Ptr = poly.TryGetConcrete<TPolyDerived1>();
+ drv1Ptr = poly.TryGetConcrete<TPolyDerived1>();
EXPECT_TRUE(drv1Ptr.operator bool());
EXPECT_EQ(drv1Ptr->BaseField, 11);
EXPECT_EQ(drv1Ptr->Field1, 123);
+ ///////////////
+
node = BuildYsonNodeFluently()
.BeginMap()
.Item("type").Value("drv2")
@@ -3502,6 +3516,8 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefault)
Deserialize(poly, node->AsMap());
EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultType::Drv2);
+ ///////////////
+
node = BuildYsonNodeFluently()
.BeginMap()
.Item("base_field").Value(11)
@@ -3528,6 +3544,18 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefaultEnum)
{
TMyPolyDefaultEnum poly;
+ auto empty = BuildYsonNodeFluently()
+ .BeginMap()
+ .EndMap();
+
+ Deserialize(poly, empty->AsMap());
+
+ EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Base);
+ auto basePtr = poly.TryGetConcrete<TPolyBase>();
+ EXPECT_TRUE(basePtr.operator bool());
+
+ ///////////////
+
auto node = BuildYsonNodeFluently()
.BeginMap()
.Item("base_field").Value(11)
@@ -3537,10 +3565,12 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefaultEnum)
Deserialize(poly, node->AsMap());
EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Base);
- auto basePtr = poly.TryGetConcrete<TPolyBase>();
+ basePtr = poly.TryGetConcrete<TPolyBase>();
EXPECT_TRUE(basePtr.operator bool());
EXPECT_EQ(basePtr->BaseField, 11);
+ ///////////////
+
node = BuildYsonNodeFluently()
.BeginMap()
.Item("type").Value("drv1")
@@ -3551,6 +3581,8 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructDefaultEnum)
Deserialize(poly, node->AsMap());
EXPECT_EQ(poly.GetCurrentType(), EMyPolyDefaultEnum::Drv1);
+ ///////////////
+
node = BuildYsonNodeFluently()
.BeginMap()
.Item("base_field").Value(11)
@@ -3585,7 +3617,8 @@ TEST(TYsonStructTest, TestPolymorphicYsonStructSerializeEmpty)
auto node = ConvertToNode(holder);
- Deserialize(holder, node->AsMap());
+ // Field `type` is mandatory for structs without configured default type.
+ EXPECT_THROW(Deserialize(holder, node->AsMap()), std::exception);
}
TEST(TYsonStructTest, TestPolymorphicYsonStructAsField)