userver: /data/code/userver/libraries/proto-structs/codegen-tests/src/simple/simple_test.cpp Source File
Loading...
Searching...
No Matches
simple_test.cpp
1#include <type_traits>
2#include <unordered_map>
3#include <vector>
4
5#include <gtest/gtest.h>
6
7#include <userver/formats/json/value_builder.hpp>
8#include <userver/formats/parse/common_containers.hpp>
9#include <userver/formats/serialize/common_containers.hpp>
10#include <userver/proto-structs/convert.hpp>
11#include <userver/proto-structs/type_mapping.hpp>
12
13#include <simple/base/base.pb.h>
14#include <simple/base/base.structs.usrv.pb.hpp>
15
16namespace ss = simple::base::structs;
17
18USERVER_NAMESPACE_BEGIN
19
20TEST(SingleFile, SimpleStruct) {
21 static_assert(std::is_aggregate_v<ss::SimpleStruct>);
22 [[maybe_unused]] ss::SimpleStruct message;
23 message.some_integer = 5;
24 message.some_text = std::optional<std::string>("foo");
25 message.is_condition = true;
26 message.some_bytes = {"foo", "bar"};
27 message.something.set_bar("bar_val");
28 message.inner_enum = ss::SimpleStruct::InnerEnum2::kFooVal;
29 message.nested.swag = "foo";
30 message.optional_nested = std::optional<ss::SimpleStruct::NestedStruct>{{.swag = "foo"}};
31
32 auto vanilla = ::proto_structs::StructToMessage(std::move(message));
33
34 EXPECT_EQ(vanilla.some_integer(), 5);
35 EXPECT_EQ(vanilla.some_text(), "foo");
36 EXPECT_EQ(vanilla.is_condition(), true);
37 EXPECT_EQ(vanilla.some_bytes().Get(0), "foo");
38 EXPECT_EQ(vanilla.some_bytes().Get(1), "bar");
39 EXPECT_EQ(vanilla.bar(), "bar_val");
40 EXPECT_EQ(vanilla.inner_enum(), ss::SimpleStruct::ProtobufMessage::FOO_VAL);
41 EXPECT_EQ(vanilla.nested().swag(), "foo");
42 EXPECT_EQ(vanilla.optional_nested().swag(), "foo");
43
44 ss::SimpleStruct to;
45 ::proto_structs::MessageToStruct(vanilla, to);
46
47 ASSERT_EQ(to.some_integer, 5);
48 ASSERT_EQ(to.some_text, std::optional<std::string>("foo"));
49 ASSERT_TRUE(to.is_condition);
50 std::vector<std::string> exp = {"foo", "bar"};
51 ASSERT_EQ(to.some_bytes, exp);
52 ASSERT_EQ(to.something.bar(), "bar_val");
53 ASSERT_THROW([[maybe_unused]] auto foo = to.something.foo(), proto_structs::OneofAccessError);
54}
55
56TEST(SingleFile, NestedStruct) {
57 static_assert(std::is_aggregate_v<ss::SimpleStruct::NestedStruct>);
58 [[maybe_unused]] ss::SimpleStruct::NestedStruct nested;
59 nested.swag = "foo";
60
61 static_assert(std::is_aggregate_v<ss::SimpleStruct::NestedStruct::NestedStruct2>);
62 [[maybe_unused]] ss::SimpleStruct::NestedStruct::NestedStruct2 nested2;
63 nested2.swag2 = "bar";
64}
65
66TEST(SingleFile, InnerEnum1) {
67 static_assert(std::is_enum_v<ss::SimpleStruct::NestedStruct::NestedStruct2::InnerEnum1>);
68 [[maybe_unused]] const auto inner_enum1 = ss::SimpleStruct::NestedStruct::NestedStruct2::InnerEnum1::kBarVal;
69}
70
71TEST(SingleFile, InnerEnum2) {
72 static_assert(std::is_enum_v<ss::SimpleStruct::InnerEnum2>);
73 [[maybe_unused]] const auto inner_enum2 = ss::SimpleStruct::InnerEnum2::kFooVal;
74}
75
76TEST(SingleFile, SecondStruct) {
77 static_assert(std::is_aggregate_v<ss::SecondStruct>);
78 [[maybe_unused]] ss::SecondStruct message;
79}
80
81TEST(SingleFile, GlobalEnum) {
82 static_assert(std::is_enum_v<ss::GlobalEnum>);
83 [[maybe_unused]] ss::GlobalEnum message{};
84}
85
86TEST(Oneof, Empty) {
87 const ss::SimpleStruct::Something none;
88 EXPECT_FALSE(none);
89 EXPECT_FALSE(none.has_foo());
90 EXPECT_FALSE(none.has_bar());
91 EXPECT_THROW([[maybe_unused]] const auto& not_found1 = none.foo(), proto_structs::OneofAccessError);
92 EXPECT_THROW([[maybe_unused]] const auto& not_found2 = none.bar(), proto_structs::OneofAccessError);
93}
94
95TEST(Oneof, MakeFoo) {
96 ss::SimpleStruct::Something foo;
97 foo.set_foo(42);
98 EXPECT_TRUE(foo);
99 EXPECT_TRUE(foo.has_foo());
100 EXPECT_NO_THROW(EXPECT_EQ(foo.foo(), 42));
101 EXPECT_FALSE(foo.has_bar());
102 EXPECT_THROW([[maybe_unused]] const auto& not_found = foo.bar(), proto_structs::OneofAccessError);
103}
104
105TEST(Oneof, MakeBar) {
106 ss::SimpleStruct::Something bar;
107 bar.set_bar("bar");
108 EXPECT_TRUE(bar);
109 EXPECT_FALSE(bar.has_foo());
110 EXPECT_THROW([[maybe_unused]] const auto& not_found = bar.foo(), proto_structs::OneofAccessError);
111 EXPECT_TRUE(bar.has_bar());
112 EXPECT_NO_THROW(EXPECT_EQ(bar.bar(), "bar"));
113}
114
115TEST(Oneof, OneofInStruct) {
116 [[maybe_unused]] ss::SimpleStruct message;
117 message.something.set_bar("bar");
118 EXPECT_EQ(message.something.bar(), "bar");
119}
120
121TEST(Oneof, WellKnownTypes) {
122 const std::chrono::seconds seconds{1};
123 const std::chrono::nanoseconds nanoseconds{1};
124 const std::chrono::year year{2025};
125 const std::chrono::month month{10};
126 const std::chrono::day day{30};
127 const std::chrono::hours hours{20};
128 const std::chrono::minutes minutes{10};
129 const std::string string_value{"swag"};
130 const formats::json::Value json_bool = formats::json::ValueBuilder{true}.ExtractValue();
131 const formats::json::Array json_array{formats::json::ValueBuilder{std::vector<double>{-1.5, 1.5}}.ExtractValue()};
132 const formats::json::Object json_object{
133 formats::json::ValueBuilder(std::unordered_map<std::string, std::string>{{"a", "1"}, {"b", "2"}}).ExtractValue()
134 };
135
136 ss::WellKnownUsrv message;
137
138 message.f1 = proto_structs::Timestamp(seconds, nanoseconds);
139 message.f2 = proto_structs::Duration(seconds, nanoseconds);
140 message.f3 = proto_structs::Date(year, month, day);
141 message.f4 = proto_structs::TimeOfDay(hours, minutes, seconds);
142
143 google::protobuf::Any pbuf_any;
144 proto_structs::traits::CompatibleMessageType<ss::ForAny> for_any;
145 for_any.set_f1(string_value);
146
147 ASSERT_TRUE(pbuf_any.PackFrom(for_any));
148
149 message.f5 = proto_structs::Any{pbuf_any};
150 message.f6 = json_bool;
151 message.f7 = json_array;
152 message.f8 = json_object;
153
154 const auto vanilla = proto_structs::StructToMessage(std::move(message));
155
156 ss::WellKnownUsrv parsed;
157 proto_structs::MessageToStruct(vanilla, parsed);
158
159 ASSERT_EQ(parsed.f1.Seconds(), seconds);
160 ASSERT_EQ(parsed.f1.Nanos(), nanoseconds);
161
162 ASSERT_EQ(parsed.f2.Seconds(), seconds);
163 ASSERT_EQ(parsed.f2.Nanos(), nanoseconds);
164
165 ASSERT_TRUE(parsed.f3.Year().has_value());
166 ASSERT_TRUE(parsed.f3.Month().has_value());
167 ASSERT_TRUE(parsed.f3.Day().has_value());
168
169 ASSERT_EQ(parsed.f3.Year(), year);
170 ASSERT_EQ(parsed.f3.Month(), month);
171 ASSERT_EQ(parsed.f3.Day(), day);
172
173 ASSERT_EQ(parsed.f4.Hours(), hours);
174 ASSERT_EQ(parsed.f4.Minutes(), minutes);
175 ASSERT_EQ(parsed.f4.Seconds(), seconds);
176 ASSERT_EQ(parsed.f4.Nanos(), std::chrono::nanoseconds{0});
177
178 ASSERT_TRUE(parsed.f5.Is<proto_structs::traits::CompatibleMessageType<ss::ForAny>>());
179
180 const auto parsed_any = parsed.f5.Unpack<ss::ForAny>();
181 ASSERT_EQ(parsed_any.f1, string_value);
182
183 ASSERT_EQ(parsed.f6, json_bool);
184 ASSERT_EQ(parsed.f7, json_array);
185 ASSERT_EQ(parsed.f8, json_object);
186}
187
188USERVER_NAMESPACE_END