From 4df8e40e43a7de8865b5797e134e12e492c9bf4c Mon Sep 17 00:00:00 2001 From: niksaveliev Date: Wed, 9 Apr 2025 15:39:38 +0000 Subject: [PATCH 1/4] Commit for autopartitioned topics (#11629) --- include/ydb-cpp-sdk/client/topic/control_plane.h | 4 +++- include/ydb-cpp-sdk/client/topic/read_events.h | 6 ++++++ src/api/protos/ydb_topic.proto | 3 ++- src/client/topic/impl/read_session_impl.h | 3 +++ src/client/topic/impl/read_session_impl.ipp | 10 ++++++++-- src/client/topic/impl/topic_impl.h | 4 +++- 6 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/ydb-cpp-sdk/client/topic/control_plane.h b/include/ydb-cpp-sdk/client/topic/control_plane.h index 72f2394f42..e957ea6a5c 100644 --- a/include/ydb-cpp-sdk/client/topic/control_plane.h +++ b/include/ydb-cpp-sdk/client/topic/control_plane.h @@ -766,6 +766,8 @@ struct TDescribePartitionSettings: public TOperationRequestSettings {}; +struct TCommitOffsetSettings : public TOperationRequestSettings { + FLUENT_SETTING_OPTIONAL(std::string, ReadSessionId); +}; } // namespace NYdb::NTopic diff --git a/include/ydb-cpp-sdk/client/topic/read_events.h b/include/ydb-cpp-sdk/client/topic/read_events.h index 81f0d88dd1..48754f23ef 100644 --- a/include/ydb-cpp-sdk/client/topic/read_events.h +++ b/include/ydb-cpp-sdk/client/topic/read_events.h @@ -31,6 +31,11 @@ struct TPartitionSession: public TThrRefBase, public TPrintable { template > TPartitionStreamImpl(ui64 partitionStreamId, std::string topicPath, + std::string readSessionId, i64 partitionId, i64 assignId, i64 readOffset, @@ -617,6 +618,7 @@ class TPartitionStreamImpl : public TAPartitionStream { { TAPartitionStream::PartitionSessionId = partitionStreamId; TAPartitionStream::TopicPath = std::move(topicPath); + TAPartitionStream::ReadSessionId = std::move(readSessionId); TAPartitionStream::PartitionId = static_cast(partitionId); MaxCommittedOffset = static_cast(readOffset); } @@ -1333,6 +1335,7 @@ class TSingleClusterReadSessionImpl : public TEnableSelfContext::OnReadDoneImpl( LOG_LAZY(Log, TLOG_INFO, GetLogPrefix() << "Server session id: " << msg.session_id()); RetryState = nullptr; + ReadSessionId = msg.session_id(); // Successful init. Do nothing. ContinueReadingDataImpl(); @@ -1222,6 +1223,7 @@ inline void TSingleClusterReadSessionImpl::OnReadDoneImpl( Y_UNUSED(deferred); RetryState = nullptr; + ReadSessionId = msg.session_id(); LOG_LAZY(Log, TLOG_INFO, GetLogPrefix() << "Server session id: " << msg.session_id()); @@ -1321,8 +1323,12 @@ inline void TSingleClusterReadSessionImpl::OnReadDoneImpl( Y_ABORT_UNLESS(Lock.IsLocked()); auto partitionStream = MakeIntrusive>( - NextPartitionStreamId, msg.partition_session().path(), msg.partition_session().partition_id(), - msg.partition_session().partition_session_id(), msg.committed_offset(), + NextPartitionStreamId, + msg.partition_session().path(), + ReadSessionId, + msg.partition_session().partition_id(), + msg.partition_session().partition_session_id(), + msg.committed_offset(), SelfContext); NextPartitionStreamId += PartitionStreamIdStep; diff --git a/src/client/topic/impl/topic_impl.h b/src/client/topic/impl/topic_impl.h index 06684fb70d..90902dd791 100644 --- a/src/client/topic/impl/topic_impl.h +++ b/src/client/topic/impl/topic_impl.h @@ -282,7 +282,9 @@ class TTopicClient::TImpl : public TClientImplCommon { request.set_partition_id(partitionId); request.set_consumer(TStringType{consumerName}); request.set_offset(offset); - + if (settings.ReadSessionId_) { + request.set_read_session_id(*settings.ReadSessionId_); + } return RunSimple( std::move(request), &Ydb::Topic::V1::TopicService::Stub::AsyncCommitOffset, From c765da11d10a666fff5b11f3490e2c0ea1802a43 Mon Sep 17 00:00:00 2001 From: Bulat Date: Wed, 9 Apr 2025 15:40:44 +0000 Subject: [PATCH 2/4] Retuned Value and Params tests to ydb-cpp-sdk CI (#16960) --- tests/unit/client/params/params_ut.cpp | 405 ++--- tests/unit/client/value/value_ut.cpp | 2328 ++++++++++++------------ 2 files changed, 1411 insertions(+), 1322 deletions(-) diff --git a/tests/unit/client/params/params_ut.cpp b/tests/unit/client/params/params_ut.cpp index 1919774ff0..9d66fe05e7 100644 --- a/tests/unit/client/params/params_ut.cpp +++ b/tests/unit/client/params/params_ut.cpp @@ -1,244 +1,241 @@ +#include #include - -#include - -#include -#include +#include +#include using namespace NYdb; using TExpectedErrorException = yexception; -Y_UNIT_TEST_SUITE(ParamsBuilder) { - Y_UNIT_TEST(Build) { - auto params = TParamsBuilder() - .AddParam("$param1") - .BeginList() - .AddListItem() - .BeginOptional() - .Uint64(10) - .EndOptional() - .AddListItem() - .EmptyOptional() - .EndList() - .Build() - .AddParam("$param2") - .String("test") - .Build() - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param1")->GetType()), - R"(List)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param1")), - R"([[10u];#])"); - - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param2")->GetType()), - R"(String)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param2")), - R"("test")"); - } +void CheckProtoValue(const Ydb::Value& value, const TString& expected) { + TStringType protoStr; + google::protobuf::TextFormat::PrintToString(value, &protoStr); + ASSERT_EQ(protoStr, expected); +} - Y_UNIT_TEST(BuildFromValue) { - auto value2 = TValueBuilder() +TEST(ParamsBuilder, Build) { + auto params = TParamsBuilder() + .AddParam("$param1") .BeginList() .AddListItem() .BeginOptional() - .BeginTuple() - .AddElement() - .Int32(-11) - .AddElement() - .String("test2") - .EndTuple() + .Uint64(10) .EndOptional() .AddListItem() .EmptyOptional() .EndList() - .Build(); - - auto params = TParamsBuilder() - .AddParam("$param1") - .Utf8("test1") - .Build() - .AddParam("$param2", value2) - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param1")->GetType()), - R"(Utf8)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param1")), - R"("test1")"); - - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param2")->GetType()), - R"(List?>)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param2")), - R"([[[-11;"test2"]];#])"); - } - - Y_UNIT_TEST(BuildWithTypeInfo) { - auto param1Type = TTypeBuilder() - .BeginList() - .Primitive(EPrimitiveType::String) - .EndList() - .Build(); + .Build() + .AddParam("$param2") + .String("test") + .Build() + .Build(); + + ASSERT_EQ(FormatType(params.GetValue("$param1")->GetType()), "List"); + + CheckProtoValue(params.GetValue("$param1")->GetProto(), + "items {\n" + " uint64_value: 10\n" + "}\n" + "items {\n" + " null_flag_value: NULL_VALUE\n" + "}\n"); + + ASSERT_EQ(FormatType(params.GetValue("$param2")->GetType()), "String"); + CheckProtoValue(params.GetValue("$param2")->GetProto(), "bytes_value: \"test\"\n"); +} - auto param2Type = TTypeBuilder() +TEST(ParamsBuilder, BuildFromValue) { + auto value2 = TValueBuilder() + .BeginList() + .AddListItem() .BeginOptional() - .Primitive(EPrimitiveType::Uint32) + .BeginTuple() + .AddElement() + .Int32(-11) + .AddElement() + .String("test2") + .EndTuple() .EndOptional() - .Build(); + .AddListItem() + .EmptyOptional() + .EndList() + .Build(); + + auto params = TParamsBuilder() + .AddParam("$param1") + .Utf8("test1") + .Build() + .AddParam("$param2", value2) + .Build(); + + ASSERT_EQ(FormatType(params.GetValue("$param1")->GetType()), "Utf8"); + + CheckProtoValue(params.GetValue("$param1")->GetProto(), "text_value: \"test1\"\n"); + + ASSERT_EQ(FormatType(params.GetValue("$param2")->GetType()), "List?>"); + CheckProtoValue(params.GetValue("$param2")->GetProto(), + "items {\n" + " items {\n" + " int32_value: -11\n" + " }\n" + " items {\n" + " bytes_value: \"test2\"\n" + " }\n" + "}\n" + "items {\n" + " null_flag_value: NULL_VALUE\n" + "}\n"); +} - std::map paramsMap; - paramsMap.emplace("$param1", param1Type); - paramsMap.emplace("$param2", param2Type); +TEST(ParamsBuilder, BuildWithTypeInfo) { + auto param1Type = TTypeBuilder() + .BeginList() + .Primitive(EPrimitiveType::String) + .EndList() + .Build(); + + auto param2Type = TTypeBuilder() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .Build(); + + std::map paramsMap; + paramsMap.emplace("$param1", param1Type); + paramsMap.emplace("$param2", param2Type); + + auto value1 = TValueBuilder() + .BeginList() + .AddListItem() + .String("str1") + .AddListItem() + .String("str2") + .EndList() + .Build(); + + auto params = TParamsBuilder(paramsMap) + .AddParam("$param1", value1) + .AddParam("$param2") + .EmptyOptional() + .Build() + .Build(); + + ASSERT_EQ(FormatType(params.GetValue("$param1")->GetType()), "List"); + CheckProtoValue(params.GetValue("$param1")->GetProto(), + "items {\n" + " bytes_value: \"str1\"\n" + "}\n" + "items {\n" + " bytes_value: \"str2\"\n" + "}\n"); + + ASSERT_EQ(FormatType(params.GetValue("$param2")->GetType()), "Uint32?"); + CheckProtoValue(params.GetValue("$param2")->GetProto(), "null_flag_value: NULL_VALUE\n"); +} - auto value1 = TValueBuilder() - .BeginList() - .AddListItem() - .String("str1") - .AddListItem() - .String("str2") - .EndList() - .Build(); +TEST(ParamsBuilder, MissingParam) { + auto param1Type = TTypeBuilder() + .BeginList() + .Primitive(EPrimitiveType::String) + .EndList() + .Build(); + auto param2Type = TTypeBuilder() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .Build(); + + std::map paramsMap; + paramsMap.emplace("$param1", param1Type); + paramsMap.emplace("$param2", param2Type); + + ASSERT_THROW({ auto params = TParamsBuilder(paramsMap) - .AddParam("$param1", value1) - .AddParam("$param2") + .AddParam("$param3") .EmptyOptional() .Build() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param1")->GetType()), - R"(List)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param1")), - R"(["str1";"str2"])"); +TEST(ParamsBuilder, IncompleteParam) { + auto paramsBuilder = TParamsBuilder(); - UNIT_ASSERT_NO_DIFF(FormatType(params.GetValue("$param2")->GetType()), - R"(Uint32?)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(*params.GetValue("$param2")), - R"(#)"); - } + auto& param1Builder = paramsBuilder.AddParam("$param1"); + auto& param2Builder = paramsBuilder.AddParam("$param2"); - Y_UNIT_TEST(MissingParam) { - auto param1Type = TTypeBuilder() - .BeginList() - .Primitive(EPrimitiveType::String) - .EndList() - .Build(); - - auto param2Type = TTypeBuilder() + param1Builder + .BeginList() + .AddListItem() .BeginOptional() - .Primitive(EPrimitiveType::Uint32) + .Uint64(10) .EndOptional() - .Build(); + .AddListItem() + .EmptyOptional() + .EndList() + .Build(); - std::map paramsMap; - paramsMap.emplace("$param1", param1Type); - paramsMap.emplace("$param2", param2Type); + param2Builder.String("test"); - try { - auto params = TParamsBuilder(paramsMap) - .AddParam("$param3") - .EmptyOptional() - .Build() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } + ASSERT_THROW(paramsBuilder.Build(), TExpectedErrorException); +} - UNIT_ASSERT(false); - } +TEST(ParamsBuilder, TypeMismatch) { + auto param1Type = TTypeBuilder() + .BeginList() + .Primitive(EPrimitiveType::String) + .EndList() + .Build(); - Y_UNIT_TEST(IncompleteParam) { - auto paramsBuilder = TParamsBuilder(); + auto param2Type = TTypeBuilder() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .Build(); - auto& param1Builder = paramsBuilder.AddParam("$param1"); - auto& param2Builder = paramsBuilder.AddParam("$param2"); + std::map paramsMap; + paramsMap.emplace("$param1", param1Type); + paramsMap.emplace("$param2", param2Type); - param1Builder - .BeginList() - .AddListItem() - .BeginOptional() - .Uint64(10) - .EndOptional() - .AddListItem() + ASSERT_THROW({ + auto params = TParamsBuilder(paramsMap) + .AddParam("$param1") .EmptyOptional() - .EndList() - .Build(); - - param2Builder.String("test"); - - try { - paramsBuilder.Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(TypeMismatch) { - auto param1Type = TTypeBuilder() - .BeginList() - .Primitive(EPrimitiveType::String) - .EndList() - .Build(); - - auto param2Type = TTypeBuilder() - .BeginOptional() - .Primitive(EPrimitiveType::Uint32) - .EndOptional() - .Build(); - - std::map paramsMap; - paramsMap.emplace("$param1", param1Type); - paramsMap.emplace("$param2", param2Type); - - try { - auto params = TParamsBuilder(paramsMap) - .AddParam("$param1") - .EmptyOptional() - .Build() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(TypeMismatchFromValue) { - auto param1Type = TTypeBuilder() - .BeginList() - .Primitive(EPrimitiveType::String) - .EndList() - .Build(); - - auto param2Type = TTypeBuilder() - .BeginOptional() - .Primitive(EPrimitiveType::Uint32) - .EndOptional() + .Build() .Build(); + }, TExpectedErrorException); +} - std::map paramsMap; - paramsMap.emplace("$param1", param1Type); - paramsMap.emplace("$param2", param2Type); - - auto value1 = TValueBuilder() - .BeginList() - .AddListItem() - .String("str1") - .AddListItem() - .String("str2") - .EndList() +TEST(ParamsBuilder, TypeMismatchFromValue) { + auto param1Type = TTypeBuilder() + .BeginList() + .Primitive(EPrimitiveType::String) + .EndList() + .Build(); + + auto param2Type = TTypeBuilder() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .Build(); + + std::map paramsMap; + paramsMap.emplace("$param1", param1Type); + paramsMap.emplace("$param2", param2Type); + + auto value1 = TValueBuilder() + .BeginList() + .AddListItem() + .String("str1") + .AddListItem() + .String("str2") + .EndList() + .Build(); + + ASSERT_THROW({ + auto params = TParamsBuilder(paramsMap) + .AddParam("$param2", value1) .Build(); - - try { - auto params = TParamsBuilder(paramsMap) - .AddParam("$param2", value1) - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } + }, TExpectedErrorException); } diff --git a/tests/unit/client/value/value_ut.cpp b/tests/unit/client/value/value_ut.cpp index f0551cf1ff..459e185dba 100644 --- a/tests/unit/client/value/value_ut.cpp +++ b/tests/unit/client/value/value_ut.cpp @@ -1,700 +1,575 @@ +#include #include #include - #include #include -#include -#include - -#include -#include - #include namespace NYdb { using TExpectedErrorException = yexception; -Y_UNIT_TEST_SUITE(YdbValue) { - Y_UNIT_TEST(ParseType1) { - auto protoTypeStr = R"( - struct_type { - members { - name: "Member1" - type { - type_id: UINT32 - } +void CheckProtoValue(const Ydb::Value& value, const TString& expected) { + TStringType protoStr; + google::protobuf::TextFormat::PrintToString(value, &protoStr); + ASSERT_EQ(protoStr, expected); +} + +TEST(YdbValue, ParseType1) { + auto protoTypeStr = R"( + struct_type { + members { + name: "Member1" + type { + type_id: UINT32 } - members { - name: "Member2" - type { - list_type { - item { - type_id: STRING - } + } + members { + name: "Member2" + type { + list_type { + item { + type_id: STRING } } } - members { - name: "Member3" - type { - tuple_type { - elements { - optional_type { - item { - type_id: UTF8 - } - } - } - elements { - decimal_type { - precision: 8 - scale: 13 + } + members { + name: "Member3" + type { + tuple_type { + elements { + optional_type { + item { + type_id: UTF8 } } - elements { - void_type: NULL_VALUE + } + elements { + decimal_type { + precision: 8 + scale: 13 } } + elements { + void_type: NULL_VALUE + } } } } - )"; + } + )"; - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - UNIT_ASSERT_NO_DIFF(FormatType(protoType), - R"(Struct<'Member1':Uint32,'Member2':List,'Member3':Tuple>)"); - } + ASSERT_EQ(FormatType(protoType), + R"(Struct<'Member1':Uint32,'Member2':List,'Member3':Tuple>)"); +} - Y_UNIT_TEST(ParseType2) { - auto protoTypeStr = R"( - dict_type { - key { - type_id: UINT32 - } - payload { - struct_type { - members { - name: "Member1" - type { - type_id: DATE - } +TEST(YdbValue, ParseType2) { + auto protoTypeStr = R"( + dict_type { + key { + type_id: UINT32 + } + payload { + struct_type { + members { + name: "Member1" + type { + type_id: DATE } } } } - )"; + } + )"; - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - UNIT_ASSERT_NO_DIFF(FormatType(protoType), - R"(Dict>)"); - } + ASSERT_EQ(FormatType(protoType), + R"(Dict>)"); +} - Y_UNIT_TEST(ParseTaggedType) { - auto protoTypeStr = R"( - tagged_type { - tag: "my_tag" - type { - type_id: STRING - } +TEST(YdbValue, ParseTaggedType) { + auto protoTypeStr = R"( + tagged_type { + tag: "my_tag" + type { + type_id: STRING } - )"; + } + )"; - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - UNIT_ASSERT_NO_DIFF(FormatType(protoType), - R"(Tagged)"); - } + ASSERT_EQ(FormatType(protoType), + R"(Tagged)"); +} - Y_UNIT_TEST(BuildTaggedType) { - auto type = TTypeBuilder() - .BeginTagged("my_tag") - .BeginList() - .BeginOptional() - .Primitive(EPrimitiveType::Uint32) - .EndOptional() - .EndList() - .EndTagged() - .Build(); +TEST(YdbValue, BuildTaggedType) { + auto type = TTypeBuilder() + .BeginTagged("my_tag") + .BeginList() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .EndList() + .EndTagged() + .Build(); - UNIT_ASSERT_NO_DIFF(FormatType(type), - R"(Tagged,'my_tag'>)"); - } + ASSERT_EQ(FormatType(type), + R"(Tagged,'my_tag'>)"); +} - Y_UNIT_TEST(BuildType) { - auto type = TTypeBuilder() - .BeginStruct() - .AddMember("Member1") - .BeginList() +TEST(YdbValue, BuildType) { + auto type = TTypeBuilder() + .BeginStruct() + .AddMember("Member1") + .BeginList() + .BeginOptional() + .Primitive(EPrimitiveType::Uint32) + .EndOptional() + .EndList() + .AddMember("Member2") + .BeginDict() + .DictKey().Primitive(EPrimitiveType::Int64) + .DictPayload() + .BeginTuple() + .AddElement() + .Decimal(TDecimalType(8, 13)) + .AddElement() + .Pg(TPgType("pgint2")) + .AddElement() .BeginOptional() - .Primitive(EPrimitiveType::Uint32) + .Primitive(EPrimitiveType::Utf8) .EndOptional() - .EndList() - .AddMember("Member2") - .BeginDict() - .DictKey().Primitive(EPrimitiveType::Int64) - .DictPayload() - .BeginTuple() - .AddElement() - .Decimal(TDecimalType(8, 13)) - .AddElement() - .Pg(TPgType("pgint2")) - .AddElement() - .BeginOptional() - .Primitive(EPrimitiveType::Utf8) - .EndOptional() - .EndTuple() - .EndDict() - .EndStruct() - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(type), - R"(Struct<'Member1':List,'Member2':Dict>>)"); - } - - Y_UNIT_TEST(BuildTypeReuse) { - auto intType = TTypeBuilder() - .Primitive(EPrimitiveType::Int32) - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(intType), - R"(Int32)"); - - auto optIntType = TTypeBuilder() - .Optional(intType) - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(optIntType), - R"(Int32?)"); + .EndTuple() + .EndDict() + .EndStruct() + .Build(); - auto structType = TTypeBuilder() - .BeginStruct() - .AddMember("Member1", intType) - .AddMember("Member2") - .List(optIntType) - .EndStruct() - .Build(); + ASSERT_EQ(FormatType(type), + R"(Struct<'Member1':List,'Member2':Dict>>)"); +} - UNIT_ASSERT_NO_DIFF(FormatType(structType), - R"(Struct<'Member1':Int32,'Member2':List>)"); +TEST(YdbValue, BuildTypeReuse) { + auto intType = TTypeBuilder() + .Primitive(EPrimitiveType::Int32) + .Build(); + + ASSERT_EQ(FormatType(intType), + R"(Int32)"); + + auto optIntType = TTypeBuilder() + .Optional(intType) + .Build(); + + ASSERT_EQ(FormatType(optIntType), + R"(Int32?)"); + + auto structType = TTypeBuilder() + .BeginStruct() + .AddMember("Member1", intType) + .AddMember("Member2") + .List(optIntType) + .EndStruct() + .Build(); + + ASSERT_EQ(FormatType(structType), + R"(Struct<'Member1':Int32,'Member2':List>)"); + + auto tupleType = TTypeBuilder() + .BeginTuple() + .AddElement(optIntType) + .AddElement() + .Primitive(EPrimitiveType::String) + .EndTuple() + .Build(); + + ASSERT_EQ(FormatType(tupleType), + R"(Tuple)"); + + auto type = TTypeBuilder() + .BeginDict() + .DictKey(tupleType) + .DictPayload(structType) + .EndDict() + .Build(); + + ASSERT_EQ(FormatType(type), + R"(Dict,Struct<'Member1':Int32,'Member2':List>>)"); +} - auto tupleType = TTypeBuilder() +TEST(YdbValue, BuildTypeIncomplete) { + ASSERT_THROW({ + auto value = TTypeBuilder() .BeginTuple() - .AddElement(optIntType) + .AddElement() + .Primitive(EPrimitiveType::Uint32) .AddElement() .Primitive(EPrimitiveType::String) - .EndTuple() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(tupleType), - R"(Tuple)"); - - auto type = TTypeBuilder() - .BeginDict() - .DictKey(tupleType) - .DictPayload(structType) - .EndDict() - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(type), - R"(Dict,Struct<'Member1':Int32,'Member2':List>>)"); - } - - Y_UNIT_TEST(BuildTypeIncomplete) { - try { - auto value = TTypeBuilder() - .BeginTuple() - .AddElement() - .Primitive(EPrimitiveType::Uint32) - .AddElement() - .Primitive(EPrimitiveType::String) - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(ParseValue1) { - auto protoTypeStr = R"( - struct_type { - members { - name: "Member1" - type { - type_id: UINT32 - } +TEST(YdbValue, ParseValue1) { + auto protoTypeStr = R"( + struct_type { + members { + name: "Member1" + type { + type_id: UINT32 } - members { - name: "Member2" - type { - list_type { - item { - type_id: STRING - } + } + members { + name: "Member2" + type { + list_type { + item { + type_id: STRING } } } - members { - name: "Member3" - type { - tuple_type { - elements { - optional_type { - item { - type_id: UTF8 - } + } + members { + name: "Member3" + type { + tuple_type { + elements { + optional_type { + item { + type_id: UTF8 } } - elements { - type_id: UTF8 - } - elements { - void_type: NULL_VALUE - } + } + elements { + type_id: UTF8 + } + elements { + void_type: NULL_VALUE } } } } - )"; + } + )"; + + auto protoValueStr = + "items {\n" + " uint32_value: 137\n" + "}\n" + "items {\n" + " items {\n" + " bytes_value: \"String1\"\n" + " }\n" + " items {\n" + " bytes_value: \"String2\"\n" + " }\n" + "}\n" + "items {\n" + " items {\n" + " null_flag_value: NULL_VALUE\n" + " }\n" + " items {\n" + " text_value: \"UtfString\"\n" + " }\n" + " items {\n" + " }\n" + "}\n"; + + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + + Ydb::Value protoValue; + google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); + + TValue value(TType(protoType), protoValue); + + CheckProtoValue(value.GetProto(), protoValueStr); +} - auto protoValueStr = R"( - items { - uint32_value: 137 +TEST(YdbValue, ParseValue2) { + auto protoTypeStr = R"( + dict_type { + key { + type_id: UINT32 } - items { - items { - bytes_value: "String1" - } - items { - bytes_value: "String2" - } - } - items { - items { - null_flag_value: NULL_VALUE - } - items { - text_value: "UtfString" - } - items { - } - } - )"; - - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - - Ydb::Value protoValue; - google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); - - TValue value(TType(protoType), protoValue); - - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([137u;["String1";"String2"];[#;"UtfString";"Void"]])"); - } - - Y_UNIT_TEST(ParseValue2) { - auto protoTypeStr = R"( - dict_type { - key { - type_id: UINT32 - } - payload { - struct_type { - members { - name: "Member1" - type { - type_id: DATE - } + payload { + struct_type { + members { + name: "Member1" + type { + type_id: DATE } } } } - )"; + } + )"; + + auto protoValueStr = + "pairs {\n" + " key {\n" + " uint32_value: 10\n" + " }\n" + " payload {\n" + " items {\n" + " uint32_value: 1000\n" + " }\n" + " }\n" + "}\n" + "pairs {\n" + " key {\n" + " uint32_value: 20\n" + " }\n" + " payload {\n" + " items {\n" + " uint32_value: 2000\n" + " }\n" + " }\n" + "}\n"; + + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + + Ydb::Value protoValue; + google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); + + TValue value(TType(protoType), protoValue); + + CheckProtoValue(value.GetProto(), protoValueStr); +} - auto protoValueStr = R"( - pairs { - key { - uint32_value: 10 - } - payload { - items { - uint32_value: 1000 +TEST(YdbValue, ParseValuePg) { + auto protoTypeStr = R"( + struct_type { + members { + name: "A" + type { + pg_type { + oid: 123 + typlen: 345 + typmod: -321 } } } - pairs { - key { - uint32_value: 20 - } - payload { - items { - uint32_value: 2000 + members { + name: "B" + type { + pg_type { + oid: 123 + typlen: -345 + typmod: 321 } } } - )"; - - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - - Ydb::Value protoValue; - google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); - - TValue value(TType(protoType), protoValue); - - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[10u;[1000u]];[20u;[2000u]]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[10,{"Member1":"1972-09-27"}],[20,{"Member1":"1975-06-24"}]])"); - } - - Y_UNIT_TEST(ParseValuePg) { - auto protoTypeStr = R"( - struct_type { - members { - name: "A" - type { - pg_type { - oid: 123 - typlen: 345 - typmod: -321 - } - } - } - members { - name: "B" - type { - pg_type { - oid: 123 - typlen: -345 - typmod: 321 - } - } - } - members { - name: "C" - type { - pg_type { - oid: 123 - typlen: -345 - typmod: -321 - } + members { + name: "C" + type { + pg_type { + oid: 123 + typlen: -345 + typmod: -321 } } - members { - name: "D" - type { - pg_type { - oid: 123 - typlen: -1 - typmod: -1 - } + } + members { + name: "D" + type { + pg_type { + oid: 123 + typlen: -1 + typmod: -1 } } - members { - name: "E" - type { - pg_type { - oid: 123 - typlen: -1 - typmod: -1 - } + } + members { + name: "E" + type { + pg_type { + oid: 123 + typlen: -1 + typmod: -1 } } } - )"; - - auto protoValueStr = R"( - items { - text_value: "my_text_value" - } - items { - bytes_value: "my_binary_value" - } - items { - text_value: "" - } - items { - bytes_value: "" - } - items { - } + } )"; - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - - Ydb::Value protoValue; - google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); - - TValue value(TType(protoType), protoValue); - - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"(["my_text_value";["my_binary_value"];"";[""];#])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"({"A":"my_text_value","B":["my_binary_value"],"C":"","D":[""],"E":null})"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Base64), - R"({"A":"my_text_value","B":["bXlfYmluYXJ5X3ZhbHVl"],"C":"","D":[""],"E":null})"); - } + auto protoValueStr = + "items {\n" + " text_value: \"my_text_value\"\n" + "}\n" + "items {\n" + " bytes_value: \"my_binary_value\"\n" + "}\n" + "items {\n" + " text_value: \"\"\n" + "}\n" + "items {\n" + " bytes_value: \"\"\n" + "}\n"; + + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + + Ydb::Value protoValue; + google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); + + TValue value(TType(protoType), protoValue); + + CheckProtoValue(value.GetProto(), protoValueStr); +} - Y_UNIT_TEST(ParseValueMaybe) { - auto protoTypeStr = R"( - tuple_type { - elements { - optional_type { - item { - type_id: UTF8 - } +TEST(YdbValue, ParseValueMaybe) { + auto protoTypeStr = R"( + tuple_type { + elements { + optional_type { + item { + type_id: UTF8 } } - elements { - optional_type { - item { - type_id: INT8 - } - } - } - elements { - optional_type { - item { - type_id: DOUBLE - } - } - } - elements { - optional_type { - item { - type_id: UINT64 - } + } + elements { + optional_type { + item { + type_id: INT8 } } - elements { - optional_type { - item { - type_id: DYNUMBER - } + } + elements { + optional_type { + item { + type_id: DOUBLE } } } - )"; - - auto protoValueStr = R"( - items { - text_value: "SomeUtf" - } - items { - int32_value: -5 - } - items { - null_flag_value: NULL_VALUE - } - items { - nested_value { - uint64_value: 7 + elements { + optional_type { + item { + type_id: UINT64 + } } } - items { - nested_value { - text_value: "12.345" + elements { + optional_type { + item { + type_id: DYNUMBER + } } } - )"; - - Ydb::Type protoType; - google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); - - Ydb::Value protoValue; - google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); - - TValue value(TType(protoType), protoValue); - TValueParser parser(value); - - parser.OpenTuple(); - UNIT_ASSERT(parser.TryNextElement()); - UNIT_ASSERT(parser.GetOptionalUtf8() == "SomeUtf"); - UNIT_ASSERT(parser.TryNextElement()); - UNIT_ASSERT(parser.GetOptionalInt8() == -5); - UNIT_ASSERT(parser.TryNextElement()); - UNIT_ASSERT(parser.GetOptionalDouble() == std::optional()); - UNIT_ASSERT(parser.TryNextElement()); - UNIT_ASSERT(parser.GetOptionalUint64() == (ui64)7); - UNIT_ASSERT(parser.TryNextElement()); - UNIT_ASSERT(parser.GetOptionalDyNumber() == "12.345"); - parser.CloseTuple(); - } - - Y_UNIT_TEST(BuildValueIncomplete) { - try { - auto value = TValueBuilder() - .BeginTuple() - .AddElement() - .Uint32(10) - .AddElement() - .String("test") - .Build(); - } catch (const TExpectedErrorException& e) { - return; } + )"; - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueListItemMismatch1) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .Int32(17) - .AddListItem() - .Uint32(19) - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; + auto protoValueStr = R"( + items { + text_value: "SomeUtf" } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueListItemMismatch2) { - auto itemValue = TValueBuilder() - .String("Test") - .Build(); - - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem(itemValue) - .AddListItem() - .Int32(17) - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; + items { + int32_value: -5 } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueListItemMismatch3) { - auto itemValue = TValueBuilder() - .String("Test") - .Build(); - - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .Int32(17) - .AddListItem(itemValue) - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; + items { + null_flag_value: NULL_VALUE } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueListItemMismatch4) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginList() - .AddListItem() - .Uint32(10) - .EndList() - .AddListItem() - .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint64).Build()) - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; + items { + nested_value { + uint64_value: 7 + } } - - UNIT_ASSERT(false); - } - - - Y_UNIT_TEST(BuildValueEmptyListUnknown) { - try { - auto value = TValueBuilder() - .EmptyList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; + items { + nested_value { + text_value: "12.345" + } } + )"; + + Ydb::Type protoType; + google::protobuf::TextFormat::ParseFromString(protoTypeStr, &protoType); + + Ydb::Value protoValue; + google::protobuf::TextFormat::ParseFromString(protoValueStr, &protoValue); + + TValue value(TType(protoType), protoValue); + TValueParser parser(value); + + parser.OpenTuple(); + ASSERT_TRUE(parser.TryNextElement()); + ASSERT_EQ(parser.GetOptionalUtf8(), "SomeUtf"); + ASSERT_TRUE(parser.TryNextElement()); + ASSERT_EQ(parser.GetOptionalInt8(), -5); + ASSERT_TRUE(parser.TryNextElement()); + ASSERT_EQ(parser.GetOptionalDouble(), std::optional()); + ASSERT_TRUE(parser.TryNextElement()); + ASSERT_EQ(parser.GetOptionalUint64(), (ui64)7); + ASSERT_TRUE(parser.TryNextElement()); + ASSERT_EQ(parser.GetOptionalDyNumber(), "12.345"); + parser.CloseTuple(); +} - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildDyNumberValue) { +TEST(YdbValue, BuildValueIncomplete) { + ASSERT_THROW({ auto value = TValueBuilder() - .DyNumber("12.345") + .BeginTuple() + .AddElement() + .Uint32(10) + .AddElement() + .String("test") .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"("12.345")"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"("12.345")"); - } - - Y_UNIT_TEST(BuildTaggedValue) { +TEST(YdbValue, BuildValueListItemMismatch1) { + ASSERT_THROW({ auto value = TValueBuilder() - .BeginTagged("my_tag") - .DyNumber("12.345") - .EndTagged() + .BeginList() + .AddListItem() + .Int32(17) + .AddListItem() + .Uint32(19) + .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"("12.345")"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"("12.345")"); - } - - Y_UNIT_TEST(BuildValueList) { - auto intValue = TValueBuilder() - .Int32(21) - .Build(); +TEST(YdbValue, BuildValueListItemMismatch2) { + auto itemValue = TValueBuilder() + .String("Test") + .Build(); + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() + .AddListItem(itemValue) .AddListItem() .Int32(17) - .AddListItem() - .Int32(19) - .AddListItem(intValue) .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([17;19;21])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([17,19,21])"); - } +TEST(YdbValue, BuildValueListItemMismatch3) { + auto itemValue = TValueBuilder() + .String("Test") + .Build(); - Y_UNIT_TEST(BuildValueListEmpty) { + ASSERT_THROW({ auto value = TValueBuilder() - .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build()) + .BeginList() + .AddListItem() + .Int32(17) + .AddListItem(itemValue) + .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(List)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([])"); - } - - Y_UNIT_TEST(BuildValueListEmpty2) { +TEST(YdbValue, BuildValueListItemMismatch4) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() .AddListItem() @@ -703,195 +578,318 @@ Y_UNIT_TEST_SUITE(YdbValue) { .Uint32(10) .EndList() .AddListItem() - .EmptyList() + .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint64).Build()) + .EndList() + .Build(); + }, TExpectedErrorException); +} + +TEST(YdbValue, BuildValueEmptyListUnknown) { + ASSERT_THROW({ + auto value = TValueBuilder() + .EmptyList() + .Build(); + }, TExpectedErrorException); +} + +TEST(YdbValue, BuildDyNumberValue) { + auto value = TValueBuilder() + .DyNumber("12.345") + .Build(); + + CheckProtoValue(value.GetProto(), "text_value: \"12.345\"\n"); +} + +TEST(YdbValue, BuildTaggedValue) { + auto value = TValueBuilder() + .BeginTagged("my_tag") + .DyNumber("12.345") + .EndTagged() + .Build(); + + CheckProtoValue(value.GetProto(), "text_value: \"12.345\"\n"); +} + +TEST(YdbValue, BuildValueList) { + auto intValue = TValueBuilder() + .Int32(21) + .Build(); + + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .Int32(17) + .AddListItem() + .Int32(19) + .AddListItem(intValue) + .EndList() + .Build(); + + CheckProtoValue(value.GetProto(), + "items {\n" + " int32_value: 17\n" + "}\n" + "items {\n" + " int32_value: 19\n" + "}\n" + "items {\n" + " int32_value: 21\n" + "}\n"); +} + +TEST(YdbValue, BuildValueListEmpty) { + auto value = TValueBuilder() + .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build()) + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(List)"); + CheckProtoValue(value.GetProto(), ""); +} + +TEST(YdbValue, BuildValueListEmpty2) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginList() + .AddListItem() + .Uint32(10) + .EndList() + .AddListItem() + .EmptyList() + .EndList() + .Build(); + + CheckProtoValue(value.GetProto(), + "items {\n" + " items {\n" + " uint32_value: 10\n" + " }\n" + "}\n" + "items {\n" + "}\n"); +} + +TEST(YdbValue, BuildValueListEmpty3) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build()) + .AddListItem() + .BeginList() + .AddListItem() + .Uint32(10) .EndList() - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[10u];[]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[10],[]])"); - } + .EndList() + .Build(); + + CheckProtoValue(value.GetProto(), + "items {\n" + "}\n" + "items {\n" + " items {\n" + " uint32_value: 10\n" + " }\n" + "}\n"); +} - Y_UNIT_TEST(BuildValueListEmpty3) { +TEST(YdbValue, BuildValueBadCall) { + ASSERT_THROW({ auto value = TValueBuilder() - .BeginList() - .AddListItem() - .EmptyList(TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build()) .AddListItem() - .BeginList() - .AddListItem() - .Uint32(10) - .EndList() .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[];[10u]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[],[10]])"); - } - - Y_UNIT_TEST(BuildValueBadCall) { - try { - auto value = TValueBuilder() - .AddListItem() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } +TEST(YdbValue, BuildValueOptional) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .OptionalInt32(1) + .AddListItem() + .EmptyOptional() + .AddListItem() + .BeginOptional() + .Int32(57) + .EndOptional() + .AddListItem() + .EmptyOptional(TTypeBuilder().Primitive(EPrimitiveType::Int32).Build()) + .EndList() + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(List)"); + + auto expectedProtoValueStr = + "items {\n" + " int32_value: 1\n" + "}\n" + "items {\n" + " null_flag_value: NULL_VALUE\n" + "}\n" + "items {\n" + " int32_value: 57\n" + "}\n" + "items {\n" + " null_flag_value: NULL_VALUE\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - UNIT_ASSERT(false); - } +TEST(YdbValue, BuildValueNestedOptional) { + auto value = TValueBuilder() + .BeginTuple() + .AddElement() + .BeginOptional() + .BeginOptional() + .Int32(10) + .EndOptional() + .EndOptional() + .AddElement() + .BeginOptional() + .BeginOptional() + .BeginOptional() + .Int64(-1) + .EndOptional() + .EndOptional() + .EndOptional() + .AddElement() + .BeginOptional() + .EmptyOptional(TTypeBuilder().Primitive(EPrimitiveType::String).Build()) + .EndOptional() + .AddElement() + .BeginOptional() + .BeginOptional() + .EmptyOptional(EPrimitiveType::Utf8) + .EndOptional() + .EndOptional() + .EndTuple() + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(Tuple)"); + + auto expectedProtoValueStr = + "items {\n" + " int32_value: 10\n" + "}\n" + "items {\n" + " int64_value: -1\n" + "}\n" + "items {\n" + " nested_value {\n" + " null_flag_value: NULL_VALUE\n" + " }\n" + "}\n" + "items {\n" + " nested_value {\n" + " nested_value {\n" + " null_flag_value: NULL_VALUE\n" + " }\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueOptional) { +TEST(YdbValue, BuildValueOptionalMismatch1) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() - .AddListItem() - .OptionalInt32(1) - .AddListItem() - .EmptyOptional() .AddListItem() .BeginOptional() - .Int32(57) + .Uint32(10) .EndOptional() .AddListItem() - .EmptyOptional(TTypeBuilder().Primitive(EPrimitiveType::Int32).Build()) + .BeginOptional() + .Int32(20) + .EndOptional() .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(List)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[1];#;[57];#])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([1,null,57,null])"); - - auto expectedProtoValueStr = - "items {\n" - " int32_value: 1\n" - "}\n" - "items {\n" - " null_flag_value: NULL_VALUE\n" - "}\n" - "items {\n" - " int32_value: 57\n" - "}\n" - "items {\n" - " null_flag_value: NULL_VALUE\n" - "}\n"; - - TStringType protoValueStr; - google::protobuf::TextFormat::PrintToString(value.GetProto(), &protoValueStr); - UNIT_ASSERT_NO_DIFF(protoValueStr, expectedProtoValueStr); - } - - Y_UNIT_TEST(BuildValueNestedOptional) { +TEST(YdbValue, BuildValueOptionalMismatch2) { + ASSERT_THROW({ auto value = TValueBuilder() - .BeginTuple() - .AddElement() - .BeginOptional() - .BeginOptional() - .Int32(10) - .EndOptional() - .EndOptional() - .AddElement() - .BeginOptional() - .BeginOptional() - .BeginOptional() - .Int64(-1) - .EndOptional() - .EndOptional() - .EndOptional() - .AddElement() + .BeginList() + .AddListItem() .BeginOptional() - .EmptyOptional(TTypeBuilder().Primitive(EPrimitiveType::String).Build()) + .Uint32(10) .EndOptional() - .AddElement() + .AddListItem() .BeginOptional() - .BeginOptional() - .EmptyOptional(EPrimitiveType::Utf8) - .EndOptional() + .Int32(57) .EndOptional() - .EndTuple() + .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(Tuple)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[[10]];[[[-1]]];[#];[[#]]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([10,-1,null,null])"); - - auto expectedProtoValueStr = - "items {\n" - " int32_value: 10\n" - "}\n" - "items {\n" - " int64_value: -1\n" - "}\n" - "items {\n" - " nested_value {\n" - " null_flag_value: NULL_VALUE\n" - " }\n" - "}\n" - "items {\n" - " nested_value {\n" - " nested_value {\n" - " null_flag_value: NULL_VALUE\n" - " }\n" - " }\n" - "}\n"; - - TStringType protoValueStr; - google::protobuf::TextFormat::PrintToString(value.GetProto(), &protoValueStr); - UNIT_ASSERT_NO_DIFF(protoValueStr, expectedProtoValueStr); - } - - Y_UNIT_TEST(BuildValueOptionalMismatch1) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginOptional() - .Uint32(10) - .EndOptional() - .AddListItem() - .BeginOptional() - .Int32(20) - .EndOptional() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueOptionalMismatch2) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginOptional() - .Uint32(10) - .EndOptional() - .AddListItem() - .BeginOptional() - .Int32(57) - .EndOptional() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } +TEST(YdbValue, BuildValueStruct) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginStruct() + .AddMember("Id") + .Uint32(1) + .AddMember("Name") + .String("Anna") + .AddMember("Value") + .Int32(-100) + .AddMember("Description") + .EmptyOptional(EPrimitiveType::Utf8) + .EndStruct() + .AddListItem() + .BeginStruct() + .AddMember("Name") + .String("Paul") + .AddMember("Value", TValueBuilder().Int32(-200).Build()) + .AddMember("Id") + .Uint32(2) + .AddMember("Description") + .OptionalUtf8("Some details") + .EndStruct() + .EndList() + .Build(); + + auto expectedProtoValueStr = + "items {\n" + " items {\n" + " uint32_value: 1\n" + " }\n" + " items {\n" + " bytes_value: \"Anna\"\n" + " }\n" + " items {\n" + " int32_value: -100\n" + " }\n" + " items {\n" + " null_flag_value: NULL_VALUE\n" + " }\n" + "}\n" + "items {\n" + " items {\n" + " uint32_value: 2\n" + " }\n" + " items {\n" + " bytes_value: \"Paul\"\n" + " }\n" + " items {\n" + " int32_value: -200\n" + " }\n" + " items {\n" + " text_value: \"Some details\"\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueStruct) { +TEST(YdbValue, BuildValueStructMissingMember) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() .AddListItem() @@ -902,100 +900,223 @@ Y_UNIT_TEST_SUITE(YdbValue) { .String("Anna") .AddMember("Value") .Int32(-100) - .AddMember("Description") - .EmptyOptional(EPrimitiveType::Utf8) .EndStruct() .AddListItem() .BeginStruct() - .AddMember("Name") - .String("Paul") - .AddMember("Value", TValueBuilder().Int32(-200).Build()) + .AddMember("Value") + .Int32(-200) .AddMember("Id") .Uint32(2) - .AddMember("Description") - .OptionalUtf8("Some details") .EndStruct() .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[1u;"Anna";-100;#];[2u;"Paul";-200;["Some details"]]])"); - UNIT_ASSERT_NO_DIFF( - FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([{"Id":1,"Name":"Anna","Value":-100,"Description":null},)" - R"({"Id":2,"Name":"Paul","Value":-200,"Description":"Some details"}])" - ); - } - - Y_UNIT_TEST(BuildValueStructMissingMember) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginStruct() - .AddMember("Id") - .Uint32(1) - .AddMember("Name") - .String("Anna") - .AddMember("Value") - .Int32(-100) - .EndStruct() - .AddListItem() - .BeginStruct() - .AddMember("Value") - .Int32(-200) - .AddMember("Id") - .Uint32(2) - .EndStruct() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } +TEST(YdbValue, BuildValueTuplePrimitives) { + auto value = TValueBuilder() + .BeginTuple() + .AddElement().Bool(true) + .AddElement().Int8(-1) + .AddElement().Uint8(1) + .AddElement().Int16(-2) + .AddElement().Uint16(2) + .AddElement().Int32(-3) + .AddElement().Uint32(3) + .AddElement().Int64(-4) + .AddElement().Uint64(4) + .AddElement().Float(-5.5) + .AddElement().Double(6.6) + .AddElement().Date(TInstant::Days(7)) + .AddElement().Datetime(TInstant::Seconds(8)) + .AddElement().Timestamp(TInstant::MicroSeconds(9)) + .AddElement().Interval(-10) + .AddElement().TzDate("2018-02-02,Europe/Moscow") + .AddElement().TzDatetime("2018-02-03T15:00:00,Europe/Moscow") + .AddElement().TzTimestamp("2018-02-07T15:00:00,Europe/Moscow") + .AddElement().String("TestString") + .AddElement().Utf8("TestUtf8") + .AddElement().Yson("[]") + .AddElement().Json("{}") + .EndTuple() + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(Tuple)"); + + auto expectedProtoValueStr = + "items {\n" + " bool_value: true\n" + "}\n" + "items {\n" + " int32_value: -1\n" + "}\n" + "items {\n" + " uint32_value: 1\n" + "}\n" + "items {\n" + " int32_value: -2\n" + "}\n" + "items {\n" + " uint32_value: 2\n" + "}\n" + "items {\n" + " int32_value: -3\n" + "}\n" + "items {\n" + " uint32_value: 3\n" + "}\n" + "items {\n" + " int64_value: -4\n" + "}\n" + "items {\n" + " uint64_value: 4\n" + "}\n" + "items {\n" + " float_value: -5.5\n" + "}\n" + "items {\n" + " double_value: 6.6\n" + "}\n" + "items {\n" + " uint32_value: 7\n" + "}\n" + "items {\n" + " uint32_value: 8\n" + "}\n" + "items {\n" + " uint64_value: 9\n" + "}\n" + "items {\n" + " int64_value: -10\n" + "}\n" + "items {\n" + " text_value: \"2018-02-02,Europe/Moscow\"\n" + "}\n" + "items {\n" + " text_value: \"2018-02-03T15:00:00,Europe/Moscow\"\n" + "}\n" + "items {\n" + " text_value: \"2018-02-07T15:00:00,Europe/Moscow\"\n" + "}\n" + "items {\n" + " bytes_value: \"TestString\"\n" + "}\n" + "items {\n" + " text_value: \"TestUtf8\"\n" + "}\n" + "items {\n" + " bytes_value: \"[]\"\n" + "}\n" + "items {\n" + " text_value: \"{}\"\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - UNIT_ASSERT(false); - } +TEST(YdbValue, BuildValueTuple1) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginTuple() + .AddElement() + .Int32(10) + .AddElement() + .String("Str1") + .EndTuple() + .AddListItem() + .BeginTuple() + .AddElement(TValueBuilder().Int32(20).Build()) + .AddElement() + .String("Str2") + .EndTuple() + .EndList() + .Build(); + + auto expectedProtoValueStr = + "items {\n" + " items {\n" + " int32_value: 10\n" + " }\n" + " items {\n" + " bytes_value: \"Str1\"\n" + " }\n" + "}\n" + "items {\n" + " items {\n" + " int32_value: 20\n" + " }\n" + " items {\n" + " bytes_value: \"Str2\"\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueTuplePrimitives) { - auto value = TValueBuilder() +TEST(YdbValue, BuildValueTuple2) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginTuple() + .AddElement(TValueBuilder().Int32(-10).Build()) + .AddElement(TValueBuilder().Utf8("Utf1").Build()) + .EndTuple() + .AddListItem() .BeginTuple() - .AddElement().Bool(true) - .AddElement().Int8(-1) - .AddElement().Uint8(1) - .AddElement().Int16(-2) - .AddElement().Uint16(2) - .AddElement().Int32(-3) - .AddElement().Uint32(3) - .AddElement().Int64(-4) - .AddElement().Uint64(4) - .AddElement().Float(-5.5) - .AddElement().Double(6.6) - .AddElement().Date(TInstant::Days(7)) - .AddElement().Datetime(TInstant::Seconds(8)) - .AddElement().Timestamp(TInstant::MicroSeconds(9)) - .AddElement().Interval(-10) - .AddElement().TzDate("2018-02-02,Europe/Moscow") - .AddElement().TzDatetime("2018-02-03T15:00:00,Europe/Moscow") - .AddElement().TzTimestamp("2018-02-07T15:00:00,Europe/Moscow") - .AddElement().String("TestString") - .AddElement().Utf8("TestUtf8") - .AddElement().Yson("[]") - .AddElement().Json("{}") + .AddElement() + .Int32(-20) + .AddElement() + .Utf8("Utf2") .EndTuple() + .EndList() + .Build(); + + auto expectedProtoValueStr = + "items {\n" + " items {\n" + " int32_value: -10\n" + " }\n" + " items {\n" + " text_value: \"Utf1\"\n" + " }\n" + "}\n" + "items {\n" + " items {\n" + " int32_value: -20\n" + " }\n" + " items {\n" + " text_value: \"Utf2\"\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} + +TEST(YdbValue, BuildValueTupleElementsMismatch1) { + ASSERT_THROW({ + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginTuple() + .AddElement() + .Int32(10) + .AddElement() + .String("Str1") + .EndTuple() + .AddListItem() + .BeginTuple() + .AddElement() + .Int32(-20) + .EndTuple() + .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(Tuple)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([%true;-1;1u;-2;2u;-3;3u;-4;4u;-5.5;6.6;7u;8u;9u;-10;"2018-02-02,Europe/Moscow";"2018-02-03T15:00:00,Europe/Moscow";"2018-02-07T15:00:00,Europe/Moscow";"TestString";"TestUtf8";"[]";"{}"])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([true,-1,1,-2,2,-3,3,-4,4,-5.5,6.6,"1970-01-08","1970-01-01T00:00:08Z",)" - R"("1970-01-01T00:00:00.000009Z",-10,"2018-02-02,Europe/Moscow",)" - R"("2018-02-03T15:00:00,Europe/Moscow","2018-02-07T15:00:00,Europe/Moscow",)" - R"("TestString","TestUtf8","[]","{}"])"); - } - - Y_UNIT_TEST(BuildValueTuple1) { +TEST(YdbValue, BuildValueTupleElementsMismatch2) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() .AddListItem() @@ -1007,125 +1128,113 @@ Y_UNIT_TEST_SUITE(YdbValue) { .EndTuple() .AddListItem() .BeginTuple() - .AddElement(TValueBuilder().Int32(20).Build()) + .AddElement() + .Int32(20) .AddElement() .String("Str2") + .AddElement() + .Uint64(1) .EndTuple() .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[10;"Str1"];[20;"Str2"]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[10,"Str1"],[20,"Str2"]])"); - } - - Y_UNIT_TEST(BuildValueTuple2) { +TEST(YdbValue, BuildValueTupleTypeMismatch) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() .AddListItem() .BeginTuple() - .AddElement(TValueBuilder().Int32(-10).Build()) - .AddElement(TValueBuilder().Utf8("Utf1").Build()) + .AddElement() + .Int32(10) + .AddElement() + .String("Str1") .EndTuple() .AddListItem() .BeginTuple() .AddElement() - .Int32(-20) + .Int32(20) .AddElement() .Utf8("Utf2") .EndTuple() .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[-10;"Utf1"];[-20;"Utf2"]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[-10,"Utf1"],[-20,"Utf2"]])"); - } - - Y_UNIT_TEST(BuildValueTupleElementsMismatch1) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(10) - .AddElement() - .String("Str1") - .EndTuple() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(-20) - .EndTuple() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueTupleElementsMismatch2) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(10) - .AddElement() - .String("Str1") - .EndTuple() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(20) - .AddElement() - .String("Str2") - .AddElement() - .Uint64(1) - .EndTuple() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueTupleTypeMismatch) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(10) - .AddElement() - .String("Str1") - .EndTuple() - .AddListItem() - .BeginTuple() - .AddElement() - .Int32(20) - .AddElement() - .Utf8("Utf2") - .EndTuple() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } +TEST(YdbValue, BuildValueDict1) { + auto value = TValueBuilder() + .BeginDict() + .AddDictItem() + .DictKey(TValueBuilder().Int32(1).Build()) + .DictPayload(TValueBuilder().String("Str1").Build()) + .AddDictItem() + .DictKey() + .Int32(2) + .DictPayload() + .String("Str2") + .EndDict() + .Build(); + + auto expectedProtoValueStr = + "pairs {\n" + " key {\n" + " int32_value: 1\n" + " }\n" + " payload {\n" + " bytes_value: \"Str1\"\n" + " }\n" + "}\n" + "pairs {\n" + " key {\n" + " int32_value: 2\n" + " }\n" + " payload {\n" + " bytes_value: \"Str2\"\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - UNIT_ASSERT(false); - } +TEST(YdbValue, BuildValueDict2) { + auto value = TValueBuilder() + .BeginDict() + .AddDictItem() + .DictKey() + .Int32(1) + .DictPayload() + .String("Str1") + .AddDictItem() + .DictKey(TValueBuilder().Int32(2).Build()) + .DictPayload(TValueBuilder().String("Str2").Build()) + .EndDict() + .Build(); + + auto expectedProtoValueStr = + "pairs {\n" + " key {\n" + " int32_value: 1\n" + " }\n" + " payload {\n" + " bytes_value: \"Str1\"\n" + " }\n" + "}\n" + "pairs {\n" + " key {\n" + " int32_value: 2\n" + " }\n" + " payload {\n" + " bytes_value: \"Str2\"\n" + " }\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueDict1) { +TEST(YdbValue, BuildValueDictTypeMismatch1) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginDict() .AddDictItem() @@ -1135,17 +1244,14 @@ Y_UNIT_TEST_SUITE(YdbValue) { .DictKey() .Int32(2) .DictPayload() - .String("Str2") + .Utf8("Utf2") .EndDict() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[1;"Str1"];[2;"Str2"]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[1,"Str1"],[2,"Str2"]])"); - } - - Y_UNIT_TEST(BuildValueDict2) { +TEST(YdbValue, BuildValueDictTypeMismatch2) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginDict() .AddDictItem() @@ -1154,224 +1260,210 @@ Y_UNIT_TEST_SUITE(YdbValue) { .DictPayload() .String("Str1") .AddDictItem() - .DictKey(TValueBuilder().Int32(2).Build()) + .DictKey(TValueBuilder().Uint32(2).Build()) .DictPayload(TValueBuilder().String("Str2").Build()) .EndDict() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[1;"Str1"];[2;"Str2"]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[1,"Str1"],[2,"Str2"]])"); - } - - Y_UNIT_TEST(BuildValueDictTypeMismatch1) { - try { - auto value = TValueBuilder() - .BeginDict() - .AddDictItem() - .DictKey(TValueBuilder().Int32(1).Build()) - .DictPayload(TValueBuilder().String("Str1").Build()) - .AddDictItem() - .DictKey() - .Int32(2) - .DictPayload() - .Utf8("Utf2") - .EndDict() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } +TEST(YdbValue, BuildValueDictEmpty1) { + auto value = TValueBuilder() + .EmptyDict( + TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build(), + TTypeBuilder().Primitive(EPrimitiveType::String).Build()) + .Build(); - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueDictTypeMismatch2) { - try { - auto value = TValueBuilder() - .BeginDict() - .AddDictItem() - .DictKey() - .Int32(1) - .DictPayload() - .String("Str1") - .AddDictItem() - .DictKey(TValueBuilder().Uint32(2).Build()) - .DictPayload(TValueBuilder().String("Str2").Build()) - .EndDict() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } + ASSERT_EQ(FormatType(value.GetType()), + R"(Dict)"); - UNIT_ASSERT(false); - } + auto expectedProtoValueStr = ""; + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueDictEmpty1) { - auto value = TValueBuilder() +TEST(YdbValue, BuildValueDictEmpty2) { + auto value = TValueBuilder() + .BeginList() + .AddListItem() + .BeginDict() + .AddDictItem() + .DictKey() + .Int32(1) + .DictPayload() + .String("Str1") + .EndDict() + .AddListItem() + .EmptyDict() + .AddListItem() .EmptyDict( - TTypeBuilder().Primitive(EPrimitiveType::Uint32).Build(), + TTypeBuilder().Primitive(EPrimitiveType::Int32).Build(), TTypeBuilder().Primitive(EPrimitiveType::String).Build()) - .Build(); - - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(Dict)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([])"); - } + .EndList() + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(List>)"); + + auto expectedProtoValueStr = + "items {\n" + " pairs {\n" + " key {\n" + " int32_value: 1\n" + " }\n" + " payload {\n" + " bytes_value: \"Str1\"\n" + " }\n" + " }\n" + "}\n" + "items {\n" + "}\n" + "items {\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - Y_UNIT_TEST(BuildValueDictEmpty2) { +TEST(YdbValue, BuildValueDictEmptyNoType) { + ASSERT_THROW({ auto value = TValueBuilder() .BeginList() - .AddListItem() - .BeginDict() - .AddDictItem() - .DictKey() - .Int32(1) - .DictPayload() - .String("Str1") - .EndDict() .AddListItem() .EmptyDict() + .EndList() + .Build(); + }, TExpectedErrorException); +} + +TEST(YdbValue, BuildValueDictEmptyTypeMismatch) { + ASSERT_THROW({ + auto value = TValueBuilder() + .BeginList() .AddListItem() .EmptyDict( TTypeBuilder().Primitive(EPrimitiveType::Int32).Build(), TTypeBuilder().Primitive(EPrimitiveType::String).Build()) + .AddListItem() + .EmptyDict( + TTypeBuilder().Primitive(EPrimitiveType::Int32).Build(), + TTypeBuilder().Primitive(EPrimitiveType::Utf8).Build()) .EndList() .Build(); + }, TExpectedErrorException); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(List>)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([[[1;"Str1"]];[];[]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([[[1,"Str1"]],[],[]])"); - } - - Y_UNIT_TEST(BuildValueDictEmptyNoType) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .EmptyDict() - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueDictEmptyTypeMismatch) { - try { - auto value = TValueBuilder() - .BeginList() - .AddListItem() - .EmptyDict( - TTypeBuilder().Primitive(EPrimitiveType::Int32).Build(), - TTypeBuilder().Primitive(EPrimitiveType::String).Build()) - .AddListItem() - .EmptyDict( - TTypeBuilder().Primitive(EPrimitiveType::Int32).Build(), - TTypeBuilder().Primitive(EPrimitiveType::Utf8).Build()) - .EndList() - .Build(); - } catch (const TExpectedErrorException& e) { - return; - } - - UNIT_ASSERT(false); - } - - Y_UNIT_TEST(BuildValueWithType) { - auto type = TTypeBuilder() - .BeginTuple() - .AddElement() - .BeginStruct() - .AddMember("Name") - .Primitive(EPrimitiveType::String) - .AddMember("Value") - .Primitive(EPrimitiveType::Uint64) - .EndStruct() - .AddElement() +TEST(YdbValue, BuildValueWithType) { + auto type = TTypeBuilder() + .BeginTuple() + .AddElement() + .BeginStruct() + .AddMember("Name") + .Primitive(EPrimitiveType::String) + .AddMember("Value") + .Primitive(EPrimitiveType::Uint64) + .EndStruct() + .AddElement() + .BeginOptional() + .Primitive(EPrimitiveType::Utf8) + .EndOptional() + .AddElement() + .BeginList() + .Primitive(EPrimitiveType::Bool) + .EndList() + .AddElement() + .BeginDict() + .DictKey() + .Primitive(EPrimitiveType::Int32) + .DictPayload() .BeginOptional() - .Primitive(EPrimitiveType::Utf8) + .Primitive(EPrimitiveType::Uint8) .EndOptional() - .AddElement() - .BeginList() - .Primitive(EPrimitiveType::Bool) - .EndList() - .AddElement() - .BeginDict() + .EndDict() + .AddElement() + .BeginOptional() + .Primitive(EPrimitiveType::DyNumber) + .EndOptional() + .EndTuple() + .Build(); + + auto value = TValueBuilder(type) + .BeginTuple() + .AddElement() + .BeginStruct() + .AddMember("Value") + .Uint64(1) + .AddMember("Name") + .String("Sergey") + .EndStruct() + .AddElement() + .EmptyOptional() + .AddElement() + .BeginList() + .AddListItem() + .Bool(true) + .EndList() + .AddElement() + .BeginDict() + .AddDictItem() .DictKey() - .Primitive(EPrimitiveType::Int32) + .Int32(10) .DictPayload() - .BeginOptional() - .Primitive(EPrimitiveType::Uint8) - .EndOptional() - .EndDict() - .AddElement() - .BeginOptional() - .Primitive(EPrimitiveType::DyNumber) - .EndOptional() - .EndTuple() - .Build(); - - auto value = TValueBuilder(type) - .BeginTuple() - .AddElement() - .BeginStruct() - .AddMember("Value") - .Uint64(1) - .AddMember("Name") - .String("Sergey") - .EndStruct() - .AddElement() - .EmptyOptional() - .AddElement() - .BeginList() - .AddListItem() - .Bool(true) - .EndList() - .AddElement() - .BeginDict() - .AddDictItem() - .DictKey() - .Int32(10) - .DictPayload() - .EmptyOptional() - .EndDict() - .AddElement() - .BeginOptional() - .DyNumber("12.345") - .EndOptional() - .EndTuple() - .Build(); + .EmptyOptional() + .EndDict() + .AddElement() + .BeginOptional() + .DyNumber("12.345") + .EndOptional() + .EndTuple() + .Build(); + + ASSERT_EQ(FormatType(value.GetType()), + R"(Tuple,Utf8?,List,Dict,DyNumber?>)"); + + auto expectedProtoValueStr = + "items {\n" + " items {\n" + " bytes_value: \"Sergey\"\n" + " }\n" + " items {\n" + " uint64_value: 1\n" + " }\n" + "}\n" + "items {\n" + " null_flag_value: NULL_VALUE\n" + "}\n" + "items {\n" + " items {\n" + " bool_value: true\n" + " }\n" + "}\n" + "items {\n" + " pairs {\n" + " key {\n" + " int32_value: 10\n" + " }\n" + " payload {\n" + " null_flag_value: NULL_VALUE\n" + " }\n" + " }\n" + "}\n" + "items {\n" + " text_value: \"12.345\"\n" + "}\n"; + + CheckProtoValue(value.GetProto(), expectedProtoValueStr); +} - UNIT_ASSERT_NO_DIFF(FormatType(value.GetType()), - R"(Tuple,Utf8?,List,Dict,DyNumber?>)"); - UNIT_ASSERT_NO_DIFF(FormatValueYson(value), - R"([["Sergey";1u];#;[%true];[[10;#]];["12.345"]])"); - UNIT_ASSERT_NO_DIFF(FormatValueJson(value, EBinaryStringEncoding::Unicode), - R"([{"Name":"Sergey","Value":1},null,[true],[[10,null]],"12.345"])"); - } - - Y_UNIT_TEST(CorrectUuid) { - std::string uuidStr = "5ca32c22-841b-11e8-adc0-fa7ae01bbebc"; - TUuidValue uuid(uuidStr); - UNIT_ASSERT_VALUES_EQUAL(uuidStr, uuid.ToString()); - } - - Y_UNIT_TEST(IncorrectUuid) { - UNIT_ASSERT_EXCEPTION(TUuidValue(""), TContractViolation); - UNIT_ASSERT_EXCEPTION(TUuidValue("0123456789abcdef0123456789abcdef0123456789abcdef"), TContractViolation); - UNIT_ASSERT_EXCEPTION(TUuidValue("5ca32c22+841b-11e8-adc0-fa7ae01bbebc"), TContractViolation); - UNIT_ASSERT_EXCEPTION(TUuidValue("5ca32-c22841b-11e8-adc0-fa7ae01bbebc"), TContractViolation); - } +TEST(YdbValue, CorrectUuid) { + std::string uuidStr = "5ca32c22-841b-11e8-adc0-fa7ae01bbebc"; + TUuidValue uuid(uuidStr); + ASSERT_EQ(uuidStr, uuid.ToString()); +} +TEST(YdbValue, IncorrectUuid) { + ASSERT_THROW(TUuidValue(""), TContractViolation); + ASSERT_THROW(TUuidValue("0123456789abcdef0123456789abcdef0123456789abcdef"), TContractViolation); + ASSERT_THROW(TUuidValue("5ca32c22+841b-11e8-adc0-fa7ae01bbebc"), TContractViolation); + ASSERT_THROW(TUuidValue("5ca32-c22841b-11e8-adc0-fa7ae01bbebc"), TContractViolation); } } // namespace NYdb From 402711a688944b7d99c114324fcaac6714dd454a Mon Sep 17 00:00:00 2001 From: Nikolay Shestakov Date: Wed, 9 Apr 2025 15:41:35 +0000 Subject: [PATCH 3/4] Added max_committed_time_lag for DescribeConsumer (#16857) --- .../ydb-cpp-sdk/client/topic/control_plane.h | 2 ++ src/api/protos/ydb_topic.proto | 4 ++++ src/client/topic/impl/topic.cpp | 5 +++++ .../ut/ut_utils/topic_sdk_test_setup.cpp | 21 +++++++++++++++++++ .../topic/ut/ut_utils/topic_sdk_test_setup.h | 3 +++ 5 files changed, 35 insertions(+) diff --git a/include/ydb-cpp-sdk/client/topic/control_plane.h b/include/ydb-cpp-sdk/client/topic/control_plane.h index e957ea6a5c..b7935aa18b 100644 --- a/include/ydb-cpp-sdk/client/topic/control_plane.h +++ b/include/ydb-cpp-sdk/client/topic/control_plane.h @@ -111,6 +111,7 @@ class TPartitionConsumerStats { const TInstant& GetLastReadTime() const; const TDuration& GetMaxReadTimeLag() const; const TDuration& GetMaxWriteTimeLag() const; + const TDuration& GetMaxCommittedTimeLag() const; private: uint64_t CommittedOffset_; @@ -120,6 +121,7 @@ class TPartitionConsumerStats { TInstant LastReadTime_; TDuration MaxReadTimeLag_; TDuration MaxWriteTimeLag_; + TDuration MaxCommittedTimeLag_; }; // Topic partition location diff --git a/src/api/protos/ydb_topic.proto b/src/api/protos/ydb_topic.proto index 59cf0a4039..e28e0bce42 100644 --- a/src/api/protos/ydb_topic.proto +++ b/src/api/protos/ydb_topic.proto @@ -810,6 +810,8 @@ message Consumer { google.protobuf.Duration max_read_time_lag = 2; // Maximum of differences between write timestamp and create timestamp for all messages, read during last minute. google.protobuf.Duration max_write_time_lag = 3; + // The difference between the write timestamp of the last commited message and the current time. + google.protobuf.Duration max_committed_time_lag = 5; // Bytes read statistics. MultipleWindowsStat bytes_read = 4; } @@ -1214,6 +1216,8 @@ message DescribeConsumerResult { google.protobuf.Duration max_read_time_lag = 6; // Maximum of differences between write timestamp and create timestamp for all messages, read during last minute. google.protobuf.Duration max_write_time_lag = 7; + // The difference between the write timestamp of the last commited message and the current time. + google.protobuf.Duration max_committed_time_lag = 13; // How much bytes were read during several windows statistics from this partition. MultipleWindowsStat bytes_read = 8; diff --git a/src/client/topic/impl/topic.cpp b/src/client/topic/impl/topic.cpp index 8a0eb5f9f3..4f49700af7 100644 --- a/src/client/topic/impl/topic.cpp +++ b/src/client/topic/impl/topic.cpp @@ -376,6 +376,7 @@ TPartitionConsumerStats::TPartitionConsumerStats(const Ydb::Topic::DescribeConsu , LastReadTime_(TInstant::Seconds(partitionStats.last_read_time().seconds())) , MaxReadTimeLag_(TDuration::Seconds(partitionStats.max_read_time_lag().seconds())) , MaxWriteTimeLag_(TDuration::Seconds(partitionStats.max_write_time_lag().seconds())) + , MaxCommittedTimeLag_(TDuration::Seconds(partitionStats.max_committed_time_lag().seconds())) {} uint64_t TPartitionConsumerStats::GetCommittedOffset() const { @@ -406,6 +407,10 @@ const TDuration& TPartitionConsumerStats::GetMaxWriteTimeLag() const { return MaxWriteTimeLag_; } +const TDuration& TPartitionConsumerStats::GetMaxCommittedTimeLag() const { + return MaxCommittedTimeLag_; +} + TPartitionLocation::TPartitionLocation(const Ydb::Topic::PartitionLocation& partitionLocation) : NodeId_(partitionLocation.node_id()) , Generation_(partitionLocation.generation()) diff --git a/src/client/topic/ut/ut_utils/topic_sdk_test_setup.cpp b/src/client/topic/ut/ut_utils/topic_sdk_test_setup.cpp index c3253d1ea7..b61ec85322 100644 --- a/src/client/topic/ut/ut_utils/topic_sdk_test_setup.cpp +++ b/src/client/topic/ut/ut_utils/topic_sdk_test_setup.cpp @@ -66,6 +66,27 @@ TTopicDescription TTopicSdkTestSetup::DescribeTopic(const TString& path) return status.GetTopicDescription(); } +TConsumerDescription TTopicSdkTestSetup::DescribeConsumer(const TString& path, const TString& consumer) +{ + TTopicClient client(MakeDriver()); + + TDescribeConsumerSettings settings; + settings.IncludeStats(true); + settings.IncludeLocation(true); + + auto status = client.DescribeConsumer(path, consumer, settings).GetValueSync(); + UNIT_ASSERT(status.IsSuccess()); + + return status.GetConsumerDescription(); +} + +TStatus TTopicSdkTestSetup::Commit(const TString& path, const TString& consumerName, size_t partitionId, size_t offset) { + TTopicClient client(MakeDriver()); + + return client.CommitOffset(path, partitionId, consumerName, offset).GetValueSync(); +} + + TString TTopicSdkTestSetup::GetEndpoint() const { return "localhost:" + ToString(Server.GrpcPort); } diff --git a/src/client/topic/ut/ut_utils/topic_sdk_test_setup.h b/src/client/topic/ut/ut_utils/topic_sdk_test_setup.h index 7a28780148..3f8550db2e 100644 --- a/src/client/topic/ut/ut_utils/topic_sdk_test_setup.h +++ b/src/client/topic/ut/ut_utils/topic_sdk_test_setup.h @@ -22,6 +22,9 @@ class TTopicSdkTestSetup { size_t maxPartitionCount = 100); TTopicDescription DescribeTopic(const TString& path = TString{TEST_TOPIC}); + TConsumerDescription DescribeConsumer(const TString& path = TString{TEST_TOPIC}, const TString& consumer = TString{TEST_CONSUMER}); + + TStatus Commit(const TString& path, const TString& consumerName, size_t partitionId, size_t offset); TString GetEndpoint() const; TString GetTopicPath(const TString& name = TString{TEST_TOPIC}) const; From 503c70accfa261f43b57fe3ba803cad373e60c68 Mon Sep 17 00:00:00 2001 From: Bulat Gayazov Date: Wed, 9 Apr 2025 15:45:01 +0000 Subject: [PATCH 4/4] Added params and value tests to CI --- cmake/testing.cmake | 6 +++ .../integration/basic_example/CMakeLists.txt | 3 +- tests/integration/bulk_upsert/CMakeLists.txt | 3 +- .../integration/server_restart/CMakeLists.txt | 3 +- tests/unit/client/CMakeLists.txt | 49 +++++++------------ 5 files changed, 28 insertions(+), 36 deletions(-) diff --git a/cmake/testing.cmake b/cmake/testing.cmake index b4f1014f9a..ab20c3169a 100644 --- a/cmake/testing.cmake +++ b/cmake/testing.cmake @@ -130,6 +130,9 @@ function(add_ydb_test) WORKING_DIRECTORY ${YDB_TEST_WORKING_DIRECTORY} ) + target_link_libraries(${YDB_TEST_NAME} PRIVATE + GTest::gtest_main + ) else() add_yunittest( NAME @@ -146,6 +149,9 @@ function(add_ydb_test) WORKING_DIRECTORY ${YDB_TEST_WORKING_DIRECTORY} ) + target_link_libraries(${YDB_TEST_NAME} PRIVATE + cpp-testing-unittest_main + ) endif() set_yunittest_property( diff --git a/tests/integration/basic_example/CMakeLists.txt b/tests/integration/basic_example/CMakeLists.txt index 573e9745a1..6178b80c71 100644 --- a/tests/integration/basic_example/CMakeLists.txt +++ b/tests/integration/basic_example/CMakeLists.txt @@ -1,4 +1,4 @@ -add_ydb_test(NAME basic-example +add_ydb_test(NAME basic-example GTEST SOURCES main.cpp basic_example_data.cpp @@ -9,7 +9,6 @@ add_ydb_test(NAME basic-example YDB-CPP-SDK::Driver YDB-CPP-SDK::Proto YDB-CPP-SDK::Table - GTest::gtest_main LABELS integration ) diff --git a/tests/integration/bulk_upsert/CMakeLists.txt b/tests/integration/bulk_upsert/CMakeLists.txt index 1dbed97089..05a141963f 100644 --- a/tests/integration/bulk_upsert/CMakeLists.txt +++ b/tests/integration/bulk_upsert/CMakeLists.txt @@ -1,4 +1,4 @@ -add_ydb_test(NAME bulk_upsert +add_ydb_test(NAME bulk_upsert GTEST SOURCES main.cpp bulk_upsert.cpp @@ -6,7 +6,6 @@ add_ydb_test(NAME bulk_upsert LINK_LIBRARIES yutil YDB-CPP-SDK::Table - GTest::gtest_main LABELS integration ) diff --git a/tests/integration/server_restart/CMakeLists.txt b/tests/integration/server_restart/CMakeLists.txt index 37fab1cd77..2420bae608 100644 --- a/tests/integration/server_restart/CMakeLists.txt +++ b/tests/integration/server_restart/CMakeLists.txt @@ -1,4 +1,4 @@ -add_ydb_test(NAME server_restart +add_ydb_test(NAME server_restart GTEST SOURCES main.cpp LINK_LIBRARIES @@ -6,7 +6,6 @@ add_ydb_test(NAME server_restart api-grpc YDB-CPP-SDK::Query gRPC::grpc++ - GTest::gtest_main LABELS integration ) diff --git a/tests/unit/client/CMakeLists.txt b/tests/unit/client/CMakeLists.txt index 78778d8d13..f38938b7f9 100644 --- a/tests/unit/client/CMakeLists.txt +++ b/tests/unit/client/CMakeLists.txt @@ -3,7 +3,6 @@ add_ydb_test(NAME client-ydb_coordination_ut coordination/coordination_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main YDB-CPP-SDK::Coordination api-grpc LABELS @@ -15,7 +14,6 @@ add_ydb_test(NAME client-extensions-discovery_mutator_ut discovery_mutator/discovery_mutator_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main YDB-CPP-SDK::DiscoveryMutator YDB-CPP-SDK::Table LABELS @@ -27,7 +25,6 @@ add_ydb_test(NAME client-ydb_driver_ut driver/driver_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main YDB-CPP-SDK::Driver YDB-CPP-SDK::Table LABELS @@ -41,7 +38,6 @@ add_ydb_test(NAME client-impl-ydb_endpoints_ut endpoints/endpoints_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main client-impl-ydb_endpoints LABELS unit @@ -53,7 +49,6 @@ add_ydb_test(NAME client-oauth2_ut oauth2_token_exchange/jwt_token_source_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main http-server json string_utils-base64 @@ -62,40 +57,34 @@ add_ydb_test(NAME client-oauth2_ut unit ) -# add_ydb_test(NAME client-ydb_params_ut -# SOURCES -# params/params_ut.cpp -# LINK_LIBRARIES -# yutil -# cpp-testing-unittest_main -# YDB-CPP-SDK::Params -# YDB-CPP-SDK::YsonValue -# LABELS -# unit -# ) +add_ydb_test(NAME client-ydb_params_ut GTEST + SOURCES + params/params_ut.cpp + LINK_LIBRARIES + yutil + YDB-CPP-SDK::Params + LABELS + unit +) add_ydb_test(NAME client-ydb_result_ut SOURCES result/result_ut.cpp LINK_LIBRARIES yutil - cpp-testing-unittest_main YDB-CPP-SDK::Result YDB-CPP-SDK::Params LABELS unit ) -# add_ydb_test(NAME client-ydb_value_ut -# SOURCES -# value/value_ut.cpp -# LINK_LIBRARIES -# yutil -# cpp-testing-unittest_main -# YDB-CPP-SDK::Value -# YDB-CPP-SDK::JsonValue -# YDB-CPP-SDK::YsonValue -# YDB-CPP-SDK::Params -# LABELS -# unit -# ) +add_ydb_test(NAME client-ydb_value_ut GTEST + SOURCES + value/value_ut.cpp + LINK_LIBRARIES + yutil + YDB-CPP-SDK::Value + YDB-CPP-SDK::Params + LABELS + unit +)