diff options
author | Nobuaki Sukegawa <nsuke@apache.org> | 2016-09-10 14:02:19 +0900 |
---|---|---|
committer | Nobuaki Sukegawa <nsuke@apache.org> | 2016-09-26 01:42:01 +0900 |
commit | 11da87e6f30c237869a09e28ab44fe4a59db270e (patch) | |
tree | 4c81e09a6c5647cf8b4216379c30ec8ec2cb5517 /compiler/cpp/test | |
parent | 1e3cf9b9fdcf9a7b7ffc18a2e6148465b154e66b (diff) | |
download | thrift-11da87e6f30c237869a09e28ab44fe4a59db270e.tar.gz |
THRIFT-2835 Add possibility to distribute generators separately from thrift core, and load them dynamically
Client: Compiler
Patch: Nobuaki Sukegawa, rebased by dtmuller
Also fixed by dtmuller:
* Add plugin namespace for erlang language binding
* Fix unit test test_const_value
* Don't clear type cache with every t_program conversion
* Type "wb" may not be supported by popen on non-Windows platforms
* Fix constness of AST type signatures
Diffstat (limited to 'compiler/cpp/test')
-rw-r--r-- | compiler/cpp/test/CMakeLists.txt | 77 | ||||
-rw-r--r-- | compiler/cpp/test/Makefile.am | 51 | ||||
-rw-r--r-- | compiler/cpp/test/cpp_plugin_test.cmake | 45 | ||||
-rwxr-xr-x | compiler/cpp/test/cpp_plugin_test.sh | 27 | ||||
-rw-r--r-- | compiler/cpp/test/plugin/conversion_test.cc | 496 | ||||
-rw-r--r-- | compiler/cpp/test/plugin/cpp_plugin.cc | 43 |
6 files changed, 739 insertions, 0 deletions
diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt new file mode 100644 index 000000000..047e23ec5 --- /dev/null +++ b/compiler/cpp/test/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +if(${WITH_PLUGIN}) + include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") + + # Make sure gen-cpp files can be included + include_directories("${CMAKE_CURRENT_BINARY_DIR}") + + set(plugintest_SOURCES + plugin/conversion_test.cc + ) + add_executable(plugintest ${plugintest_SOURCES}) + if(WITH_SHARED_LIB AND NOT MSVC) + target_link_libraries(plugintest + thriftc + ${Boost_LIBRARIES} + ) + else() + target_link_libraries(plugintest + thriftc_static + thrift_static + ${Boost_LIBRARIES} + ) + endif() + add_test(NAME PluginUnitTest COMMAND plugintest) + + set(thrift-gen-mycpp_SOURCES + ../src/generate/t_cpp_generator.cc + plugin/cpp_plugin.cc + ) + add_executable(thrift-gen-mycpp ${thrift-gen-mycpp_SOURCES}) + if(WITH_SHARED_LIB AND NOT MSVC) + target_link_libraries(thrift-gen-mycpp thriftc) + else() + target_link_libraries(thrift-gen-mycpp thriftc_static thrift_static) + endif() + + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(BUILDTYPE "Debug") + else() + # RelWithDebInfo generates binaries in "Release" directory too + set(BUILDTYPE "Release") + endif() + + set_directory_properties(PROPERTIES + ADDITIONAL_MAKE_CLEAN_FILES gen-cpp + ADDITIONAL_MAKE_CLEAN_FILES gen-mycpp) + + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-mycpp) + add_test(NAME PluginIntegrationTest + COMMAND ${CMAKE_COMMAND} + -DTHRIFT_COMPILER=${THRIFT_COMPILER} + -DBINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + -DBUILDTYPE=${BUILDTYPE} + -DCURDIR=${CMAKE_CURRENT_BINARY_DIR} + -DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cpp_plugin_test.cmake) +endif() diff --git a/compiler/cpp/test/Makefile.am b/compiler/cpp/test/Makefile.am new file mode 100644 index 000000000..5a232029a --- /dev/null +++ b/compiler/cpp/test/Makefile.am @@ -0,0 +1,51 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# +# Contains some contributions under the Thrift Software License. +# Please see doc/old-thrift-license.txt in the Thrift distribution for +# details. + +AUTOMAKE_OPTIONS = subdir-objects serial-tests + +AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/compiler/cpp/src +AM_LDFLAGS = $(BOOST_LDFLAGS) +AM_CXXFLAGS = -Wall -Wextra -pedantic + +if WITH_PLUGIN +check_PROGRAMS = plugintest + +noinst_PROGRAMS = thrift-gen-mycpp + +AM_CPPFLAGS += -I$(top_srcdir)/lib/cpp/src -I$(top_builddir)/lib/cpp/src + +plugintest_SOURCES = plugin/conversion_test.cc +plugintest_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la + +thrift_gen_mycpp_SOURCES = plugin/cpp_plugin.cc \ + plugin/t_cpp_generator.cc +thrift_gen_mycpp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/compiler/cpp -I$(top_srcdir)/compiler/cpp/src/generate +thrift_gen_mycpp_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la + +cpp_plugin_test.sh: thrift-gen-mycpp +TESTS = $(check_PROGRAMS) cpp_plugin_test.sh + +clean-local: + $(RM) -rf gen-cpp gen-mycpp + +endif diff --git a/compiler/cpp/test/cpp_plugin_test.cmake b/compiler/cpp/test/cpp_plugin_test.cmake new file mode 100644 index 000000000..fd182818d --- /dev/null +++ b/compiler/cpp/test/cpp_plugin_test.cmake @@ -0,0 +1,45 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +file(MAKE_DIRECTORY ${CURDIR}/gen-cpp) +execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-cpp -gen cpp ${SRCDIR}/../../../test/Include.thrift) +if(EXITCODE) + message(FATAL_ERROR "FAILED: \"${ARGV}\": \"${EXITCODE}\"") +endif() +if(WIN32) + set(ENV{PATH} "${BINDIR}/${BUILDTYPE};${BINDIR};$ENV{PATH}") +else() + set(ENV{PATH} "${BINDIR}:$ENV{PATH}") +endif() + +file(MAKE_DIRECTORY ${CURDIR}/gen-mycpp) +execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-mycpp -gen mycpp ${SRCDIR}/../../../test/Include.thrift RESULT_VARIABLE EXITCODE) +if(EXITCODE) + message(FATAL_ERROR "FAILED: \"${EXITCODE}\"") +endif() + +find_program(DIFF diff) +if(DIFF) + execute_process(COMMAND ${DIFF} -urN gen-cpp gen-mycpp RESULT_VARIABLE EXITCODE) + if(EXITCODE) + message(FATAL_ERROR "FAILED: \"${EXITCODE}\"") + endif() +else() + message(WARNING "diff executable is not available. Not validating plugin-generated code.") +endif() diff --git a/compiler/cpp/test/cpp_plugin_test.sh b/compiler/cpp/test/cpp_plugin_test.sh new file mode 100755 index 000000000..ddb2e0a09 --- /dev/null +++ b/compiler/cpp/test/cpp_plugin_test.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# this file is intended to be invoked by make. +set -e +mkdir -p gen-cpp gen-mycpp +PATH=.:"$PATH" ../thrift -r -out gen-cpp -gen cpp ../../../test/Include.thrift +PATH=.:"$PATH" ../thrift -r -out gen-mycpp -gen mycpp ../../../test/Include.thrift +diff -urN gen-cpp gen-mycpp diff --git a/compiler/cpp/test/plugin/conversion_test.cc b/compiler/cpp/test/plugin/conversion_test.cc new file mode 100644 index 000000000..f2d140797 --- /dev/null +++ b/compiler/cpp/test/plugin/conversion_test.cc @@ -0,0 +1,496 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "parse/t_program.h" +#include "plugin/type_util.h" +#include "plugin/plugin_types.h" + +#include <map> +#include <vector> + +#include <boost/preprocessor.hpp> +#include <boost/test/included/unit_test.hpp> +#include <boost/test/parameterized_test.hpp> + +using namespace apache::thrift; +using namespace boost::unit_test; + +namespace test_data { +#define T_TEST_TYPES \ + BOOST_PP_TUPLE_TO_LIST(14, \ + (program, \ + base_type, \ + enum_value, \ + enum, \ + const_value, \ + const, \ + list, \ + set, \ + map, \ + field, \ + struct, \ + typedef, \ + function, \ + service)) +#define T_DELETE_TESTDATA(r, d, elem) \ + for (std::vector<t_##elem*>::reverse_iterator it = elem##s.rbegin(); it != elem##s.rend(); it++) \ + delete *it; +#define T_DECL_TESTDATA(r, d, elem) static std::vector< ::t_##elem*> elem##s; +BOOST_PP_LIST_FOR_EACH(T_DECL_TESTDATA, _, T_TEST_TYPES) +#undef T_DECL_TESTDATA + +bool has_data = false; +void cleanup() { + if (has_data) { + has_data = false; + BOOST_PP_LIST_FOR_EACH(T_DELETE_TESTDATA, _, T_TEST_TYPES) + } +} + +void init_programs() { + programs.push_back(new t_program("prog path", "prog_name")); +} + +void init_base_types() { + base_types.push_back(new ::t_base_type("name0", ::t_base_type::TYPE_VOID)); + base_types.push_back(new ::t_base_type("name1", ::t_base_type::TYPE_STRING)); + base_types.push_back(new ::t_base_type("name2", ::t_base_type::TYPE_BOOL)); + base_types.push_back(new ::t_base_type("name3", ::t_base_type::TYPE_I8)); + base_types.push_back(new ::t_base_type("name4", ::t_base_type::TYPE_I16)); + base_types.push_back(new ::t_base_type("name5", ::t_base_type::TYPE_I32)); + base_types.push_back(new ::t_base_type("name6", ::t_base_type::TYPE_I64)); + base_types.push_back(new ::t_base_type("name7", ::t_base_type::TYPE_DOUBLE)); +} + +void init_const_values() { + const_values.push_back(new t_const_value(42)); + const_values.push_back(new t_const_value("foo")); + { + t_const_value* x = new t_const_value; + x->set_double(3.1415); + const_values.push_back(x); + } + { + t_const_value* x = new t_const_value; + x->set_identifier("bar"); + x->set_enum(enums[0]); + const_values.push_back(x); + } + { + t_const_value* x = new t_const_value; + x->set_map(); + x->add_map(const_values[0], const_values[1]); + x->add_map(const_values[1], const_values[0]); + const_values.push_back(x); + } + { + t_const_value* x = new t_const_value; + x->set_list(); + x->add_list(const_values[0]); + x->add_list(const_values[1]); + const_values.push_back(x); + } +} + +void init_consts() { + // base_type/enum indexes for this and other tests are arbitrary + consts.push_back(new t_const(base_types[2], "aaa", const_values[0])); + consts.back()->set_doc("soem doc"); + consts.push_back(new t_const(base_types[3], "bbb", const_values[1])); +} + +void init_enum_values() { + enum_values.push_back(new t_enum_value("VAL1", 11)); + enum_values.back()->set_doc("enum doc 1"); + enum_values.back()->annotations_.insert(std::make_pair("anno1", "val1")); + + enum_values.push_back(new t_enum_value("VAL2", 22)); +} + +void init_enums() { + enums.push_back(new t_enum(programs[0])); + enums.back()->set_doc("enum doc 1"); + enums.back()->annotations_.insert(std::make_pair("anno1", "val1")); + enums.back()->set_name("fooo"); + enums.back()->append(enum_values[0]); + enums.back()->append(enum_values[1]); +} + +void init_lists() { + lists.push_back(new t_list(enums[0])); + lists.push_back(new t_list(base_types[5])); + lists.back()->set_cpp_name("list_cpp_name_1"); +} +void init_sets() { + sets.push_back(new t_set(base_types[4])); + sets.push_back(new t_set(enums[0])); + sets.back()->set_cpp_name("set_cpp_name_1"); +} +void init_maps() { + maps.push_back(new t_map(base_types[4], base_types[1])); + maps.push_back(new t_map(base_types[5], enums[0])); + maps.back()->set_cpp_name("map_cpp_name_1"); +} + +void init_typedefs() { + typedefs.push_back(new t_typedef(programs[0], base_types[3], "VAL1")); +} +void init_fields() { + fields.push_back(new t_field(base_types[1], "f1")); + fields.back()->set_reference(false); + fields.back()->set_req(t_field::T_OPTIONAL); + fields.push_back(new t_field(base_types[2], "f2", 9)); + fields.back()->set_reference(true); + fields.push_back(new t_field(base_types[3], "f3", 11)); + fields.back()->set_req(t_field::T_REQUIRED); + fields.back()->set_value(const_values[0]); +} +void init_structs() { + structs.push_back(new t_struct(programs[0], "struct1")); + structs.back()->append(fields[0]); + structs.back()->append(fields[1]); + structs.push_back(new t_struct(programs[0], "union1")); + structs.back()->append(fields[0]); + structs.back()->append(fields[1]); + structs.back()->set_union(true); + structs.push_back(new t_struct(programs[0], "xcept1")); + structs.back()->set_xception(true); +} +void init_functions() { + structs.push_back(new t_struct(programs[0], "errs1")); + t_struct* errors = structs.back(); + structs.push_back(new t_struct(programs[0], "args1")); + t_struct* arglist = structs.back(); + functions.push_back(new t_function(base_types[0], "func1", errors, arglist, false)); + functions.push_back(new t_function(base_types[0], "func2", errors, arglist, true)); +} +void init_services() { + services.push_back(new t_service(programs[0])); + services.back()->set_doc("srv1 doc"); + services.back()->set_name("srv1"); + services.back()->add_function(functions[0]); + services.back()->add_function(functions[1]); + + services.push_back(new t_service(programs[0])); + services.back()->set_name("srv2"); + services.back()->set_extends(services[0]); +} + +std::vector<t_type*> types; +void init_types() { +#define T_COPY_TYPES(type) std::copy(type##s.begin(), type##s.end(), std::back_inserter(types)) + T_COPY_TYPES(base_type); + T_COPY_TYPES(enum); + T_COPY_TYPES(typedef); + T_COPY_TYPES(struct); + T_COPY_TYPES(list); + T_COPY_TYPES(set); + T_COPY_TYPES(map); +// T_COPY_TYPES(service); +#undef T_COPY_TYPES +} + +void init() { + if (!has_data) { + has_data = true; +#define T_INIT_TESTDATA(r, d, elem) init_##elem##s(); + BOOST_PP_LIST_FOR_EACH(T_INIT_TESTDATA, _, T_TEST_TYPES) + init_types(); +#undef T_INIT_TESTDATA + } +} +} +struct GlobalFixture { + ~GlobalFixture() { test_data::cleanup(); } +}; +#if (BOOST_VERSION >= 105900) +BOOST_GLOBAL_FIXTURE(GlobalFixture); +#else +BOOST_GLOBAL_FIXTURE(GlobalFixture) +#endif + +void migrate_global_cache() { + plugin::TypeRegistry reg; + plugin_output::get_global_cache(reg); + plugin::set_global_cache(reg); + plugin_output::clear_global_cache(); +} +template <typename T> +T* round_trip(T* t) { + typename plugin::ToType<T>::type p; + plugin_output::convert(t, p); + migrate_global_cache(); + return plugin::convert(p); +} + +void test_base_type(::t_base_type* sut) { + plugin::t_base_type p; + plugin_output::convert(sut, p); + boost::scoped_ptr< ::t_base_type> sut2(plugin::convert(p)); + +#define THRIFT_CHECK(r, data, elem) BOOST_PP_EXPAND(BOOST_CHECK_EQUAL(data elem, sut2->elem)); + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(7, + (is_void(), + is_string(), + is_bool(), + is_string_list(), + is_binary(), + is_string_enum(), + is_base_type()))) +} + +void test_const_value(t_const_value* sut) { + boost::scoped_ptr<t_const_value> sut2(round_trip(sut)); + + BOOST_CHECK_EQUAL(sut->get_type(), sut2->get_type()); + switch (sut->get_type()) { +#define T_CONST_VALUE_CASE(type, name) \ + case t_const_value::type: \ + BOOST_CHECK_EQUAL(sut->get_##name(), sut2->get_##name()); \ + break + T_CONST_VALUE_CASE(CV_INTEGER, integer); + T_CONST_VALUE_CASE(CV_DOUBLE, double); + T_CONST_VALUE_CASE(CV_STRING, string); + T_CONST_VALUE_CASE(CV_IDENTIFIER, identifier); +#undef T_CONST_VALUE_CASE + case t_const_value::CV_MAP: + BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size()); + { + std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut_values; + for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut->get_map().begin(); + it != sut->get_map().end(); it++) { + sut_values[it->first->get_type()] = it->second->get_type(); + } + std::map<t_const_value::t_const_value_type, t_const_value::t_const_value_type> sut2_values; + for (std::map<t_const_value*, t_const_value*>::const_iterator it = sut2->get_map().begin(); + it != sut2->get_map().end(); it++) { + sut2_values[it->first->get_type()] = it->second->get_type(); + } + BOOST_CHECK_EQUAL(sut_values.begin()->first, sut2_values.begin()->first); + BOOST_CHECK_EQUAL(sut_values.begin()->second, sut2_values.begin()->second); + } + break; + case t_const_value::CV_LIST: + BOOST_CHECK_EQUAL(sut->get_list().size(), sut2->get_list().size()); + BOOST_CHECK_EQUAL(sut->get_list().front()->get_type(), sut2->get_list().front()->get_type()); + break; + default: + BOOST_ASSERT(false); + break; + } +} + +void test_const(t_const* sut) { + boost::scoped_ptr< ::t_const> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(4, + (get_type()->get_name(), + get_name(), + get_value()->get_type(), + get_doc()))) +} + +void test_enum_value(t_enum_value* sut) { + boost::scoped_ptr<t_enum_value> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(3, (get_name(), get_value(), get_doc()))) +} + +void test_enum(t_enum* sut) { + boost::scoped_ptr< ::t_enum> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(6, + (get_name(), + get_min_value()->get_value(), + get_max_value()->get_value(), + get_constant_by_value(11)->get_value(), + get_constant_by_name("VAL1")->get_value(), + get_doc()))) +} + +void test_list(t_list* sut) { + boost::scoped_ptr<t_list> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(4, + (get_elem_type()->get_name(), + has_cpp_name(), + get_doc(), + get_name()))) + if (sut->has_cpp_name()) + BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); +} +void test_set(t_set* sut) { + boost::scoped_ptr<t_set> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(4, + (get_elem_type()->get_name(), + has_cpp_name(), + get_doc(), + get_name()))) + if (sut->has_cpp_name()) + BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); +} +void test_map(t_map* sut) { + boost::scoped_ptr<t_map> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(5, + (get_key_type()->get_name(), + get_val_type()->get_name(), + has_cpp_name(), + get_doc(), + get_name()))) + if (sut->has_cpp_name()) + BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); +} + +void test_typedef(t_typedef* sut) { + boost::scoped_ptr<t_typedef> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(4, + (get_doc(), + get_name(), + get_symbolic(), + is_forward_typedef()))) +} + +void test_type(t_type* sut) { + boost::scoped_ptr<t_type> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(15, + (is_void(), + is_base_type(), + is_string(), + is_bool(), + is_typedef(), + is_enum(), + is_struct(), + is_xception(), + is_container(), + is_list(), + is_set(), + is_map(), + is_service(), + get_doc(), + get_name()))) +} + +void test_field(t_field* sut) { + boost::scoped_ptr<t_field> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(5, + (get_req(), + get_reference(), + get_key(), + get_doc(), + get_name()))) + if (sut->get_value()) { + THRIFT_CHECK(, sut->, get_value()->get_type()); + } else { + BOOST_CHECK(!sut2->get_value()); + } + if (sut->get_type()) { + THRIFT_CHECK(, sut->, get_type()->get_name()); + } else { + BOOST_CHECK(!sut2->get_type()); + } +} +void test_struct(t_struct* sut) { + boost::scoped_ptr<t_struct> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(5, + (is_union(), + is_xception(), + is_struct(), + get_doc(), + get_name()))) +} + +void test_function(t_function* sut) { + boost::scoped_ptr<t_function> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH( + THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(4, (get_doc(), get_name(), get_returntype()->get_name(), is_oneway()))) +} +void test_service(t_service* sut) { + boost::scoped_ptr<t_service> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, + sut->, + BOOST_PP_TUPLE_TO_LIST(3, (get_doc(), get_name(), get_functions().size()))) + if (sut->get_extends()) { + THRIFT_CHECK(, sut->, get_extends()->get_name()); + } else { + BOOST_CHECK(!sut2->get_extends()); + } +} + +void test_program(t_program* sut) { + boost::scoped_ptr<t_program> sut2(round_trip(sut)); + + BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, sut->, BOOST_PP_TUPLE_TO_LIST(2, (get_doc(), get_name()))) +} +boost::unit_test::test_suite* do_init_unit_test_suite() { + test_data::init(); + test_suite* ts = BOOST_TEST_SUITE("PluginConversionTest"); + +#define T_TEST_CASE(r, d, type) \ + ts->add(BOOST_PARAM_TEST_CASE(test_##type, test_data::type##s.begin(), test_data::type##s.end())); + BOOST_PP_LIST_FOR_EACH(T_TEST_CASE, _, T_TEST_TYPES) + T_TEST_CASE(_, _, type) +#undef T_TEST_CASE + return ts; +} + +#ifdef BOOST_TEST_DYN_LINK +bool init_unit_test_suite() { + framework::master_test_suite().add(do_init_unit_test_suite()); + return true; +} +int main(int argc, char* argv[]) { + return ::boost::unit_test::unit_test_main(&init_unit_test_suite, argc, argv); +} +#else +boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { + return do_init_unit_test_suite(); +} +#endif diff --git a/compiler/cpp/test/plugin/cpp_plugin.cc b/compiler/cpp/test/plugin/cpp_plugin.cc new file mode 100644 index 000000000..43a62d4a8 --- /dev/null +++ b/compiler/cpp/test/plugin/cpp_plugin.cc @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "plugin/plugin.h" +#include "generate/t_generator.h" + +namespace apache { +namespace thrift { +namespace plugin { + +class MyCppGenerator : public GeneratorPlugin { + virtual int generate(::t_program* program, + const std::map<std::string, std::string>& parsed_options) { + t_generator* gen = t_generator_registry::get_generator(program, "cpp", parsed_options, ""); + gen->generate_program(); + delete gen; + return 0; + } +}; +} +} +} + +int main(int argc, char* argv[]) { + apache::thrift::plugin::MyCppGenerator p; + return p.exec(argc, argv); +} |