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_struct.h>
18 
19 #include <thrift/lib/cpp2/reflection/internal/test_helpers.h>
20 
21 #include <folly/portability/GTest.h>
22 
23 FATAL_S(struct1s, "struct1");
24 FATAL_S(field0s, "field0");
25 FATAL_S(field1s, "field1");
26 FATAL_S(field2s, "field2");
27 FATAL_S(field3s, "field3");
28 FATAL_S(field4s, "field4");
29 FATAL_S(field5s, "field5");
30 FATAL_S(fieldAs, "fieldA");
31 FATAL_S(fieldBs, "fieldB");
32 FATAL_S(fieldCs, "fieldC");
33 FATAL_S(fieldDs, "fieldD");
34 FATAL_S(fieldEs, "fieldE");
35 FATAL_S(fieldFs, "fieldF");
36 FATAL_S(fieldGs, "fieldG");
37 
38 template <apache::thrift::field_id_t Id>
39 using field_id = std::integral_constant<apache::thrift::field_id_t, Id>;
40 
41 template <apache::thrift::optionality Optionality>
42 using required =
43     std::integral_constant<apache::thrift::optionality, Optionality>;
44 
45 namespace test_cpp2 {
46 namespace cpp_reflection {
47 
48 using apache::thrift::detail::st::IsThriftClass;
49 using apache::thrift::detail::st::IsThriftUnion;
50 
51 static_assert(IsThriftClass<union1>::value);
52 static_assert(IsThriftClass<union2>::value);
53 static_assert(IsThriftClass<union3>::value);
54 static_assert(IsThriftClass<struct1>::value);
55 static_assert(IsThriftClass<struct2>::value);
56 static_assert(IsThriftClass<struct3>::value);
57 static_assert(!IsThriftClass<enum1>::value);
58 static_assert(!IsThriftClass<enum2>::value);
59 static_assert(!IsThriftClass<enum3>::value);
60 static_assert(IsThriftUnion<union1>::value);
61 static_assert(IsThriftUnion<union2>::value);
62 static_assert(IsThriftUnion<union3>::value);
63 static_assert(!IsThriftUnion<struct1>::value);
64 static_assert(!IsThriftUnion<struct2>::value);
65 static_assert(!IsThriftUnion<struct3>::value);
66 static_assert(!IsThriftUnion<enum1>::value);
67 static_assert(!IsThriftUnion<enum2>::value);
68 static_assert(!IsThriftUnion<enum3>::value);
69 
TEST(fatal_struct,struct1_sanity_check)70 TEST(fatal_struct, struct1_sanity_check) {
71   using traits = apache::thrift::reflect_struct<struct1>;
72 
73   EXPECT_SAME<struct1, traits::type>();
74   EXPECT_SAME<struct1s, traits::name>();
75   EXPECT_SAME<reflection_tags::module, traits::module>();
76 
77   EXPECT_SAME<traits, apache::thrift::try_reflect_struct<struct1, void>>();
78   EXPECT_SAME<void, apache::thrift::try_reflect_struct<int, void>>();
79 
80   EXPECT_SAME<field0s, traits::member::field0::name>();
81   EXPECT_SAME<field1s, traits::member::field1::name>();
82   EXPECT_SAME<field2s, traits::member::field2::name>();
83   EXPECT_SAME<field3s, traits::member::field3::name>();
84   EXPECT_SAME<field4s, traits::member::field4::name>();
85   EXPECT_SAME<field5s, traits::member::field5::name>();
86 
87   struct1 pod;
88   *pod.field0_ref() = 19;
89   pod.field1_ref() = "hello";
90   *pod.field2_ref() = enum1::field2;
91   *pod.field3_ref() = enum2::field1_2;
92   pod.field4_ref() = {};
93   pod.field4_ref()->set_ud(5.6);
94   pod.field5_ref()->set_us_2("world");
95 
96   EXPECT_EQ(*pod.field0_ref(), traits::member::field0::getter{}(pod));
97   EXPECT_EQ(*pod.field1_ref(), traits::member::field1::getter{}(pod));
98   EXPECT_EQ(*pod.field2_ref(), traits::member::field2::getter{}(pod));
99   EXPECT_EQ(*pod.field3_ref(), traits::member::field3::getter{}(pod));
100   EXPECT_EQ(*pod.field4_ref(), traits::member::field4::getter{}(pod));
101   EXPECT_EQ(*pod.field5_ref(), traits::member::field5::getter{}(pod));
102 
103   traits::member::field0::getter{}(pod) = 98;
104   EXPECT_EQ(98, *pod.field0_ref());
105 
106   traits::member::field1::getter{}(pod) = "test";
107   EXPECT_EQ("test", *pod.field1_ref());
108 
109   traits::member::field2::getter{}(pod) = enum1::field0;
110   EXPECT_EQ(enum1::field0, *pod.field2_ref());
111 
112   traits::member::field3::getter{}(pod) = enum2::field2_2;
113   EXPECT_EQ(enum2::field2_2, *pod.field3_ref());
114 
115   traits::member::field4::getter{}(pod).set_ui(56);
116   EXPECT_EQ(union1::Type::ui, pod.field4_ref()->getType());
117   EXPECT_EQ(56, pod.field4_ref()->get_ui());
118 
119   traits::member::field5::getter{}(pod).set_ue_2(enum1::field1);
120   EXPECT_EQ(union2::Type::ue_2, pod.field5_ref()->getType());
121   EXPECT_EQ(enum1::field1, pod.field5_ref()->get_ue_2());
122 
123   EXPECT_SAME<
124       field0s,
125       fatal::get<traits::members, field0s, fatal::get_type::name>::name>();
126   EXPECT_SAME<
127       field1s,
128       fatal::get<traits::members, field1s, fatal::get_type::name>::name>();
129   EXPECT_SAME<
130       field2s,
131       fatal::get<traits::members, field2s, fatal::get_type::name>::name>();
132   EXPECT_SAME<
133       field3s,
134       fatal::get<traits::members, field3s, fatal::get_type::name>::name>();
135   EXPECT_SAME<
136       field4s,
137       fatal::get<traits::members, field4s, fatal::get_type::name>::name>();
138   EXPECT_SAME<
139       field5s,
140       fatal::get<traits::members, field5s, fatal::get_type::name>::name>();
141 
142   EXPECT_SAME<
143       std::int32_t,
144       fatal::get<traits::members, field0s, fatal::get_type::name>::type>();
145   EXPECT_SAME<
146       std::string,
147       fatal::get<traits::members, field1s, fatal::get_type::name>::type>();
148   EXPECT_SAME<
149       enum1,
150       fatal::get<traits::members, field2s, fatal::get_type::name>::type>();
151   EXPECT_SAME<
152       enum2,
153       fatal::get<traits::members, field3s, fatal::get_type::name>::type>();
154   EXPECT_SAME<
155       union1,
156       fatal::get<traits::members, field4s, fatal::get_type::name>::type>();
157   EXPECT_SAME<
158       union2,
159       fatal::get<traits::members, field5s, fatal::get_type::name>::type>();
160 
161   EXPECT_SAME<
162       field_id<1>,
163       fatal::get<traits::members, field0s, fatal::get_type::name>::id>();
164   EXPECT_SAME<
165       field_id<2>,
166       fatal::get<traits::members, field1s, fatal::get_type::name>::id>();
167   EXPECT_SAME<
168       field_id<4>,
169       fatal::get<traits::members, field2s, fatal::get_type::name>::id>();
170   EXPECT_SAME<
171       field_id<8>,
172       fatal::get<traits::members, field3s, fatal::get_type::name>::id>();
173   EXPECT_SAME<
174       field_id<16>,
175       fatal::get<traits::members, field4s, fatal::get_type::name>::id>();
176   EXPECT_SAME<
177       field_id<32>,
178       fatal::get<traits::members, field5s, fatal::get_type::name>::id>();
179 
180   EXPECT_SAME<
181       required<apache::thrift::optionality::required>,
182       fatal::get<traits::members, field0s, fatal::get_type::name>::optional>();
183   EXPECT_SAME<
184       required<apache::thrift::optionality::optional>,
185       fatal::get<traits::members, field1s, fatal::get_type::name>::optional>();
186   EXPECT_SAME<
187       required<apache::thrift::optionality::required_of_writer>,
188       fatal::get<traits::members, field2s, fatal::get_type::name>::optional>();
189   EXPECT_SAME<
190       required<apache::thrift::optionality::required>,
191       fatal::get<traits::members, field3s, fatal::get_type::name>::optional>();
192   EXPECT_SAME<
193       required<apache::thrift::optionality::optional>,
194       fatal::get<traits::members, field4s, fatal::get_type::name>::optional>();
195   EXPECT_SAME<
196       required<apache::thrift::optionality::required_of_writer>,
197       fatal::get<traits::members, field5s, fatal::get_type::name>::optional>();
198 
199   EXPECT_EQ(
200       98,
201       (fatal::get<
202           traits::members,
203           traits::member::field0::name,
204           fatal::get_type::name>::getter{}(pod)));
205   EXPECT_EQ(
206       "test",
207       (fatal::get<
208           traits::members,
209           traits::member::field1::name,
210           fatal::get_type::name>::getter{}(pod)));
211   EXPECT_EQ(
212       enum1::field0,
213       (fatal::get<
214           traits::members,
215           traits::member::field2::name,
216           fatal::get_type::name>::getter{}(pod)));
217   EXPECT_EQ(
218       enum2::field2_2,
219       (fatal::get<
220           traits::members,
221           traits::member::field3::name,
222           fatal::get_type::name>::getter{}(pod)));
223   EXPECT_EQ(
224       union1::Type::ui,
225       (fatal::get<
226            traits::members,
227            traits::member::field4::name,
228            fatal::get_type::name>::getter{}(pod)
229            .getType()));
230   EXPECT_EQ(
231       56,
232       (fatal::get<
233            traits::members,
234            traits::member::field4::name,
235            fatal::get_type::name>::getter{}(pod)
236            .get_ui()));
237   EXPECT_EQ(
238       union2::Type::ue_2,
239       (fatal::get<
240            traits::members,
241            traits::member::field5::name,
242            fatal::get_type::name>::getter{}(pod)
243            .getType()));
244   EXPECT_EQ(
245       enum1::field1,
246       (fatal::get<
247            traits::members,
248            traits::member::field5::name,
249            fatal::get_type::name>::getter{}(pod)
250            .get_ue_2()));
251 
252   EXPECT_SAME<
253       apache::thrift::type_class::integral,
254       fatal::get<traits::members, field0s, fatal::get_type::name>::
255           type_class>();
256   EXPECT_SAME<
257       apache::thrift::type_class::string,
258       fatal::get<traits::members, field1s, fatal::get_type::name>::
259           type_class>();
260   EXPECT_SAME<
261       apache::thrift::type_class::enumeration,
262       fatal::get<traits::members, field2s, fatal::get_type::name>::
263           type_class>();
264   EXPECT_SAME<
265       apache::thrift::type_class::enumeration,
266       fatal::get<traits::members, field3s, fatal::get_type::name>::
267           type_class>();
268   EXPECT_SAME<
269       apache::thrift::type_class::variant,
270       fatal::get<traits::members, field4s, fatal::get_type::name>::
271           type_class>();
272   EXPECT_SAME<
273       apache::thrift::type_class::variant,
274       fatal::get<traits::members, field5s, fatal::get_type::name>::
275           type_class>();
276 
277   EXPECT_SAME<
278       traits::member::field0,
279       fatal::get<
280           traits::members,
281           traits::member::field0::name,
282           fatal::get_type::name>>();
283   EXPECT_SAME<
284       traits::member::field1,
285       fatal::get<
286           traits::members,
287           traits::member::field1::name,
288           fatal::get_type::name>>();
289   EXPECT_SAME<
290       traits::member::field2,
291       fatal::get<
292           traits::members,
293           traits::member::field2::name,
294           fatal::get_type::name>>();
295   EXPECT_SAME<
296       traits::member::field3,
297       fatal::get<
298           traits::members,
299           traits::member::field3::name,
300           fatal::get_type::name>>();
301   EXPECT_SAME<
302       traits::member::field4,
303       fatal::get<
304           traits::members,
305           traits::member::field4::name,
306           fatal::get_type::name>>();
307   EXPECT_SAME<
308       traits::member::field5,
309       fatal::get<
310           traits::members,
311           traits::member::field5::name,
312           fatal::get_type::name>>();
313 }
314 
315 FATAL_S(structB_annotation1k, "multi_line_annotation");
316 FATAL_S(structB_annotation1v, "line one\nline two");
317 FATAL_S(structB_annotation2k, "some.annotation");
318 FATAL_S(structB_annotation2v, "this is its value");
319 FATAL_S(structB_annotation3k, "some.other.annotation");
320 FATAL_S(structB_annotation3v, "this is its other value");
321 
TEST(fatal_struct,annotations)322 TEST(fatal_struct, annotations) {
323   EXPECT_SAME<
324       fatal::list<>,
325       apache::thrift::reflect_struct<struct1>::annotations::map>();
326 
327   EXPECT_SAME<
328       fatal::list<>,
329       apache::thrift::reflect_struct<struct2>::annotations::map>();
330 
331   EXPECT_SAME<
332       fatal::list<>,
333       apache::thrift::reflect_struct<struct3>::annotations::map>();
334 
335   EXPECT_SAME<
336       fatal::list<>,
337       apache::thrift::reflect_struct<structA>::annotations::map>();
338 
339   using structB_annotations =
340       apache::thrift::reflect_struct<structB>::annotations;
341 
342   EXPECT_SAME<
343       structB_annotation1k,
344       structB_annotations::keys::multi_line_annotation>();
345   EXPECT_SAME<
346       structB_annotation1v,
347       structB_annotations::values::multi_line_annotation>();
348   EXPECT_SAME<
349       structB_annotation2k,
350       structB_annotations::keys::some_annotation>();
351   EXPECT_SAME<
352       structB_annotation2v,
353       structB_annotations::values::some_annotation>();
354   EXPECT_SAME<
355       structB_annotation3k,
356       structB_annotations::keys::some_other_annotation>();
357   EXPECT_SAME<
358       structB_annotation3v,
359       structB_annotations::values::some_other_annotation>();
360   EXPECT_SAME<
361       fatal::list<
362           apache::thrift::
363               annotation<structB_annotation1k, structB_annotation1v>,
364           apache::thrift::
365               annotation<structB_annotation2k, structB_annotation2v>,
366           apache::thrift::
367               annotation<structB_annotation3k, structB_annotation3v>>,
368       structB_annotations::map>();
369 
370   EXPECT_SAME<
371       fatal::list<>,
372       apache::thrift::reflect_struct<structC>::annotations::map>();
373 }
374 
375 FATAL_S(structBd_annotation1k, "another.annotation");
376 FATAL_S(structBd_annotation1v, "another value");
377 FATAL_S(structBd_annotation2k, "some.annotation");
378 FATAL_S(structBd_annotation2v, "some value");
379 
TEST(fatal_struct,member_annotations)380 TEST(fatal_struct, member_annotations) {
381   using info = apache::thrift::reflect_struct<structB>;
382 
383   EXPECT_SAME<fatal::list<>, info::members_annotations::c::map>();
384   EXPECT_SAME<
385       fatal::list<>,
386       fatal::get<info::members, info::member::c::name, fatal::get_type::name>::
387           annotations::map>();
388 
389   using annotations_d =
390       fatal::get<info::members, info::member::d::name, fatal::get_type::name>::
391           annotations;
392   using expected_d_map = fatal::list<
393       apache::thrift::annotation<structBd_annotation1k, structBd_annotation1v>,
394       apache::thrift::annotation<structBd_annotation2k, structBd_annotation2v>>;
395 
396   EXPECT_SAME<expected_d_map, info::members_annotations::d::map>();
397   EXPECT_SAME<expected_d_map, annotations_d::map>();
398 
399   EXPECT_SAME<
400       structBd_annotation1k,
401       info::members_annotations::d::keys::another_annotation>();
402   EXPECT_SAME<
403       structBd_annotation1v,
404       info::members_annotations::d::values::another_annotation>();
405   EXPECT_SAME<
406       structBd_annotation2k,
407       info::members_annotations::d::keys::some_annotation>();
408   EXPECT_SAME<
409       structBd_annotation2v,
410       info::members_annotations::d::values::some_annotation>();
411 
412   EXPECT_SAME<structBd_annotation1k, annotations_d::keys::another_annotation>();
413   EXPECT_SAME<
414       structBd_annotation1v,
415       annotations_d::values::another_annotation>();
416   EXPECT_SAME<structBd_annotation2k, annotations_d::keys::some_annotation>();
417   EXPECT_SAME<structBd_annotation2v, annotations_d::values::some_annotation>();
418 }
419 
420 FATAL_S(annotated_s_b_false, "s_b_false");
421 FATAL_S(annotated_s_b_true, "s_b_true");
422 FATAL_S(annotated_s_int, "s_int");
423 FATAL_S(annotated_s_string, "s_string");
424 FATAL_S(annotated_s_int_list, "s_int_list");
425 FATAL_S(annotated_s_str_list, "s_str_list");
426 FATAL_S(annotated_s_mixed_list, "s_mixed_list");
427 FATAL_S(annotated_s_int_map, "s_int_map");
428 FATAL_S(annotated_s_str_map, "s_str_map");
429 FATAL_S(annotated_s_mixed_map, "s_mixed_map");
430 
431 FATAL_S(annotated_v_s_b_false, "false");
432 FATAL_S(annotated_v_s_b_true, "true");
433 FATAL_S(annotated_v_s_int, "10");
434 FATAL_S(annotated_v_s_string, "\"hello\"");
435 FATAL_S(annotated_v_s_int_list, "[-1, 2, 3]");
436 FATAL_S(annotated_v_s_str_list, "[\"a\", \"b\", \"c\"]");
437 FATAL_S(annotated_v_s_mixed_list, "[\"a\", 1, \"b\", 2]");
438 FATAL_S(annotated_v_s_int_map, "{\"a\": 1, \"b\": -2, \"c\": -3}");
439 FATAL_S(annotated_v_s_str_map, "{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\"}");
440 FATAL_S(annotated_v_s_mixed_map, "{\"a\": -2, \"b\": \"B\", \"c\": 3}");
441 
TEST(fatal_struct,structured_annotations)442 TEST(fatal_struct, structured_annotations) {
443   using info = apache::thrift::reflect_struct<annotated>::annotations;
444 
445   using bf =
446       apache::thrift::annotation<annotated_s_b_false, annotated_v_s_b_false>;
447   using bt =
448       apache::thrift::annotation<annotated_s_b_true, annotated_v_s_b_true>;
449   using i = apache::thrift::annotation<annotated_s_int, annotated_v_s_int>;
450   using s =
451       apache::thrift::annotation<annotated_s_string, annotated_v_s_string>;
452   using il =
453       apache::thrift::annotation<annotated_s_int_list, annotated_v_s_int_list>;
454   using sl =
455       apache::thrift::annotation<annotated_s_str_list, annotated_v_s_str_list>;
456   using ml = apache::thrift::
457       annotation<annotated_s_mixed_list, annotated_v_s_mixed_list>;
458   using im =
459       apache::thrift::annotation<annotated_s_int_map, annotated_v_s_int_map>;
460   using sm =
461       apache::thrift::annotation<annotated_s_str_map, annotated_v_s_str_map>;
462   using mm = apache::thrift::
463       annotation<annotated_s_mixed_map, annotated_v_s_mixed_map>;
464 
465   EXPECT_SAME<bf, fatal::get<info::map, info::keys::s_b_false>>();
466   EXPECT_SAME<bt, fatal::get<info::map, info::keys::s_b_true>>();
467   EXPECT_SAME<i, fatal::get<info::map, info::keys::s_int>>();
468   EXPECT_SAME<s, fatal::get<info::map, info::keys::s_string>>();
469   EXPECT_SAME<il, fatal::get<info::map, info::keys::s_int_list>>();
470   EXPECT_SAME<sl, fatal::get<info::map, info::keys::s_str_list>>();
471   EXPECT_SAME<ml, fatal::get<info::map, info::keys::s_mixed_list>>();
472   EXPECT_SAME<im, fatal::get<info::map, info::keys::s_int_map>>();
473   EXPECT_SAME<sm, fatal::get<info::map, info::keys::s_str_map>>();
474   EXPECT_SAME<mm, fatal::get<info::map, info::keys::s_mixed_map>>();
475 
476   EXPECT_SAME<fatal::list<bf, bt, i, il, im, ml, mm, sl, sm, s>, info::map>();
477 }
478 
479 FATAL_S(annotated_m_b_false, "m_b_false");
480 FATAL_S(annotated_m_b_true, "m_b_true");
481 FATAL_S(annotated_m_int, "m_int");
482 FATAL_S(annotated_m_string, "m_string");
483 FATAL_S(annotated_m_int_list, "m_int_list");
484 FATAL_S(annotated_m_str_list, "m_str_list");
485 FATAL_S(annotated_m_mixed_list, "m_mixed_list");
486 FATAL_S(annotated_m_int_map, "m_int_map");
487 FATAL_S(annotated_m_str_map, "m_str_map");
488 FATAL_S(annotated_m_mixed_map, "m_mixed_map");
489 
490 FATAL_S(annotated_v_m_b_false, "false");
491 FATAL_S(annotated_v_m_b_true, "true");
492 FATAL_S(annotated_v_m_int, "10");
493 FATAL_S(annotated_v_m_string, "\"hello\"");
494 FATAL_S(annotated_v_m_int_list, "[-1, 2, 3]");
495 FATAL_S(annotated_v_m_str_list, "[\"a\", \"b\", \"c\"]");
496 FATAL_S(annotated_v_m_mixed_list, "[\"a\", 1, \"b\", 2]");
497 FATAL_S(annotated_v_m_int_map, "{\"a\": 1, \"b\": -2, \"c\": -3}");
498 FATAL_S(annotated_v_m_str_map, "{\"a\": \"A\", \"b\": \"B\", \"c\": \"C\"}");
499 FATAL_S(annotated_v_m_mixed_map, "{\"a\": -2, \"b\": \"B\", \"c\": 3}");
500 
TEST(fatal_struct,structured_member_annotations)501 TEST(fatal_struct, structured_member_annotations) {
502   using info =
503       apache::thrift::reflect_struct<annotated>::members_annotations::a;
504 
505   using bf =
506       apache::thrift::annotation<annotated_m_b_false, annotated_v_m_b_false>;
507   using bt =
508       apache::thrift::annotation<annotated_m_b_true, annotated_v_m_b_true>;
509   using i = apache::thrift::annotation<annotated_m_int, annotated_v_m_int>;
510   using s =
511       apache::thrift::annotation<annotated_m_string, annotated_v_m_string>;
512   using il =
513       apache::thrift::annotation<annotated_m_int_list, annotated_v_m_int_list>;
514   using sl =
515       apache::thrift::annotation<annotated_m_str_list, annotated_v_m_str_list>;
516   using ml = apache::thrift::
517       annotation<annotated_m_mixed_list, annotated_v_m_mixed_list>;
518   using im =
519       apache::thrift::annotation<annotated_m_int_map, annotated_v_m_int_map>;
520   using sm =
521       apache::thrift::annotation<annotated_m_str_map, annotated_v_m_str_map>;
522   using mm = apache::thrift::
523       annotation<annotated_m_mixed_map, annotated_v_m_mixed_map>;
524 
525   EXPECT_SAME<bf, fatal::get<info::map, info::keys::m_b_false>>();
526   EXPECT_SAME<bt, fatal::get<info::map, info::keys::m_b_true>>();
527   EXPECT_SAME<i, fatal::get<info::map, info::keys::m_int>>();
528   EXPECT_SAME<s, fatal::get<info::map, info::keys::m_string>>();
529   EXPECT_SAME<il, fatal::get<info::map, info::keys::m_int_list>>();
530   EXPECT_SAME<sl, fatal::get<info::map, info::keys::m_str_list>>();
531   EXPECT_SAME<ml, fatal::get<info::map, info::keys::m_mixed_list>>();
532   EXPECT_SAME<im, fatal::get<info::map, info::keys::m_int_map>>();
533   EXPECT_SAME<sm, fatal::get<info::map, info::keys::m_str_map>>();
534   EXPECT_SAME<mm, fatal::get<info::map, info::keys::m_mixed_map>>();
535 
536   EXPECT_SAME<fatal::list<bf, bt, i, il, im, ml, mm, sl, sm, s>, info::map>();
537 }
538 
TEST(fatal_struct,set_methods)539 TEST(fatal_struct, set_methods) {
540   using info = apache::thrift::reflect_struct<struct4>;
541   using req_field = fatal::
542       get<info::members, info::member::field0::name, fatal::get_type::name>;
543   using opt_field = fatal::
544       get<info::members, info::member::field1::name, fatal::get_type::name>;
545   using def_field = fatal::
546       get<info::members, info::member::field2::name, fatal::get_type::name>;
547 
548   using ref_field = fatal::
549       get<info::members, info::member::field3::name, fatal::get_type::name>;
550 
551   struct4 a;
552   EXPECT_TRUE(req_field::is_set(a));
553   EXPECT_TRUE(req_field::mark_set(a, true));
554   EXPECT_TRUE(req_field::is_set(a));
555   EXPECT_FALSE(req_field::mark_set(a, false));
556   EXPECT_TRUE(req_field::is_set(a));
557 
558   EXPECT_FALSE(opt_field::is_set(a));
559   EXPECT_TRUE(opt_field::mark_set(a, true));
560   EXPECT_TRUE(opt_field::is_set(a));
561   EXPECT_FALSE(opt_field::mark_set(a, false));
562   EXPECT_FALSE(opt_field::is_set(a));
563 
564   EXPECT_FALSE(def_field::is_set(a));
565   EXPECT_TRUE(def_field::mark_set(a, true));
566   EXPECT_TRUE(def_field::is_set(a));
567   EXPECT_FALSE(def_field::mark_set(a, false));
568   EXPECT_FALSE(def_field::is_set(a));
569 
570   EXPECT_TRUE(ref_field::is_set(a));
571   EXPECT_TRUE(ref_field::mark_set(a, true));
572 }
573 
TEST(fatal_struct,field_ref_getter)574 TEST(fatal_struct, field_ref_getter) {
575   using info = apache::thrift::reflect_struct<struct4>;
576   using req_field = fatal::
577       get<info::members, info::member::field0::name, fatal::get_type::name>;
578   using opt_field = fatal::
579       get<info::members, info::member::field1::name, fatal::get_type::name>;
580   using def_field = fatal::
581       get<info::members, info::member::field2::name, fatal::get_type::name>;
582 
583   using ref_field = fatal::
584       get<info::members, info::member::field3::name, fatal::get_type::name>;
585 
586   struct4 a;
587 
588   req_field::field_ref_getter req;
589   EXPECT_TRUE(req(a).has_value());
590   req(a) = 1;
591   EXPECT_EQ(a.field0_ref(), 1);
592   a.field0_ref() = 2;
593   EXPECT_EQ(req(a), 2);
594   static_assert(
595       std::is_same<
596           apache::thrift::required_field_ref<std::int32_t&>,
597           decltype(req(a))>::value,
598       "");
599 
600   opt_field::field_ref_getter opt;
601   EXPECT_FALSE(opt(a));
602   opt(a) = "1";
603   EXPECT_EQ(a.field1_ref(), "1");
604   a.field1_ref() = "2";
605   EXPECT_EQ(opt(a), "2");
606   static_assert(
607       std::is_same<
608           apache::thrift::optional_field_ref<std::string&>,
609           decltype(opt(a))>::value,
610       "");
611 
612   def_field::field_ref_getter def;
613   EXPECT_FALSE(def(a).is_set());
614   def(a) = enum1::field1;
615   EXPECT_EQ(a.field2_ref(), enum1::field1);
616   a.field2_ref() = enum1::field2;
617   EXPECT_EQ(def(a), enum1::field2);
618   static_assert(
619       std::is_same<apache::thrift::field_ref<enum1&>, decltype(def(a))>::value,
620       "");
621 
622   ref_field::field_ref_getter ref;
623   EXPECT_TRUE(ref(a));
624   ref(a)->a_ref() = 1;
625   EXPECT_EQ(a.field3_ref()->a_ref(), 1);
626   a.field3_ref()->a_ref() = 2;
627   EXPECT_EQ(ref(a)->a_ref(), 2);
628   static_assert(
629       std::is_same<std::unique_ptr<structA>&, decltype(ref(a))>::value, "");
630 }
631 
TEST(fatal_struct,renamed_field)632 TEST(fatal_struct, renamed_field) {
633   using meta = apache::thrift::reflect_struct<struct_with_renamed_field>;
634   using fmeta = meta::member::boring_cxx_name;
635   auto fname = fatal::to_instance<std::string, fmeta::name>();
636   EXPECT_EQ("fancy.idl.name", fname);
637 }
638 
639 } // namespace cpp_reflection
640 } // namespace test_cpp2
641