summaryrefslogtreecommitdiff
path: root/compiler/cpp/test
diff options
context:
space:
mode:
authorNobuaki Sukegawa <nsuke@apache.org>2016-09-10 14:02:19 +0900
committerNobuaki Sukegawa <nsuke@apache.org>2016-09-26 01:42:01 +0900
commit11da87e6f30c237869a09e28ab44fe4a59db270e (patch)
tree4c81e09a6c5647cf8b4216379c30ec8ec2cb5517 /compiler/cpp/test
parent1e3cf9b9fdcf9a7b7ffc18a2e6148465b154e66b (diff)
downloadthrift-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.txt77
-rw-r--r--compiler/cpp/test/Makefile.am51
-rw-r--r--compiler/cpp/test/cpp_plugin_test.cmake45
-rwxr-xr-xcompiler/cpp/test/cpp_plugin_test.sh27
-rw-r--r--compiler/cpp/test/plugin/conversion_test.cc496
-rw-r--r--compiler/cpp/test/plugin/cpp_plugin.cc43
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);
+}