1#include <gtest/gtest.h>
9#include <google/protobuf/dynamic_message.h>
11#include <userver/protobuf/datetime.hpp>
12#include <userver/protobuf/json/convert.hpp>
13#include <userver/utest/assert_macros.hpp>
17USERVER_NAMESPACE_BEGIN
19namespace protobuf::json::tests {
21using namespace std::chrono_literals;
23constexpr auto kTestSeconds = 1s + 1min + 1h + 24h + (31 * 24h) + (365 * 24h);
25struct TimestampToJsonSuccessTestParam {
27 std::string expected_json = {};
28 PrintOptions options = {};
31struct TimestampToJsonFailureTestParam {
33 PrintErrorCode expected_errc = {};
34 std::string expected_path = {};
35 PrintOptions options = {};
38 bool skip_native_check =
false;
41void PrintTo(
const TimestampToJsonSuccessTestParam& param, std::ostream* os) {
42 *os << fmt::format(
"{{ input = {{.seconds={}, .nanos={}}} }}", param.input.seconds, param.input.nanos);
45void PrintTo(
const TimestampToJsonFailureTestParam& param, std::ostream* os) {
46 *os << fmt::format(
"{{ input = {{.seconds={}, .nanos={}}} }}", param.input.seconds, param.input.nanos);
49class TimestampToJsonSuccessTest :
public ::testing::TestWithParam<TimestampToJsonSuccessTestParam> {};
50class TimestampToJsonFailureTest :
public ::testing::TestWithParam<TimestampToJsonFailureTestParam> {};
52INSTANTIATE_TEST_SUITE_P(
54 TimestampToJsonSuccessTest,
56 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 0,
true}, R"({})"},
57 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 0}, R"({"field1": "1970-01-01T00:00:00Z"})"},
58 TimestampToJsonSuccessTestParam{
59 TimestampMessageData{kTestSeconds.count(), 123456789},
60 R"({"field1": "1971-02-02T01:01:01.123456789Z"})"
62 TimestampToJsonSuccessTestParam{
63 TimestampMessageData{-kTestSeconds.count(), 987654321},
64 R"({"field1": "1968-11-29T22:58:59.987654321Z"})"
66 TimestampToJsonSuccessTestParam{
67 TimestampMessageData{kMaxTimestampSeconds, kMaxTimestampNanos},
68 R"({"field1": "9999-12-31T23:59:59.999999999Z"})"
70 TimestampToJsonSuccessTestParam{
71 TimestampMessageData{kMinTimestampSeconds, kMinTimestampNanos},
72 R"({"field1": "0001-01-01T00:00:00Z"})"
74 TimestampToJsonSuccessTestParam{
75 TimestampMessageData{0, 123456780},
76 R"({"field1": "1970-01-01T00:00:00.123456780Z"})"
78 TimestampToJsonSuccessTestParam{
79 TimestampMessageData{0, 123456000},
80 R"({"field1": "1970-01-01T00:00:00.123456Z"})"
82 TimestampToJsonSuccessTestParam{
83 TimestampMessageData{0, 123400000},
84 R"({"field1": "1970-01-01T00:00:00.123400Z"})"
86 TimestampToJsonSuccessTestParam{
87 TimestampMessageData{0, 100000000},
88 R"({"field1": "1970-01-01T00:00:00.100Z"})"
90 TimestampToJsonSuccessTestParam{
91 TimestampMessageData{1456704000, 123450000},
92 R"({"field1": "2016-02-29T00:00:00.123450Z"})"
94 TimestampToJsonSuccessTestParam{TimestampMessageData{0, 9}, R"({"field1": "1970-01-01T00:00:00.000000009Z"})"}
98INSTANTIATE_TEST_SUITE_P(
100 TimestampToJsonFailureTest,
102 TimestampToJsonFailureTestParam{
103 TimestampMessageData{kMaxTimestampSeconds + 1, 0},
104 PrintErrorCode::kInvalidValue,
107 TimestampToJsonFailureTestParam{
108 TimestampMessageData{kMinTimestampSeconds - 1, 0},
109 PrintErrorCode::kInvalidValue,
112 TimestampToJsonFailureTestParam{
113 TimestampMessageData{0, kMaxTimestampNanos + 1},
114 PrintErrorCode::kInvalidValue,
117#if GOOGLE_PROTOBUF_VERSION
>= 6033000
123 TimestampToJsonFailureTestParam{
124 TimestampMessageData{0, kMinTimestampNanos - 1},
125 PrintErrorCode::kInvalidValue,
128#if GOOGLE_PROTOBUF_VERSION
>= 6033000
137TEST_P(TimestampToJsonSuccessTest, Test) {
138 const auto& param = GetParam();
140 auto input = PrepareTestData(param.input);
143 UASSERT_NO_THROW((json = MessageToJson(input, param.options)));
144 UASSERT_NO_THROW((expected_json = PrepareJsonTestData(param.expected_json)));
145 UASSERT_NO_THROW((sample_json = CreateSampleJson(input, param.options)));
147 EXPECT_EQ(json, expected_json);
148 EXPECT_EQ(expected_json, sample_json);
151TEST_P(TimestampToJsonFailureTest, Test) {
152 const auto& param = GetParam();
153 auto input = PrepareTestData(param.input);
155 EXPECT_PRINT_ERROR((
void)MessageToJson(input, param.options), param.expected_errc, param.expected_path);
157 if (!param.skip_native_check) {
158 UEXPECT_THROW((
void)CreateSampleJson(input, param.options), SampleError);
162TEST(TimestampToJsonAdditionalTest, InlinedNonNull) {
164 auto message = PrepareTestData(data);
167 UASSERT_NO_THROW((json = MessageToJson(message.field1(), {})));
168 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
170 EXPECT_EQ(json, sample);
171 EXPECT_EQ(json.As<std::string>(),
"1970-01-01T00:02:03.000000321Z");
174TEST(TimestampToJsonAdditionalTest, InlinedNull) {
175 proto_json::messages::TimestampMessage message;
178 UASSERT_NO_THROW((json = MessageToJson(message.field1(), {})));
179 UASSERT_NO_THROW((sample = CreateSampleJson(message.field1())));
181 EXPECT_EQ(json, sample);
182 EXPECT_EQ(json.As<std::string>(),
"1970-01-01T00:00:00Z");
185TEST(TimestampToJsonAdditionalTest, DynamicMessage) {
186 using Message = ::google::protobuf::Timestamp;
187 ::google::protobuf::DynamicMessageFactory factory;
190 std::unique_ptr<::google::protobuf::Message> message(factory.GetPrototype(Message::descriptor())->New());
191 const auto reflection = message->GetReflection();
192 const auto seconds_desc = message->GetDescriptor()->FindFieldByName(
"seconds");
193 const auto nanos_desc = message->GetDescriptor()->FindFieldByName(
"nanos");
195 reflection->SetInt64(message.get(), seconds_desc, 1456704000);
196 reflection->SetInt32(message.get(), nanos_desc, 123450000);
200 UASSERT_NO_THROW((json = MessageToJson(*message, {})));
202 EXPECT_EQ(json.As<std::string>(),
"2016-02-29T00:00:00.123450Z");