aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralexnick <alexnick@yandex-team.ru>2022-06-16 19:14:03 +0300
committeralexnick <alexnick@yandex-team.ru>2022-06-16 19:14:03 +0300
commita6f15ab7c05a0b9968f8095bef8663d3efdd9fd5 (patch)
tree9d7eeba541a988ab80bd6f4ae6f40a6cd4aa3854
parentd43766311a9dd62501ad3b56b1495f5d5f23bd15 (diff)
downloadydb-a6f15ab7c05a0b9968f8095bef8663d3efdd9fd5.tar.gz
introduce optional values support
ref:ef87f66708060223660eb2f86c6614b865d9e569
-rw-r--r--ydb/public/lib/validation/main.cpp45
-rw-r--r--ydb/public/lib/validation/ut.cpp56
-rw-r--r--ydb/public/lib/validation/ut/protos/validation_test.proto14
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;
}
}