1#include <gmock/gmock.h>
2#include <gtest/gtest.h>
6#include <google/protobuf/util/time_util.h>
8#include <userver/proto-structs/convert.hpp>
9#include <userver/utest/assert_macros.hpp>
11#include "messages.pb.h"
14USERVER_NAMESPACE_BEGIN
16namespace proto_structs::tests {
18TEST(MessageToStruct, Empty) {
22 UASSERT_NO_THROW(MessageToStruct(msg, obj));
23 UASSERT_NO_THROW((obj = MessageToStruct<structs::
Empty>(msg)));
26TEST(MessageToStruct, Scalar) {
30 msg.set_f2(std::numeric_limits<int32_t>::min());
31 msg.set_f3(std::numeric_limits<uint32_t>::max());
32 msg.set_f4(std::numeric_limits<int64_t>::min());
33 msg.set_f5(std::numeric_limits<uint64_t>::max());
34 msg.set_f6(
static_cast<
float>(1.5));
38 msg.set_f10(messages::TestEnum::TEST_ENUM_VALUE1);
41 auto obj = MessageToStruct<structs::
Scalar>(msg);
43 CheckScalarEqual(obj, msg);
50 CheckScalarEqual(obj, msg);
57 UASSERT_NO_THROW(MessageToStruct(msg, obj));
58 CheckScalarEqual(obj, msg);
64 UASSERT_NO_THROW(MessageToStruct(msg, obj));
65 CheckScalarEqual(obj, msg);
72 UEXPECT_THROW_MSG(
static_cast<
void>(MessageToStruct<structs::Scalar>(msg)), ReadError,
"'messages.Scalar.f11'");
76TEST(MessageToStruct, WellKnownStd) {
77 auto create_valid = []() {
78 messages::WellKnownStd msg;
79 msg.mutable_f3()->set_year(1);
80 msg.mutable_f3()->set_month(1);
81 msg.mutable_f3()->set_day(1);
85 UASSERT_NO_THROW(
static_cast<
void>(MessageToStruct<structs::
WellKnownStd>(create_valid())));
88 messages::WellKnownStd msg;
89 *msg.mutable_f1() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(123'456'789'987'654'321LL);
90 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(987'654'321'123'456'789LL);
91 msg.mutable_f3()->set_year(2025);
92 msg.mutable_f3()->set_month(8);
93 msg.mutable_f3()->set_day(27);
94 msg.mutable_f4()->set_hours(19);
95 msg.mutable_f4()->set_minutes(30);
96 msg.mutable_f4()->set_seconds(50);
97 msg.mutable_f4()->set_nanos(123'456'789);
101 CheckWellKnownStdEqual(obj, msg);
105 messages::WellKnownStd msg = create_valid();
108 *msg.mutable_f1() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(-987'654'321'123'456'789LL);
109 obj.f1 = std::chrono::system_clock::now();
110 obj.f2 = std::chrono::milliseconds(1001);
112 UASSERT_NO_THROW(MessageToStruct(msg, obj));
113 CheckWellKnownStdEqual(obj, msg);
115 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
116 msg.mutable_f4()->set_hours(24);
117 msg.mutable_f4()->set_minutes(0);
118 msg.mutable_f4()->set_seconds(0);
119 msg.mutable_f4()->set_nanos(0);
121 UASSERT_NO_THROW(MessageToStruct(msg, obj));
122 CheckWellKnownStdEqual(obj, msg);
126 messages::WellKnownStd msg = create_valid();
127 msg.mutable_f1()->set_nanos(1'999'999'999);
130 static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)),
132 "'messages.WellKnownStd.f1'"
137 messages::WellKnownStd msg = create_valid();
138 msg.mutable_f2()->set_nanos(-1'999'999'999);
141 static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)),
143 "'messages.WellKnownStd.f2'"
148 messages::WellKnownStd msg = create_valid();
149 msg.mutable_f3()->set_day(0);
152 static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)),
154 "'messages.WellKnownStd.f3'"
159 messages::WellKnownStd msg = create_valid();
160 msg.mutable_f4()->set_seconds(60);
163 static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)),
165 "'messages.WellKnownStd.f4'"
170TEST(MessageToStruct, WellKnownUsrv) {
171 auto create_valid = []() {
172 messages::WellKnownUsrv msg;
173 msg.mutable_f7()->set_value(
"0.000");
177 UASSERT_NO_THROW(
static_cast<
void>(MessageToStruct<structs::
WellKnownUsrv>(create_valid())));
180 messages::WellKnownUsrv msg;
181 messages::Simple any_payload;
183 any_payload.set_f1(100);
185 ASSERT_TRUE(msg.mutable_f1()->PackFrom(any_payload));
186 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(123'456'789'987'654'321LL);
187 *msg.mutable_f3() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(987'654'321'123'456'789LL);
188 msg.mutable_f4()->set_year(2025);
189 msg.mutable_f4()->set_month(8);
190 msg.mutable_f4()->set_day(27);
191 msg.mutable_f5()->set_hours(19);
192 msg.mutable_f5()->set_minutes(30);
193 msg.mutable_f5()->set_seconds(50);
194 msg.mutable_f5()->set_nanos(123'456'789);
195 msg.mutable_f6()->set_hours(2);
196 msg.mutable_f6()->set_minutes(10);
197 msg.mutable_f6()->set_seconds(11);
198 msg.mutable_f6()->set_nanos(987'654'321);
199 msg.mutable_f7()->set_value(
"1.123");
203 CheckWellKnownUsrvEqual(obj, msg);
204 CheckSimpleEqual(obj.f1.Unpack<structs::
Simple>(), any_payload);
208 messages::WellKnownUsrv msg = create_valid();
210 messages::Simple any_payload;
212 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(-987'654'321'123'456'789LL);
213 msg.mutable_f7()->set_value(
"1001.001");
214 obj.f1.Pack<structs::
Scalar>({.f10 = structs::TestEnum::kValue1});
215 obj.f2 = std::chrono::system_clock::now();
216 obj.f3 = std::chrono::milliseconds(1001);
218 UASSERT_NO_THROW(MessageToStruct(msg, obj));
219 CheckWellKnownUsrvEqual(obj, msg);
221 any_payload.set_f1(5);
222 ASSERT_TRUE(msg.mutable_f1()->PackFrom(any_payload));
224 *msg.mutable_f3() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
225 msg.mutable_f5()->set_hours(24);
226 msg.mutable_f5()->set_minutes(0);
227 msg.mutable_f5()->set_seconds(0);
228 msg.mutable_f5()->set_nanos(0);
229 msg.mutable_f7()->set_value(
"-1001.001");
231 UASSERT_NO_THROW(MessageToStruct(msg, obj));
232 CheckWellKnownUsrvEqual(obj, msg);
233 CheckSimpleEqual(obj.f1.Unpack<structs::
Simple>(), any_payload);
237 messages::WellKnownUsrv msg = create_valid();
238 msg.mutable_f2()->set_nanos(1'999'999'999);
241 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
243 "'messages.WellKnownUsrv.f2'"
248 messages::WellKnownUsrv msg = create_valid();
249 msg.mutable_f3()->set_nanos(-1'999'999'999);
252 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
254 "'messages.WellKnownUsrv.f3'"
259 messages::WellKnownUsrv msg = create_valid();
260 msg.mutable_f4()->set_year(10'000);
263 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
265 "'messages.WellKnownUsrv.f4'"
270 messages::WellKnownUsrv msg = create_valid();
271 msg.mutable_f5()->set_hours(-1);
274 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
276 "'messages.WellKnownUsrv.f5'"
281 messages::WellKnownUsrv msg = create_valid();
282 msg.mutable_f6()->set_hours(24);
285 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
287 "'messages.WellKnownUsrv.f6'"
290 msg = create_valid();
291 msg.mutable_f6()->set_seconds(60);
294 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
296 "'messages.WellKnownUsrv.f6'"
301 messages::WellKnownUsrv msg = create_valid();
302 msg.mutable_f7()->set_value(
"");
305 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
307 "'messages.WellKnownUsrv.f7'"
311 msg.mutable_f7()->set_value(
"1.1234");
314 static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)),
316 "'messages.WellKnownUsrv.f7'"
321TEST(MessageToStruct, WellKnownJson) {
322 auto create_valid = []() {
323 messages::WellKnownJson msg;
324 msg.mutable_f1()->set_null_value(::google::protobuf::NULL_VALUE);
328 auto create_list = [](
double num,
const std::string& str,
bool b) {
329 ::google::protobuf::ListValue list;
330 list.add_values()->set_null_value(::google::protobuf::NULL_VALUE);
331 list.add_values()->set_number_value(num);
332 list.add_values()->set_string_value(str);
333 list.add_values()->set_bool_value(b);
337 auto create_struct = [](
double num,
const std::string& str,
bool b) {
338 ::google::protobuf::Struct obj;
339 (*obj.mutable_fields())[
"key0"].set_null_value(::google::protobuf::NULL_VALUE);
340 (*obj.mutable_fields())[
"key1"].set_number_value(num);
341 (*obj.mutable_fields())[
"key2"].set_string_value(str);
342 (*obj.mutable_fields())[
"key3"].set_bool_value(b);
346 UASSERT_NO_THROW(
static_cast<
void>(MessageToStruct<structs::
WellKnownJson>(create_valid())));
349 messages::WellKnownJson msg = create_valid();
352 CheckWellKnownJsonEqual(obj, msg);
356 messages::WellKnownJson msg;
357 *(msg.mutable_f1()->mutable_list_value()) = create_list(1,
"test",
true);
360 CheckWellKnownJsonEqual(obj, msg);
364 messages::WellKnownJson msg;
365 *(msg.mutable_f1()->mutable_struct_value()) = create_struct(5,
"test2",
false);
368 CheckWellKnownJsonEqual(obj, msg);
372 messages::WellKnownJson msg;
373 msg.mutable_f1()->set_number_value(1001);
374 *msg.mutable_f2() = create_list(10,
"hello",
false);
375 *msg.mutable_f3() = create_struct(20,
"world",
true);
379 CheckWellKnownJsonEqual(obj, msg);
383 messages::WellKnownJson msg;
384 *msg.mutable_f1()->mutable_list_value()->add_values()->mutable_list_value() = create_list(5,
"hi",
true);
387 CheckWellKnownJsonEqual(obj, msg);
391 messages::WellKnownJson msg;
392 auto& top = *msg.mutable_f1()->mutable_struct_value()->mutable_fields();
393 *top[
"top"].mutable_struct_value() = create_struct(6,
"bonjour",
false);
396 CheckWellKnownJsonEqual(obj, msg);
400 messages::WellKnownJson msg = create_valid();
401 msg.mutable_f2()->add_values();
404 static_cast<
void>(MessageToStruct<structs::WellKnownJson>(msg)),
406 "'messages.WellKnownJson.f2'"
411 messages::WellKnownJson msg = create_valid();
412 static_cast<
void>((*msg.mutable_f3()->mutable_fields())[
"key"]);
415 static_cast<
void>(MessageToStruct<structs::WellKnownJson>(msg)),
417 "'messages.WellKnownJson.f3'"
422TEST(MessageToStruct, Optional) {
424 messages::Optional msg;
427 msg.set_f3(messages::TestEnum::TEST_ENUM_VALUE1);
428 msg.mutable_f4()->set_f1(10);
430 auto obj = MessageToStruct<structs::
Optional>(msg);
432 CheckOptionalEqual(obj, msg);
436 messages::Optional msg;
439 CheckOptionalEqual(obj, msg);
442 msg.mutable_f4()->set_f1(13);
444 obj.f3 = structs::TestEnum::kValue2;
447 UASSERT_NO_THROW(MessageToStruct(msg, obj));
448 CheckOptionalEqual(obj, msg);
452 UASSERT_NO_THROW(MessageToStruct(msg, obj));
453 CheckOptionalEqual(obj, msg);
457TEST(MessageToStruct, Repeated) {
459 messages::Repeated msg;
465 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE1);
466 msg.add_f3(messages::TestEnum::TEST_ENUM_UNSPECIFIED);
467 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE2);
468 msg.add_f3(
static_cast<messages::TestEnum>(1001));
469 msg.mutable_f4()->Add()->set_f1(1000);
470 msg.mutable_f4()->Add()->set_f1(1001);
472 auto obj = MessageToStruct<structs::
Repeated>(msg);
474 CheckRepeatedEqual(obj, msg);
478 messages::Repeated msg;
481 CheckRepeatedEqual(obj, msg);
484 msg.mutable_f4()->Add()->set_f1(13);
487 obj.f4 = {{.f1 = 5}};
489 UASSERT_NO_THROW(MessageToStruct(msg, obj));
490 CheckRepeatedEqual(obj, msg);
494 UASSERT_NO_THROW(MessageToStruct(msg, obj));
495 CheckRepeatedEqual(obj, msg);
499TEST(MessageToStruct, Map) {
502 (*msg.mutable_f1())[5] = 15;
503 (*msg.mutable_f1())[6] = 16;
504 (*msg.mutable_f1())[7] = 17;
505 (*msg.mutable_f2())[
"key1"] =
"value1";
506 (*msg.mutable_f2())[
"key2"] =
"value2";
507 (*msg.mutable_f3())[
false] = messages::TestEnum::TEST_ENUM_UNSPECIFIED;
508 (*msg.mutable_f3())[
true] = messages::TestEnum::TEST_ENUM_VALUE2;
509 (*msg.mutable_f4())[
"simple1"].set_f1(1001);
510 (*msg.mutable_f4())[
"simple2"].set_f1(1002);
512 auto obj = MessageToStruct<structs::
Map>(msg);
514 CheckMapEqual(obj, msg);
521 CheckMapEqual(obj, msg);
523 (*msg.mutable_f1())[5] = 15;
524 (*msg.mutable_f4())[
"simple1"].set_f1(1001);
525 obj.f1 = {{1, 1}, {2, 2}, {3, 3}};
526 obj.f2 = {{
"key1",
"value1"}};
527 obj.f4 = {{
"simple1", {.f1 = 5}}};
529 UASSERT_NO_THROW(MessageToStruct(msg, obj));
530 CheckMapEqual(obj, msg);
532 (*msg.mutable_f2())[
"key2"] =
"value2";
534 UASSERT_NO_THROW(MessageToStruct(msg, obj));
535 CheckMapEqual(obj, msg);
539TEST(MessageToStruct, Oneof) {
544 auto obj = MessageToStruct<structs::
Oneof>(msg);
546 CheckOneofEqual(obj, msg);
553 CheckOneofEqual(obj, msg);
556 obj.test_oneof.Set<0>(1);
558 UASSERT_NO_THROW(MessageToStruct(msg, obj));
559 CheckOneofEqual(obj, msg);
561 msg.set_f3(messages::TestEnum::TEST_ENUM_UNSPECIFIED);
563 UASSERT_NO_THROW(MessageToStruct(msg, obj));
564 CheckOneofEqual(obj, msg);
566 msg.mutable_f4()->set_f1(1001);
568 UASSERT_NO_THROW(MessageToStruct(msg, obj));
569 CheckOneofEqual(obj, msg);
573TEST(MessageToStruct, Indirect) {
575 messages::Indirect msg;
576 msg.mutable_f1()->set_f1(1);
577 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(123'456'789'987'654'321LL);
578 msg.mutable_f3()->Add()->set_f1(3);
579 msg.mutable_f3()->Add()->set_f1(4);
580 (*msg.mutable_f4())[1].set_f1(5);
581 (*msg.mutable_f4())[2].set_f1(6);
582 msg.mutable_f5()->set_f1(7);
584 msg.add_f8(messages::TEST_ENUM_UNSPECIFIED);
585 (*msg.mutable_f9())[
"3"].set_f1(8);
587 auto obj = MessageToStruct<structs::
Indirect>(msg);
589 CheckIndirectEqual(obj, msg);
593 messages::Indirect msg;
596 CheckIndirectEqual(obj, msg);
598 msg.mutable_f1()->set_f1(10);
599 msg.mutable_f3()->Add()->set_f1(11);
601 obj.f1 = {.f1 = 1001};
602 obj.f4 = {{10, structs::
Simple{.f1 = 1002}}};
603 obj.test_oneof.Set<0>(structs::
Simple{.f1 = 30});
605 UASSERT_NO_THROW(MessageToStruct(msg, obj));
606 CheckIndirectEqual(obj, msg);
608 msg.mutable_f5()->set_f1(12);
609 msg.add_f8(messages::TEST_ENUM_VALUE2);
610 msg.add_f8(messages::TEST_ENUM_VALUE1);
611 obj.test_oneof.Set<0>(structs::
Simple{.f1 = 1003});
613 UASSERT_NO_THROW(MessageToStruct(msg, obj));
614 CheckIndirectEqual(obj, msg);
618TEST(MessageToStruct, Strong) {
620 messages::Strong msg;
623 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE1);
624 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE2);
625 (*msg.mutable_f4())[1].set_f1(1002);
626 (*msg.mutable_f4())[2].set_f1(1003);
627 *msg.mutable_f5() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(123'456'789'987'654'321LL);
629 auto obj = MessageToStruct<structs::
Strong>(msg);
631 CheckStrongEqual(obj, msg);
635 messages::Strong msg;
638 CheckStrongEqual(obj, msg);
641 *msg.mutable_f5() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
642 obj.f1 = structs::Strong::F1Strong{5};
643 obj.f4[100] = structs::Strong::F4Strong{structs::Simple{.f1 = 6}};
645 UASSERT_NO_THROW(MessageToStruct(msg, obj));
646 CheckStrongEqual(obj, msg);
649 obj.test_oneof.Set<0>(structs::Strong::F5Strong{std::chrono::nanoseconds{123'456'789'987'654'321}});
651 UASSERT_NO_THROW(MessageToStruct(msg, obj));
652 CheckStrongEqual(obj, msg);
656TEST(MessageToStruct, Erroneous) {
658 messages::Erroneous msg;
661 EXPECT_NO_THROW(obj = MessageToStruct<structs::
Erroneous>(msg));
665 messages::Erroneous msg;
666 msg.mutable_f1()->set_error_type(messages::ConversionFailure::TYPE_EXCEPTION);
669 auto result = MessageToStruct<structs::
Erroneous>(msg);
670 FAIL() <<
"exception should be thrown";
671 }
catch (
const ReadError& e) {
672 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f1'"));
673 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_exception"));
675 FAIL() <<
"unexpected exception type";
680 messages::Erroneous msg;
681 msg.mutable_f2()->Add()->set_error_type(messages::ConversionFailure::TYPE_ERROR);
684 auto result = MessageToStruct<structs::
Erroneous>(msg);
685 FAIL() <<
"exception should be thrown";
686 }
catch (
const ReadError& e) {
687 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f2.error_field'"));
688 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error"));
690 FAIL() <<
"unexpected exception type";
695 messages::Erroneous msg;
696 (*msg.mutable_f3())[10].set_error_type(messages::ConversionFailure::TYPE_ERROR_WITH_UNKNOWN_FIELD);
699 auto result = MessageToStruct<structs::
Erroneous>(msg);
700 FAIL() <<
"exception should be thrown";
701 }
catch (
const ReadError& e) {
702 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f3.<unknown_1001>'"));
703 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error_with_unknown_field"));
705 FAIL() <<
"unexpected exception type";
710 messages::Erroneous msg;
711 msg.mutable_f4()->set_error_type(messages::ConversionFailure::TYPE_ERROR_WITH_UNKNOWN_FIELD);
714 auto result = MessageToStruct<structs::
Erroneous>(msg);
715 FAIL() <<
"exception should be thrown";
716 }
catch (
const ReadError& e) {
717 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f4.<unknown_1001>'"));
718 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error_with_unknown_field"));
720 FAIL() <<
"unexpected exception type";