diff options
author | alexnick <alexnick@yandex-team.ru> | 2022-06-16 19:14:03 +0300 |
---|---|---|
committer | alexnick <alexnick@yandex-team.ru> | 2022-06-16 19:14:03 +0300 |
commit | a6f15ab7c05a0b9968f8095bef8663d3efdd9fd5 (patch) | |
tree | 9d7eeba541a988ab80bd6f4ae6f40a6cd4aa3854 | |
parent | d43766311a9dd62501ad3b56b1495f5d5f23bd15 (diff) | |
download | ydb-a6f15ab7c05a0b9968f8095bef8663d3efdd9fd5.tar.gz |
introduce optional values support
ref:ef87f66708060223660eb2f86c6614b865d9e569
-rw-r--r-- | ydb/public/lib/validation/main.cpp | 45 | ||||
-rw-r--r-- | ydb/public/lib/validation/ut.cpp | 56 | ||||
-rw-r--r-- | ydb/public/lib/validation/ut/protos/validation_test.proto | 14 |
3 files changed, 103 insertions, 12 deletions
diff --git a/ydb/public/lib/validation/main.cpp b/ydb/public/lib/validation/main.cpp index 68c4bda65cb..30058aaa728 100644 --- a/ydb/public/lib/validation/main.cpp +++ b/ydb/public/lib/validation/main.cpp @@ -52,6 +52,24 @@ private: }; // TPrinter + +bool IsScalarType(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_STRING: + return true; + default: + return false; + } + return false; +} + class TFieldGenerator: public TThrRefBase { void Required(TPrinter& printer) const { Y_VERIFY(!Field->is_repeated(), "Repeated fields cannot be required or not"); @@ -59,7 +77,7 @@ class TFieldGenerator: public TThrRefBase { if (Field->options().GetExtension(Ydb::required)) { if (Field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { printer->Print(Vars, "if ($field$().empty()) {\n"); - } else if (Field->message_type()) { + } else if (Field->has_presence()) { printer->Print(Vars, "if (!has_$field$()) {\n"); } else { Y_FAIL_S(" Field type = " << Field->type_name() << " cannot be required or not"); @@ -153,6 +171,7 @@ class TFieldGenerator: public TThrRefBase { Y_FAIL_S("Invalid value: " << annValue); } + void CheckValue(TPrinter& printer, const FieldDescriptor* field, TVariables vars) const { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: @@ -274,9 +293,18 @@ class TFieldGenerator: public TThrRefBase { void Body(TPrinter& printer) const { const auto& opts = Field->options(); + if (opts.HasExtension(Ydb::required)) { Required(printer); } + + if (Field->has_presence() && IsScalarType(Field)) { + printer->Print(Vars, "if (!has_$field$()) {\n"); + printer->Indent(); + printer->Print(Vars, "return true;\n"); + printer->Outdent(); + printer->Print(Vars, "}\n"); + } if (opts.HasExtension(Ydb::size)) { Size(printer); } @@ -515,18 +543,23 @@ public: TItems items; + for (int i = 0; i < Message->real_oneof_decl_count(); i++) { + const OneofDescriptor* oneof = Message->oneof_decl(i); + TOneofGenerator::TPtr oneofGen = new TOneofGenerator(oneof, Vars.at("class")); + items.emplace(oneof, TItem(oneofGen)); + } + for (auto i = 0; i < Message->field_count(); ++i) { const FieldDescriptor* field = Message->field(i); const OneofDescriptor* oneof = field->containing_oneof(); TFieldGenerator::TPtr fieldGen = new TFieldGenerator(field, Vars.at("class")); - TOneofGenerator::TPtr oneofGen = oneof ? new TOneofGenerator(oneof, Vars.at("class")) : nullptr; auto it = items.find(oneof); if (it == items.end()) { - it = items.emplace(oneof, TItem(oneofGen)).first; + it = items.emplace(nullptr, TItem(nullptr)).first; } - + Y_VERIFY(it != items.end()); it->second.AddField(fieldGen); } @@ -570,6 +603,10 @@ class TCodeGenerator: public CodeGenerator { return true; } + uint64 GetSupportedFeatures() const override { + return FEATURE_PROTO3_OPTIONAL; + } + }; // TCodeGenerator } // NValidation diff --git a/ydb/public/lib/validation/ut.cpp b/ydb/public/lib/validation/ut.cpp index ae736bf895a..3cbff41b821 100644 --- a/ydb/public/lib/validation/ut.cpp +++ b/ydb/public/lib/validation/ut.cpp @@ -267,22 +267,66 @@ Y_UNIT_TEST_SUITE(ValidationTests) { oneof.set_check_required("set"); } + // none of oneof values are set + UNIT_ASSERT(Validate(oneof)); + // check oneof (1) { - oneof.set_check_le_1("12"); - Validate(oneof, "length is not <="); + oneof.set_check_ge_1(""); + Validate(oneof, "length is not >="); - oneof.set_check_le_1("1"); + oneof.set_check_ge_1("22"); UNIT_ASSERT(Validate(oneof)); } // check oneof (2) { - oneof.set_check_le_2("123"); - Validate(oneof, "length is not <="); + oneof.set_check_ge_2("1"); + Validate(oneof, "length is not >="); + + oneof.set_check_ge_2("333"); + UNIT_ASSERT(Validate(oneof)); + } - oneof.set_check_le_2("12"); +/* // check oneof (3) + { + oneof.mutable_some_message(); UNIT_ASSERT(Validate(oneof)); } +*/ + } + + Y_UNIT_TEST(Optional) { + MessageOptional optional; + + + { + Validate(optional, "required but not set"); + optional.set_check_required(10); + } + + // empty is correct + UNIT_ASSERT(Validate(optional)); + + // check set incorrect value + { + optional.set_check_value_int32(0); + Validate(optional, "value is not"); + optional.set_check_value_int32(1); + } + + // check set correct value + UNIT_ASSERT(Validate(optional)); + { + + optional.set_check_length("abacaba"); + Validate(optional, "length is not in"); + optional.set_check_length("val"); + } + // check correct length + UNIT_ASSERT(Validate(optional)); + + } + } diff --git a/ydb/public/lib/validation/ut/protos/validation_test.proto b/ydb/public/lib/validation/ut/protos/validation_test.proto index f2c26ab3887..09e05711f36 100644 --- a/ydb/public/lib/validation/ut/protos/validation_test.proto +++ b/ydb/public/lib/validation/ut/protos/validation_test.proto @@ -46,6 +46,12 @@ message MessageBasic { int32 check_value_range_4 = 25 [(value) = "(1; 10)"]; } +message MessageOptional { + optional int32 check_required = 1 [(required) = true]; + optional string check_length = 2 [(length).range = {min: 1, max: 3}]; + optional int32 check_value_int32 = 3 [(value) = "> 0"]; +} + message MessageMap { map<string, string> values = 1 [(size).gt = 0, (map_key).length.lt = 2, (length).lt = 2, (map_key).value = '!= "k"', (value) = '!= "v"']; } @@ -54,7 +60,11 @@ message MessageOneof { uint32 key = 1; string check_required = 2 [(required) = true]; oneof value { - string check_le_1 = 3 [(length).le = 1]; - string check_le_2 = 4 [(length).le = 2]; + string check_ge_1 = 3 [(length).ge = 1]; + string check_ge_2 = 4 [(length).ge = 2]; + } + + message SomeMessage { + int32 some_value = 1; } } |