blob: 3c8d812cfba837d04393aca44e0510eab9fc73af [file] [log] [blame]
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +09001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
dtmuller052abc32016-07-26 11:58:28 +020020#include "thrift/parse/t_program.h"
21#include "thrift/plugin/type_util.h"
22#include "thrift/plugin/plugin_types.h"
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +090023
24#include <map>
25#include <vector>
26
27#include <boost/preprocessor.hpp>
28#include <boost/test/included/unit_test.hpp>
29#include <boost/test/parameterized_test.hpp>
30
31using namespace apache::thrift;
32using namespace boost::unit_test;
33
34namespace test_data {
35#define T_TEST_TYPES \
36 BOOST_PP_TUPLE_TO_LIST(14, \
37 (program, \
38 base_type, \
39 enum_value, \
40 enum, \
41 const_value, \
42 const, \
43 list, \
44 set, \
45 map, \
46 field, \
47 struct, \
48 typedef, \
49 function, \
50 service))
51#define T_DELETE_TESTDATA(r, d, elem) \
52 for (std::vector<t_##elem*>::reverse_iterator it = elem##s.rbegin(); it != elem##s.rend(); it++) \
53 delete *it;
54#define T_DECL_TESTDATA(r, d, elem) static std::vector< ::t_##elem*> elem##s;
55BOOST_PP_LIST_FOR_EACH(T_DECL_TESTDATA, _, T_TEST_TYPES)
56#undef T_DECL_TESTDATA
57
58bool has_data = false;
59void cleanup() {
60 if (has_data) {
61 has_data = false;
62 BOOST_PP_LIST_FOR_EACH(T_DELETE_TESTDATA, _, T_TEST_TYPES)
63 }
64}
65
66void init_programs() {
67 programs.push_back(new t_program("prog path", "prog_name"));
68}
69
70void init_base_types() {
71 base_types.push_back(new ::t_base_type("name0", ::t_base_type::TYPE_VOID));
72 base_types.push_back(new ::t_base_type("name1", ::t_base_type::TYPE_STRING));
73 base_types.push_back(new ::t_base_type("name2", ::t_base_type::TYPE_BOOL));
74 base_types.push_back(new ::t_base_type("name3", ::t_base_type::TYPE_I8));
75 base_types.push_back(new ::t_base_type("name4", ::t_base_type::TYPE_I16));
76 base_types.push_back(new ::t_base_type("name5", ::t_base_type::TYPE_I32));
77 base_types.push_back(new ::t_base_type("name6", ::t_base_type::TYPE_I64));
78 base_types.push_back(new ::t_base_type("name7", ::t_base_type::TYPE_DOUBLE));
79}
80
81void init_const_values() {
82 const_values.push_back(new t_const_value(42));
83 const_values.push_back(new t_const_value("foo"));
84 {
85 t_const_value* x = new t_const_value;
86 x->set_double(3.1415);
87 const_values.push_back(x);
88 }
89 {
90 t_const_value* x = new t_const_value;
91 x->set_identifier("bar");
92 x->set_enum(enums[0]);
93 const_values.push_back(x);
94 }
95 {
96 t_const_value* x = new t_const_value;
97 x->set_map();
98 x->add_map(const_values[0], const_values[1]);
99 x->add_map(const_values[1], const_values[0]);
100 const_values.push_back(x);
101 }
102 {
103 t_const_value* x = new t_const_value;
104 x->set_list();
105 x->add_list(const_values[0]);
106 x->add_list(const_values[1]);
107 const_values.push_back(x);
108 }
109}
110
111void init_consts() {
112 // base_type/enum indexes for this and other tests are arbitrary
113 consts.push_back(new t_const(base_types[2], "aaa", const_values[0]));
114 consts.back()->set_doc("soem doc");
115 consts.push_back(new t_const(base_types[3], "bbb", const_values[1]));
116}
117
118void init_enum_values() {
119 enum_values.push_back(new t_enum_value("VAL1", 11));
120 enum_values.back()->set_doc("enum doc 1");
121 enum_values.back()->annotations_.insert(std::make_pair("anno1", "val1"));
122
123 enum_values.push_back(new t_enum_value("VAL2", 22));
124}
125
126void init_enums() {
127 enums.push_back(new t_enum(programs[0]));
128 enums.back()->set_doc("enum doc 1");
129 enums.back()->annotations_.insert(std::make_pair("anno1", "val1"));
130 enums.back()->set_name("fooo");
131 enums.back()->append(enum_values[0]);
132 enums.back()->append(enum_values[1]);
133}
134
135void init_lists() {
136 lists.push_back(new t_list(enums[0]));
137 lists.push_back(new t_list(base_types[5]));
138 lists.back()->set_cpp_name("list_cpp_name_1");
139}
140void init_sets() {
141 sets.push_back(new t_set(base_types[4]));
142 sets.push_back(new t_set(enums[0]));
143 sets.back()->set_cpp_name("set_cpp_name_1");
144}
145void init_maps() {
146 maps.push_back(new t_map(base_types[4], base_types[1]));
147 maps.push_back(new t_map(base_types[5], enums[0]));
148 maps.back()->set_cpp_name("map_cpp_name_1");
149}
150
151void init_typedefs() {
152 typedefs.push_back(new t_typedef(programs[0], base_types[3], "VAL1"));
153}
154void init_fields() {
155 fields.push_back(new t_field(base_types[1], "f1"));
156 fields.back()->set_reference(false);
157 fields.back()->set_req(t_field::T_OPTIONAL);
158 fields.push_back(new t_field(base_types[2], "f2", 9));
159 fields.back()->set_reference(true);
160 fields.push_back(new t_field(base_types[3], "f3", 11));
161 fields.back()->set_req(t_field::T_REQUIRED);
162 fields.back()->set_value(const_values[0]);
163}
164void init_structs() {
165 structs.push_back(new t_struct(programs[0], "struct1"));
166 structs.back()->append(fields[0]);
167 structs.back()->append(fields[1]);
168 structs.push_back(new t_struct(programs[0], "union1"));
169 structs.back()->append(fields[0]);
170 structs.back()->append(fields[1]);
171 structs.back()->set_union(true);
172 structs.push_back(new t_struct(programs[0], "xcept1"));
173 structs.back()->set_xception(true);
174}
175void init_functions() {
176 structs.push_back(new t_struct(programs[0], "errs1"));
177 t_struct* errors = structs.back();
178 structs.push_back(new t_struct(programs[0], "args1"));
179 t_struct* arglist = structs.back();
180 functions.push_back(new t_function(base_types[0], "func1", errors, arglist, false));
181 functions.push_back(new t_function(base_types[0], "func2", errors, arglist, true));
182}
183void init_services() {
184 services.push_back(new t_service(programs[0]));
185 services.back()->set_doc("srv1 doc");
186 services.back()->set_name("srv1");
187 services.back()->add_function(functions[0]);
188 services.back()->add_function(functions[1]);
189
190 services.push_back(new t_service(programs[0]));
191 services.back()->set_name("srv2");
192 services.back()->set_extends(services[0]);
193}
194
195std::vector<t_type*> types;
196void init_types() {
197#define T_COPY_TYPES(type) std::copy(type##s.begin(), type##s.end(), std::back_inserter(types))
198 T_COPY_TYPES(base_type);
199 T_COPY_TYPES(enum);
200 T_COPY_TYPES(typedef);
201 T_COPY_TYPES(struct);
202 T_COPY_TYPES(list);
203 T_COPY_TYPES(set);
204 T_COPY_TYPES(map);
205// T_COPY_TYPES(service);
206#undef T_COPY_TYPES
207}
208
209void init() {
210 if (!has_data) {
211 has_data = true;
212#define T_INIT_TESTDATA(r, d, elem) init_##elem##s();
213 BOOST_PP_LIST_FOR_EACH(T_INIT_TESTDATA, _, T_TEST_TYPES)
214 init_types();
215#undef T_INIT_TESTDATA
216 }
217}
218}
219struct GlobalFixture {
220 ~GlobalFixture() { test_data::cleanup(); }
221};
222#if (BOOST_VERSION >= 105900)
223BOOST_GLOBAL_FIXTURE(GlobalFixture);
224#else
225BOOST_GLOBAL_FIXTURE(GlobalFixture)
226#endif
227
228void migrate_global_cache() {
229 plugin::TypeRegistry reg;
230 plugin_output::get_global_cache(reg);
231 plugin::set_global_cache(reg);
232 plugin_output::clear_global_cache();
233}
234template <typename T>
235T* round_trip(T* t) {
236 typename plugin::ToType<T>::type p;
Chet Murthy6ae40232017-11-26 21:42:26 -0800237 plugin::clear_global_cache();
238 plugin_output::clear_global_cache();
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +0900239 plugin_output::convert(t, p);
240 migrate_global_cache();
241 return plugin::convert(p);
242}
243
244void test_base_type(::t_base_type* sut) {
245 plugin::t_base_type p;
246 plugin_output::convert(sut, p);
247 boost::scoped_ptr< ::t_base_type> sut2(plugin::convert(p));
248
249#define THRIFT_CHECK(r, data, elem) BOOST_PP_EXPAND(BOOST_CHECK_EQUAL(data elem, sut2->elem));
250 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
251 sut->,
252 BOOST_PP_TUPLE_TO_LIST(7,
253 (is_void(),
254 is_string(),
255 is_bool(),
256 is_string_list(),
257 is_binary(),
258 is_string_enum(),
259 is_base_type())))
260}
261
262void test_const_value(t_const_value* sut) {
263 boost::scoped_ptr<t_const_value> sut2(round_trip(sut));
264
265 BOOST_CHECK_EQUAL(sut->get_type(), sut2->get_type());
266 switch (sut->get_type()) {
267#define T_CONST_VALUE_CASE(type, name) \
268 case t_const_value::type: \
269 BOOST_CHECK_EQUAL(sut->get_##name(), sut2->get_##name()); \
270 break
271 T_CONST_VALUE_CASE(CV_INTEGER, integer);
272 T_CONST_VALUE_CASE(CV_DOUBLE, double);
273 T_CONST_VALUE_CASE(CV_STRING, string);
274 T_CONST_VALUE_CASE(CV_IDENTIFIER, identifier);
275#undef T_CONST_VALUE_CASE
276 case t_const_value::CV_MAP:
277 BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size());
278 {
279 std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut_values;
Roman Sorokae58f75d2018-03-08 15:45:22 -0800280 for (std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator it = sut->get_map().begin();
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +0900281 it != sut->get_map().end(); it++) {
282 sut_values[it->first->get_type()] = it->second->get_type();
283 }
284 std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut2_values;
Roman Sorokae58f75d2018-03-08 15:45:22 -0800285 for (std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator it = sut2->get_map().begin();
Nobuaki Sukegawa11da87e2016-09-10 14:02:19 +0900286 it != sut2->get_map().end(); it++) {
287 sut2_values[it->first->get_type()] = it->second->get_type();
288 }
289 BOOST_CHECK_EQUAL(sut_values.begin()->first, sut2_values.begin()->first);
290 BOOST_CHECK_EQUAL(sut_values.begin()->second, sut2_values.begin()->second);
291 }
292 break;
293 case t_const_value::CV_LIST:
294 BOOST_CHECK_EQUAL(sut->get_list().size(), sut2->get_list().size());
295 BOOST_CHECK_EQUAL(sut->get_list().front()->get_type(), sut2->get_list().front()->get_type());
296 break;
297 default:
298 BOOST_ASSERT(false);
299 break;
300 }
301}
302
303void test_const(t_const* sut) {
304 boost::scoped_ptr< ::t_const> sut2(round_trip(sut));
305
306 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
307 sut->,
308 BOOST_PP_TUPLE_TO_LIST(4,
309 (get_type()->get_name(),
310 get_name(),
311 get_value()->get_type(),
312 get_doc())))
313}
314
315void test_enum_value(t_enum_value* sut) {
316 boost::scoped_ptr<t_enum_value> sut2(round_trip(sut));
317
318 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
319 sut->,
320 BOOST_PP_TUPLE_TO_LIST(3, (get_name(), get_value(), get_doc())))
321}
322
323void test_enum(t_enum* sut) {
324 boost::scoped_ptr< ::t_enum> sut2(round_trip(sut));
325
326 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
327 sut->,
328 BOOST_PP_TUPLE_TO_LIST(6,
329 (get_name(),
330 get_min_value()->get_value(),
331 get_max_value()->get_value(),
332 get_constant_by_value(11)->get_value(),
333 get_constant_by_name("VAL1")->get_value(),
334 get_doc())))
335}
336
337void test_list(t_list* sut) {
338 boost::scoped_ptr<t_list> sut2(round_trip(sut));
339
340 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
341 sut->,
342 BOOST_PP_TUPLE_TO_LIST(4,
343 (get_elem_type()->get_name(),
344 has_cpp_name(),
345 get_doc(),
346 get_name())))
347 if (sut->has_cpp_name())
348 BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
349}
350void test_set(t_set* sut) {
351 boost::scoped_ptr<t_set> sut2(round_trip(sut));
352
353 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
354 sut->,
355 BOOST_PP_TUPLE_TO_LIST(4,
356 (get_elem_type()->get_name(),
357 has_cpp_name(),
358 get_doc(),
359 get_name())))
360 if (sut->has_cpp_name())
361 BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
362}
363void test_map(t_map* sut) {
364 boost::scoped_ptr<t_map> sut2(round_trip(sut));
365
366 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
367 sut->,
368 BOOST_PP_TUPLE_TO_LIST(5,
369 (get_key_type()->get_name(),
370 get_val_type()->get_name(),
371 has_cpp_name(),
372 get_doc(),
373 get_name())))
374 if (sut->has_cpp_name())
375 BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name());
376}
377
378void test_typedef(t_typedef* sut) {
379 boost::scoped_ptr<t_typedef> sut2(round_trip(sut));
380
381 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
382 sut->,
383 BOOST_PP_TUPLE_TO_LIST(4,
384 (get_doc(),
385 get_name(),
386 get_symbolic(),
387 is_forward_typedef())))
388}
389
390void test_type(t_type* sut) {
391 boost::scoped_ptr<t_type> sut2(round_trip(sut));
392
393 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
394 sut->,
395 BOOST_PP_TUPLE_TO_LIST(15,
396 (is_void(),
397 is_base_type(),
398 is_string(),
399 is_bool(),
400 is_typedef(),
401 is_enum(),
402 is_struct(),
403 is_xception(),
404 is_container(),
405 is_list(),
406 is_set(),
407 is_map(),
408 is_service(),
409 get_doc(),
410 get_name())))
411}
412
413void test_field(t_field* sut) {
414 boost::scoped_ptr<t_field> sut2(round_trip(sut));
415
416 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
417 sut->,
418 BOOST_PP_TUPLE_TO_LIST(5,
419 (get_req(),
420 get_reference(),
421 get_key(),
422 get_doc(),
423 get_name())))
424 if (sut->get_value()) {
425 THRIFT_CHECK(, sut->, get_value()->get_type());
426 } else {
427 BOOST_CHECK(!sut2->get_value());
428 }
429 if (sut->get_type()) {
430 THRIFT_CHECK(, sut->, get_type()->get_name());
431 } else {
432 BOOST_CHECK(!sut2->get_type());
433 }
434}
435void test_struct(t_struct* sut) {
436 boost::scoped_ptr<t_struct> sut2(round_trip(sut));
437
438 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
439 sut->,
440 BOOST_PP_TUPLE_TO_LIST(5,
441 (is_union(),
442 is_xception(),
443 is_struct(),
444 get_doc(),
445 get_name())))
446}
447
448void test_function(t_function* sut) {
449 boost::scoped_ptr<t_function> sut2(round_trip(sut));
450
451 BOOST_PP_LIST_FOR_EACH(
452 THRIFT_CHECK,
453 sut->,
454 BOOST_PP_TUPLE_TO_LIST(4, (get_doc(), get_name(), get_returntype()->get_name(), is_oneway())))
455}
456void test_service(t_service* sut) {
457 boost::scoped_ptr<t_service> sut2(round_trip(sut));
458
459 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK,
460 sut->,
461 BOOST_PP_TUPLE_TO_LIST(3, (get_doc(), get_name(), get_functions().size())))
462 if (sut->get_extends()) {
463 THRIFT_CHECK(, sut->, get_extends()->get_name());
464 } else {
465 BOOST_CHECK(!sut2->get_extends());
466 }
467}
468
469void test_program(t_program* sut) {
470 boost::scoped_ptr<t_program> sut2(round_trip(sut));
471
472 BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, sut->, BOOST_PP_TUPLE_TO_LIST(2, (get_doc(), get_name())))
473}
474boost::unit_test::test_suite* do_init_unit_test_suite() {
475 test_data::init();
476 test_suite* ts = BOOST_TEST_SUITE("PluginConversionTest");
477
478#define T_TEST_CASE(r, d, type) \
479 ts->add(BOOST_PARAM_TEST_CASE(test_##type, test_data::type##s.begin(), test_data::type##s.end()));
480 BOOST_PP_LIST_FOR_EACH(T_TEST_CASE, _, T_TEST_TYPES)
481 T_TEST_CASE(_, _, type)
482#undef T_TEST_CASE
483 return ts;
484}
485
486#ifdef BOOST_TEST_DYN_LINK
487bool init_unit_test_suite() {
488 framework::master_test_suite().add(do_init_unit_test_suite());
489 return true;
490}
491int main(int argc, char* argv[]) {
492 return ::boost::unit_test::unit_test_main(&init_unit_test_suite, argc, argv);
493}
494#else
495boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
496 return do_init_unit_test_suite();
497}
498#endif