1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <thrift/test/reflection/gen-cpp2/reflection_fatal_union.h>
18 
19 #include <thrift/lib/cpp2/reflection/internal/test_helpers.h>
20 #include <thrift/lib/cpp2/reflection/reflection.h>
21 
22 #include <folly/portability/GTest.h>
23 
24 #include <fatal/type/transform.h>
25 
26 namespace test_cpp2 {
27 namespace cpp_reflection {
28 
29 FATAL_S(union1s, "union1");
30 FATAL_S(uis, "ui");
31 FATAL_S(uds, "ud");
32 FATAL_S(uss, "us");
33 FATAL_S(ues, "ue");
34 
35 using uii = std::integral_constant<union1::Type, union1::Type::ui>;
36 using udi = std::integral_constant<union1::Type, union1::Type::ud>;
37 using usi = std::integral_constant<union1::Type, union1::Type::us>;
38 using uei = std::integral_constant<union1::Type, union1::Type::ue>;
39 
TEST(fatal_union,variants)40 TEST(fatal_union, variants) {
41   using traits = fatal::variant_traits<union1>;
42 
43   EXPECT_SAME<union1, traits::type>();
44   EXPECT_SAME<union1s, traits::name>();
45   EXPECT_SAME<union1::Type, traits::id>();
46 
47   EXPECT_SAME<uii, traits::ids::ui>();
48   EXPECT_SAME<udi, traits::ids::ud>();
49   EXPECT_SAME<usi, traits::ids::us>();
50   EXPECT_SAME<uei, traits::ids::ue>();
51 
52   EXPECT_SAME<
53       fatal::list<uii, udi, usi, uei>,
54       fatal::transform<traits::descriptors, fatal::get_type::id>>();
55 
56   EXPECT_SAME<
57       fatal::list<std::int32_t, double, std::string, enum1>,
58       fatal::transform<traits::descriptors, fatal::get_type::type>>();
59 }
60 
TEST(fatal_union,by_id)61 TEST(fatal_union, by_id) {
62   using vtraits = fatal::variant_traits<union1>;
63   using traits = vtraits::by_id;
64 
65   EXPECT_SAME<uii, traits::id<uii>>();
66   EXPECT_SAME<udi, traits::id<udi>>();
67   EXPECT_SAME<usi, traits::id<usi>>();
68   EXPECT_SAME<uei, traits::id<uei>>();
69 
70   EXPECT_SAME<std::int32_t, traits::type<uii>>();
71   EXPECT_SAME<double, traits::type<udi>>();
72   EXPECT_SAME<std::string, traits::type<usi>>();
73   EXPECT_SAME<enum1, traits::type<uei>>();
74 
75   union1 u;
76   union1 const& uc = u;
77   union1& ul = u;
78   union1&& ur = std::move(u);
79   EXPECT_TRUE(vtraits::empty(u));
80   EXPECT_TRUE(vtraits::empty(uc));
81   EXPECT_TRUE(vtraits::empty(ul));
82   EXPECT_TRUE(vtraits::empty(ur));
83 
84   traits::set<uii>(u, 10);
85   EXPECT_FALSE(vtraits::empty(u));
86   EXPECT_FALSE(vtraits::empty(uc));
87   EXPECT_FALSE(vtraits::empty(ul));
88   EXPECT_FALSE(vtraits::empty(ur));
89   EXPECT_EQ(union1::Type::ui, u.getType());
90   EXPECT_EQ(union1::Type::ui, vtraits::get_id(u));
91   EXPECT_EQ(union1::Type::ui, vtraits::get_id(uc));
92   EXPECT_EQ(union1::Type::ui, vtraits::get_id(ul));
93   EXPECT_EQ(union1::Type::ui, vtraits::get_id(ur));
94   EXPECT_EQ(10, u.get_ui());
95   EXPECT_EQ(10, traits::get<uii>(ul));
96   EXPECT_EQ(10, traits::get<uii>(uc));
97   EXPECT_EQ(10, traits::get<uii>(ur));
98 
99   traits::set<udi>(u, 5.6);
100   EXPECT_FALSE(vtraits::empty(u));
101   EXPECT_FALSE(vtraits::empty(uc));
102   EXPECT_FALSE(vtraits::empty(ul));
103   EXPECT_FALSE(vtraits::empty(ur));
104   EXPECT_EQ(union1::Type::ud, u.getType());
105   EXPECT_EQ(union1::Type::ud, vtraits::get_id(u));
106   EXPECT_EQ(union1::Type::ud, vtraits::get_id(uc));
107   EXPECT_EQ(union1::Type::ud, vtraits::get_id(ul));
108   EXPECT_EQ(union1::Type::ud, vtraits::get_id(ur));
109   EXPECT_EQ(5.6, u.get_ud());
110   EXPECT_EQ(5.6, traits::get<udi>(ul));
111   EXPECT_EQ(5.6, traits::get<udi>(uc));
112   EXPECT_EQ(5.6, traits::get<udi>(ur));
113 
114   traits::set<usi>(u, "hello");
115   EXPECT_FALSE(vtraits::empty(u));
116   EXPECT_FALSE(vtraits::empty(uc));
117   EXPECT_FALSE(vtraits::empty(ul));
118   EXPECT_FALSE(vtraits::empty(ur));
119   EXPECT_EQ(union1::Type::us, u.getType());
120   EXPECT_EQ(union1::Type::us, vtraits::get_id(u));
121   EXPECT_EQ(union1::Type::us, vtraits::get_id(uc));
122   EXPECT_EQ(union1::Type::us, vtraits::get_id(ul));
123   EXPECT_EQ(union1::Type::us, vtraits::get_id(ur));
124   EXPECT_EQ("hello", u.get_us());
125   EXPECT_EQ("hello", traits::get<usi>(ul));
126   EXPECT_EQ("hello", traits::get<usi>(uc));
127   EXPECT_EQ("hello", traits::get<usi>(ur));
128 
129   traits::set<uei>(u, enum1::field1);
130   EXPECT_FALSE(vtraits::empty(u));
131   EXPECT_FALSE(vtraits::empty(uc));
132   EXPECT_FALSE(vtraits::empty(ul));
133   EXPECT_FALSE(vtraits::empty(ur));
134   EXPECT_EQ(union1::Type::ue, u.getType());
135   EXPECT_EQ(union1::Type::ue, vtraits::get_id(u));
136   EXPECT_EQ(union1::Type::ue, vtraits::get_id(uc));
137   EXPECT_EQ(union1::Type::ue, vtraits::get_id(ul));
138   EXPECT_EQ(union1::Type::ue, vtraits::get_id(ur));
139   EXPECT_EQ(enum1::field1, u.get_ue());
140   EXPECT_EQ(enum1::field1, traits::get<uei>(ul));
141   EXPECT_EQ(enum1::field1, traits::get<uei>(uc));
142   EXPECT_EQ(enum1::field1, traits::get<uei>(ur));
143 }
144 
TEST(fatal_union,by_type)145 TEST(fatal_union, by_type) {
146   using vtraits = fatal::variant_traits<union1>;
147   using traits = vtraits::by_type;
148 
149   EXPECT_SAME<uii, traits::id<std::int32_t>>();
150   EXPECT_SAME<udi, traits::id<double>>();
151   EXPECT_SAME<usi, traits::id<std::string>>();
152   EXPECT_SAME<uei, traits::id<enum1>>();
153 
154   EXPECT_SAME<std::int32_t, traits::type<std::int32_t>>();
155   EXPECT_SAME<double, traits::type<double>>();
156   EXPECT_SAME<std::string, traits::type<std::string>>();
157   EXPECT_SAME<enum1, traits::type<enum1>>();
158 
159   union1 u;
160   union1 const& uc = u;
161   union1& ul = u;
162   union1&& ur = std::move(u);
163   EXPECT_TRUE(vtraits::empty(u));
164   EXPECT_TRUE(vtraits::empty(uc));
165   EXPECT_TRUE(vtraits::empty(ul));
166   EXPECT_TRUE(vtraits::empty(ur));
167 
168   traits::set<std::int32_t>(u, 10);
169   EXPECT_FALSE(vtraits::empty(u));
170   EXPECT_FALSE(vtraits::empty(uc));
171   EXPECT_FALSE(vtraits::empty(ul));
172   EXPECT_FALSE(vtraits::empty(ur));
173   EXPECT_EQ(union1::Type::ui, u.getType());
174   EXPECT_EQ(union1::Type::ui, vtraits::get_id(u));
175   EXPECT_EQ(union1::Type::ui, vtraits::get_id(uc));
176   EXPECT_EQ(union1::Type::ui, vtraits::get_id(ul));
177   EXPECT_EQ(union1::Type::ui, vtraits::get_id(ur));
178   EXPECT_EQ(10, u.get_ui());
179   EXPECT_EQ(10, traits::get<std::int32_t>(ul));
180   EXPECT_EQ(10, traits::get<std::int32_t>(uc));
181   EXPECT_EQ(10, traits::get<std::int32_t>(ur));
182 
183   traits::set<double>(u, 5.6);
184   EXPECT_FALSE(vtraits::empty(u));
185   EXPECT_FALSE(vtraits::empty(uc));
186   EXPECT_FALSE(vtraits::empty(ul));
187   EXPECT_FALSE(vtraits::empty(ur));
188   EXPECT_EQ(union1::Type::ud, u.getType());
189   EXPECT_EQ(union1::Type::ud, vtraits::get_id(u));
190   EXPECT_EQ(union1::Type::ud, vtraits::get_id(uc));
191   EXPECT_EQ(union1::Type::ud, vtraits::get_id(ul));
192   EXPECT_EQ(union1::Type::ud, vtraits::get_id(ur));
193   EXPECT_EQ(5.6, u.get_ud());
194   EXPECT_EQ(5.6, traits::get<double>(ul));
195   EXPECT_EQ(5.6, traits::get<double>(uc));
196   EXPECT_EQ(5.6, traits::get<double>(ur));
197 
198   traits::set<std::string>(u, "hello");
199   EXPECT_FALSE(vtraits::empty(u));
200   EXPECT_FALSE(vtraits::empty(uc));
201   EXPECT_FALSE(vtraits::empty(ul));
202   EXPECT_FALSE(vtraits::empty(ur));
203   EXPECT_EQ(union1::Type::us, u.getType());
204   EXPECT_EQ(union1::Type::us, vtraits::get_id(u));
205   EXPECT_EQ(union1::Type::us, vtraits::get_id(uc));
206   EXPECT_EQ(union1::Type::us, vtraits::get_id(ul));
207   EXPECT_EQ(union1::Type::us, vtraits::get_id(ur));
208   EXPECT_EQ("hello", u.get_us());
209   EXPECT_EQ("hello", traits::get<std::string>(ul));
210   EXPECT_EQ("hello", traits::get<std::string>(uc));
211   EXPECT_EQ("hello", traits::get<std::string>(ur));
212 
213   traits::set<enum1>(u, enum1::field1);
214   EXPECT_FALSE(vtraits::empty(u));
215   EXPECT_FALSE(vtraits::empty(uc));
216   EXPECT_FALSE(vtraits::empty(ul));
217   EXPECT_FALSE(vtraits::empty(ur));
218   EXPECT_EQ(union1::Type::ue, u.getType());
219   EXPECT_EQ(union1::Type::ue, vtraits::get_id(u));
220   EXPECT_EQ(union1::Type::ue, vtraits::get_id(uc));
221   EXPECT_EQ(union1::Type::ue, vtraits::get_id(ul));
222   EXPECT_EQ(union1::Type::ue, vtraits::get_id(ur));
223   EXPECT_EQ(enum1::field1, u.get_ue());
224   EXPECT_EQ(enum1::field1, traits::get<enum1>(ul));
225   EXPECT_EQ(enum1::field1, traits::get<enum1>(uc));
226   EXPECT_EQ(enum1::field1, traits::get<enum1>(ur));
227 }
228 
229 FATAL_S(unionA_annotation1k, "another.annotation");
230 FATAL_S(unionA_annotation1v, "some more text");
231 FATAL_S(unionA_annotation2k, "sample.annotation");
232 FATAL_S(unionA_annotation2v, "some text here");
233 
TEST(fatal_union,annotations)234 TEST(fatal_union, annotations) {
235   EXPECT_SAME<
236       fatal::list<>,
237       apache::thrift::reflect_variant<union1>::annotations::map>();
238 
239   EXPECT_SAME<
240       fatal::list<>,
241       apache::thrift::reflect_variant<union2>::annotations::map>();
242 
243   EXPECT_SAME<
244       fatal::list<>,
245       apache::thrift::reflect_variant<union3>::annotations::map>();
246 
247   using actual_unionA = apache::thrift::reflect_variant<unionA>::annotations;
248 
249   EXPECT_SAME<unionA_annotation1k, actual_unionA::keys::another_annotation>();
250   EXPECT_SAME<unionA_annotation1v, actual_unionA::values::another_annotation>();
251   EXPECT_SAME<unionA_annotation2k, actual_unionA::keys::sample_annotation>();
252   EXPECT_SAME<unionA_annotation2v, actual_unionA::values::sample_annotation>();
253 
254   EXPECT_SAME<
255       fatal::list<
256           apache::thrift::annotation<unionA_annotation1k, unionA_annotation1v>,
257           apache::thrift::annotation<unionA_annotation2k, unionA_annotation2v>>,
258       actual_unionA::map>();
259 }
260 
TEST(fatal_union,by_name)261 TEST(fatal_union, by_name) {
262   using id_traits = fatal::enum_traits<union1::Type>;
263   using info = apache::thrift::reflect_variant<union1>;
264   using member_info = info::by_name<id_traits::member::ui::name>;
265 
266   union1 u;
267   u.set_ui(10);
268 
269   ASSERT_EQ(u.getType(), union1::Type::ui);
270   EXPECT_EQ(10, member_info::get(u));
271 }
272 
TEST(fatal_union,by_type_id)273 TEST(fatal_union, by_type_id) {
274   using info = apache::thrift::reflect_variant<union1>;
275   using member_info = info::by_type_id<union1::Type::ui>;
276 
277   union1 u;
278   u.set_ui(10);
279 
280   ASSERT_EQ(u.getType(), union1::Type::ui);
281   EXPECT_EQ(10, member_info::get(u));
282 }
283 
TEST(fatal_union,by_field_id)284 TEST(fatal_union, by_field_id) {
285   using info = apache::thrift::reflect_variant<union1>;
286   using member_info = info::by_field_id<1>;
287 
288   union1 u;
289   u.set_ui(10);
290 
291   ASSERT_EQ(u.getType(), union1::Type::ui);
292   EXPECT_EQ(10, member_info::get(u));
293 }
294 
TEST(fatal_struct,renamed_field)295 TEST(fatal_struct, renamed_field) {
296   using emeta = fatal::enum_traits<union_with_renamed_field::Type>;
297   using vmeta = emeta::member::boring_cxx_name;
298   auto vname = fatal::to_instance<std::string, vmeta::name>();
299   EXPECT_EQ("fancy.idl.name", vname);
300 
301   using umeta = apache::thrift::reflect_variant<union_with_renamed_field>;
302   using fmeta =
303       umeta::by_type_id<union_with_renamed_field::Type::boring_cxx_name>;
304   auto fname = fatal::to_instance<std::string, fmeta::metadata::name>();
305   EXPECT_EQ("fancy.idl.name", fname);
306 }
307 
308 } // namespace cpp_reflection
309 } // namespace test_cpp2
310