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>
10#include "messages.pb.h"
13USERVER_NAMESPACE_BEGIN
15namespace proto_structs::tests {
17TEST(MessageToStruct, Empty) {
21 ASSERT_NO_THROW(MessageToStruct(msg, obj));
22 ASSERT_NO_THROW((obj = MessageToStruct<structs::
Empty>(msg)));
25TEST(MessageToStruct, Scalar) {
29 msg.set_f2(std::numeric_limits<int32_t>::min());
30 msg.set_f3(std::numeric_limits<uint32_t>::max());
31 msg.set_f4(std::numeric_limits<int64_t>::min());
32 msg.set_f5(std::numeric_limits<uint64_t>::max());
33 msg.set_f6(
static_cast<
float>(1.5));
37 msg.set_f10(messages::TestEnum::TEST_ENUM_VALUE1);
40 auto obj = MessageToStruct<structs::
Scalar>(msg);
42 CheckScalarEqual(obj, msg);
49 CheckScalarEqual(obj, msg);
56 ASSERT_NO_THROW(MessageToStruct(msg, obj));
57 CheckScalarEqual(obj, msg);
63 ASSERT_NO_THROW(MessageToStruct(msg, obj));
64 CheckScalarEqual(obj, msg);
72 auto result = MessageToStruct<structs::
Scalar>(msg);
73 FAIL() <<
"exception should be thrown";
74 }
catch (
const ups::ReadError& e) {
75 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Scalar.f11'"));
77 FAIL() <<
"unexpected exception type";
82TEST(MessageToStruct, WellKnownStd) {
83 auto CreateValid = []() {
84 messages::WellKnownStd msg;
85 msg.mutable_f3()->set_year(1);
86 msg.mutable_f3()->set_month(1);
87 msg.mutable_f3()->set_day(1);
91 ASSERT_NO_THROW(
static_cast<
void>(MessageToStruct<structs::
WellKnownStd>(CreateValid())));
94 messages::WellKnownStd msg;
95 *msg.mutable_f1() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(123'456'789'987'654'321LL);
96 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(987'654'321'123'456'789LL);
97 msg.mutable_f3()->set_year(2025);
98 msg.mutable_f3()->set_month(8);
99 msg.mutable_f3()->set_day(27);
100 msg.mutable_f4()->set_hours(19);
101 msg.mutable_f4()->set_minutes(30);
102 msg.mutable_f4()->set_seconds(50);
103 msg.mutable_f4()->set_nanos(123'456'789);
107 CheckWellKnownStdEqual(obj, msg);
111 messages::WellKnownStd msg = CreateValid();
114 *msg.mutable_f1() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(-987'654'321'123'456'789LL);
115 obj.f1 = std::chrono::system_clock::now();
116 obj.f2 = std::chrono::milliseconds(1001);
118 ASSERT_NO_THROW(MessageToStruct(msg, obj));
119 CheckWellKnownStdEqual(obj, msg);
121 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
122 msg.mutable_f4()->set_hours(24);
123 msg.mutable_f4()->set_minutes(0);
124 msg.mutable_f4()->set_seconds(0);
125 msg.mutable_f4()->set_nanos(0);
127 ASSERT_NO_THROW(MessageToStruct(msg, obj));
128 CheckWellKnownStdEqual(obj, msg);
132 messages::WellKnownStd msg = CreateValid();
133 msg.mutable_f1()->set_nanos(1'999'999'999);
136 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)); },
137 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownStd.f1'"))
142 messages::WellKnownStd msg = CreateValid();
143 msg.mutable_f2()->set_nanos(-1'999'999'999);
146 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)); },
147 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownStd.f2'"))
152 messages::WellKnownStd msg = CreateValid();
153 msg.mutable_f3()->set_day(0);
156 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)); },
157 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownStd.f3'"))
162 messages::WellKnownStd msg = CreateValid();
163 msg.mutable_f4()->set_seconds(60);
166 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownStd>(msg)); },
167 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownStd.f4'"))
172TEST(MessageToStruct, WellKnownUsrv) {
173 auto CreateValid = []() {
174 messages::WellKnownUsrv msg;
175 msg.mutable_f7()->set_value(
"0.000");
179 ASSERT_NO_THROW(
static_cast<
void>(MessageToStruct<structs::
WellKnownUsrv>(CreateValid())));
182 messages::WellKnownUsrv msg;
183 messages::Simple any_payload;
185 any_payload.set_f1(100);
187 ASSERT_TRUE(msg.mutable_f1()->PackFrom(any_payload));
188 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(123'456'789'987'654'321LL);
189 *msg.mutable_f3() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(987'654'321'123'456'789LL);
190 msg.mutable_f4()->set_year(2025);
191 msg.mutable_f4()->set_month(8);
192 msg.mutable_f4()->set_day(27);
193 msg.mutable_f5()->set_hours(19);
194 msg.mutable_f5()->set_minutes(30);
195 msg.mutable_f5()->set_seconds(50);
196 msg.mutable_f5()->set_nanos(123'456'789);
197 msg.mutable_f6()->set_hours(2);
198 msg.mutable_f6()->set_minutes(10);
199 msg.mutable_f6()->set_seconds(11);
200 msg.mutable_f6()->set_nanos(987'654'321);
201 msg.mutable_f7()->set_value(
"1.123");
205 CheckWellKnownUsrvEqual(obj, msg);
206 CheckSimpleEqual(obj.f1.Unpack<structs::
Simple>(), any_payload);
210 messages::WellKnownUsrv msg = CreateValid();
212 messages::Simple any_payload;
214 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToTimestamp(-987'654'321'123'456'789LL);
215 msg.mutable_f7()->set_value(
"1001.001");
216 obj.f1.Pack<structs::
Scalar>({.f10 = structs::TestEnum::kValue1});
217 obj.f2 = std::chrono::system_clock::now();
218 obj.f3 = std::chrono::milliseconds(1001);
220 ASSERT_NO_THROW(MessageToStruct(msg, obj));
221 CheckWellKnownUsrvEqual(obj, msg);
223 any_payload.set_f1(5);
224 ASSERT_TRUE(msg.mutable_f1()->PackFrom(any_payload));
226 *msg.mutable_f3() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
227 msg.mutable_f5()->set_hours(24);
228 msg.mutable_f5()->set_minutes(0);
229 msg.mutable_f5()->set_seconds(0);
230 msg.mutable_f5()->set_nanos(0);
231 msg.mutable_f7()->set_value(
"-1001.001");
233 ASSERT_NO_THROW(MessageToStruct(msg, obj));
234 CheckWellKnownUsrvEqual(obj, msg);
235 CheckSimpleEqual(obj.f1.Unpack<structs::
Simple>(), any_payload);
239 messages::WellKnownUsrv msg = CreateValid();
240 msg.mutable_f2()->set_nanos(1'999'999'999);
243 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
244 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f2'"))
249 messages::WellKnownUsrv msg = CreateValid();
250 msg.mutable_f3()->set_nanos(-1'999'999'999);
253 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
254 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f3'"))
259 messages::WellKnownUsrv msg = CreateValid();
260 msg.mutable_f4()->set_year(10'000);
263 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
264 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f4'"))
269 messages::WellKnownUsrv msg = CreateValid();
270 msg.mutable_f5()->set_hours(-1);
273 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
274 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f5'"))
279 messages::WellKnownUsrv msg = CreateValid();
280 msg.mutable_f6()->set_hours(24);
283 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
284 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f6'"))
288 msg.mutable_f6()->set_seconds(60);
291 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
292 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f6'"))
297 messages::WellKnownUsrv msg = CreateValid();
298 msg.mutable_f7()->set_value(
"");
301 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
302 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f7'"))
306 msg.mutable_f7()->set_value(
"1.1234");
309 [&msg]() {
static_cast<
void>(MessageToStruct<structs::WellKnownUsrv>(msg)); },
310 ::testing::ThrowsMessage<ReadError>(::testing::HasSubstr(
"'messages.WellKnownUsrv.f7'"))
315TEST(MessageToStruct, Optional) {
317 messages::Optional msg;
320 msg.set_f3(messages::TestEnum::TEST_ENUM_VALUE1);
321 msg.mutable_f4()->set_f1(10);
323 auto obj = MessageToStruct<structs::
Optional>(msg);
325 CheckOptionalEqual(obj, msg);
329 messages::Optional msg;
332 CheckOptionalEqual(obj, msg);
335 msg.mutable_f4()->set_f1(13);
337 obj.f3 = structs::TestEnum::kValue2;
340 ASSERT_NO_THROW(MessageToStruct(msg, obj));
341 CheckOptionalEqual(obj, msg);
345 ASSERT_NO_THROW(MessageToStruct(msg, obj));
346 CheckOptionalEqual(obj, msg);
350TEST(MessageToStruct, Repeated) {
352 messages::Repeated msg;
358 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE1);
359 msg.add_f3(messages::TestEnum::TEST_ENUM_UNSPECIFIED);
360 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE2);
361 msg.add_f3(
static_cast<messages::TestEnum>(1001));
362 msg.mutable_f4()->Add()->set_f1(1000);
363 msg.mutable_f4()->Add()->set_f1(1001);
365 auto obj = MessageToStruct<structs::
Repeated>(msg);
367 CheckRepeatedEqual(obj, msg);
371 messages::Repeated msg;
374 CheckRepeatedEqual(obj, msg);
377 msg.mutable_f4()->Add()->set_f1(13);
380 obj.f4 = {{.f1 = 5}};
382 ASSERT_NO_THROW(MessageToStruct(msg, obj));
383 CheckRepeatedEqual(obj, msg);
387 ASSERT_NO_THROW(MessageToStruct(msg, obj));
388 CheckRepeatedEqual(obj, msg);
392TEST(MessageToStruct, Map) {
395 (*msg.mutable_f1())[5] = 15;
396 (*msg.mutable_f1())[6] = 16;
397 (*msg.mutable_f1())[7] = 17;
398 (*msg.mutable_f2())[
"key1"] =
"value1";
399 (*msg.mutable_f2())[
"key2"] =
"value2";
400 (*msg.mutable_f3())[
false] = messages::TestEnum::TEST_ENUM_UNSPECIFIED;
401 (*msg.mutable_f3())[
true] = messages::TestEnum::TEST_ENUM_VALUE2;
402 (*msg.mutable_f4())[
"simple1"].set_f1(1001);
403 (*msg.mutable_f4())[
"simple2"].set_f1(1002);
405 auto obj = MessageToStruct<structs::
Map>(msg);
407 CheckMapEqual(obj, msg);
414 CheckMapEqual(obj, msg);
416 (*msg.mutable_f1())[5] = 15;
417 (*msg.mutable_f4())[
"simple1"].set_f1(1001);
418 obj.f1 = {{1, 1}, {2, 2}, {3, 3}};
419 obj.f2 = {{
"key1",
"value1"}};
420 obj.f4 = {{
"simple1", {.f1 = 5}}};
422 ASSERT_NO_THROW(MessageToStruct(msg, obj));
423 CheckMapEqual(obj, msg);
425 (*msg.mutable_f2())[
"key2"] =
"value2";
427 ASSERT_NO_THROW(MessageToStruct(msg, obj));
428 CheckMapEqual(obj, msg);
432TEST(MessageToStruct, Oneof) {
437 auto obj = MessageToStruct<structs::
Oneof>(msg);
439 CheckOneofEqual(obj, msg);
446 CheckOneofEqual(obj, msg);
449 obj.test_oneof.Set<0>(1);
451 ASSERT_NO_THROW(MessageToStruct(msg, obj));
452 CheckOneofEqual(obj, msg);
454 msg.set_f3(messages::TestEnum::TEST_ENUM_UNSPECIFIED);
456 ASSERT_NO_THROW(MessageToStruct(msg, obj));
457 CheckOneofEqual(obj, msg);
459 msg.mutable_f4()->set_f1(1001);
461 ASSERT_NO_THROW(MessageToStruct(msg, obj));
462 CheckOneofEqual(obj, msg);
466TEST(MessageToStruct, Indirect) {
468 messages::Indirect msg;
469 msg.mutable_f1()->set_f1(1);
470 *msg.mutable_f2() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(123'456'789'987'654'321LL);
471 msg.mutable_f3()->Add()->set_f1(3);
472 msg.mutable_f3()->Add()->set_f1(4);
473 (*msg.mutable_f4())[1].set_f1(5);
474 (*msg.mutable_f4())[2].set_f1(6);
475 msg.mutable_f5()->set_f1(7);
477 msg.add_f8(messages::TEST_ENUM_UNSPECIFIED);
478 (*msg.mutable_f9())[
"3"].set_f1(8);
480 auto obj = MessageToStruct<structs::
Indirect>(msg);
482 CheckIndirectEqual(obj, msg);
486 messages::Indirect msg;
489 CheckIndirectEqual(obj, msg);
491 msg.mutable_f1()->set_f1(10);
492 msg.mutable_f3()->Add()->set_f1(11);
494 obj.f1 = {.f1 = 1001};
495 obj.f4 = {{10, structs::
Simple{.f1 = 1002}}};
496 obj.test_oneof.Set<0>(structs::
Simple{.f1 = 30});
498 ASSERT_NO_THROW(MessageToStruct(msg, obj));
499 CheckIndirectEqual(obj, msg);
501 msg.mutable_f5()->set_f1(12);
502 msg.add_f8(messages::TEST_ENUM_VALUE2);
503 msg.add_f8(messages::TEST_ENUM_VALUE1);
504 obj.test_oneof.Set<0>(structs::
Simple{.f1 = 1003});
506 ASSERT_NO_THROW(MessageToStruct(msg, obj));
507 CheckIndirectEqual(obj, msg);
511TEST(MessageToStruct, Strong) {
513 messages::Strong msg;
516 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE1);
517 msg.add_f3(messages::TestEnum::TEST_ENUM_VALUE2);
518 (*msg.mutable_f4())[1].set_f1(1002);
519 (*msg.mutable_f4())[2].set_f1(1003);
520 *msg.mutable_f5() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(123'456'789'987'654'321LL);
522 auto obj = MessageToStruct<structs::
Strong>(msg);
524 CheckStrongEqual(obj, msg);
528 messages::Strong msg;
531 CheckStrongEqual(obj, msg);
534 *msg.mutable_f5() = ::google::protobuf::util::TimeUtil::NanosecondsToDuration(-123'456'789'987'654'321LL);
535 obj.f1 = structs::Strong::F1Strong{5};
536 obj.f4[100] = structs::Strong::F4Strong{structs::Simple{.f1 = 6}};
538 ASSERT_NO_THROW(MessageToStruct(msg, obj));
539 CheckStrongEqual(obj, msg);
542 obj.test_oneof.Set<0>(structs::Strong::F5Strong{std::chrono::nanoseconds{123'456'789'987'654'321}});
544 ASSERT_NO_THROW(MessageToStruct(msg, obj));
545 CheckStrongEqual(obj, msg);
549TEST(MessageToStruct, Erroneous) {
551 messages::Erroneous msg;
554 EXPECT_NO_THROW(obj = MessageToStruct<structs::
Erroneous>(msg));
558 messages::Erroneous msg;
559 msg.mutable_f1()->set_error_type(messages::ConversionFailure::TYPE_EXCEPTION);
562 auto result = MessageToStruct<structs::
Erroneous>(msg);
563 FAIL() <<
"exception should be thrown";
564 }
catch (
const ups::ReadError& e) {
565 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f1'"));
566 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_exception"));
568 FAIL() <<
"unexpected exception type";
573 messages::Erroneous msg;
574 msg.mutable_f2()->Add()->set_error_type(messages::ConversionFailure::TYPE_ERROR);
577 auto result = MessageToStruct<structs::
Erroneous>(msg);
578 FAIL() <<
"exception should be thrown";
579 }
catch (
const ups::ReadError& e) {
580 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f2.error_field'"));
581 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error"));
583 FAIL() <<
"unexpected exception type";
588 messages::Erroneous msg;
589 (*msg.mutable_f3())[10].set_error_type(messages::ConversionFailure::TYPE_ERROR_WITH_UNKNOWN_FIELD);
592 auto result = MessageToStruct<structs::
Erroneous>(msg);
593 FAIL() <<
"exception should be thrown";
594 }
catch (
const ups::ReadError& e) {
595 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f3.<unknown_1001>'"));
596 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error_with_unknown_field"));
598 FAIL() <<
"unexpected exception type";
603 messages::Erroneous msg;
604 msg.mutable_f4()->set_error_type(messages::ConversionFailure::TYPE_ERROR_WITH_UNKNOWN_FIELD);
607 auto result = MessageToStruct<structs::
Erroneous>(msg);
608 FAIL() <<
"exception should be thrown";
609 }
catch (
const ups::ReadError& e) {
610 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"'messages.Erroneous.f4.<unknown_1001>'"));
611 EXPECT_THAT(e.what(), ::testing::HasSubstr(
"conversion_failure_error_with_unknown_field"));
613 FAIL() <<
"unexpected exception type";