diff options
Diffstat (limited to 'src/jaegertracing/thrift/lib/c_glib/test')
21 files changed, 7691 insertions, 0 deletions
diff --git a/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt b/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt new file mode 100644 index 000000000..318b57629 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/CMakeLists.txt @@ -0,0 +1,202 @@ +# +# 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. +# + + +set(TEST_PREFIX "c_glib") + +# include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) + +#Make sure gen-cpp and gen-c_glib files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# Create the thrift C test library +set(testgenc_SOURCES + gen-c_glib/t_test_debug_proto_test_types.c + gen-c_glib/t_test_enum_test_types.c + gen-c_glib/t_test_enum_test_service.c + gen-c_glib/t_test_empty_service.c + gen-c_glib/t_test_inherited.c + gen-c_glib/t_test_optional_required_test_types.c + gen-c_glib/t_test_reverse_order_service.c + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_service_for_exception_with_a_map.c + gen-c_glib/t_test_srv.c + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_debug_proto_test_types.h + gen-c_glib/t_test_enum_test_types.h + gen-c_glib/t_test_enum_test_service.h + gen-c_glib/t_test_empty_service.h + gen-c_glib/t_test_inherited.h + gen-c_glib/t_test_optional_required_test_types.h + gen-c_glib/t_test_reverse_order_service.h + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_service_for_exception_with_a_map.h + gen-c_glib/t_test_srv.h + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.h +) + +add_library(testgenc STATIC ${testgenc_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(testgenc thrift_c_glib) + + +add_executable(testserialization testserialization.c) +target_link_libraries(testserialization testgenc) +LINK_AGAINST_THRIFT_LIBRARY(testserialization thrift_c_glib) +add_test(NAME testserialization COMMAND testserialization) + +add_executable(testapplicationexception testapplicationexception.c) +LINK_AGAINST_THRIFT_LIBRARY(testapplicationexception thrift_c_glib) +add_test(NAME testapplicationexception COMMAND testapplicationexception) + +add_executable(testtransportsocket testtransportsocket.c) +LINK_AGAINST_THRIFT_LIBRARY(testtransportsocket thrift_c_glib) +add_test(NAME testtransportsocket COMMAND testtransportsocket) + +add_executable(testbinaryprotocol testbinaryprotocol.c) +LINK_AGAINST_THRIFT_LIBRARY(testbinaryprotocol thrift_c_glib) +add_test(NAME testbinaryprotocol COMMAND testbinaryprotocol) + +add_executable(testcompactprotocol testcompactprotocol.c) +LINK_AGAINST_THRIFT_LIBRARY(testcompactprotocol thrift_c_glib) +add_test(NAME testcompactprotocol COMMAND testcompactprotocol) + +add_executable(testbufferedtransport testbufferedtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testbufferedtransport thrift_c_glib) +add_test(NAME testbufferedtransport COMMAND testbufferedtransport) + +add_executable(testframedtransport testframedtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testframedtransport thrift_c_glib) +add_test(NAME testframedtransport COMMAND testframedtransport) + +add_executable(testfdtransport testfdtransport.c) +LINK_AGAINST_THRIFT_LIBRARY(testfdtransport thrift_c_glib) +add_test(NAME testfdtransport COMMAND testfdtransport) + +add_executable(testmemorybuffer testmemorybuffer.c) +LINK_AGAINST_THRIFT_LIBRARY(testmemorybuffer thrift_c_glib) +add_test(NAME testmemorybuffer COMMAND testmemorybuffer) + +add_executable(testsimpleserver testsimpleserver.c) +LINK_AGAINST_THRIFT_LIBRARY(testsimpleserver thrift_c_glib) +add_test(NAME testsimpleserver COMMAND testsimpleserver) + +add_executable(testdebugproto testdebugproto.c) +target_link_libraries(testdebugproto testgenc) +add_test(NAME testdebugproto COMMAND testdebugproto) + +add_executable(testoptionalrequired testoptionalrequired.c) +target_link_libraries(testoptionalrequired testgenc) +add_test(NAME testoptionalrequired COMMAND testoptionalrequired) + +include_directories("${PROJECT_SOURCE_DIR}/test/c_glib/src" "${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") + +add_executable(testthrifttest testthrifttest.c + ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_test_handler.c + ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_test_handler.h + ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_second_service_handler.c + ${PROJECT_SOURCE_DIR}/test/c_glib/src/thrift_second_service_handler.h + gen-c_glib/t_test_thrift_test_types.h) +target_link_libraries(testthrifttest testgenc) +add_test(NAME testthrifttest COMMAND testthrifttest) + + +if(BUILD_CPP) + + include_directories("${PROJECT_SOURCE_DIR}/lib/cpp/src") + + # Create the thrift C++ test library + set(testgenc_cpp_SOURCES + gen-cpp/ThriftTest.cpp + gen-cpp/ThriftTest_constants.cpp + gen-cpp/ThriftTest_types.cpp + gen-cpp/ThriftTest.h + gen-cpp/ThriftTest_constants.h + gen-cpp/ThriftTest_types.h + ) + + add_library(testgenc_cpp STATIC ${testgenc_cpp_SOURCES}) + LINK_AGAINST_THRIFT_LIBRARY(testgenc_cpp thrift) + + #HACK: testthrifttestclient.cpp includes ThriftTest.h without gen-*/ prefixes + # so we include it here + include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-cpp" "${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") + + add_executable(testthrifttestclient testthrifttestclient.cpp) + target_link_libraries(testthrifttestclient testgenc testgenc_cpp ${ZLIB_LIBRARIES}) + add_test(NAME testthrifttestclient COMMAND testthrifttestclient) + +endif(BUILD_CPP) + +# +# Common thrift code generation rules +# + +add_custom_command(OUTPUT + gen-c_glib/t_test_debug_proto_test_types.c + gen-c_glib/t_test_debug_proto_test_types.h + gen-c_glib/t_test_empty_service.c + gen-c_glib/t_test_empty_service.h + gen-c_glib/t_test_inherited.c + gen-c_glib/t_test_inherited.h + gen-c_glib/t_test_reverse_order_service.c + gen-c_glib/t_test_reverse_order_service.h + gen-c_glib/t_test_service_for_exception_with_a_map.c + gen-c_glib/t_test_service_for_exception_with_a_map.h + gen-c_glib/t_test_srv.c + gen-c_glib/t_test_srv.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/DebugProtoTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_enum_test_types.c + gen-c_glib/t_test_enum_test_types.h + gen-c_glib/t_test_enum_test_service.c + gen-c_glib/t_test_enum_test_service.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/EnumTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_optional_required_test_types.c + gen-c_glib/t_test_optional_required_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/OptionalRequiredTest.thrift +) + +add_custom_command(OUTPUT + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) + +add_custom_command(OUTPUT + gen-cpp/ThriftTest.cpp + gen-cpp/ThriftTest_constants.cpp + gen-cpp/ThriftTest_types.cpp + gen-cpp/ThriftTest.h + gen-cpp/ThriftTest_constants.h + gen-cpp/ThriftTest_types.h + COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) + +# TODO: Add memory checks using ctest_memcheck or similar diff --git a/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift b/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift new file mode 100644 index 000000000..a92a9a51c --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/ContainerTest.thrift @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace c_glib TTest + +typedef list<string> StringList +typedef list<StringList> ListStringList + +struct ContainersWithDefaultValues { + 1: list<string> StringList = [ "Apache", "Thrift" ]; +} + +service ContainerService { + void receiveStringList(1: list<string> stringList); + list<string> returnStringList(); + + list<list<string>> returnListStringList(); + ListStringList returnTypedefdListStringList(); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am b/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am new file mode 100755 index 000000000..c99e0da83 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/Makefile.am @@ -0,0 +1,324 @@ +# +# 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. +# +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc + +SUBDIRS = + +BUILT_SOURCES = \ + gen-c_glib/t_test_container_test_types.c \ + gen-c_glib/t_test_container_test_types.h \ + gen-c_glib/t_test_debug_proto_test_types.h \ + gen-c_glib/t_test_empty_service.h \ + gen-c_glib/t_test_inherited.h \ + gen-c_glib/t_test_optional_required_test_types.h \ + gen-c_glib/t_test_reverse_order_service.h \ + gen-c_glib/t_test_second_service.h \ + gen-c_glib/t_test_service_for_exception_with_a_map.h \ + gen-c_glib/t_test_container_service.c \ + gen-c_glib/t_test_container_service.h \ + gen-c_glib/t_test_srv.h \ + gen-c_glib/t_test_thrift_test.h \ + gen-c_glib/t_test_thrift_test_types.h + +AM_CPPFLAGS = -I../src -I./gen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift +AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) \ + @GCOV_CFLAGS@ +AM_CXXFLAGS = $(AM_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@ + +check_PROGRAMS = \ + testserialization \ + testapplicationexception \ + testcontainertest \ + testtransportsocket \ + testtransportsslsocket \ + testbinaryprotocol \ + testcompactprotocol \ + testbufferedtransport \ + testframedtransport \ + testfdtransport \ + testmemorybuffer \ + teststruct \ + testsimpleserver \ + testdebugproto \ + testoptionalrequired \ + testthrifttest + +if WITH_CPP + BUILT_SOURCES += gen-cpp/ThriftTest_types.cpp + check_PROGRAMS += testthrifttestclient +endif + +testserialization_SOURCES = testserialization.c +testserialization_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + libtestgenc.la + +testapplicationexception_SOURCES = testapplicationexception.c +testapplicationexception_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_application_exception.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_struct.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +testcontainertest_SOURCES = testcontainertest.c +testcontainertest_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/libthrift_c_glib_la-thrift_struct.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/processor/libthrift_c_glib_la-thrift_processor.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/server/libthrift_c_glib_la-thrift_server.o \ + libtestgenc.la + +testtransportsocket_SOURCES = testtransportsocket.c +testtransportsocket_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_buffered_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + + +testtransportsslsocket_SOURCES = testtransportsslsocket.c +testtransportsslsocket_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_buffered_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + + +testbinaryprotocol_SOURCES = testbinaryprotocol.c +testbinaryprotocol_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_framed_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testcompactprotocol_SOURCES = testcompactprotocol.c +testcompactprotocol_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_framed_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testbufferedtransport_SOURCES = testbufferedtransport.c +testbufferedtransport_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testframedtransport_SOURCES = testframedtransport.c +testframedtransport_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o + +testfdtransport_SOURCES = testfdtransport.c +testfdtransport_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_fd_transport.o + +testmemorybuffer_SOURCES = testmemorybuffer.c +testmemorybuffer_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +teststruct_SOURCES = teststruct.c +teststruct_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o + +testsimpleserver_SOURCES = testsimpleserver.c +testsimpleserver_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/processor/libthrift_c_glib_la-thrift_processor.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_binary_protocol_factory.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_transport.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_server_socket.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/server/libthrift_c_glib_la-thrift_server.o + +testdebugproto_SOURCES = testdebugproto.c +testdebugproto_LDADD = libtestgenc.la + +testoptionalrequired_SOURCES = testoptionalrequired.c +testoptionalrequired_LDADD = \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/protocol/libthrift_c_glib_la-thrift_protocol.o \ + $(top_builddir)/lib/c_glib/src/thrift/c_glib/transport/libthrift_c_glib_la-thrift_transport.o \ + libtestgenc.la + +testthrifttest_SOURCES = testthrifttest.c +testthrifttest_LDADD = libtestgenc.la \ + $(top_builddir)/test/c_glib/src/thrift_test_handler.o +testthrifttest_CFLAGS = -I$(top_srcdir)/test/c_glib/src -I./gen-c_glib $(GLIB_CFLAGS) + +testthrifttestclient_SOURCES = testthrifttestclient.cpp +testthrifttestclient_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp -I../src -I./gen-c_glib $(GLIB_CFLAGS) +testthrifttestclient_LDADD = ../../cpp/.libs/libthrift.la ../libthrift_c_glib.la libtestgenc.la libtestgencpp.la +testthrifttestclient_LDFLAGS = -L../.libs -L../../cpp/.libs $(GLIB_LIBS) $(GOBJECT_LIBS) + +check_LTLIBRARIES = libtestgenc.la + +if WITH_CPP + check_LTLIBRARIES += libtestgencpp.la +endif + +nodist_libtestgenc_la_SOURCES = \ + gen-c_glib/t_test_container_test_types.c \ + gen-c_glib/t_test_debug_proto_test_types.c \ + gen-c_glib/t_test_enum_test_types.c \ + gen-c_glib/t_test_enum_test_service.c \ + gen-c_glib/t_test_empty_service.c \ + gen-c_glib/t_test_inherited.c \ + gen-c_glib/t_test_optional_required_test_types.c \ + gen-c_glib/t_test_reverse_order_service.c \ + gen-c_glib/t_test_second_service.c \ + gen-c_glib/t_test_service_for_exception_with_a_map.c \ + gen-c_glib/t_test_srv.c \ + gen-c_glib/t_test_container_service.c \ + gen-c_glib/t_test_thrift_test.c \ + gen-c_glib/t_test_thrift_test_types.c \ + gen-c_glib/t_test_container_test_types.h \ + gen-c_glib/t_test_debug_proto_test_types.h \ + gen-c_glib/t_test_enum_test_types.h \ + gen-c_glib/t_test_enum_test_service.h \ + gen-c_glib/t_test_empty_service.h \ + gen-c_glib/t_test_inherited.h \ + gen-c_glib/t_test_optional_required_test_types.h \ + gen-c_glib/t_test_reverse_order_service.h \ + gen-c_glib/t_test_second_service.h \ + gen-c_glib/t_test_service_for_exception_with_a_map.h \ + gen-c_glib/t_test_srv.h \ + gen-c_glib/t_test_container_service.h \ + gen-c_glib/t_test_thrift_test.h \ + gen-c_glib/t_test_thrift_test_types.h +libtestgenc_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la +libtestgenc_la_CPPFLAGS = $(AM_CPPFLAGS) -Wno-unused-function + +nodist_libtestgencpp_la_SOURCES = \ + gen-cpp/ThriftTest.cpp \ + gen-cpp/ThriftTest_constants.cpp \ + gen-cpp/ThriftTest_types.cpp \ + gen-cpp/ThriftTest.h \ + gen-cpp/ThriftTest_constants.h \ + gen-cpp/ThriftTest_types.h +libtestgencpp_la_CPPFLAGS = -I../../cpp/src $(BOOST_CPPFLAGS) -I./gen-cpp + +gen-c_glib/t_test_container_test_types.c gen-c_glib/t_test_container_test_types.h gen-c_glib/t_test_container_service.c gen-c_glib/t_test_container_service.h: ContainerTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_debug_proto_test_types.c gen-c_glib/t_test_debug_proto_test_types.h gen-c_glib/t_test_empty_service.c gen-c_glib/t_test_empty_service.h gen-c_glib/t_test_inherited.c gen-c_glib/t_test_inherited.h gen-c_glib/t_test_reverse_order_service.c gen-c_glib/t_test_reverse_order_service.h gen-c_glib/t_test_service_for_exception_with_a_map.c gen-c_glib/t_test_service_for_exception_with_a_map.h gen-c_glib/t_test_srv.c gen-c_glib/t_test_srv.h: ../../../test/DebugProtoTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_enum_test_types.c gen-c_glib/t_test_enum_test_types.h gen-c_glib/t_test_enum_test_service.c gen-c_glib/t_test_enum_test_service.h : ../../../test/EnumTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_optional_required_test_types.c gen-c_glib/t_test_optional_required_test_types.h: ../../../test/OptionalRequiredTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-c_glib/t_test_second_service.c gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.h: ../../../test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen c_glib $< + +gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest_types.cpp: ../../../test/ThriftTest.thrift $(THRIFT) + $(THRIFT) --gen cpp $< + +TESTS = \ + $(check_PROGRAMS) \ + $(check_SCRIPTS) + +# globally added to all instances of valgrind calls +# VALGRIND_OPTS = --suppressions=glib.suppress +VALGRIND_OPTS = + +# globally added to all memcheck calls +VALGRIND_MEM_OPTS = --tool=memcheck \ + --num-callers=10 \ + ${myextravalgrindmemopts} + +# globally added to all leakcheck calls +VALGRIND_LEAK_OPTS = --tool=memcheck \ + --num-callers=10 \ + --leak-check=full \ + --leak-resolution=high \ + ${myextravalgrindleakopts} + +memcheck: $(check_PROGRAMS) + @for x in $(check_PROGRAMS); \ + do \ + $(MAKE) memcheck-$$x; \ + done + +leakcheck: $(check_PROGRAMS) + @for x in $(check_PROGRAMS); \ + do \ + $(MAKE) leakcheck-$$x; \ + done + +memcheck-%: % + @echo "*****************************************"; \ + echo "MEMCHECK: $<"; \ + echo "ARGS: ${VALGRIND_OPTS} ${VALGRIND_MEM_OPTS} ${$<_VALGRIND_MEM_OPTS}"; \ + $(LIBTOOL) --mode=execute \ + valgrind \ + ${VALGRIND_OPTS} \ + ${VALGRIND_MEM_OPTS} \ + ${$<_VALGRIND_MEM_OPTS} ./$< + +leakcheck-%: % + @echo "*****************************************"; \ + echo "LEAKCHECK: $<"; \ + echo "ARGS: ${VALGRIND_OPTS} ${VALGRIND_LEAK_OPTS} ${$<_VALGRIND_LEAK_OPTS}"; \ + G_SLICE=always-malloc $(LIBTOOL) --mode=execute \ + valgrind \ + ${VALGRIND_OPTS} \ + ${VALGRIND_LEAK_OPTS} \ + ${$<_VALGRIND_LEAK_OPTS} ./$< + +clean-local: + $(RM) gen-c_glib/* gen-cpp/* + +CLEANFILES = \ + *.bb \ + *.bbg \ + *.da \ + *.gcno \ + *.gcda \ + *.gcov + +EXTRA_DIST = \ + CMakeLists.txt \ + ContainerTest.thrift + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress b/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress new file mode 100644 index 000000000..0e0e9fe27 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/glib.suppress @@ -0,0 +1,64 @@ +{ + g_type_init_1 + Memcheck:Leak + fun:malloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_init_2 + Memcheck:Leak + fun:calloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_init_3 + Memcheck:Leak + fun:realloc + ... + fun:g_type_init_with_debug_flags +} + +{ + g_type_register_static_1 + Memcheck:Leak + fun:realloc + ... + fun:g_type_register_static +} + +{ + g_type_register_statuc_2 + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + ... + fun:g_type_register_static +} + +{ + type_class_init_Wm1 + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_class_init_Wm + fun:g_type_class_ref + ... + fun:g_object_newv +} + +{ + type_class_init_Wm2 + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_class_init_Wm + fun:g_type_class_ref + ... + fun:type_class_init_Wm +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c b/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c new file mode 100644 index 000000000..89e39e262 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testapplicationexception.c @@ -0,0 +1,180 @@ +/* + * 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 <glib.h> +#include <string.h> + +#include <thrift/c_glib/thrift_application_exception.h> + +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A ThriftApplicationException can be created... */ + object = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + + g_assert (object != NULL); + g_assert (THRIFT_IS_APPLICATION_EXCEPTION (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_initialize (void) +{ + ThriftApplicationException *xception = NULL; + gint32 type = THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR; + gchar *message = "Exception message"; + gint32 retrieved_type = 0; + gchar *retrieved_message = NULL; + + /* A ThriftApplicationException has "type" and "message" properties that can + be initialized at object creation */ + xception = + g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, + "type", type, + "message", message, + NULL); + + g_assert (xception != NULL); + + /* A ThriftApplicationException's properties can be retrieved */ + g_object_get (xception, + "type", &retrieved_type, + "message", &retrieved_message, + NULL); + + g_assert (retrieved_type == type); + g_assert (retrieved_message != NULL); + g_assert_cmpstr (retrieved_message, ==, message); + + g_free (retrieved_message); + g_object_unref (xception); +} + +static void +test_properties_test (void) +{ + ThriftApplicationException *xception = NULL; + gint32 retrieved_type; + + xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + +#define TEST_TYPE_VALUE(_type) \ + retrieved_type = -1; \ + g_object_set (xception, "type", _type, NULL); \ + g_object_get (xception, "type", &retrieved_type, NULL); \ + g_assert_cmpint (retrieved_type, ==, _type); + + /* The "type" property can be set to any valid Thrift exception type */ + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_BAD_SEQUENCE_ID); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_MISSING_RESULT); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL); + TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE); + +/* "g_test_expect_message" is required for the property range tests below but is + not present in GLib before version 2.34 */ +#if (GLIB_CHECK_VERSION (2, 34, 0)) + g_object_set (xception, + "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN, + NULL); + + /* The "type" property cannot be set to a value too low (less than zero) */ + g_test_expect_message ("GLib-GObject", + G_LOG_LEVEL_WARNING, + "value*out of range*type*"); + g_object_set (xception, "type", -1, NULL); + g_test_assert_expected_messages (); + + g_object_get (xception, "type", &retrieved_type, NULL); + g_assert_cmpint (retrieved_type, !=, -1); + g_assert_cmpint (retrieved_type, + ==, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); + + /* The "type" property cannot be set to a value too high (greater than the + highest defined exception-type value) */ + g_test_expect_message ("GLib-GObject", + G_LOG_LEVEL_WARNING, + "value*out of range*type*"); + g_object_set (xception, "type", THRIFT_APPLICATION_EXCEPTION_ERROR_N, NULL); + g_test_assert_expected_messages (); + + g_object_get (xception, "type", &retrieved_type, NULL); + g_assert_cmpint (retrieved_type, !=, THRIFT_APPLICATION_EXCEPTION_ERROR_N); + g_assert_cmpint (retrieved_type, + ==, + THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN); +#endif + + g_object_unref (xception); +} + +static void +test_properties_message (void) +{ + ThriftApplicationException *xception = NULL; + gchar *message = "Exception message"; + gchar *retrieved_message; + + xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL); + + /* The "message" property can be set to NULL */ + g_object_set (xception, "message", NULL, NULL); + g_object_get (xception, "message", &retrieved_message, NULL); + g_assert (retrieved_message == NULL); + + /* The "message" property can be set to a valid string */ + g_object_set (xception, "message", message, NULL); + g_object_get (xception, "message", &retrieved_message, NULL); + g_assert_cmpint (strcmp (retrieved_message, message), ==, 0); + + g_free (retrieved_message); + g_object_unref (xception); +} + +int +main (int argc, char **argv) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testapplicationexception/CreateAndDestroy", + test_create_and_destroy); + g_test_add_func ("/testapplicationexception/Initialize", + test_initialize); + g_test_add_func ("/testapplicationexception/Properties/test", + test_properties_test); + g_test_add_func ("/testapplicationexception/Properties/message", + test_properties_message); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c b/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c new file mode 100755 index 000000000..14f4fb063 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testbinaryprotocol.c @@ -0,0 +1,859 @@ +/* + * 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. + */ + +/* Disable string-function optimizations when glibc is used, as these produce + compiler warnings about string length when a string function is used inside + a call to g_assert () */ +#ifdef __GLIBC__ +#include <features.h> +#define __NO_STRING_INLINES 1 +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <sys/wait.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> + +#define TEST_BOOL TRUE +#define TEST_BYTE 123 +#define TEST_I16 12345 +#define TEST_I32 1234567890 +#define TEST_I64 G_GINT64_CONSTANT (123456789012345) +#define TEST_DOUBLE 1234567890.123 +#define TEST_STRING "this is a test string 1234567890!@#$%^&*()" +#define TEST_PORT 51199 + +static int transport_read_count = 0; +static int transport_read_error = 0; +static int transport_read_error_at = -1; +gint32 +my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + if (transport_read_count != transport_read_error_at + && transport_read_error == 0) + { + transport_read_count++; + return thrift_transport_read_all (transport, buf, len, error); + } + return -1; +} + +static int transport_write_count = 0; +static int transport_write_error = 0; +static int transport_write_error_at = -1; +gboolean +my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + if (transport_write_count != transport_write_error_at + && transport_write_error == 0) + { + transport_write_count++; + return thrift_transport_write (transport, buf, len, error); + } + return FALSE; +} + +#define thrift_transport_read_all my_thrift_transport_read_all +#define thrift_transport_write my_thrift_transport_write +#include "../src/thrift/c_glib/protocol/thrift_binary_protocol.c" +#undef thrift_transport_read_all +#undef thrift_transport_write + +static void thrift_server_primitives (const int port); +static void thrift_server_complex_types (const int port); +static void thrift_server_many_frames (const int port); + +static void +test_create_and_destroy(void) +{ + GObject *object = NULL; + + /* create an object and then destroy it */ + object = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_initialize(void) +{ + ThriftSocket *tsocket = NULL; + ThriftBinaryProtocol *protocol = NULL; + ThriftSocket *temp = NULL; + + /* create a ThriftTransport */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", 51188, NULL); + g_assert (tsocket != NULL); + /* create a ThriftBinaryProtocol using the Transport */ + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tsocket, NULL); + g_assert (protocol != NULL); + /* fetch the properties */ + g_object_get (G_OBJECT(protocol), "transport", &temp, NULL); + g_object_unref (temp); + + /* clean up memory */ + g_object_unref (protocol); + g_object_unref (tsocket); +} + +static void +test_read_and_write_primitives(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_primitives (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftBinaryTransport */ + tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tb); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0); + g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + g_assert (thrift_binary_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + g_assert (thrift_binary_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + g_assert (thrift_binary_protocol_write_string (protocol, "", NULL) > 0); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + g_assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + + /* test write errors */ + transport_write_error = 1; + g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, + NULL) == -1); + g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) == -1); + g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) == -1); + g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) == -1); + g_assert (thrift_binary_protocol_write_double (protocol, TEST_DOUBLE, + NULL) == -1); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, len, + NULL) == -1); + transport_write_error = 0; + + /* test binary partial failure */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_complex_types (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_complex_types (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftBinaryTransport */ + tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tb); + g_assert (protocol != NULL); + + /* test structures */ + g_assert (thrift_binary_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_binary_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_field_end (protocol, NULL) == 0); + + /* test write error */ + transport_write_error = 1; + g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_binary_protocol_write_field_begin (protocol, "test", T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test 2nd read failure on a field */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test write_field_stop */ + g_assert (thrift_binary_protocol_write_field_stop (protocol, NULL) > 0); + + /* write a map */ + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_map_end (protocol, NULL) == 0); + + /* test 2nd read failure on a map */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test 3rd read failure on a map */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test 1st write failure on a map */ + transport_write_error = 1; + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write failure on a map */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test 3rd write failure on a map */ + transport_write_count = 0; + transport_write_error_at = 2; + g_assert (thrift_binary_protocol_write_map_begin (protocol, T_VOID, T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test negative map size */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_i32 (protocol, -10, NULL); + + /* test list operations */ + g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_list_end (protocol, NULL) == 0); + + /* test 2nd read failure on a list */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + + /* test negative list size */ + thrift_binary_protocol_write_byte (protocol, T_VOID, NULL); + thrift_binary_protocol_write_i32 (protocol, -10, NULL); + + /* test first write error on a list */ + transport_write_error = 1; + g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error on a list */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_binary_protocol_write_list_begin (protocol, T_VOID, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test set operation s*/ + g_assert (thrift_binary_protocol_write_set_begin (protocol, T_VOID, + 1, NULL) > 0); + g_assert (thrift_binary_protocol_write_set_end (protocol, NULL) == 0); + + /* invalid version */ + g_assert (thrift_binary_protocol_write_i32 (protocol, -1, NULL) > 0); + + /* sz > 0 for a message */ + g_assert (thrift_binary_protocol_write_i32 (protocol, 1, NULL) > 0); + + /* send a valid message */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + thrift_binary_protocol_write_string (protocol, "test", NULL); + thrift_binary_protocol_write_i32 (protocol, 1, NULL); + + /* broken 2nd read */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + + /* send a broken 3rd read */ + thrift_binary_protocol_write_i32 (protocol, 0x80010000, NULL); + thrift_binary_protocol_write_string (protocol, "test", NULL); + + /* send a valid message */ + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) > 0); + + g_assert (thrift_binary_protocol_write_message_end (protocol, NULL) == 0); + + /* send broken writes */ + transport_write_error = 1; + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error = 0; + + transport_write_count = 0; + transport_write_error_at = 2; + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + transport_write_count = 0; + transport_write_error_at = 3; + g_assert (thrift_binary_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_many_frames (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftFramedTransport *ft = NULL; + ThriftBinaryProtocol *tb = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + const guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_many_frames (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + g_assert (tsocket != NULL); + transport = THRIFT_TRANSPORT (tsocket); + + /* wrap in a framed transport */ + ft = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", transport, + "w_buf_size", 1, NULL); + g_assert (ft != NULL); + transport = THRIFT_TRANSPORT (ft); + + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a binary protocol */ + tb = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + transport, NULL); + protocol = THRIFT_PROTOCOL (tb); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_binary_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_string (protocol, "", NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_binary (protocol, NULL, 0, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_binary_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + + /* clean up */ + thrift_transport_write_end (transport, NULL); + thrift_transport_close (transport, NULL); + g_object_unref (ft); + g_object_unref (tsocket); + g_object_unref (tb); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + + +static void +thrift_server_primitives (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_binary_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_binary_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + + g_assert (value_boolean == TEST_BOOL); + g_assert (value_byte == TEST_BYTE); + g_assert (value_16 == TEST_I16); + g_assert (value_32 == TEST_I32); + g_assert (value_64 == TEST_I64); + g_assert (value_double == TEST_DOUBLE); + g_assert (strcmp (TEST_STRING, string) == 0); + g_assert (strcmp ("", empty_string) == 0); + g_assert (memcmp (comparator, binary, len) == 0); + + g_free (string); + g_free (empty_string); + g_free (binary); + + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + g_assert (binary == NULL); + g_assert (len == 0); + g_free (binary); + + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) == -1); + g_assert (thrift_binary_protocol_read_byte (protocol, + &value_byte, NULL) == -1); + g_assert (thrift_binary_protocol_read_i16 (protocol, + &value_16, NULL) == -1); + g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) == -1); + g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) == -1); + g_assert (thrift_binary_protocol_read_double (protocol, + &value_double, NULL) == -1); + transport_read_error = 0; + + /* test partial write failure */ + thrift_protocol_read_i32 (protocol, &value_32, NULL); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tbp); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_complex_types (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + gchar *struct_name = NULL; + gchar *field_name = NULL; + gchar *message_name = NULL; + ThriftType element_type, key_type, value_type, field_type; + ThriftMessageType message_type; + gint8 value = 0; + gint16 field_id = 0; + guint32 size = 0; + gint32 seqid = 0; + gint32 version = 0; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + thrift_binary_protocol_read_struct_begin (protocol, &struct_name, NULL); + thrift_binary_protocol_read_struct_end (protocol, NULL); + + thrift_binary_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + thrift_binary_protocol_read_field_end (protocol, NULL); + + /* test first read error on a field */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error = 0; + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test 2nd read failure on a field */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error_at = -1; + + /* test field stop */ + thrift_binary_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + + thrift_binary_protocol_read_map_begin (protocol, &key_type, &value_type, + &size, NULL); + thrift_binary_protocol_read_map_end (protocol, NULL); + + /* test read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 3rd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 2; + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test 3rd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test negative map size */ + g_assert (thrift_binary_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + + /* test list operations */ + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + thrift_binary_protocol_read_list_end (protocol, NULL); + + /* test read failure */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test 2nd read failure */ + transport_read_count = 0; + transport_read_error_at = 1; + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + transport_read_error_at = -1; + + /* test negative list size failure */ + thrift_binary_protocol_read_list_begin (protocol, &element_type, &size, NULL); + + /* test 2nd write failure */ + thrift_binary_protocol_read_byte (protocol, &value, NULL); + + /* test set operations */ + thrift_binary_protocol_read_set_begin (protocol, &element_type, &size, NULL); + thrift_binary_protocol_read_set_end (protocol, NULL); + + /* broken read */ + transport_read_error = 1; + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error = 0; + + /* invalid protocol version */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* sz > 0 */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + + /* read a valid message */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + /* broken 2nd read on a message */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 3rd read on a message */ + transport_read_count = 0; + transport_read_error_at = 3; /* read_string does two reads */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + g_free (message_name); + transport_read_error_at = -1; + + /* read a valid message */ + g_assert (thrift_binary_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + g_assert (thrift_binary_protocol_read_message_end (protocol, NULL) == 0); + + /* handle 2nd write failure on a message */ + thrift_binary_protocol_read_i32 (protocol, &version, NULL); + + /* handle 2nd write failure on a message */ + thrift_binary_protocol_read_i32 (protocol, &version, NULL); + thrift_binary_protocol_read_string (protocol, &message_name, NULL); + + g_object_unref (client); + /* TODO: investigate g_object_unref (tbp); */ + g_object_unref (tsocket); +} + +static void +thrift_server_many_frames (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftBinaryProtocol *tbp = NULL; + ThriftProtocol *protocol = NULL; + ThriftServerSocket *tsocket = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a framed transport */ + client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 1, NULL); + g_assert (client != NULL); + + tbp = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tbp); + + g_assert (thrift_binary_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_binary_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_binary_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_binary_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_binary_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_binary_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_binary_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_binary_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + + g_assert (value_boolean == TEST_BOOL); + g_assert (value_byte == TEST_BYTE); + g_assert (value_16 == TEST_I16); + g_assert (value_32 == TEST_I32); + g_assert (value_64 == TEST_I64); + g_assert (value_double == TEST_DOUBLE); + g_assert (strcmp (TEST_STRING, string) == 0); + g_assert (strcmp ("", empty_string) == 0); + g_assert (memcmp (comparator, binary, len) == 0); + + g_free (string); + g_free (empty_string); + g_free (binary); + + g_assert (thrift_binary_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + g_assert (binary == NULL); + g_assert (len == 0); + g_free (binary); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tbp); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testbinaryprotocol/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testbinaryprotocol/Initialize", test_initialize); + g_test_add_func ("/testbinaryprotocol/ReadAndWritePrimitives", test_read_and_write_primitives); + g_test_add_func ("/testbinaryprotocol/ReadAndWriteComplexTypes", test_read_and_write_complex_types); + g_test_add_func ("/testbinaryprotocol/ReadAndWriteManyFrames", + test_read_and_write_many_frames); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c new file mode 100755 index 000000000..d01806d61 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testbufferedtransport.c @@ -0,0 +1,325 @@ +/* + * 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 <netdb.h> +#include <signal.h> +#include <sys/wait.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +#include "../src/thrift/c_glib/transport/thrift_buffered_transport.c" + +static void thrift_server (const int port); +static void thrift_socket_server_open (const int port, int times); + +/* test object creation and destruction */ +static void +test_create_and_destroy(void) +{ + ThriftTransport *transport = NULL; + guint r_buf_size = 0; + guint w_buf_size = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT (object), "transport", &transport, + "r_buf_size", &r_buf_size, + "w_buf_size", &w_buf_size, NULL); + g_object_unref (object); +} + +static void +test_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + pid_t pid; + int port = 51199; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port,1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + /* this shouldn't work */ + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport) == TRUE); + g_assert (thrift_buffered_transport_close (transport, NULL) == TRUE); + g_object_unref (transport); + g_object_unref (tsocket); + + /* try and underlying socket failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + g_assert (thrift_buffered_transport_open (transport, &err) == FALSE); + g_object_unref (transport); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51199; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport)); + + /* write 10 bytes */ + thrift_buffered_transport_write (transport, buf, 10, NULL); + + /* write 1 byte at a time */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + + /* overflow the buffer */ + thrift_buffered_transport_write (transport, buf, 2, NULL); + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_flush (transport, NULL); + + /* write 1 byte and flush */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_flush (transport, NULL); + + /* write and overflow buffer with 2 system calls */ + thrift_buffered_transport_write (transport, buf, 1, NULL); + thrift_buffered_transport_write (transport, buf, 3, NULL); + + /* write 10 bytes */ + thrift_buffered_transport_write (transport, buf, 10, NULL); + + thrift_buffered_transport_write_end (transport, NULL); + thrift_buffered_transport_flush (transport, NULL); + thrift_buffered_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + int i; + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + for(i=0;i<times;i++){ + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + thrift_socket_close (client, NULL); + g_object_unref (client); + } + g_object_unref (tsocket); +} + +static void +thrift_server (const int port) +{ + int bytes = 0; + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + guchar buf[10]; /* a buffer */ + guchar match[10] = TEST_DATA; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a BufferedTransport */ + client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 5, NULL); + g_assert (client != NULL); + + /* read 10 bytes */ + bytes = thrift_buffered_transport_read (client, buf, 10, NULL); + g_assert (bytes == 10); /* make sure we've read 10 bytes */ + g_assert ( memcmp (buf, match, 10) == 0 ); /* make sure what we got matches */ + + /* read 1 byte */ + bytes = thrift_buffered_transport_read (client, buf, 1, NULL); + + bytes = thrift_buffered_transport_read (client, buf, 6, NULL); + bytes = thrift_buffered_transport_read (client, buf, 2, NULL); + bytes = thrift_buffered_transport_read (client, buf, 1, NULL); + + thrift_buffered_transport_read_end (client, NULL); + thrift_buffered_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +test_write_fail(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51198; + guchar buf[10] = TEST_DATA; /* a buffer */ + + /* SIGPIPE when send to disconnected socket */ + signal(SIGPIPE, SIG_IGN); + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a BufferedTransport */ + client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 5, NULL); + g_assert (client != NULL); + + /* just close socket */ + thrift_buffered_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + + g_assert (thrift_buffered_transport_open (transport, NULL) == TRUE); + g_assert (thrift_buffered_transport_is_open (transport)); + + /* recognize disconnection */ + sleep(1); + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == TRUE); + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE); + + /* write and overflow buffer */ + g_assert (thrift_buffered_transport_write (transport, buf, 10, NULL) == FALSE); + + /* write 1 and flush */ + g_assert (thrift_buffered_transport_write (transport, buf, 1, NULL) == TRUE); + g_assert (thrift_buffered_transport_flush (transport, NULL) == FALSE); + + thrift_buffered_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testbufferedtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testbufferedtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testbufferedtransport/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testbufferedtransport/WriteFail", test_write_fail); + + return g_test_run (); +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c b/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c new file mode 100755 index 000000000..e5ad49120 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testcompactprotocol.c @@ -0,0 +1,1293 @@ +/* + * 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. + */ + +/* Disable string-function optimizations when glibc is used, as these produce + compiler warnings about string length when a string function is used inside + a call to g_assert () */ +#if !defined(__APPLE__) && !defined(__FreeBSD__) && \ + !defined(__OpenBSD__) && !defined(__NetBSD__) +#include <features.h> +#endif + +#ifdef __GLIBC__ +#define __NO_STRING_INLINES 1 +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <sys/wait.h> + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_framed_transport.h> + +#define TEST_BOOL TRUE +#define TEST_BYTE 123 +#define TEST_I16 12345 +#define TEST_I32 1234567890 +#define TEST_I64 123456789012345 +#define TEST_NI16 (-12345) +#define TEST_NI32 (-1234567890) +#define TEST_NI64 (-123456789012345) +#define TEST_DOUBLE 1234567890.123 +#define TEST_STRING "this is a test string 1234567890!@#$%^&*()" +#define TEST_PORT 51199 + +static int transport_read_count = 0; +static int transport_read_error = 0; +static int transport_read_error_at = -1; +gint32 +my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf, + guint32 len, GError **error) +{ + if (transport_read_count != transport_read_error_at + && transport_read_error == 0) + { + transport_read_count++; + return thrift_transport_read_all (transport, buf, len, error); + } + return -1; +} + +static int transport_write_count = 0; +static int transport_write_error = 0; +static int transport_write_error_at = -1; +gboolean +my_thrift_transport_write (ThriftTransport *transport, const gpointer buf, + const guint32 len, GError **error) +{ + if (transport_write_count != transport_write_error_at + && transport_write_error == 0) + { + transport_write_count++; + return thrift_transport_write (transport, buf, len, error); + } + return FALSE; +} + +#define thrift_transport_read_all my_thrift_transport_read_all +#define thrift_transport_write my_thrift_transport_write +#include "../src/thrift/c_glib/protocol/thrift_compact_protocol.c" +#undef thrift_transport_read_all +#undef thrift_transport_write + +static void thrift_server_primitives (const int port); +static void thrift_server_complex_types (const int port); +static void thrift_server_many_frames (const int port); + +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + + /* create an object and then destroy it */ + object = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_initialize (void) +{ + ThriftSocket *tsocket = NULL; + ThriftCompactProtocol *protocol = NULL; + ThriftSocket *temp = NULL; + + /* create a ThriftTransport */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", 51188, NULL); + g_assert (tsocket != NULL); + /* create a ThriftCompactProtocol using the Transport */ + protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + g_assert (protocol != NULL); + /* fetch the properties */ + g_object_get (G_OBJECT (protocol), "transport", &temp, NULL); + g_object_unref (temp); + + /* clean up memory */ + g_object_unref (protocol); + g_object_unref (tsocket); +} + +static void +test_read_and_write_primitives (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_primitives (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftCompactTransport */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, 2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i16 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i32 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_i64 (protocol, -2, NULL) > 0); + g_assert (thrift_compact_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + g_assert (thrift_compact_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + g_assert (thrift_compact_protocol_write_string (protocol, "", NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, NULL, 0, NULL) > 0); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + + /* test write errors */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) == -1); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) == -1); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) == -1); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, + NULL) == -1); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, + NULL) == -1); + g_assert (thrift_compact_protocol_write_double (protocol, TEST_DOUBLE, + NULL) == -1); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, len, + NULL) == -1); + transport_write_error = 0; + + /* test binary partial failure */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_complex_types (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_complex_types (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a ThriftCompactTransport */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + tsocket, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* test structures */ + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + /* test field state w.r.t. deltas */ + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, 1, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 16, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 15, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 30, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 46, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 47, NULL) == 1); + + /* test fields */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + /* test field state w.r.t. structs */ + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 16, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_struct_begin (protocol, + NULL, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 19, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 25, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 17, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + + /* test field state w.r.t. bools */ + + /* deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 18, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 19, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 20, NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 21, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) == 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + + /* no deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 1, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", T_BOOL, + 1, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 1); + g_assert (thrift_compact_protocol_write_field_end (protocol, NULL) == 0); + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, NULL) > 0); + + /* test write error */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_field_begin (protocol, "test", + T_DOUBLE, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test 2nd read failure on a field */ + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test write_field_stop */ + g_assert (thrift_compact_protocol_write_field_stop (protocol, NULL) > 0); + + /* write a map */ + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) > 0); + g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0); + + /* test 1st read failure on map---nothing to do on our side */ + + /* test 2nd read failure on a map */ + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test 1st write failure on a map */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write failure on a map */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_map_begin (protocol, T_DOUBLE, + T_DOUBLE, + 1, NULL) == -1); + transport_write_error_at = -1; + + /* test negative map size */ + thrift_compact_protocol_write_varint32 (tc, -10, NULL); + thrift_compact_protocol_write_byte (protocol, T_DOUBLE, NULL); + + /* test list operations */ + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) > 0); + g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0); + + /* test 1st read failure on a small list---nothing to do on our end */ + + /* test 1st read failure on a big list---nothing to do on our end */ + + /* test 2nd read failure on a big list */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0xf0, NULL); + + /* test negative list size */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0xf0, NULL); + thrift_compact_protocol_write_varint32 (tc, -10, NULL); + + /* test first write error on a small list */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 14, NULL) == -1); + transport_write_error = 0; + + /* test first write error on a big list */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) == -1); + transport_write_error = 0; + + /* test 2nd write error on a big list */ + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_list_begin (protocol, T_DOUBLE, + 15, NULL) == -1); + transport_write_error_at = -1; + + /* test set operation s*/ + g_assert (thrift_compact_protocol_write_set_begin (protocol, T_DOUBLE, + 1, NULL) > 0); + g_assert (thrift_compact_protocol_write_set_end (protocol, NULL) == 0); + + /* invalid protocol */ + g_assert (thrift_compact_protocol_write_byte (protocol, 0, NULL) > 0); + + /* invalid version */ + g_assert (thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, + NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, 0, NULL) > 0); + + /* send a valid message */ + g_assert (thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, + NULL) > 0); + g_assert (thrift_compact_protocol_write_byte (protocol, 0x01u, NULL) > 0); + thrift_compact_protocol_write_varint32 (tc, 1, NULL); + thrift_compact_protocol_write_string (protocol, "test", NULL); + + /* broken 2nd read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + + /* send a broken 3rd read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + thrift_compact_protocol_write_byte (protocol, 0x01u, NULL); + + /* send a broken 4th read */ + thrift_compact_protocol_write_byte (protocol, (gint8) 0x82u, NULL); + thrift_compact_protocol_write_byte (protocol, 0x01u, NULL); + thrift_compact_protocol_write_varint32 (tc, 1, NULL); + + /* send a valid message */ + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) > 0); + + g_assert (thrift_compact_protocol_write_message_end (protocol, NULL) == 0); + + /* send broken writes */ + transport_write_error = 1; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error = 0; + + transport_write_count = 0; + transport_write_error_at = 1; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + transport_write_count = 0; + transport_write_error_at = 2; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + transport_write_count = 0; + transport_write_error_at = 3; + g_assert (thrift_compact_protocol_write_message_begin (protocol, "test", + T_CALL, 1, NULL) == -1); + transport_write_error_at = -1; + + /* clean up */ + thrift_transport_close (transport, NULL); + g_object_unref (tsocket); + g_object_unref (protocol); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +test_read_and_write_many_frames (void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + ThriftFramedTransport *ft = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gpointer binary = (gpointer *) TEST_STRING; + const guint32 len = strlen (TEST_STRING); + int port = TEST_PORT; + + /* fork a server from the client */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + /* child listens */ + thrift_server_many_frames (port); + exit (0); + } else { + /* parent. wait a bit for the socket to be created. */ + sleep (1); + + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + g_assert (tsocket != NULL); + transport = THRIFT_TRANSPORT (tsocket); + + /* wrap in a framed transport */ + ft = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", transport, + "w_buf_size", 1, NULL); + g_assert (ft != NULL); + transport = THRIFT_TRANSPORT (ft); + + thrift_transport_open (transport, NULL); + g_assert (thrift_transport_is_open (transport)); + + /* create a compact protocol */ + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + transport, NULL); + protocol = THRIFT_PROTOCOL (tc); + g_assert (protocol != NULL); + + /* write a bunch of primitives */ + g_assert (thrift_compact_protocol_write_bool (protocol, TEST_BOOL, + NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_byte (protocol, TEST_BYTE, + NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_I16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_I32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_I64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, TEST_NI16, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, TEST_NI32, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, TEST_NI64, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, 2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i16 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i32 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_i64 (protocol, -2, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_double (protocol, + TEST_DOUBLE, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_string (protocol, + TEST_STRING, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_string (protocol, "", NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, NULL, + 0, NULL) > 0); + thrift_transport_flush (transport, NULL); + g_assert (thrift_compact_protocol_write_binary (protocol, binary, + len, NULL) > 0); + thrift_transport_flush (transport, NULL); + + /* clean up */ + thrift_transport_write_end (transport, NULL); + thrift_transport_close (transport, NULL); + g_object_unref (ft); + g_object_unref (tsocket); + g_object_unref (tc); + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + + +static void +thrift_server_primitives (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0, + zigzag_p16 = 0, zigzag_p32 = 0, zigzag_p64 = 0, + zigzag_n16 = 0, zigzag_n32 = 0, zigzag_n64 = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gint16 value_n16 = 0; + gint32 value_n32 = 0; + gint64 value_n64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tc); + + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + + g_assert (value_boolean == TEST_BOOL); + g_assert (value_byte == TEST_BYTE); + g_assert (value_16 == TEST_I16); + g_assert (value_32 == TEST_I32); + g_assert (value_64 == TEST_I64); + g_assert (value_n16 == TEST_NI16); + g_assert (value_n32 == TEST_NI32); + g_assert (value_n64 == TEST_NI64); + g_assert (zigzag_p16 == 4); + g_assert (zigzag_p32 == 4); + g_assert (zigzag_p64 == 4); + g_assert (zigzag_n16 == 3); + g_assert (zigzag_n32 == 3); + g_assert (zigzag_n64 == 3); + g_assert (value_double == TEST_DOUBLE); + g_assert (strcmp (TEST_STRING, string) == 0); + g_assert (strcmp ("", empty_string) == 0); + g_assert (memcmp (comparator, binary, len) == 0); + + g_free (string); + g_free (empty_string); + g_free (binary); + + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + g_assert (binary == NULL); + g_assert (len == 0); + g_free (binary); + + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) == -1); + transport_read_error_at = -1; + + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == -1); + g_assert (thrift_compact_protocol_read_byte (protocol, + &value_byte, NULL) == -1); + g_assert (thrift_compact_protocol_read_i16 (protocol, + &value_16, NULL) == -1); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) == -1); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) == -1); + g_assert (thrift_compact_protocol_read_i16 (protocol, + &value_n16, NULL) == -1); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) == -1); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) == -1); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) == -1); + transport_read_error = 0; + + /* test partial write failure */ + thrift_protocol_read_i32 (protocol, &value_32, NULL); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tc); + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_complex_types (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tc = NULL; + ThriftProtocol *protocol = NULL; + gchar *struct_name = NULL; + gchar *field_name = NULL; + gchar *message_name = NULL; + ThriftType element_type, key_type, value_type, field_type; + ThriftMessageType message_type; + gboolean value_boolean = ! TEST_BOOL; + gint8 value = 0; + gint16 field_id = 0; + guint32 size = 0; + gint32 seqid = 0; + gint8 version_and_type = 0; + gint8 protocol_id = 0; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tc); + + /* test struct operations */ + + thrift_compact_protocol_read_struct_begin (protocol, &struct_name, NULL); + thrift_compact_protocol_read_struct_end (protocol, NULL); + + /* test field state w.r.t. deltas */ + + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 1); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 16); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 17); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 15); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 30); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 46); + field_id = 0; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 47); + field_id = 0; + + /* test field operations */ + + thrift_compact_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + thrift_compact_protocol_read_field_end (protocol, NULL); + + /* test field state w.r.t. structs */ + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 1); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 16); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + g_assert (thrift_compact_protocol_read_struct_begin (protocol, + &struct_name, NULL) == 0); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 17); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + g_assert (thrift_compact_protocol_read_struct_begin (protocol, + &struct_name, NULL) == 0); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_id == 18); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 19); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 18); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 25); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_struct_end (protocol, NULL) == 0); + + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_id == 17); + field_id = 0; + thrift_compact_protocol_read_field_end (protocol, NULL); + + /* test field state w.r.t. bools */ + + /* deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) == 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + + /* no deltas */ + /* non-bool field -> bool field -> non-bool field */ + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + thrift_compact_protocol_read_field_end (protocol, NULL); + /* bool -> bool field -> bool */ + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + g_assert (thrift_compact_protocol_read_field_begin (protocol, &field_name, + &field_type, + &field_id, NULL) > 1); + g_assert (field_type == T_BOOL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) == 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + thrift_compact_protocol_read_field_end (protocol, NULL); + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (value_boolean == TEST_BOOL); + value_boolean = ! TEST_BOOL; + + /* test first read error on a field */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error = 0; + + /* test 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test 2nd read failure on a field */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_field_begin (protocol, + &field_name, &field_type, + &field_id, NULL) == -1); + transport_read_error_at = -1; + + /* test field stop */ + thrift_compact_protocol_read_field_begin (protocol, &field_name, &field_type, + &field_id, NULL); + + /* test map operations */ + + thrift_compact_protocol_read_map_begin (protocol, &key_type, &value_type, + &size, NULL); + thrift_compact_protocol_read_map_end (protocol, NULL); + + /* test 1st read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 0; + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 2nd read failure on a map */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + transport_read_error_at = -1; + + /* test 1st write failure on map---nothing to do on our side */ + + /* test 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test negative map size */ + g_assert (thrift_compact_protocol_read_map_begin (protocol, + &key_type, &value_type, + &size, NULL) == -1); + + /* test list operations */ + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + thrift_compact_protocol_read_list_end (protocol, NULL); + + /* test small list 1st read failure */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test big list 1st read failure */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type, + &size, NULL) == -1); + transport_read_error = 0; + + /* test big list 2nd read failure */ + transport_read_count = 0; + transport_read_error_at = 1; + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + transport_read_error_at = -1; + + /* test negative list size failure */ + thrift_compact_protocol_read_list_begin (protocol, &element_type, &size, + NULL); + + /* test small list 1st write failure---nothing to do on our end */ + + /* test big list 1st write failure---nothing to do on our end */ + + /* test big list 2nd write failure */ + thrift_compact_protocol_read_byte (protocol, &value, NULL); + + /* test set operations */ + thrift_compact_protocol_read_set_begin (protocol, &element_type, &size, NULL); + thrift_compact_protocol_read_set_end (protocol, NULL); + + /* broken read */ + transport_read_error = 1; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error = 0; + + /* invalid protocol */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* invalid version */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + + /* read a valid message */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + /* broken 2nd read on a message */ + transport_read_count = 0; + transport_read_error_at = 1; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 3rd read on a message */ + transport_read_count = 0; + transport_read_error_at = 2; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* broken 4th read on a message */ + transport_read_count = 0; + transport_read_error_at = 3; + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) == -1); + transport_read_error_at = -1; + + /* read a valid message */ + g_assert (thrift_compact_protocol_read_message_begin (protocol, &message_name, + &message_type, &seqid, + NULL) > 0); + g_free (message_name); + + g_assert (thrift_compact_protocol_read_message_end (protocol, NULL) == 0); + + /* handle 2nd write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + + /* handle 3rd write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + thrift_compact_protocol_read_byte (protocol, &version_and_type, NULL); + + /* handle 4th write failure on a message */ + thrift_compact_protocol_read_byte (protocol, &protocol_id, NULL); + thrift_compact_protocol_read_byte (protocol, &version_and_type, NULL); + thrift_compact_protocol_read_varint32 (tc, &seqid, NULL); + + g_object_unref (client); + g_object_unref (tsocket); +} + +static void +thrift_server_many_frames (const int port) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + ThriftCompactProtocol *tcp = NULL; + ThriftProtocol *protocol = NULL; + ThriftServerSocket *tsocket = NULL; + gboolean value_boolean = FALSE; + gint8 value_byte = 0, + zigzag_p16 = 0, zigzag_p32 = 0, zigzag_p64 = 0, + zigzag_n16 = 0, zigzag_n32 = 0, zigzag_n64 = 0; + gint16 value_16 = 0; + gint32 value_32 = 0; + gint64 value_64 = 0; + gint16 value_n16 = 0; + gint32 value_n32 = 0; + gint64 value_n64 = 0; + gdouble value_double = 0; + gchar *string = NULL; + gchar *empty_string = NULL; + gpointer binary = NULL; + guint32 len = 0; + void *comparator = (void *) TEST_STRING; + + tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a framed transport */ + client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 1, NULL); + g_assert (client != NULL); + + tcp = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", + client, NULL); + protocol = THRIFT_PROTOCOL (tcp); + + g_assert (thrift_compact_protocol_read_bool (protocol, + &value_boolean, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &value_byte, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_64, NULL) > 0); + g_assert (thrift_compact_protocol_read_i16 (protocol, &value_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_i32 (protocol, &value_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_i64 (protocol, &value_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_p64, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n16, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n32, NULL) > 0); + g_assert (thrift_compact_protocol_read_byte (protocol, &zigzag_n64, NULL) > 0); + g_assert (thrift_compact_protocol_read_double (protocol, + &value_double, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &string, NULL) > 0); + g_assert (thrift_compact_protocol_read_string (protocol, &empty_string, + NULL) > 0); + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + + g_assert (value_boolean == TEST_BOOL); + g_assert (value_byte == TEST_BYTE); + g_assert (value_16 == TEST_I16); + g_assert (value_32 == TEST_I32); + g_assert (value_64 == TEST_I64); + g_assert (value_n16 == TEST_NI16); + g_assert (value_n32 == TEST_NI32); + g_assert (value_n64 == TEST_NI64); + g_assert (zigzag_p16 == 4); + g_assert (zigzag_p32 == 4); + g_assert (zigzag_p64 == 4); + g_assert (zigzag_n16 == 3); + g_assert (zigzag_n32 == 3); + g_assert (zigzag_n64 == 3); + g_assert (value_double == TEST_DOUBLE); + g_assert (strcmp (TEST_STRING, string) == 0); + g_assert (strcmp ("", empty_string) == 0); + g_assert (memcmp (comparator, binary, len) == 0); + + g_free (string); + g_free (empty_string); + g_free (binary); + + g_assert (thrift_compact_protocol_read_binary (protocol, &binary, + &len, NULL) > 0); + g_assert (binary == NULL); + g_assert (len == 0); + g_free (binary); + + thrift_transport_read_end (client, NULL); + thrift_transport_close (client, NULL); + + g_object_unref (tcp); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main (int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testcompactprotocol/CreateAndDestroy", + test_create_and_destroy); + g_test_add_func ("/testcompactprotocol/Initialize", test_initialize); + g_test_add_func ("/testcompactprotocol/ReadAndWritePrimitives", + test_read_and_write_primitives); + g_test_add_func ("/testcompactprotocol/ReadAndWriteComplexTypes", + test_read_and_write_complex_types); + g_test_add_func ("/testcompactprotocol/ReadAndWriteManyFrames", + test_read_and_write_many_frames); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c b/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c new file mode 100644 index 000000000..5fc51d516 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testcontainertest.c @@ -0,0 +1,529 @@ +/* + * 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 "gen-c_glib/t_test_container_test_types.h" +#include "gen-c_glib/t_test_container_service.h" + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol_factory.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol_factory.h> +#include <thrift/c_glib/server/thrift_server.h> +#include <thrift/c_glib/server/thrift_simple_server.h> +#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> + +#include <glib-object.h> +#include <glib.h> + +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <sys/wait.h> +#include <sys/types.h> + +#define TEST_SERVER_HOSTNAME "localhost" +#define TEST_SERVER_PORT 9090 + +/* -------------------------------------------------------------------------- + The ContainerService handler we'll use for testing */ + +G_BEGIN_DECLS + +GType test_container_service_handler_get_type (void); + +#define TYPE_TEST_CONTAINER_SERVICE_HANDLER \ + (test_container_service_handler_get_type ()) + +#define TEST_CONTAINER_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandler)) +#define TEST_CONTAINER_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_CAST ((c), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandlerClass)) +#define IS_TEST_CONTAINER_SERVICE_HANDLER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER)) +#define IS_TEST_CONTAINER_SERVICE_HANDLER_CLASS(c) \ + (G_TYPE_CHECK_CLASS_TYPE ((c), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER)) +#define TEST_CONTAINER_SERVICE_HANDLER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + TYPE_TEST_CONTAINER_SERVICE_HANDLER, \ + TestContainerServiceHandlerClass)) + +struct _TestContainerServiceHandler { + TTestContainerServiceHandler parent_instance; + + /* private */ + GPtrArray *string_list; +}; +typedef struct _TestContainerServiceHandler TestContainerServiceHandler; + +struct _TestContainerServiceHandlerClass { + TTestContainerServiceHandlerClass parent_class; +}; +typedef struct _TestContainerServiceHandlerClass + TestContainerServiceHandlerClass; + +G_END_DECLS + +/* -------------------------------------------------------------------------- */ + +G_DEFINE_TYPE (TestContainerServiceHandler, + test_container_service_handler, + T_TEST_TYPE_CONTAINER_SERVICE_HANDLER) + +/* A helper function used to append copies of strings to a string list */ +static void append_string_to_ptr_array (gpointer element, gpointer ptr_array) +{ + g_ptr_array_add ((GPtrArray *)ptr_array, g_strdup ((gchar *)element)); +} + +/* Accept a string list from the client and append its contents to our internal + list */ +static gboolean +test_container_service_handler_receive_string_list (TTestContainerServiceIf *iface, + const GPtrArray *stringList, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + + /* Append the client's strings to our own internal string list */ + g_ptr_array_foreach ((GPtrArray *)stringList, + append_string_to_ptr_array, + self->string_list); + + g_clear_error (error); + return TRUE; +} + +/* Return the contents of our internal string list to the client */ +static gboolean +test_container_service_handler_return_string_list (TTestContainerServiceIf *iface, + GPtrArray **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + + /* Return (copies of) the strings contained in our list */ + g_ptr_array_foreach (self->string_list, + append_string_to_ptr_array, + *_return); + + g_clear_error (error); + return TRUE; +} + +static gboolean +test_container_service_handler_return_list_string_list (TTestContainerServiceIf *iface, + GPtrArray **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + GPtrArray *nested_list; + + /* Return a list containing our list of strings */ + nested_list + = g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_ptr_array_add (nested_list, self->string_list); + g_ptr_array_ref (self->string_list); + + g_ptr_array_add (*_return, nested_list); + + g_clear_error (error); + return TRUE; +} + +static gboolean +test_container_service_handler_return_typedefd_list_string_list (TTestContainerServiceIf *iface, + TTestListStringList **_return, + GError **error) +{ + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (iface); + TTestStringList *nested_list; + + /* Return a list containing our list of strings */ + nested_list + = g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_ptr_array_add (nested_list, self->string_list); + g_ptr_array_ref (self->string_list); + + g_ptr_array_add (*_return, nested_list); + + g_clear_error (error); + return TRUE; +} + +static void +test_container_service_handler_finalize (GObject *object) { + TestContainerServiceHandler *self = TEST_CONTAINER_SERVICE_HANDLER (object); + + /* Destroy our internal containers */ + g_ptr_array_unref (self->string_list); + self->string_list = NULL; + + G_OBJECT_CLASS (test_container_service_handler_parent_class)-> + finalize (object); +} + +static void +test_container_service_handler_init (TestContainerServiceHandler *self) +{ + /* Create our internal containers */ + self->string_list = g_ptr_array_new_with_free_func (g_free); +} + +static void +test_container_service_handler_class_init (TestContainerServiceHandlerClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + TTestContainerServiceHandlerClass *parent_class = + T_TEST_CONTAINER_SERVICE_HANDLER_CLASS (klass); + + gobject_class->finalize = test_container_service_handler_finalize; + + parent_class->receive_string_list = + test_container_service_handler_receive_string_list; + parent_class->return_string_list = + test_container_service_handler_return_string_list; + parent_class->return_list_string_list = + test_container_service_handler_return_list_string_list; + parent_class->return_typedefd_list_string_list = + test_container_service_handler_return_typedefd_list_string_list; +} + +/* -------------------------------------------------------------------------- */ + +/* Our test server, declared globally so we can access it within a signal + handler */ +ThriftServer *server = NULL; + +/* A signal handler used to detect when the child process (the test suite) has + exited so we know to shut down the server and terminate ourselves */ +static void +sigchld_handler (int signal_number) +{ + THRIFT_UNUSED_VAR (signal_number); + + /* The child process (the tests) has exited or been terminated; shut down the + server gracefully */ + if (server != NULL) + thrift_server_stop (server); +} + +/* A helper function that executes a test case against a newly constructed + service client */ +static void +execute_with_service_client (void (*test_case)(TTestContainerServiceIf *, + GError **)) +{ + ThriftSocket *socket; + ThriftTransport *transport; + ThriftProtocol *protocol; + + TTestContainerServiceIf *client; + + GError *error = NULL; + + /* Create a client with which to access the server */ + socket = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", TEST_SERVER_HOSTNAME, + "port", TEST_SERVER_PORT, + NULL); + transport = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", socket, + NULL); + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, + NULL); + + thrift_transport_open (transport, &error); + g_assert_no_error (error); + + client = g_object_new (T_TEST_TYPE_CONTAINER_SERVICE_CLIENT, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + /* Execute the test against this client */ + (*test_case)(client, &error); + g_assert_no_error (error); + + /* Clean up and exit */ + thrift_transport_close (transport, NULL); + + g_object_unref (client); + g_object_unref (protocol); + g_object_unref (transport); + g_object_unref (socket); +} + +static void +test_containers_with_default_values (void) +{ + TTestContainersWithDefaultValues *default_values; + GPtrArray *string_list; + + /* Fetch a new ContainersWithDefaultValues struct and its StringList member */ + default_values = g_object_new (T_TEST_TYPE_CONTAINERS_WITH_DEFAULT_VALUES, + NULL); + g_object_get (default_values, + "StringList", &string_list, + NULL); + + /* Make sure the list has been populated with its default values */ + g_assert_cmpint (string_list->len, ==, 2); + g_assert_cmpstr (((gchar **)string_list->pdata)[0], ==, "Apache"); + g_assert_cmpstr (((gchar **)string_list->pdata)[1], ==, "Thrift"); + + g_ptr_array_unref (string_list); + g_object_unref (default_values); +} + +static void +test_container_service_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + gchar *test_data[] = { "one", "two", "three" }; + + GPtrArray *outgoing_string_list; + GPtrArray *incoming_string_list; + guint index; + + g_clear_error (error); + + /* Prepare our test data (our string list to send) */ + outgoing_string_list = g_ptr_array_new (); + for (index = 0; index < 3; index += 1) + g_ptr_array_add (outgoing_string_list, &test_data[index]); + + /* Send our data to the server and make sure we get the same data back on + retrieve */ + g_assert + (t_test_container_service_client_receive_string_list (client, + outgoing_string_list, + error) && + *error == NULL); + + incoming_string_list = g_ptr_array_new (); + g_assert + (t_test_container_service_client_return_string_list (client, + &incoming_string_list, + error) && + *error == NULL); + + /* Make sure the two lists are equivalent */ + g_assert_cmpint (incoming_string_list->len, ==, outgoing_string_list->len); + for (index = 0; index < incoming_string_list->len; index += 1) + g_assert_cmpstr (((gchar **)incoming_string_list->pdata)[index], + ==, + ((gchar **)outgoing_string_list->pdata)[index]); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_string_list); + g_ptr_array_unref (outgoing_string_list); +} + +static void +test_container_service_string_list (void) +{ + execute_with_service_client (test_container_service_string_list_inner); +} + +static void +test_container_service_list_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + GPtrArray *incoming_list; + GPtrArray *nested_list; + + g_clear_error (error); + + /* Receive a list of string lists from the server */ + incoming_list = + g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_assert + (t_test_container_service_client_return_list_string_list (client, + &incoming_list, + error) && + *error == NULL); + + /* Make sure the list and its contents are valid */ + g_assert_cmpint (incoming_list->len, >, 0); + + nested_list = (GPtrArray *)g_ptr_array_index (incoming_list, 0); + g_assert (nested_list != NULL); + g_assert_cmpint (nested_list->len, >=, 0); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_list); +} + +static void +test_container_service_list_string_list (void) +{ + execute_with_service_client (test_container_service_list_string_list_inner); +} + +static void +test_container_service_typedefd_list_string_list_inner (TTestContainerServiceIf *client, + GError **error) +{ + TTestListStringList *incoming_list; + TTestStringList *nested_list; + + g_clear_error (error); + + /* Receive a list of string lists from the server */ + incoming_list = + g_ptr_array_new_with_free_func ((GDestroyNotify)g_ptr_array_unref); + g_assert + (t_test_container_service_client_return_list_string_list (client, + &incoming_list, + error) && + *error == NULL); + + /* Make sure the list and its contents are valid */ + g_assert_cmpint (incoming_list->len, >, 0); + + nested_list = (TTestStringList *)g_ptr_array_index (incoming_list, 0); + g_assert (nested_list != NULL); + g_assert_cmpint (nested_list->len, >=, 0); + + /* Clean up and exit */ + g_ptr_array_unref (incoming_list); +} + +static void +test_container_service_typedefd_list_string_list (void) +{ + execute_with_service_client + (test_container_service_typedefd_list_string_list_inner); +} + +int +main(int argc, char *argv[]) +{ + pid_t pid; + int status; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + /* Fork to run our test suite in a child process */ + pid = fork (); + g_assert_cmpint (pid, >=, 0); + + if (pid == 0) { /* The child process */ + /* Wait a moment for the server to finish starting */ + sleep (1); + + g_test_init (&argc, &argv, NULL); + + g_test_add_func + ("/testcontainertest/ContainerTest/Structs/ContainersWithDefaultValues", + test_containers_with_default_values); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/StringList", + test_container_service_string_list); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/ListStringList", + test_container_service_list_string_list); + g_test_add_func + ("/testcontainertest/ContainerTest/Services/ContainerService/TypedefdListStringList", + test_container_service_typedefd_list_string_list); + + /* Run the tests and make the result available to our parent process */ + _exit (g_test_run ()); + } + else { + TTestContainerServiceHandler *handler; + TTestContainerServiceProcessor *processor; + + ThriftServerTransport *server_transport; + ThriftTransportFactory *transport_factory; + ThriftProtocolFactory *protocol_factory; + + struct sigaction sigchld_action; + + GError *error = NULL; + int exit_status = 1; + + /* Trap the event of the child process terminating so we know to stop the + server and exit */ + memset (&sigchld_action, 0, sizeof (sigchld_action)); + sigchld_action.sa_handler = sigchld_handler; + sigchld_action.sa_flags = SA_RESETHAND; + sigaction (SIGCHLD, &sigchld_action, NULL); + + /* Create our test server */ + handler = g_object_new (TYPE_TEST_CONTAINER_SERVICE_HANDLER, + NULL); + processor = g_object_new (T_TEST_TYPE_CONTAINER_SERVICE_PROCESSOR, + "handler", handler, + NULL); + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", TEST_SERVER_PORT, + NULL); + transport_factory = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY, + NULL); + protocol_factory = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL_FACTORY, + NULL); + + server = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, + "processor", processor, + "server_transport", server_transport, + "input_transport_factory", transport_factory, + "output_transport_factory", transport_factory, + "input_protocol_factory", protocol_factory, + "output_protocol_factory", protocol_factory, + NULL); + + /* Start the server */ + thrift_server_serve (server, &error); + + /* Make sure the server stopped only because it was interrupted (by the + child process terminating) */ + g_assert(!error || g_error_matches(error, + THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_ACCEPT)); + + /* Free our resources */ + g_clear_object (&server); + g_clear_object (&protocol_factory); + g_clear_object (&transport_factory); + g_clear_object (&server_transport); + g_clear_object (&processor); + g_clear_object (&handler); + + /* Wait for the child process to complete and return its exit status */ + g_assert (wait (&status) == pid); + if (WIFEXITED (status)) + exit_status = WEXITSTATUS (status); + + return exit_status; + } +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c b/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c new file mode 100644 index 000000000..109a48b50 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testdebugproto.c @@ -0,0 +1,941 @@ +/* + * 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 <math.h> +#include <string.h> +#include <glib-object.h> + +#ifndef M_PI +#define M_PI 3.1415926535897932385 +#endif + +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> + +#include "gen-c_glib/t_test_debug_proto_test_types.h" +#include "gen-c_glib/t_test_srv.h" +#include "gen-c_glib/t_test_inherited.h" + +static void +test_structs_doubles_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Doubles structure can be created... */ + object = g_object_new (T_TEST_TYPE_DOUBLES, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_DOUBLES (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_doubles_initialize (void) +{ + TTestDoubles *doubles = NULL; + gdouble nan; + gdouble inf; + gdouble neginf; + gdouble repeating; + gdouble big; + gdouble tiny; + gdouble zero; + gdouble negzero; + + /* Note there seems to be no way to get not-a-number ("NAN") values past + GObject's range-checking, so that portion of the test has been commented + out below. */ + + /* A Doubles structure's members are available as GObject properties + that can be initialized at construction... */ + doubles = g_object_new (T_TEST_TYPE_DOUBLES, + /* "nan", 0 * INFINITY, */ + "inf", INFINITY, + "neginf", -INFINITY, + "repeating", 1.0 / 3, + "big", G_MAXDOUBLE, + "tiny", 10E-101, + "zero", 1.0 * 0, + "negzero", -1.0 * 0, + NULL); + + g_assert (doubles != NULL); + + /* ...and later retrieved */ + g_object_get (doubles, + "nan", &nan, + "inf", &inf, + "neginf", &neginf, + "repeating", &repeating, + "big", &big, + "tiny", &tiny, + "zero", &zero, + "negzero", &negzero, + NULL); + + /* g_assert_cmpint (isnan (nan), !=, 0); */ + g_assert_cmpint (isinf (inf), ==, 1); + g_assert_cmpint (isinf (neginf), ==, -1); + + g_assert_cmpfloat (repeating, ==, 1.0 / 3); + g_assert_cmpfloat (big, ==, G_MAXDOUBLE); + g_assert_cmpfloat (tiny, ==, 10E-101); + g_assert_cmpfloat (zero, ==, 1.0 * 0); + g_assert_cmpfloat (negzero, ==, -1.0 * 0); + + g_object_unref (doubles); +} + +static void +test_structs_one_of_each_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A OneOfEach structure can be created... */ + object = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_one_of_each_initialize_default_values (void) +{ + TTestOneOfEach *one_of_each = NULL; + gint a_bite; + gint integer16; + gint64 integer64; + GArray *byte_list; + GArray *i16_list; + GArray *i64_list; + + /* A OneOfEach structure created with no explicit property values + will hold the default values specified in the .thrift file */ + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + "integer64", &integer64, + "byte_list", &byte_list, + "i16_list", &i16_list, + "i64_list", &i64_list, + NULL); + + g_assert_cmpint (a_bite, ==, 0x7f); + g_assert_cmpint (integer16, ==, 0x7fff); + g_assert_cmpint (integer64, ==, G_GINT64_CONSTANT (10000000000)); + + g_assert (byte_list != NULL); + g_assert_cmpint (byte_list->len, ==, 3); + g_assert_cmpint (g_array_index (byte_list, gint8, 0), ==, 1); + g_assert_cmpint (g_array_index (byte_list, gint8, 1), ==, 2); + g_assert_cmpint (g_array_index (byte_list, gint8, 2), ==, 3); + + g_assert (i16_list != NULL); + g_assert_cmpint (i16_list->len, ==, 3); + g_assert_cmpint (g_array_index (i16_list, gint16, 0), ==, 1); + g_assert_cmpint (g_array_index (i16_list, gint16, 1), ==, 2); + g_assert_cmpint (g_array_index (i16_list, gint16, 2), ==, 3); + + g_assert (i64_list != NULL); + g_assert_cmpint (i64_list->len, ==, 3); + g_assert_cmpint (g_array_index (i64_list, gint64, 0), ==, 1); + g_assert_cmpint (g_array_index (i64_list, gint64, 1), ==, 2); + g_assert_cmpint (g_array_index (i64_list, gint64, 2), ==, 3); + + g_array_unref (i64_list); + g_array_unref (i16_list); + g_array_unref (byte_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_initialize_specified_values (void) +{ + static const gint8 initial_byte_list[5] = { 13, 21, 34, 55, 89 }; + static const gint16 initial_i16_list[5] = { 4181, 6765, 10946, 17711, 28657 }; + static const gint64 initial_i64_list[5] = + { + G_GINT64_CONSTANT (1100087778366101931), + G_GINT64_CONSTANT (1779979416004714189), + G_GINT64_CONSTANT (2880067194370816120), + G_GINT64_CONSTANT (4660046610375530309), + G_GINT64_CONSTANT (7540113804746346429) + }; + static const guint8 initial_base64[8] = + { + 0x56, 0x47, 0x68, 0x79, 0x61, 0x57, 0x5a, 0x30 + }; + + TTestOneOfEach *one_of_each; + gboolean im_true; + gboolean im_false; + gint a_bite; + gint integer16; + gint integer32; + gint64 integer64; + double double_precision; + gchar *some_characters; + gchar *zomg_unicode; + gboolean what_who; + GByteArray *base64; + GArray *byte_list; + GArray *i16_list; + GArray *i64_list; + + base64 = g_byte_array_new (); + g_byte_array_append (base64, initial_base64, 8); + + byte_list = g_array_new (FALSE, FALSE, sizeof (gint8)); + g_array_append_vals (byte_list, initial_byte_list, 5); + + i16_list = g_array_new (FALSE, FALSE, sizeof (gint16)); + g_array_append_vals (i16_list, initial_i16_list, 5); + + i64_list = g_array_new (FALSE, FALSE, sizeof (gint64)); + g_array_append_vals (i64_list, initial_i64_list, 5); + + /* All of OneOfEach's properties can be set at construction... */ + one_of_each = + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "im_true", TRUE, + "im_false", FALSE, + "a_bite", 0x50, + "integer16", 0x7e57, + "integer32", 0xdeadbeef, + "integer64", G_GINT64_CONSTANT (0xfa15efacade15bad), + "double_precision", M_PI, + "some_characters", "Debug THIS!", + "zomg_unicode", "\xd7\n\a\t", + "what_who", TRUE, + "base64", base64, + "byte_list", byte_list, + "i16_list", i16_list, + "i64_list", i64_list, + NULL); + g_assert (one_of_each != NULL); + + g_array_unref (i64_list); + i64_list = NULL; + g_array_unref (i16_list); + i16_list = NULL; + g_array_unref (byte_list); + byte_list = NULL; + g_byte_array_unref (base64); + base64 = NULL; + + /* ...and later retrieved */ + g_object_get (one_of_each, + "im_true", &im_true, + "im_false", &im_false, + "a_bite", &a_bite, + "integer16", &integer16, + "integer32", &integer32, + "integer64", &integer64, + "double_precision", &double_precision, + "some_characters", &some_characters, + "zomg_unicode", &zomg_unicode, + "what_who", &what_who, + "base64", &base64, + "byte_list", &byte_list, + "i16_list", &i16_list, + "i64_list", &i64_list, + NULL); + + g_assert (im_true == TRUE); + g_assert (im_false == FALSE); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x7e57); + g_assert_cmphex (integer32, ==, (gint32)0xdeadbeef); + g_assert_cmphex (integer64, ==, G_GINT64_CONSTANT (0xfa15efacade15bad)); + + g_assert_cmpfloat (double_precision, ==, M_PI); + + g_assert_cmpstr (some_characters, ==, "Debug THIS!"); + g_assert_cmpstr (zomg_unicode, ==, "\xd7\n\a\t"); + + g_assert (what_who == TRUE); + + g_assert_cmpint (base64->len, ==, 8); + g_assert_cmpint (memcmp (base64->data, + initial_base64, + 8 * sizeof (guint8)), ==, 0); + + g_assert_cmpint (byte_list->len, ==, 5); + g_assert_cmpint (memcmp (byte_list->data, + initial_byte_list, + 5 * sizeof (gint8)), ==, 0); + + g_assert_cmpint (i16_list->len, ==, 5); + g_assert_cmpint (memcmp (i16_list->data, + initial_i16_list, + 5 * sizeof (gint16)), ==, 0); + + g_assert_cmpint (i64_list->len, ==, 5); + g_assert_cmpint (memcmp (i64_list->data, + initial_i64_list, + 5 * sizeof (gint64)), ==, 0); + + g_array_unref (i64_list); + g_array_unref (i16_list); + g_array_unref (byte_list); + g_byte_array_unref (base64); + + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_byte_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *byte_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "byte_list" member is a list that holds eight-bit-wide integer + values */ + g_object_get (one_of_each, "byte_list", &byte_list, NULL); + + g_assert (byte_list != NULL); + g_assert_cmpint (g_array_get_element_size (byte_list), ==, sizeof (gint8)); + + g_array_unref (byte_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_i16_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *i16_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "i16_list" member is a list that holds sixteen-bit-wide integer + values */ + g_object_get (one_of_each, "i16_list", &i16_list, NULL); + + g_assert (i16_list != NULL); + g_assert_cmpint (g_array_get_element_size (i16_list), ==, sizeof (gint16)); + + g_array_unref (i16_list); + g_object_unref (one_of_each); +} + +static void +test_structs_one_of_each_properties_i64_list (void) +{ + TTestOneOfEach *one_of_each; + GArray *i64_list = NULL; + + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL); + + /* OneOfEach's "i64_list" member is a list that holds sixty-four-bit-wide + integer values */ + g_object_get (one_of_each, "i64_list", &i64_list, NULL); + + g_assert (i64_list != NULL); + g_assert_cmpint (g_array_get_element_size (i64_list), ==, sizeof (gint64)); + + g_array_unref (i64_list); + g_object_unref (one_of_each); +} + +static void +test_structs_nesting_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Nesting structure can be created... */ + object = g_object_new (T_TEST_TYPE_NESTING, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_NESTING (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_nesting_properties_my_bonk (void) +{ + TTestNesting *nesting; + TTestBonk *bonk = NULL; + gint type; + gchar *message; + + nesting = g_object_new (T_TEST_TYPE_NESTING, NULL); + + /* Nesting's "my_bonk" member is initialized with a new, default Bonk object + during construction */ + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk != NULL); + g_assert (T_TEST_IS_BONK (bonk)); + + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 0); + g_assert (message == NULL); + + g_object_unref (bonk); + bonk = NULL; + + /* It can be replaced... */ + bonk = g_object_new (T_TEST_TYPE_BONK, + "type", 100, + "message", "Replacement Bonk", + NULL); + g_object_set (nesting, "my_bonk", bonk, NULL); + g_object_unref (bonk); + bonk = NULL; + + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk != NULL); + g_assert (T_TEST_IS_BONK (bonk)); + + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 100); + g_assert_cmpstr (message, ==, "Replacement Bonk"); + + g_free (message); + g_object_unref (bonk); + bonk = NULL; + + /* ...or set to null */ + g_object_set (nesting, "my_bonk", NULL, NULL); + g_object_get (nesting, "my_bonk", &bonk, NULL); + + g_assert (bonk == NULL); + + g_object_unref (nesting); +} + +static void +test_structs_nesting_properties_my_ooe (void) +{ + TTestNesting *nesting; + TTestOneOfEach *one_of_each = NULL; + gint a_bite; + gint integer16; + + nesting = g_object_new (T_TEST_TYPE_NESTING, NULL); + + /* Nesting's "my_ooe" member is initialized with a new, default OneOfEach + object during construction */ + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each)); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x7f); + g_assert_cmphex (integer16, ==, 0x7fff); + + g_object_unref (one_of_each); + one_of_each = NULL; + + /* It can be replaced... */ + one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x50, + "integer16", 0x5050, + NULL); + g_object_set (nesting, "my_ooe", one_of_each, NULL); + g_object_unref (one_of_each); + one_of_each = NULL; + + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each != NULL); + g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each)); + + g_object_get (one_of_each, + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x5050); + + g_object_unref (one_of_each); + one_of_each = NULL; + + /* ...or set to null */ + g_object_set (nesting, "my_ooe", NULL, NULL); + g_object_get (nesting, "my_ooe", &one_of_each, NULL); + + g_assert (one_of_each == NULL); + + g_object_unref (nesting); +} + +static void +test_structs_holy_moley_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A HolyMoley structure can be created... */ + object = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_HOLY_MOLEY (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_holy_moley_properties_big (void) +{ + TTestHolyMoley *holy_moley; + GPtrArray *big = NULL; + gint a_bite = 0; + gint integer16 = 0; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "big" member is is initialized on construction */ + g_object_get (holy_moley, "big", &big, NULL); + + g_assert (big != NULL); + g_assert_cmpint (big->len, ==, 0); + + /* It can be modified... */ + g_ptr_array_add (big, + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x50, + "integer16", 0x5050, + NULL)); + + g_ptr_array_unref (big); + big = NULL; + + g_object_get (holy_moley, "big", &big, NULL); + + g_assert_cmpint (big->len, ==, 1); + g_object_get (g_ptr_array_index (big, 0), + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x50); + g_assert_cmphex (integer16, ==, 0x5050); + + g_ptr_array_unref (big); + big = NULL; + + /* ...replaced... */ + big = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (big, + g_object_new (T_TEST_TYPE_ONE_OF_EACH, + "a_bite", 0x64, + "integer16", 0x1541, + NULL)); + + g_object_set (holy_moley, "big", big, NULL); + + g_ptr_array_unref (big); + big = NULL; + + g_object_get (holy_moley, "big", &big, NULL); + + g_assert_cmpint (big->len, ==, 1); + g_object_get (g_ptr_array_index (big, 0), + "a_bite", &a_bite, + "integer16", &integer16, + NULL); + + g_assert_cmphex (a_bite, ==, 0x64); + g_assert_cmphex (integer16, ==, 0x1541); + + g_ptr_array_unref (big); + big = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "big", NULL, NULL); + g_object_get (holy_moley, "big", &big, NULL); + + g_assert (big == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_holy_moley_properties_contain (void) +{ + static gchar *strings[2] = { "Apache", "Thrift" }; + + TTestHolyMoley *holy_moley; + GHashTable *contain = NULL; + GPtrArray *string_list; + GList *key_list; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "contain" member is initialized on construction */ + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert (contain != NULL); + g_assert_cmpint (g_hash_table_size (contain), ==, 0); + + /* It can be modified... */ + string_list = g_ptr_array_new (); + g_ptr_array_add (string_list, strings[0]); + g_ptr_array_add (string_list, strings[1]); + + g_hash_table_insert (contain, string_list, NULL); + string_list = NULL; + + g_hash_table_unref (contain); + contain = NULL; + + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert_cmpint (g_hash_table_size (contain), ==, 1); + + key_list = g_hash_table_get_keys (contain); + string_list = g_list_nth_data (key_list, 0); + + g_assert_cmpint (string_list->len, ==, 2); + g_assert_cmpstr (g_ptr_array_index (string_list, 0), ==, "Apache"); + g_assert_cmpstr (g_ptr_array_index (string_list, 1), ==, "Thrift"); + + g_list_free (key_list); + g_hash_table_unref (contain); + contain = NULL; + + /* ...replaced... */ + contain = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + (GDestroyNotify) g_ptr_array_unref, + NULL); + g_object_set (holy_moley, "contain", contain, NULL); + g_hash_table_unref (contain); + contain = NULL; + + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert_cmpint (g_hash_table_size (contain), ==, 0); + + g_hash_table_unref (contain); + contain = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "contain", NULL, NULL); + g_object_get (holy_moley, "contain", &contain, NULL); + + g_assert (contain == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_holy_moley_properties_bonks (void) +{ + TTestHolyMoley *holy_moley; + GHashTable *bonks = NULL; + GPtrArray *bonk_list = NULL; + TTestBonk *bonk = NULL; + gint type; + gchar *message; + GList *key_list; + + holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL); + + /* A HolyMoley's "bonks" member is initialized on construction */ + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert (bonks != NULL); + g_assert_cmpint (g_hash_table_size (bonks), ==, 0); + + /* It can be modified... */ + bonk = g_object_new (T_TEST_TYPE_BONK, + "type", 100, + "message", "Sample Bonk", + NULL); + bonk_list = g_ptr_array_new_with_free_func (g_object_unref); + g_ptr_array_add (bonk_list, bonk); + bonk = NULL; + + g_hash_table_insert (bonks, g_strdup ("Sample Bonks"), bonk_list); + bonk_list = NULL; + + g_hash_table_unref (bonks); + bonks = NULL; + + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert_cmpint (g_hash_table_size (bonks), ==, 1); + + key_list = g_hash_table_get_keys (bonks); + bonk_list = g_hash_table_lookup (bonks, g_list_nth_data (key_list, 0)); + + g_assert_cmpint (bonk_list->len, ==, 1); + + bonk = (g_ptr_array_index (bonk_list, 0)); + g_object_get (bonk, + "type", &type, + "message", &message, + NULL); + + g_assert_cmpint (type, ==, 100); + g_assert_cmpstr (message, ==, "Sample Bonk"); + + bonk = NULL; + g_free (message); + g_list_free (key_list); + g_hash_table_unref (bonks); + bonks = NULL; + + /* ...replaced... */ + bonks = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_ptr_array_unref); + g_object_set (holy_moley, "bonks", bonks, NULL); + g_hash_table_unref (bonks); + bonks = NULL; + + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert_cmpint (g_hash_table_size (bonks), ==, 0); + + g_hash_table_unref (bonks); + bonks = NULL; + + /* ...or set to NULL */ + g_object_set (holy_moley, "bonks", NULL, NULL); + g_object_get (holy_moley, "bonks", &bonks, NULL); + + g_assert (bonks == NULL); + + g_object_unref (holy_moley); +} + +static void +test_structs_empty (void) +{ + GObject *object = NULL; + GParamSpec **properties; + guint property_count; + + /* An Empty structure can be created */ + object = g_object_new (T_TEST_TYPE_EMPTY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_EMPTY (object)); + + /* An Empty structure has no members and thus no properties */ + properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (object), + &property_count); + g_assert_cmpint (property_count, ==, 0); + g_free (properties); + + /* An Empty structure can be destroyed */ + g_object_unref (object); +} + +static void +test_structs_wrapper_create_and_destroy (void) +{ + GObject *object = NULL; + + /* A Wrapper structure can be created... */ + object = g_object_new (T_TEST_TYPE_EMPTY, NULL); + + g_assert (object != NULL); + g_assert (T_TEST_IS_EMPTY (object)); + + /* ...and destroyed */ + g_object_unref (object); +} + +static void +test_structs_wrapper_properties_foo (void) { + TTestWrapper *wrapper; + TTestEmpty *foo; + + wrapper = g_object_new (T_TEST_TYPE_WRAPPER, NULL); + + /* A Wrapper structure has one member, "foo", which is an Empty + structure initialized during construction */ + g_object_get (wrapper, "foo", &foo, NULL); + + g_assert (foo != NULL); + g_assert (T_TEST_IS_EMPTY (foo)); + + g_object_unref (foo); + foo = NULL; + + /* A Wrapper's foo property can be replaced... */ + foo = g_object_new (T_TEST_TYPE_EMPTY, NULL); + g_object_set (wrapper, "foo", foo, NULL); + + g_object_unref (foo); + foo = NULL; + + g_object_get (wrapper, "foo", &foo, NULL); + g_assert (foo != NULL); + g_assert (T_TEST_IS_EMPTY (foo)); + + g_object_unref (foo); + foo = NULL; + + /* ...or set to NULL */ + g_object_set (wrapper, "foo", NULL, NULL); + g_object_get (wrapper, "foo", &foo, NULL); + + g_assert (foo == NULL); + + g_object_unref (wrapper); +} + +static void +test_services_inherited (void) +{ + ThriftProtocol *protocol; + TTestInheritedClient *inherited_client; + GObject *input_protocol, *output_protocol; + + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL); + inherited_client = g_object_new (T_TEST_TYPE_INHERITED_CLIENT, + NULL); + + /* TTestInheritedClient inherits from TTestSrvClient */ + g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT, + T_TEST_TYPE_SRV_CLIENT)); + + /* TTestInheritedClient implements TTestSrvClient's interface */ + g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT, + T_TEST_TYPE_SRV_IF)); + + /* TTestInheritedClient's inherited properties can be set and retrieved */ + g_object_set (inherited_client, + "input_protocol", protocol, + "output_protocol", protocol, + NULL); + + g_object_get (inherited_client, + "input_protocol", &input_protocol, + "output_protocol", &output_protocol, + NULL); + + g_assert (input_protocol == G_OBJECT(protocol)); + g_assert (output_protocol == G_OBJECT(protocol)); + + g_object_unref (output_protocol); + g_object_unref (input_protocol); + g_object_unref (inherited_client); + g_object_unref (protocol); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Doubles/CreateAndDestroy", + test_structs_doubles_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Doubles/Initialize", + test_structs_doubles_initialize); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/CreateAndDestroy", + test_structs_one_of_each_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/DefaultValues", + test_structs_one_of_each_initialize_default_values); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/SpecifiedValues", + test_structs_one_of_each_initialize_specified_values); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/byte_list", + test_structs_one_of_each_properties_byte_list); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i16_list", + test_structs_one_of_each_properties_i16_list); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i64_list", + test_structs_one_of_each_properties_i64_list); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/CreateAndDestroy", + test_structs_nesting_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_bonk", + test_structs_nesting_properties_my_bonk); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_ooe", + test_structs_nesting_properties_my_ooe); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/CreateAndDestroy", + test_structs_holy_moley_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/big", + test_structs_holy_moley_properties_big); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/contain", + test_structs_holy_moley_properties_contain); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/bonks", + test_structs_holy_moley_properties_bonks); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Empty", + test_structs_empty); + + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Wrapper/CreateAndDestroy", + test_structs_wrapper_create_and_destroy); + g_test_add_func + ("/testdebugproto/DebugProto/Structs/Wrapper/Properties/foo", + test_structs_wrapper_properties_foo); + + g_test_add_func + ("/testdebugproto/DebugProto/Services/Inherited", + test_services_inherited); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c new file mode 100755 index 000000000..1ea89be78 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testfdtransport.c @@ -0,0 +1,184 @@ +/* + * 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 <string.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <glib.h> +#include <glib/gstdio.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_fd_transport.h> + +static const gchar TEST_DATA[12] = "abcde01234!"; + +static void +test_create_and_destroy (void) +{ + GObject *object; + object = g_object_new (THRIFT_TYPE_FD_TRANSPORT, "fd", -1, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_open_and_close (void) +{ + ThriftTransport *transport; + ThriftTransportClass *klass; + GError *error; + gint fd; + gchar *filename; + + error = NULL; + filename = NULL; + + fd = g_file_open_tmp (NULL, &filename, &error); + g_assert (fd >= 0); + + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + /* open is no-op */ + g_assert (klass->is_open (transport)); + g_assert (klass->peek (transport, &error)); + g_assert (klass->open (transport, &error)); + g_assert (klass->is_open (transport)); + g_assert (klass->peek (transport, &error)); + + g_assert (klass->close (transport, &error)); + g_assert (! klass->open (transport, &error)); + g_assert (! klass->is_open (transport)); + g_assert (! klass->peek (transport, &error)); + + /* already closed */ + g_assert (close (fd) != 0); + g_assert (errno == EBADF); + + g_object_unref (transport); + + g_remove (filename); + g_free (filename); + + /* test bad fd */ + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", -1, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + g_assert (! klass->is_open (transport)); + error = NULL; + g_assert (! klass->peek (transport, &error)); + error = NULL; + g_assert (! klass->open (transport, &error)); + error = NULL; + g_assert (! klass->close (transport, &error)); + + g_object_unref (transport); +} + +static void +test_read_and_write (void) +{ + gchar out_buf[8]; + gchar *b; + gint want, got; + ThriftTransport *transport; + ThriftTransportClass *klass; + GError *error; + gint fd; + gchar *filename; + + error = NULL; + filename = NULL; + + fd = g_file_open_tmp (NULL, &filename, &error); + g_assert (fd >= 0); + + /* write */ + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + g_assert (klass->is_open (transport)); + g_assert (klass->write (transport, (gpointer) TEST_DATA, 11, &error)); + g_assert (klass->flush (transport, &error)); + g_assert (klass->close (transport, &error)); + g_object_unref (transport); + + /* read */ + fd = open(filename, O_RDONLY, S_IRUSR | S_IWUSR); + g_assert (fd >= 0); + + transport = THRIFT_TRANSPORT (g_object_new (THRIFT_TYPE_FD_TRANSPORT, + "fd", fd, + NULL)); + klass = THRIFT_TRANSPORT_GET_CLASS (transport); + + memset(out_buf, 0, 8); + b = out_buf; + want = 7; + while (want > 0) { + got = klass->read (transport, (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + b += got; + want -= got; + } + g_assert (memcmp (out_buf, TEST_DATA, 7) == 0); + + memset(out_buf, 0, 8); + b = out_buf; + want = 4; + while (want > 0) { + got = klass->read (transport, (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + b += got; + want -= got; + } + g_assert (memcmp (out_buf, TEST_DATA + 7, 4) == 0); + + g_assert (klass->close (transport, &error)); + g_object_unref (transport); + + /* clean up */ + + g_remove (filename); + g_free (filename); +} + +int +main (int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testfdtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testfdtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testfdtransport/ReadAndWrite", test_read_and_write); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c b/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c new file mode 100755 index 000000000..008e61e40 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testframedtransport.c @@ -0,0 +1,323 @@ +/* + * 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 <netdb.h> +#include <sys/wait.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +#include "../src/thrift/c_glib/transport/thrift_framed_transport.c" + +static void thrift_server (const int port); +static void thrift_socket_server_open (const int port, int times); + +/* test object creation and destruction */ +static void +test_create_and_destroy(void) +{ + ThriftTransport *transport = NULL; + guint r_buf_size = 0; + guint w_buf_size = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT (object), "transport", &transport, + "r_buf_size", &r_buf_size, + "w_buf_size", &w_buf_size, NULL); + g_object_unref (object); +} + +static void +test_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + pid_t pid; + int port = 51199; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port,1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + /* create a ThriftSocket */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + /* this shouldn't work */ + g_assert (thrift_framed_transport_open (transport, NULL) == TRUE); + g_assert (thrift_framed_transport_is_open (transport) == TRUE); + g_assert (thrift_framed_transport_close (transport, NULL) == TRUE); + g_object_unref (transport); + g_object_unref (tsocket); + + /* try and underlying socket failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + + /* create a BufferedTransport wrapper of the Socket */ + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), NULL); + + g_assert (thrift_framed_transport_open (transport, &err) == FALSE); + g_object_unref (transport); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + int status; + pid_t pid; + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + int port = 51199; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 4, NULL); + + g_assert (thrift_framed_transport_open (transport, NULL) == TRUE); + g_assert (thrift_framed_transport_is_open (transport)); + + /* write 10 bytes */ + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 1, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write (transport, buf, 10, NULL); + thrift_framed_transport_flush (transport, NULL); + + thrift_framed_transport_write_end (transport, NULL); + thrift_framed_transport_flush (transport, NULL); + thrift_framed_transport_close (transport, NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +/* test reading from the transport after the peer has unexpectedly + closed the connection */ +static void +test_read_after_peer_close(void) +{ + int status; + pid_t pid; + int port = 51199; + GError *err = NULL; + + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + ThriftServerTransport *server_transport = NULL; + ThriftTransport *client_transport = NULL; + + /* child listens */ + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + g_assert (server_transport != NULL); + + thrift_server_transport_listen (server_transport, &err); + g_assert (err == NULL); + + /* wrap the client transport in a ThriftFramedTransport */ + client_transport = g_object_new + (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", thrift_server_transport_accept (server_transport, &err), + "r_buf_size", 0, + NULL); + g_assert (err == NULL); + g_assert (client_transport != NULL); + + /* close the connection immediately after the client connects */ + thrift_transport_close (client_transport, NULL); + + g_object_unref (client_transport); + g_object_unref (server_transport); + + exit (0); + } else { + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + guchar buf[10]; /* a buffer */ + + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", port, + NULL); + transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, + "transport", THRIFT_TRANSPORT (tsocket), + "w_buf_size", 0, + NULL); + + g_assert (thrift_transport_open (transport, NULL) == TRUE); + g_assert (thrift_transport_is_open (transport)); + + /* attempting to read from the transport after the peer has closed + the connection fails gracefully without generating a critical + warning or segmentation fault */ + thrift_transport_read (transport, buf, 10, &err); + g_assert (err != NULL); + + g_error_free (err); + err = NULL; + + thrift_transport_read_end (transport, &err); + g_assert (err == NULL); + + thrift_transport_close (transport, &err); + g_assert (err == NULL); + + g_object_unref (transport); + g_object_unref (tsocket); + + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + int i; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + for(i=0;i<times;i++){ + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + thrift_socket_close (client, NULL); + g_object_unref (client); + } + g_object_unref (tsocket); +} + +static void +thrift_server (const int port) +{ + int bytes = 0; + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + guchar buf[12]; /* a buffer */ + guchar match[10] = TEST_DATA; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + + /* wrap the client in a BufferedTransport */ + client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport", + thrift_server_transport_accept (transport, NULL), + "r_buf_size", 5, NULL); + g_assert (client != NULL); + + /* read 10 bytes */ + bytes = thrift_framed_transport_read (client, buf, 10, NULL); + g_assert (bytes == 10); /* make sure we've read 10 bytes */ + g_assert ( memcmp (buf, match, 10) == 0 ); /* make sure what we got matches */ + + bytes = thrift_framed_transport_read (client, buf, 6, NULL); + bytes = thrift_framed_transport_read (client, buf, 5, NULL); + bytes = thrift_framed_transport_read (client, buf, 1, NULL); + + bytes = thrift_framed_transport_read (client, buf, 12, NULL); + + thrift_framed_transport_read_end (client, NULL); + thrift_framed_transport_close (client, NULL); + g_object_unref (client); + g_object_unref (tsocket); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testframedtransport/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testframedtransport/OpenAndClose", test_open_and_close); + g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testframedtransport/ReadAfterPeerClose", test_read_after_peer_close); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c b/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c new file mode 100755 index 000000000..9fb68b93d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testmemorybuffer.c @@ -0,0 +1,223 @@ +/* + * 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 <netdb.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +static const gchar TEST_DATA[11] = "abcdefghij"; + +#include "../src/thrift/c_glib/transport/thrift_memory_buffer.c" + +/* test object creation and destruction */ +static void +test_create_and_destroy (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf_size", 10, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_large (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf_size", 10 * 1024 * 1024, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_default (void) +{ + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_external (void) +{ + GObject *object = NULL; + GByteArray *buf = g_byte_array_new (); + g_assert (buf != NULL); + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "buf", buf, + NULL); + g_assert (object != NULL); + g_object_unref (object); +} + +static void +test_create_and_destroy_unowned (void) +{ + GObject *object = NULL; + GValue val = G_VALUE_INIT; + GByteArray *buf; + + object = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, + "owner", FALSE, + NULL); + g_assert (object != NULL); + + g_value_init (&val, G_TYPE_POINTER); + g_object_get_property (object, "buf", &val); + buf = (GByteArray*) g_value_get_pointer (&val); + g_assert (buf != NULL); + + g_byte_array_unref (buf); + g_value_unset (&val); + g_object_unref (object); +} + +static void +test_open_and_close (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + + /* create a ThriftMemoryBuffer */ + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + + /* no-ops */ + g_assert (thrift_memory_buffer_open (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE); + g_assert (thrift_memory_buffer_is_open (THRIFT_TRANSPORT (tbuffer)) == TRUE); + g_assert (thrift_memory_buffer_close (THRIFT_TRANSPORT (tbuffer), NULL) == TRUE); + + g_object_unref (tbuffer); +} + +static void +test_read_and_write (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gint got, want; + gchar read[10]; + gchar *b; + GError *error = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 5, NULL); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, + 10, &error) == FALSE); + g_assert (error != NULL); + g_error_free (error); + error = NULL; + g_object_unref (tbuffer); + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 15, NULL); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + + memset(read, 0, 10); + b = read; + want = 10; + while (want > 0) { + got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer), + (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + g_assert (error == NULL); + b += got; + want -= got; + } + g_assert (memcmp (read, TEST_DATA, 10) == 0); + g_object_unref (tbuffer); +} + +static void +test_read_and_write_default (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gint got, want, i; + gchar read[10]; + gchar *b; + GError *error = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + for (i = 0; i < 100; ++i) { + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + } + + for (i = 0; i < 100; ++i) { + memset(read, 0, 10); + b = read; + want = 10; + while (want > 0) { + got = thrift_memory_buffer_read (THRIFT_TRANSPORT (tbuffer), + (gpointer) b, want, &error); + g_assert (got > 0 && got <= want); + g_assert (error == NULL); + b += got; + want -= got; + } + g_assert (memcmp (read, TEST_DATA, 10) == 0); + } + g_object_unref (tbuffer); +} + +static void +test_read_and_write_external (void) +{ + ThriftMemoryBuffer *tbuffer = NULL; + gchar *b; + GError *error = NULL; + GByteArray *buf = g_byte_array_new (); + g_assert (buf != NULL); + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, "buf", buf, NULL); + g_assert (thrift_memory_buffer_write (THRIFT_TRANSPORT (tbuffer), + (gpointer) TEST_DATA, 10, &error) == TRUE); + g_assert (error == NULL); + + g_assert (memcmp (buf->data, TEST_DATA, 10) == 0); + g_object_unref (tbuffer); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init (); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testmemorybuffer/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyLarge", test_create_and_destroy_large); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyUnlimited", test_create_and_destroy_default); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyExternal", test_create_and_destroy_external); + g_test_add_func ("/testmemorybuffer/CreateAndDestroyUnowned", test_create_and_destroy_unowned); + g_test_add_func ("/testmemorybuffer/OpenAndClose", test_open_and_close); + g_test_add_func ("/testmemorybuffer/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testmemorybuffer/ReadAndWriteUnlimited", test_read_and_write_default); + g_test_add_func ("/testmemorybuffer/ReadAndWriteExternal", test_read_and_write_external); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c b/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c new file mode 100755 index 000000000..636c36d69 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testoptionalrequired.c @@ -0,0 +1,227 @@ +/* + * 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 <glib.h> + +#include <thrift/c_glib/thrift_struct.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/transport/thrift_memory_buffer.h> +#include "gen-c_glib/t_test_optional_required_test_types.h" + +#include "gen-c_glib/t_test_optional_required_test_types.c" + +static void +write_to_read (ThriftStruct *w, ThriftStruct *r, GError **write_error, + GError **read_error) +{ + ThriftMemoryBuffer *tbuffer = NULL; + ThriftProtocol *protocol = NULL; + + tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL); + protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", + tbuffer, NULL); + + thrift_struct_write (w, protocol, write_error); + thrift_struct_read (r, protocol, read_error); + + g_object_unref (protocol); + g_object_unref (tbuffer); +} + +static void +test_old_school1 (void) +{ + TTestOldSchool *o = NULL; + + o = g_object_new (T_TEST_TYPE_OLD_SCHOOL, NULL); + o->im_int = 10; + o->im_str = g_strdup ("test"); + o->im_big = g_ptr_array_new (); + g_ptr_array_free (o->im_big, TRUE); + o->im_big = NULL; + g_free (o->im_str); + o->im_str = NULL; + g_object_unref (o); +} + +/** + * Write to read with optional fields + */ +static void +test_simple (void) +{ + TTestSimple *s1 = NULL, *s2 = NULL, *s3 = NULL; + + s1 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + s2 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + s3 = g_object_new (T_TEST_TYPE_SIMPLE, NULL); + + /* write-to-read with optional fields */ + s1->im_optional = 10; + g_assert (s1->__isset_im_default == FALSE); + g_assert (s1->__isset_im_optional == FALSE); + write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s2), NULL, NULL); + g_assert (s2->__isset_im_default == TRUE); + g_assert (s2->__isset_im_optional == FALSE); + g_assert (s2->im_optional == 0); + + s1->__isset_im_optional = TRUE; + write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s3), NULL, NULL); + g_assert (s3->__isset_im_default == TRUE); + g_assert (s3->__isset_im_optional == TRUE); + g_assert (s3->im_optional == 10); + + g_object_unref (s1); + g_object_unref (s2); +} + +/** + * Writing between optional and default + */ +static void +test_tricky1 (void) +{ + TTestTricky1 *t1 = NULL; + TTestTricky2 *t2 = NULL; + + t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL); + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + + t2->im_optional = 10; + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t1), NULL, NULL); + write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t2), NULL, NULL); + + g_assert (t1->__isset_im_default == FALSE); + g_assert (t2->__isset_im_optional == TRUE); + g_assert (t1->im_default == t2->im_optional); + g_assert (t1->im_default == 0); + + g_object_unref (t1); + g_object_unref (t2); +} + +/** + * Writing between default and required. + */ +static void +test_tricky2 (void) +{ + TTestTricky1 *t1 = NULL; + TTestTricky3 *t3 = NULL; + + t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t3), NULL, NULL); + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t1), NULL, NULL); + + g_assert (t1->__isset_im_default == TRUE); + + g_object_unref (t1); + g_object_unref (t3); +} + +/** + * Writing between optional and required. + */ +static void +test_tricky3 (void) +{ + TTestTricky2 *t2 = NULL; + TTestTricky3 *t3 = NULL; + + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + t2->__isset_im_optional = TRUE; + + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, NULL); + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL); + + g_object_unref (t2); + g_object_unref (t3); +} + +/** + * Catch an optional not set exception. To quote the + * C++ test, "Mu-hu-ha-ha-ha!" + */ +static void +test_tricky4 (void) +{ + TTestTricky2 *t2 = NULL; + TTestTricky3 *t3 = NULL; + GError *read_error = NULL; + + t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL); + t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL); + + /* throws protocol exception */ + write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, &read_error); + g_assert (read_error != NULL); + g_error_free (read_error); + + write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL); + + g_assert (t2->__isset_im_optional); + + g_object_unref (t2); + g_object_unref (t3); +} + +static void +test_non_set_binary (void) +{ + TTestBinaries *b1 = NULL; + TTestBinaries *b2 = NULL; + GError *error = NULL; + + b1 = g_object_new (T_TEST_TYPE_BINARIES, NULL); + b2 = g_object_new (T_TEST_TYPE_BINARIES, NULL); + + write_to_read (THRIFT_STRUCT (b1), THRIFT_STRUCT (b2), NULL, &error); + g_assert(!error); + write_to_read (THRIFT_STRUCT (b2), THRIFT_STRUCT (b1), NULL, &error); + g_assert(!error); + /* OK. No segfault */ + + g_object_unref (b1); + g_object_unref (b2); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testoptionalrequired/OldSchool", test_old_school1); + g_test_add_func ("/testoptionalrequired/Simple", test_simple); + g_test_add_func ("/testoptionalrequired/Tricky1", test_tricky1); + g_test_add_func ("/testoptionalrequired/Tricky2", test_tricky2); + g_test_add_func ("/testoptionalrequired/Tricky3", test_tricky3); + g_test_add_func ("/testoptionalrequired/Tricky4", test_tricky4); + g_test_add_func ("/testoptionalrequired/Binary", test_non_set_binary); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c b/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c new file mode 100644 index 000000000..67d411de1 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testserialization.c @@ -0,0 +1,95 @@ +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/transport/thrift_memory_buffer.h> +#include <thrift/c_glib/transport/thrift_transport.h> +#include "gen-c_glib/t_test_debug_proto_test_types.h" +#include "gen-c_glib/t_test_enum_test_types.h" + +static void enum_constants_read_write() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestEnumTestStruct* src = T_TEST_ENUM_TEST; + TTestEnumTestStruct* dst = g_object_new(T_TEST_TYPE_ENUM_TEST_STRUCT, NULL); + TTestEnumTestStructClass* cls = T_TEST_ENUM_TEST_STRUCT_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(protocol); + g_object_unref(transport); +} + +static void struct_constants_read_write() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 4096, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestCompactProtoTestStruct* src = T_TEST_COMPACT_TEST; + TTestCompactProtoTestStruct* dst = g_object_new(T_TEST_TYPE_COMPACT_PROTO_TEST_STRUCT, NULL); + TTestCompactProtoTestStructClass* cls = T_TEST_COMPACT_PROTO_TEST_STRUCT_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(protocol); + g_object_unref(transport); +} + +static void struct_read_write_length_should_equal() { + GError* error = NULL; + ThriftTransport* transport + = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 2048, NULL)); + ThriftProtocol* protocol + = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL)); + TTestBonk* src = g_object_new(T_TEST_TYPE_BONK, NULL); + TTestBonk* dst = g_object_new(T_TEST_TYPE_BONK, NULL); + TTestBonkClass* cls = T_TEST_BONK_GET_CLASS(src); + int write_len; + int read_len; + + write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error); + g_assert(!error); + g_assert(write_len > 0); + + read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error); + g_assert(!error); + g_assert_cmpint(write_len, ==, read_len); + + g_object_unref(dst); + g_object_unref(src); + g_object_unref(protocol); + g_object_unref(transport); +} + +int main(int argc, char* argv[]) { +#if (!GLIB_CHECK_VERSION(2, 36, 0)) + g_type_init(); +#endif + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/testserialization/StructReadWriteLengthShouldEqual", + struct_read_write_length_should_equal); + g_test_add_func("/testserialization/StructConstants", struct_constants_read_write); + g_test_add_func("/testserialization/EnumConstants", enum_constants_read_write); + return g_test_run(); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c b/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c new file mode 100755 index 000000000..3c6f2e80d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testsimpleserver.c @@ -0,0 +1,122 @@ +/* + * 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 <glib.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/processor/thrift_processor.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_PORT 51199 + +#include <thrift/c_glib/server/thrift_simple_server.c> + +/* create a rudimentary processor */ +#define TEST_PROCESSOR_TYPE (test_processor_get_type ()) + +struct _TestProcessor +{ + ThriftProcessor parent; +}; +typedef struct _TestProcessor TestProcessor; + +struct _TestProcessorClass +{ + ThriftProcessorClass parent; +}; +typedef struct _TestProcessorClass TestProcessorClass; + +G_DEFINE_TYPE(TestProcessor, test_processor, THRIFT_TYPE_PROCESSOR) + +gboolean +test_processor_process (ThriftProcessor *processor, ThriftProtocol *in, + ThriftProtocol *out, GError **error) +{ + THRIFT_UNUSED_VAR (processor); + THRIFT_UNUSED_VAR (in); + THRIFT_UNUSED_VAR (out); + THRIFT_UNUSED_VAR (error); + + return FALSE; +} + +static void +test_processor_init (TestProcessor *p) +{ + THRIFT_UNUSED_VAR (p); +} + +static void +test_processor_class_init (TestProcessorClass *proc) +{ + (THRIFT_PROCESSOR_CLASS(proc))->process = test_processor_process; +} + +static void +test_server (void) +{ + int status; + pid_t pid; + TestProcessor *p = NULL; + ThriftServerSocket *tss = NULL; + ThriftSimpleServer *ss = NULL; + + p = g_object_new (TEST_PROCESSOR_TYPE, NULL); + tss = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", TEST_PORT, NULL); + ss = g_object_new (THRIFT_TYPE_SIMPLE_SERVER, "processor", p, + "server_transport", THRIFT_SERVER_TRANSPORT (tss), NULL); + + /* run the server in a child process */ + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + THRIFT_SERVER_GET_CLASS (THRIFT_SERVER (ss))->serve (THRIFT_SERVER (ss), + NULL); + exit (0); + } else { + sleep (5); + kill (pid, SIGINT); + + g_object_unref (ss); + g_object_unref (tss); + g_object_unref (p); + g_assert (wait (&status) == pid); + g_assert (status == SIGINT); + } +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testsimpleserver/SimpleServer", test_server); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c b/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c new file mode 100755 index 000000000..d120cbcfa --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/teststruct.c @@ -0,0 +1,111 @@ +/* + * 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 <glib-object.h> + +#include "../src/thrift/c_glib/thrift_struct.c" + +/* tests to ensure we can extend a ThriftStruct */ + +struct _ThriftTestStruct +{ + ThriftStruct parent; +}; +typedef struct _ThriftTestStruct ThriftTestStruct; + +struct _ThriftTestStructClass +{ + ThriftStructClass parent; +}; +typedef struct _ThriftTestStructClass ThriftTestStructClass; + +GType thrift_test_struct_get_type (void); + +#define THRIFT_TYPE_TEST_STRUCT (thrift_test_struct_get_type ()) +#define THRIFT_TEST_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), THRIFT_TYPE_TEST_STRUCT, ThriftTestStruct)) +#define THRIFT_TEST_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), THRIFT_TYPE_TEST_STRUCT, ThriftTestStructClass)) +#define THRIFT_IS_TEST_STRUCT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), THRIFT_TYPE_TEST_STRUCT)) +#define THRIFT_IS_TEST_STRUCT_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), THRIFT_TYPE_TEST_STRUCT)) +#define THRIFT_TEST_STRUCT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), THRIFT_TYPE_TEST_STRUCT, ThriftTestStructClass)) + +G_DEFINE_TYPE(ThriftTestStruct, thrift_test_struct, THRIFT_TYPE_STRUCT) + +gint32 +thrift_test_struct_read (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (object); + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + + return 0; +} + +gint32 +thrift_test_struct_write (ThriftStruct *object, ThriftProtocol *protocol, + GError **error) +{ + THRIFT_UNUSED_VAR (object); + THRIFT_UNUSED_VAR (protocol); + THRIFT_UNUSED_VAR (error); + + return 0; +} + +static void +thrift_test_struct_class_init (ThriftTestStructClass *cls) +{ + ThriftStructClass *ts_cls = THRIFT_STRUCT_CLASS (cls); + ts_cls->read = thrift_test_struct_read; + ts_cls->write = thrift_test_struct_write; +} + +static void +thrift_test_struct_init (ThriftTestStruct *s) +{ + THRIFT_UNUSED_VAR (s); +} + +static void +test_initialize_object (void) +{ + ThriftTestStruct *t = NULL; + + t = g_object_new (THRIFT_TYPE_TEST_STRUCT, NULL); + g_assert ( THRIFT_IS_STRUCT (t)); + thrift_struct_read (THRIFT_STRUCT (t), NULL, NULL); + thrift_struct_write (THRIFT_STRUCT (t), NULL, NULL); + thrift_test_struct_read (THRIFT_STRUCT (t), NULL, NULL); + thrift_test_struct_write (THRIFT_STRUCT (t), NULL, NULL); + g_object_unref (t); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/teststruct/InitializeObject", test_initialize_object); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c new file mode 100755 index 000000000..23a934db9 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttest.c @@ -0,0 +1,112 @@ +#include <netdb.h> + +#include <thrift/c_glib/thrift.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#include "t_test_thrift_test_types.h" +#include "thrift_test_handler.h" + +static const char TEST_ADDRESS[] = "localhost"; +static const int TEST_PORT = 64444; + +static void +test_thrift_server (void) +{ + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", TEST_PORT, NULL); + + g_object_unref (tsocket); +} + +static void +set_indicator (gpointer data, GObject *where_the_object_was) { + THRIFT_UNUSED_VAR(where_the_object_was); + + *(gboolean *) data = TRUE; +} + +static void +test_thrift_handler (void) +{ + GError *error; + GHashTable *_return; + TTestInsanity *argument; + gboolean indicator; + + TTestXtruct *xtruct, *xtruct2; + TTestNumberz numberz; + TTestNumberz numberz2; + TTestUserId user_id, *user_id_ptr, *user_id_ptr2; + GHashTable *user_map; + GPtrArray *xtructs; + + error = NULL; + indicator = FALSE; + + user_map = NULL; + xtructs = NULL; + + argument = g_object_new (T_TEST_TYPE_INSANITY, NULL); + g_object_get (argument, + "userMap", &user_map, + "xtructs", &xtructs, + NULL); + + numberz = T_TEST_NUMBERZ_FIVE; + numberz2 = T_TEST_NUMBERZ_EIGHT; + user_id_ptr = g_malloc (sizeof *user_id_ptr); + *user_id_ptr = 5; + user_id_ptr2 = g_malloc (sizeof *user_id_ptr); + *user_id_ptr2 = 8; + g_hash_table_insert (user_map, (gpointer)numberz, user_id_ptr); + g_hash_table_insert (user_map, (gpointer)numberz2, user_id_ptr2); + g_hash_table_unref (user_map); + + xtruct = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Hello2", + "byte_thing", 2, + "i32_thing", 2, + "i64_thing", 2LL, + NULL); + xtruct2 = g_object_new (T_TEST_TYPE_XTRUCT, + "string_thing", "Goodbye4", + "byte_thing", 4, + "i32_thing", 4, + "i64_thing", 4LL, + NULL); + g_ptr_array_add (xtructs, xtruct2); + g_ptr_array_add (xtructs, xtruct); + g_ptr_array_unref (xtructs); + + _return = g_hash_table_new_full (g_int64_hash, + g_int64_equal, + g_free, + (GDestroyNotify)g_hash_table_unref); + + g_object_weak_ref (G_OBJECT (argument), set_indicator, (gpointer) &indicator); + + g_assert (thrift_test_handler_test_insanity (NULL, &_return, argument, &error)); + g_assert (! indicator); + + g_hash_table_unref (_return); + g_assert (! indicator); + + g_object_unref (argument); + g_assert (indicator); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testthrift/Server", test_thrift_server); + g_test_add_func ("/testthrift/Handler", test_thrift_handler); + + return g_test_run (); +} diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp new file mode 100644 index 000000000..20fbcdb03 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testthrifttestclient.cpp @@ -0,0 +1,639 @@ +/* + * 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. + */ + +/* test a C client with a C++ server (that makes sense...) */ + +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <thrift/protocol/TBinaryProtocol.h> +#include <thrift/protocol/TDebugProtocol.h> +#include <thrift/server/TSimpleServer.h> +#include <memory> +#include <thrift/transport/TServerSocket.h> +#include "ThriftTest.h" +#include "ThriftTest_types.h" + +#include <iostream> +#include <map> +#include <set> +#include <string> +#include <vector> + +using namespace apache::thrift; +using namespace apache::thrift::concurrency; +using namespace apache::thrift::protocol; +using namespace apache::thrift::server; +using namespace apache::thrift::transport; + +using namespace thrift::test; + +using std::cout; +using std::endl; +using std::fixed; +using std::make_pair; +using std::map; +using std::set; +using std::string; +using std::vector; + +#define TEST_PORT 9980 + +// Extra functions required for ThriftTest_types to work +namespace thrift { namespace test { + +bool Insanity::operator<(thrift::test::Insanity const& other) const { + using apache::thrift::ThriftDebugString; + return ThriftDebugString(*this) < ThriftDebugString(other); +} + +}} + +class TestHandler : public ThriftTestIf { + public: + TestHandler() = default; + + void testVoid() override { + cout << "[C -> C++] testVoid()" << endl; + } + + void testString(string& out, const string &thing) override { + cout << "[C -> C++] testString(\"" << thing << "\")" << endl; + out = thing; + } + + bool testBool(const bool thing) override { + cout << "[C -> C++] testBool(" << (thing ? "true" : "false") << ")" << endl; + return thing; + } + int8_t testByte(const int8_t thing) override { + cout << "[C -> C++] testByte(" << (int)thing << ")" << endl; + return thing; + } + int32_t testI32(const int32_t thing) override { + cout << "[C -> C++] testI32(" << thing << ")" << endl; + return thing; + } + + int64_t testI64(const int64_t thing) override { + cout << "[C -> C++] testI64(" << thing << ")" << endl; + return thing; + } + + double testDouble(const double thing) override { + cout.precision(6); + cout << "[C -> C++] testDouble(" << fixed << thing << ")" << endl; + return thing; + } + + void testBinary(string& out, const string &thing) override { + cout << "[C -> C++] testBinary(\"" << thing << "\")" << endl; + out = thing; + } + + void testStruct(Xtruct& out, const Xtruct &thing) override { + cout << "[C -> C++] testStruct({\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "})" << endl; + out = thing; + } + + void testNest(Xtruct2& out, const Xtruct2& nest) override { + const Xtruct &thing = nest.struct_thing; + cout << "[C -> C++] testNest({" << (int)nest.byte_thing << ", {\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "}, " << nest.i32_thing << "})" << endl; + out = nest; + } + + void testMap(map<int32_t, int32_t> &out, const map<int32_t, int32_t> &thing) override { + cout << "[C -> C++] testMap({"; + map<int32_t, int32_t>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << m_iter->first << " => " << m_iter->second; + } + cout << "})" << endl; + out = thing; + } + + void testStringMap(map<std::string, std::string> &out, const map<std::string, std::string> &thing) override { + cout << "[C -> C++] testStringMap({"; + map<std::string, std::string>::const_iterator m_iter; + bool first = true; + for (m_iter = thing.begin(); m_iter != thing.end(); ++m_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << "\"" << m_iter->first << "\" => \"" << m_iter->second << "\""; + } + cout << "})" << endl; + out = thing; + } + + + void testSet(set<int32_t> &out, const set<int32_t> &thing) override { + cout << "[C -> C++] testSet({"; + set<int32_t>::const_iterator s_iter; + bool first = true; + for (s_iter = thing.begin(); s_iter != thing.end(); ++s_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << *s_iter; + } + cout << "})" << endl; + out = thing; + } + + void testList(vector<int32_t> &out, const vector<int32_t> &thing) override { + cout << "[C -> C++] testList({"; + vector<int32_t>::const_iterator l_iter; + bool first = true; + for (l_iter = thing.begin(); l_iter != thing.end(); ++l_iter) { + if (first) { + first = false; + } else { + cout << ", "; + } + cout << *l_iter; + } + cout << "})" << endl; + out = thing; + } + + Numberz::type testEnum(const Numberz::type thing) override { + cout << "[C -> C++] testEnum(" << thing << ")" << endl; + return thing; + } + + UserId testTypedef(const UserId thing) override { + cout << "[C -> C++] testTypedef(" << thing << ")" << endl; + return thing; } + + void testMapMap(map<int32_t, map<int32_t,int32_t> > &mapmap, const int32_t hello) override { + cout << "[C -> C++] testMapMap(" << hello << ")" << endl; + + map<int32_t,int32_t> pos; + map<int32_t,int32_t> neg; + for (int i = 1; i < 5; i++) { + pos.insert(make_pair(i,i)); + neg.insert(make_pair(-i,-i)); + } + + mapmap.insert(make_pair(4, pos)); + mapmap.insert(make_pair(-4, neg)); + + } + + void testInsanity(map<UserId, map<Numberz::type,Insanity> > &insane, const Insanity &argument) override { + THRIFT_UNUSED_VARIABLE (argument); + + cout << "[C -> C++] testInsanity()" << endl; + + Xtruct hello; + hello.string_thing = "Hello2"; + hello.byte_thing = 2; + hello.i32_thing = 2; + hello.i64_thing = 2; + + Xtruct goodbye; + goodbye.string_thing = "Goodbye4"; + goodbye.byte_thing = 4; + goodbye.i32_thing = 4; + goodbye.i64_thing = 4; + + Insanity crazy; + crazy.userMap.insert(make_pair(Numberz::EIGHT, 8)); + crazy.xtructs.push_back(goodbye); + + Insanity looney; + crazy.userMap.insert(make_pair(Numberz::FIVE, 5)); + crazy.xtructs.push_back(hello); + + map<Numberz::type, Insanity> first_map; + map<Numberz::type, Insanity> second_map; + + first_map.insert(make_pair(Numberz::TWO, crazy)); + first_map.insert(make_pair(Numberz::THREE, crazy)); + + second_map.insert(make_pair(Numberz::SIX, looney)); + + insane.insert(make_pair(1, first_map)); + insane.insert(make_pair(2, second_map)); + + cout << "return = {"; + map<UserId, map<Numberz::type,Insanity> >::const_iterator i_iter; + for (i_iter = insane.begin(); i_iter != insane.end(); ++i_iter) { + cout << i_iter->first << " => {"; + map<Numberz::type,Insanity>::const_iterator i2_iter; + for (i2_iter = i_iter->second.begin(); + i2_iter != i_iter->second.end(); + ++i2_iter) { + cout << i2_iter->first << " => {"; + map<Numberz::type, UserId> userMap = i2_iter->second.userMap; + map<Numberz::type, UserId>::const_iterator um; + cout << "{"; + for (um = userMap.begin(); um != userMap.end(); ++um) { + cout << um->first << " => " << um->second << ", "; + } + cout << "}, "; + + vector<Xtruct> xtructs = i2_iter->second.xtructs; + vector<Xtruct>::const_iterator x; + cout << "{"; + for (x = xtructs.begin(); x != xtructs.end(); ++x) { + cout << "{\"" << x->string_thing << "\", " << (int)x->byte_thing << ", " << x->i32_thing << ", " << x->i64_thing << "}, "; + } + cout << "}"; + + cout << "}, "; + } + cout << "}, "; + } + cout << "}" << endl; + + + } + + void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map<int16_t, std::string> &arg3, const Numberz::type arg4, const UserId arg5) override { + THRIFT_UNUSED_VARIABLE (arg3); + THRIFT_UNUSED_VARIABLE (arg4); + THRIFT_UNUSED_VARIABLE (arg5); + + cout << "[C -> C++] testMulti()" << endl; + + hello.string_thing = "Hello2"; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = (int64_t)arg2; + } + + void testException(const std::string &arg) + throw(Xception, apache::thrift::TException) override + { + cout << "[C -> C++] testException(" << arg << ")" << endl; + if (arg.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = arg; + throw e; + } else if (arg.compare("ApplicationException") == 0) { + apache::thrift::TException e; + throw e; + } else { + Xtruct result; + result.string_thing = arg; + return; + } + } + + void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) override { + + cout << "[C -> C++] testMultiException(" << arg0 << ", " << arg1 << ")" << endl; + + if (arg0.compare("Xception") == 0) { + Xception e; + e.errorCode = 1001; + e.message = "This is an Xception"; + throw e; + } else if (arg0.compare("Xception2") == 0) { + Xception2 e; + e.errorCode = 2002; + e.struct_thing.string_thing = "This is an Xception2"; + throw e; + } else { + result.string_thing = arg1; + return; + } + } + + void testOneway(int sleepFor) override { + cout << "testOneway(" << sleepFor << "): Sleeping..." << endl; + sleep(sleepFor); + cout << "testOneway(" << sleepFor << "): done sleeping!" << endl; + } +}; + +// C CLIENT +extern "C" { + +#undef THRIFT_SOCKET /* from lib/cpp */ + +#include "t_test_thrift_test.h" +#include "t_test_thrift_test_types.h" +#include <thrift/c_glib/transport/thrift_socket.h> +#include <thrift/c_glib/protocol/thrift_protocol.h> +#include <thrift/c_glib/protocol/thrift_binary_protocol.h> + +static void +test_thrift_client (void) +{ + ThriftSocket *tsocket = nullptr; + ThriftBinaryProtocol *protocol = nullptr; + TTestThriftTestClient *client = nullptr; + TTestThriftTestIf *iface = nullptr; + GError *error = nullptr; + gchar *string = nullptr; + gint8 byte = 0; + gint16 i16 = 0; + gint32 i32 = 0, another_i32 = 56789; + gint64 i64 = 0; + double dbl = 0.0; + TTestXtruct *xtruct_in, *xtruct_out; + TTestXtruct2 *xtruct2_in, *xtruct2_out; + GHashTable *map_in = nullptr, *map_out = nullptr; + GHashTable *set_in = nullptr, *set_out = nullptr; + GArray *list_in = nullptr, *list_out = nullptr; + TTestNumberz enum_in, enum_out; + TTestUserId user_id_in, user_id_out; + GHashTable *insanity_in = nullptr; + TTestXtruct *xtruct1, *xtruct2; + TTestInsanity *insanity_out = nullptr; + TTestXtruct *multi_in = nullptr; + GHashTable *multi_map_out = nullptr; + TTestXception *xception = nullptr; + TTestXception2 *xception2 = nullptr; + +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + // initialize gobject + g_type_init (); +#endif + + // create a C client + tsocket = (ThriftSocket *) g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", TEST_PORT, NULL); + protocol = (ThriftBinaryProtocol *) g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", + tsocket, NULL); + client = (TTestThriftTestClient *) g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL); + iface = T_TEST_THRIFT_TEST_IF (client); + + // open and send + thrift_transport_open (THRIFT_TRANSPORT(tsocket), nullptr); + + assert (t_test_thrift_test_client_test_void (iface, &error) == TRUE); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_string (iface, &string, "test123", &error) == TRUE); + assert (strcmp (string, "test123") == 0); + g_free (string); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_byte (iface, &byte, (gint8) 5, &error) == TRUE); + assert (byte == 5); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_i32 (iface, &i32, 123, &error) == TRUE); + assert (i32 == 123); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_i64 (iface, &i64, 12345, &error) == TRUE); + assert (i64 == 12345); + assert (error == nullptr); + + assert (t_test_thrift_test_client_test_double (iface, &dbl, 5.6, &error) == TRUE); + assert (dbl == 5.6); + assert (error == nullptr); + + xtruct_out = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct_out->byte_thing = 1; + xtruct_out->__isset_byte_thing = TRUE; + xtruct_out->i32_thing = 15; + xtruct_out->__isset_i32_thing = TRUE; + xtruct_out->i64_thing = 151; + xtruct_out->__isset_i64_thing = TRUE; + xtruct_out->string_thing = g_strdup ("abc123"); + xtruct_out->__isset_string_thing = TRUE; + xtruct_in = (TTestXtruct *) g_object_new(T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_struct (iface, &xtruct_in, xtruct_out, &error) == TRUE); + assert (error == nullptr); + + xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); + xtruct2_out->byte_thing = 1; + xtruct2_out->__isset_byte_thing = TRUE; + if (xtruct2_out->struct_thing != nullptr) + g_object_unref(xtruct2_out->struct_thing); + xtruct2_out->struct_thing = xtruct_out; + xtruct2_out->__isset_struct_thing = TRUE; + xtruct2_out->i32_thing = 123; + xtruct2_out->__isset_i32_thing = TRUE; + xtruct2_in = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); + assert (t_test_thrift_test_client_test_nest (iface, &xtruct2_in, xtruct2_out, &error) == TRUE); + assert (error == nullptr); + + g_object_unref (xtruct2_out); + g_object_unref (xtruct2_in); + g_object_unref (xtruct_in); + + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (map_out, &i32, &i32); + assert (t_test_thrift_test_client_test_map (iface, &map_in, map_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_out); + g_hash_table_destroy (map_in); + + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (map_out, g_strdup ("a"), g_strdup ("123")); + g_hash_table_insert (map_out, g_strdup ("a b"), g_strdup ("with spaces ")); + g_hash_table_insert (map_out, g_strdup ("same"), g_strdup ("same")); + g_hash_table_insert (map_out, g_strdup ("0"), g_strdup ("numeric key")); + assert (t_test_thrift_test_client_test_string_map (iface, &map_in, map_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_out); + g_hash_table_destroy (map_in); + + set_out = g_hash_table_new (nullptr, nullptr); + set_in = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (set_out, &i32, &i32); + assert (t_test_thrift_test_client_test_set (iface, &set_in, set_out, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (set_out); + g_hash_table_destroy (set_in); + + list_out = g_array_new(TRUE, TRUE, sizeof(gint32)); + list_in = g_array_new(TRUE, TRUE, sizeof(gint32)); + another_i32 = 456; + g_array_append_val (list_out, i32); + g_array_append_val (list_out, another_i32); + assert (t_test_thrift_test_client_test_list (iface, &list_in, list_out, &error) == TRUE); + assert (error == nullptr); + g_array_free (list_out, TRUE); + g_array_free (list_in, TRUE); + + enum_out = T_TEST_NUMBERZ_ONE; + assert (t_test_thrift_test_client_test_enum (iface, &enum_in, enum_out, &error) == TRUE); + assert (enum_in == enum_out); + assert (error == nullptr); + + user_id_out = 12345; + assert (t_test_thrift_test_client_test_typedef (iface, &user_id_in, user_id_out, &error) == TRUE); + assert (user_id_in == user_id_out); + assert (error == nullptr); + + map_in = g_hash_table_new (nullptr, nullptr); + assert (t_test_thrift_test_client_test_map_map (iface, &map_in, i32, &error) == TRUE); + assert (error == nullptr); + g_hash_table_destroy (map_in); + + // insanity + insanity_out = (TTestInsanity *) g_object_new (T_TEST_TYPE_INSANITY, nullptr); + insanity_out->userMap = g_hash_table_new (nullptr, nullptr); + g_hash_table_insert (insanity_out->userMap, GINT_TO_POINTER (enum_out), &user_id_out); + + xtruct1 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct1->byte_thing = 1; + xtruct1->__isset_byte_thing = TRUE; + xtruct1->i32_thing = 15; + xtruct1->__isset_i32_thing = TRUE; + xtruct1->i64_thing = 151; + xtruct1->__isset_i64_thing = TRUE; + xtruct1->string_thing = g_strdup ("abc123"); + xtruct1->__isset_string_thing = TRUE; + xtruct2 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + xtruct2->byte_thing = 1; + xtruct2->__isset_byte_thing = TRUE; + xtruct2->i32_thing = 15; + xtruct2->__isset_i32_thing = TRUE; + xtruct2->i64_thing = 151; + xtruct2->__isset_i64_thing = TRUE; + xtruct2->string_thing = g_strdup ("abc123"); + xtruct2->__isset_string_thing = TRUE; + + insanity_in = g_hash_table_new (nullptr, nullptr); + g_ptr_array_add (insanity_out->xtructs, xtruct1); + g_ptr_array_add (insanity_out->xtructs, xtruct2); + assert (t_test_thrift_test_client_test_insanity (iface, &insanity_in, insanity_out, &error) == TRUE); + + g_hash_table_unref (insanity_in); + g_ptr_array_free (insanity_out->xtructs, TRUE); + + multi_map_out = g_hash_table_new (nullptr, nullptr); + string = g_strdup ("abc123"); + g_hash_table_insert (multi_map_out, &i16, string); + multi_in = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi (iface, &multi_in, byte, i32, i64, multi_map_out, enum_out, user_id_out, &error) == TRUE); + assert (multi_in->i32_thing == i32); + assert (multi_in->i64_thing == i64); + g_object_unref (multi_in); + g_hash_table_unref (multi_map_out); + g_free (string); + + assert (t_test_thrift_test_client_test_exception (iface, "Xception", &xception, &error) == FALSE); + assert (xception->errorCode == 1001); + g_error_free (error); + error = nullptr; + g_object_unref (xception); + xception = nullptr; + + assert (t_test_thrift_test_client_test_exception (iface, "ApplicationException", &xception, &error) == FALSE); + g_error_free (error); + error = nullptr; + assert (xception == nullptr); + + assert (t_test_thrift_test_client_test_exception (iface, "Test", &xception, &error) == TRUE); + assert (error == nullptr); + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", nullptr, &xception, &xception2, &error) == FALSE); + assert (xception->errorCode == 1001); + assert (xception2 == nullptr); + g_error_free (error); + error = nullptr; + g_object_unref (xception); + g_object_unref (multi_in); + xception = nullptr; + multi_in = nullptr; + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", nullptr, &xception, &xception2, &error) == FALSE); + assert (xception2->errorCode == 2002); + assert (xception == nullptr); + g_error_free (error); + error = nullptr; + g_object_unref (xception2); + g_object_unref (multi_in); + xception2 = nullptr; + multi_in = nullptr; + + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, nullptr , nullptr, &xception, &xception2, &error) == TRUE); + assert (error == nullptr); + g_object_unref(multi_in); + multi_in = nullptr; + + assert (t_test_thrift_test_client_test_oneway (iface, 1, &error) == TRUE); + assert (error == nullptr); + + /* sleep to let the oneway call go through */ + sleep (5); + + thrift_transport_close (THRIFT_TRANSPORT(tsocket), nullptr); + g_object_unref (client); + g_object_unref (protocol); + g_object_unref (tsocket); +} + + +} /* extern "C" */ + + +static void +bailout (int signum) +{ + THRIFT_UNUSED_VARIABLE (signum); + + exit (1); +} + +int +main (void) +{ + int status; + int pid = fork (); + assert (pid >= 0); + + if (pid == 0) /* child */ + { + std::shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr<TestHandler> testHandler(new TestHandler()); + std::shared_ptr<ThriftTestProcessor> testProcessor(new ThriftTestProcessor(testHandler)); + std::shared_ptr<TServerSocket> serverSocket(new TServerSocket(TEST_PORT)); + std::shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); + TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory); + signal (SIGALRM, bailout); + alarm (60); + simpleServer.serve(); + } else { + sleep (1); + test_thrift_client (); + kill (pid, SIGINT); + assert (wait (&status) == pid); + } + + return 0; +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c new file mode 100755 index 000000000..89c61b910 --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsocket.c @@ -0,0 +1,361 @@ +/* + * 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 <netdb.h> +#include <sys/wait.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> + +#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } + +/* substituted functions to test failures of system and library calls */ +static int socket_error = 0; +int +my_socket(int domain, int type, int protocol) +{ + if (socket_error == 0) + { + return socket (domain, type, protocol); + } + return -1; +} + +static int recv_error = 0; +ssize_t +my_recv(int socket, void *buffer, size_t length, int flags) +{ + if (recv_error == 0) + { + return recv (socket, buffer, length, flags); + } + return -1; +} + +static int send_error = 0; +ssize_t +my_send(int socket, const void *buffer, size_t length, int flags) +{ + if (send_error == 0) + { + return send (socket, buffer, length, flags); + } + return -1; +} + +#define socket my_socket +#define recv my_recv +#define send my_send +#include "../src/thrift/c_glib/transport/thrift_socket.c" +#undef socket +#undef recv +#undef send + +static void thrift_socket_server (const int port); +static void thrift_socket_server_open (const int port, int times); +/* test object creation and destruction */ +static void +test_create_and_destroy(void) +{ + gchar *hostname = NULL; + guint port = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_SOCKET, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL); + g_free (hostname); + + g_object_unref (object); +} + +static void +test_open_and_close(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + GError *err = NULL; + int port = 51199; + pid_t pid; + int status; + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server_open (port, 1); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* open a connection and close it */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + thrift_socket_open (transport, NULL); + g_assert (thrift_socket_is_open (transport) == TRUE); + thrift_socket_close (transport, NULL); + g_assert (thrift_socket_is_open (transport) == FALSE); + + /* test close failure */ + tsocket->sd = -1; + thrift_socket_close (transport, NULL); + g_object_unref (tsocket); + + /* try a hostname lookup failure */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken", + NULL); + transport = THRIFT_TRANSPORT (tsocket); + g_assert (thrift_socket_open (transport, &err) == FALSE); + g_object_unref (tsocket); + g_error_free (err); + err = NULL; + + /* try an error call to socket() */ + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", NULL); + transport = THRIFT_TRANSPORT (tsocket); + socket_error = 1; + g_assert (thrift_socket_open (transport, &err) == FALSE); + socket_error = 0; + g_object_unref (tsocket); + g_error_free (err); + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +static void +test_read_and_write(void) +{ + ThriftSocket *tsocket = NULL; + ThriftTransport *transport = NULL; + pid_t pid; + int port = 51199; + int status; + guchar buf[10] = TEST_DATA; /* a buffer */ + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + thrift_socket_server (port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost", + "port", port, NULL); + transport = THRIFT_TRANSPORT (tsocket); + g_assert (thrift_socket_open (transport, NULL) == TRUE); + g_assert (thrift_socket_is_open (transport)); + thrift_socket_write (transport, buf, 10, NULL); + + /* write fail */ + send_error = 1; + thrift_socket_write (transport, buf, 1, NULL); + send_error = 0; + + thrift_socket_write_end (transport, NULL); + thrift_socket_flush (transport, NULL); + thrift_socket_close (transport, NULL); + g_object_unref (tsocket); + + g_assert ( wait (&status) == pid ); + g_assert ( status == 0 ); + } +} + +/* test ThriftSocket's peek() implementation */ +static void +test_peek(void) +{ + gint status; + pid_t pid; + guint port = 51199; + gchar data = 'A'; + ThriftTransport *client_transport; + GError *error = NULL; + + client_transport = g_object_new (THRIFT_TYPE_SOCKET, + "hostname", "localhost", + "port", port, + NULL); + + /* thrift_transport_peek returns FALSE when the socket is closed */ + g_assert (thrift_transport_is_open (client_transport) == FALSE); + g_assert (thrift_transport_peek (client_transport, &error) == FALSE); + g_assert (error == NULL); + + pid = fork (); + g_assert (pid >= 0); + + if (pid == 0) + { + ThriftServerTransport *server_transport = NULL; + + g_object_unref (client_transport); + + /* child listens */ + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + g_assert (server_transport != NULL); + + thrift_server_transport_listen (server_transport, &error); + g_assert (error == NULL); + + client_transport = g_object_new + (THRIFT_TYPE_BUFFERED_TRANSPORT, + "transport", thrift_server_transport_accept (server_transport, &error), + "r_buf_size", 0, + "w_buf_size", sizeof data, + NULL); + g_assert (error == NULL); + g_assert (client_transport != NULL); + + /* write exactly one character to the client */ + g_assert (thrift_transport_write (client_transport, + &data, + sizeof data, + &error) == TRUE); + + thrift_transport_flush (client_transport, &error); + thrift_transport_write_end (client_transport, &error); + thrift_transport_close (client_transport, &error); + + g_object_unref (client_transport); + g_object_unref (server_transport); + + exit (0); + } + else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* connect to the child */ + thrift_transport_open (client_transport, &error); + g_assert (error == NULL); + g_assert (thrift_transport_is_open (client_transport) == TRUE); + + /* thrift_transport_peek returns TRUE when the socket is open and there is + data available to be read */ + g_assert (thrift_transport_peek (client_transport, &error) == TRUE); + g_assert (error == NULL); + + /* read exactly one character from the server */ + g_assert_cmpint (thrift_transport_read (client_transport, + &data, + sizeof data, + &error), ==, sizeof data); + + /* thrift_transport_peek returns FALSE when the socket is open but there is + no (more) data available to be read */ + g_assert (thrift_transport_is_open (client_transport) == TRUE); + g_assert (thrift_transport_peek (client_transport, &error) == FALSE); + g_assert (error == NULL); + + thrift_transport_read_end (client_transport, &error); + thrift_transport_close (client_transport, &error); + + g_object_unref (client_transport); + + g_assert (wait (&status) == pid); + g_assert (status == 0); + } +} + +static void +thrift_socket_server_open (const int port, int times) +{ + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + int i; + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + for(i=0;i<times;i++){ + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + thrift_socket_close (client, NULL); + g_object_unref (client); + } + g_object_unref (tsocket); +} + + +static void +thrift_socket_server (const int port) +{ + int bytes = 0; + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + guchar buf[10]; /* a buffer */ + guchar match[10] = TEST_DATA; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + /* read 10 bytes */ + bytes = thrift_socket_read (client, buf, 10, NULL); + g_assert (bytes == 10); /* make sure we've read 10 bytes */ + g_assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */ + + /* failed read */ + recv_error = 1; + thrift_socket_read (client, buf, 1, NULL); + recv_error = 0; + + thrift_socket_read_end (client, NULL); + thrift_socket_close (client, NULL); + g_object_unref (tsocket); + g_object_unref (client); +} + +int +main(int argc, char *argv[]) +{ +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + g_test_add_func ("/testtransportsocket/CreateAndDestroy", test_create_and_destroy); + g_test_add_func ("/testtransportsocket/OpenAndClose", test_open_and_close); + g_test_add_func ("/testtransportsocket/ReadAndWrite", test_read_and_write); + g_test_add_func ("/testtransportsocket/Peek", test_peek); + + return g_test_run (); +} + diff --git a/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c new file mode 100644 index 000000000..3c2644d8d --- /dev/null +++ b/src/jaegertracing/thrift/lib/c_glib/test/testtransportsslsocket.c @@ -0,0 +1,542 @@ +/* + * 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. + */ +#define _POSIX_C_SOURCE 200112L /* https://stackoverflow.com/questions/37541985/storage-size-of-addrinfo-isnt-known */ + + +#include <sys/wait.h> +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> + +#include <thrift/c_glib/transport/thrift_transport.h> +#include <thrift/c_glib/transport/thrift_buffered_transport.h> +#include <thrift/c_glib/transport/thrift_server_transport.h> +#include <thrift/c_glib/transport/thrift_server_socket.h> +#include <thrift/c_glib/transport/thrift_ssl_socket.h> + +/* #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } */ +#define TEST_DATA { "GET / HTTP/1.1\n\n" } + + +/* substituted functions to test failures of system and library calls */ +static int socket_error = 0; +int +my_socket(int domain, int type, int protocol) +{ + if (socket_error == 0) + { + return socket (domain, type, protocol); + } + return -1; +} + +static int recv_error = 0; +ssize_t +my_recv(int socket, void *buffer, size_t length, int flags) +{ + if (recv_error == 0) + { + return recv (socket, buffer, length, flags); + } + return -1; +} + +static int send_error = 0; +ssize_t +my_send(int socket, const void *buffer, size_t length, int flags) +{ + if (send_error == 0) + { + return send (socket, buffer, length, flags); + } + return -1; +} + +#define socket my_socket +#define recv my_recv +#define send my_send +#include "../src/thrift/c_glib/transport/thrift_ssl_socket.c" +#undef socket +#undef recv +#undef send + +static void thrift_socket_server (const int port); + +/* test object creation and destruction */ +static void +test_ssl_create_and_destroy(void) +{ + gchar *hostname = NULL; + guint port = 0; + + GObject *object = NULL; + object = g_object_new (THRIFT_TYPE_SSL_SOCKET, NULL); + g_assert (object != NULL); + g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL); + g_free (hostname); + g_object_unref (object); +} + +static void +test_ssl_create_and_set_properties(void) +{ + gchar *hostname = NULL; + guint port = 0; + SSL_CTX* ssl_ctx= NULL; + GError *error=NULL; + + GObject *object = NULL; + object = thrift_ssl_socket_new(SSLTLS, &error); + g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, "ssl_context", &ssl_ctx, NULL); + g_assert (ssl_ctx!=NULL); + + g_free (hostname); + g_object_unref (object); +} + +static void +test_ssl_open_and_close_non_ssl_server(void) +{ + ThriftSSLSocket *tSSLSocket = NULL; + ThriftTransport *transport = NULL; + GError *error=NULL; + pid_t pid; + int non_ssl_port = 51198; + char errormsg[255]; + + + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + /* child listens */ + /* This is a non SSL server */ + thrift_socket_server (non_ssl_port); + exit (0); + } else { + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* open a connection and close it */ + tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", non_ssl_port, &error); + + transport = THRIFT_TRANSPORT (tSSLSocket); + g_assert (thrift_ssl_socket_open (transport, &error) == FALSE); + g_assert_cmpstr(error->message, == ,"Error while connect/bind: 68 -> Connection reset by peer"); + g_clear_error (&error); + g_assert (thrift_ssl_socket_is_open (transport) == FALSE); + thrift_ssl_socket_close (transport, NULL); + g_assert (thrift_ssl_socket_is_open (transport) == FALSE); + + /* test close failure */ + THRIFT_SOCKET(tSSLSocket)->sd = -1; + thrift_ssl_socket_close (transport, NULL); + g_object_unref (tSSLSocket); + + /* try a hostname lookup failure */ + tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost.broken", non_ssl_port, &error); + transport = THRIFT_TRANSPORT (tSSLSocket); + g_assert (thrift_ssl_socket_open (transport, &error) == FALSE); + snprintf(errormsg, 255, "host lookup failed for localhost.broken:%d - Unknown host", non_ssl_port); + g_assert_cmpstr(error->message, ==, errormsg); + g_clear_error (&error); + g_object_unref (tSSLSocket); + error = NULL; + + /* try an error call to socket() */ + /* + tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error); + transport = THRIFT_TRANSPORT (tSSLSocket); + socket_error = 1; + assert (thrift_ssl_socket_open (transport, &error) == FALSE); + socket_error = 0; + g_object_unref (tSSLSocket); + g_error_free (error); + */ + } +} + +static void +test_ssl_write_invalid_socket(void) +{ + ThriftSSLSocket *tSSLSocket = NULL; + ThriftTransport *transport = NULL; + GError *error=NULL; + char buffer[] = "this must not break"; + + /* open a connection and close it */ + tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188+1, &error); + + transport = THRIFT_TRANSPORT (tSSLSocket); + g_assert (thrift_ssl_socket_open (transport, NULL) == FALSE); + g_assert (thrift_ssl_socket_is_open (transport) == FALSE); + + /* FIXME This must be tested but since the assertion inside thrift_ssl_socket_write breaks the test unit + it's disabled. They idea is to disable trap/coredump during this test + g_assert (thrift_ssl_socket_write(transport, buffer, sizeof(buffer), &error) == FALSE); + g_message ("write_failed_with_error: %s", + error != NULL ? error->message : "No"); + g_clear_error (&error); + */ + thrift_ssl_socket_close (transport, NULL); + g_assert (thrift_ssl_socket_is_open (transport) == FALSE); + + /* test close failure */ + THRIFT_SOCKET(tSSLSocket)->sd = -1; + thrift_ssl_socket_close (transport, NULL); + g_object_unref (tSSLSocket); +} + + + +/** + * Print the common name of certificate + */ +unsigned char * get_cn_name(X509_NAME* const name) +{ + int idx = -1; + unsigned char *utf8 = NULL; + + do + { + if(!name) break; /* failed */ + + idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); + if(!(idx > -1)) break; /* failed */ + + X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx); + if(!entry) break; /* failed */ + + ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry); + if(!data) break; /* failed */ + + int length = ASN1_STRING_to_UTF8(&utf8, data); + if(!utf8 || !(length > 0)) break; /* failed */ + + } while (0); + return utf8; +} + +/* + * Handle IPV4 and IPV6 addr + */ +void *get_in_addr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + return &(((struct sockaddr_in*)sa)->sin_addr); + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +int verify_ip(char * hostname, struct sockaddr_storage *addr) +{ + struct addrinfo *addr_info,*p; + struct addrinfo hints; + int res; + int retval = 0; + + + memset(&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* use AF_INET6 to force IPv6 */ + hints.ai_socktype = SOCK_STREAM; + + + if ( (res = getaddrinfo(hostname, NULL, &hints, &addr_info) ) != 0) + { + /* get the host info */ + g_error("Cannot get the host address"); + return retval; + } + /* loop through all the results and connect to the first we can */ + char dnshost[INET6_ADDRSTRLEN]; /* bigger addr supported IPV6 */ + char socket_ip[INET6_ADDRSTRLEN]; + if(inet_ntop(addr->ss_family, get_in_addr(addr), socket_ip, INET6_ADDRSTRLEN)==socket_ip){ + g_debug("We are connected to host %s checking against certificate...", socket_ip); + int sizeip = socket_ip!=NULL ? strlen(socket_ip) : 0; + for(p = addr_info; p != NULL; p = p->ai_next) { + if(inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), dnshost, INET6_ADDRSTRLEN)==dnshost){ + if(dnshost!=NULL){ + g_info("DNS address [%i -> %s]", p->ai_addr, dnshost); + if(!strncmp(dnshost, socket_ip, sizeip)){ + retval=1; + break; /* if we get here, we must have connected successfully */ + } + } + } + } + } + + if(addr_info) + freeaddrinfo(addr_info); + + return retval; +} + +static void +read_from_file(char *buffer, long size, const char *file_name) +{ + char ch; + long index=0; + FILE *fp; + + fp = fopen(file_name,"r"); /* read mode */ + + if( fp == NULL ) + { + perror("Error while opening the file.\n"); + exit(EXIT_FAILURE); + } + + printf("The contents of %s file are :\n", file_name); + + while(index<size && ( ch = fgetc(fp) ) != EOF ){ + buffer[index++] = ch; + } + + fclose(fp); +} + +#define ISSUER_CN_PINNING "The Apache Software Foundation" +#define SUBJECT_CN_PINNING "localhost" +#define CERT_SERIAL_NUMBER "1" + +gboolean verify_certificate_sn(X509 *cert, const unsigned char *serial_number) +{ + gboolean retval = FALSE; + + ASN1_INTEGER *serial = X509_get_serialNumber(cert); + + BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); + if (!bn) { + fprintf(stderr, "unable to convert ASN1INTEGER to BN\n"); + return EXIT_FAILURE; + } + char *tmp = BN_bn2dec(bn); + if (!tmp) { + g_warning(stderr, "unable to convert BN to decimal string.\n"); + BN_free(bn); + return EXIT_FAILURE; + } + /* + if (strlen(tmp) >= len) { + g_warn(stderr, "buffer length shorter than serial number\n"); + BN_free(bn); + OPENSSL_free(tmp); + return EXIT_FAILURE; + } + */ + if(!strncmp(serial_number, tmp, strlen(serial_number))){ + retval=TRUE; + }else{ + g_warning("Serial number is not valid"); + } + + BN_free(bn); + OPENSSL_free(tmp); + return retval; +} + +gboolean my_access_manager(ThriftTransport * transport, X509 *cert, struct sockaddr_storage *addr, GError **error) +{ + ThriftSSLSocket *sslSocket = THRIFT_SSL_SOCKET (transport); + + g_info("Processing access to the server"); + X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL; + X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL; + + /* Issuer is the authority we trust that warrants nothing useful */ + const unsigned char * issuer = get_cn_name(iname); + if(issuer){ + gboolean valid = TRUE; + g_info("Issuer (cn) %s", issuer); + + /* Issuer pinning */ + if(strncmp(ISSUER_CN_PINNING, issuer, strlen(ISSUER_CN_PINNING))){ + g_warning("The Issuer of the certificate is not valid"); + valid=FALSE; + } + OPENSSL_free(issuer); + if(!valid) + return valid; + } + + + /* Subject is who the certificate is issued to by the authority */ + const unsigned char * subject = get_cn_name(sname); + if(subject){ + g_info("Subject (cn) %s", subject); + gboolean valid = TRUE; + + /* Subject pinning */ + if(strncmp(SUBJECT_CN_PINNING, subject, strlen(SUBJECT_CN_PINNING))){ + g_warning("The subject of the certificate is not valid"); + valid=FALSE; + } + + if(!valid) + return valid; + + /* Host pinning */ + if(verify_ip(subject, addr)){ + g_info("Verified subject"); + }else{ + g_info("Cannot verify subject"); + valid=FALSE; + } + OPENSSL_free(subject); + + if(!valid) + return valid; + } + + if(!verify_certificate_sn(cert, CERT_SERIAL_NUMBER)){ + return FALSE; + }else{ + g_info("Verified serial number"); + } + + return TRUE; + +} + + + + +#ifdef BUILD_SERVER +static void +test_ssl_authorization_manager(void) +{ + int status=0; + pid_t pid; + ThriftSSLSocket *tSSLsocket = NULL; + ThriftTransport *transport = NULL; + /* int port = 51199; */ + int port = 443; + GError *error=NULL; + + guchar buf[17] = TEST_DATA; /* a buffer */ + +/* + pid = fork (); + g_assert ( pid >= 0 ); + + if ( pid == 0 ) + { + thrift_ssl_socket_server (port); + exit (0); + } else { + */ + /* parent connects, wait a bit for the socket to be created */ + sleep (1); + + /* Test against level2 owncloud certificate */ + tSSLsocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error); + thrift_ssl_socket_set_manager(tSSLsocket, my_access_manager); /* Install pinning manager */ + /* thrift_ssl_load_cert_from_file(tSSLsocket, "./owncloud.level2crm.pem"); */ + unsigned char cert_buffer[65534]; + read_from_file(cert_buffer, 65534, "../../keys/client.pem"); + if(!thrift_ssl_load_cert_from_buffer(tSSLsocket, cert_buffer)){ + g_warning("Certificates cannot be loaded!"); + } + + transport = THRIFT_TRANSPORT (tSSLsocket); + g_assert (thrift_ssl_socket_open (transport, NULL) == TRUE); + g_assert (thrift_ssl_socket_is_open (transport)); + + thrift_ssl_socket_write (transport, buf, 17, NULL); + + /* write fail */ + send_error = 1; + /* + thrift_ssl_socket_write (transport, buf, 1, NULL); + send_error = 0; + thrift_ssl_socket_write_end (transport, NULL); + thrift_ssl_socket_flush (transport, NULL); + */ + thrift_ssl_socket_close (transport, NULL); + g_object_unref (tSSLsocket); + + /* g_assert ( wait (&status) == pid ); */ + g_assert ( status == 0 ); + /* } */ +} +#endif + + +static void +thrift_socket_server (const int port) +{ + int bytes = 0; + ThriftServerTransport *transport = NULL; + ThriftTransport *client = NULL; + guchar buf[10]; /* a buffer */ + guchar match[10] = TEST_DATA; + + ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, NULL); + + transport = THRIFT_SERVER_TRANSPORT (tsocket); + thrift_server_transport_listen (transport, NULL); + client = thrift_server_transport_accept (transport, NULL); + g_assert (client != NULL); + + /* read 10 bytes */ + bytes = thrift_ssl_socket_read (client, buf, 10, NULL); + g_assert (bytes == 10); /* make sure we've read 10 bytes */ + g_assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */ + + /* failed read */ + recv_error = 1; + thrift_ssl_socket_read (client, buf, 1, NULL); + recv_error = 0; + + thrift_ssl_socket_read_end (client, NULL); + thrift_ssl_socket_close (client, NULL); + g_object_unref (tsocket); + g_object_unref (client); +} + +int +main(int argc, char *argv[]) +{ + int retval; +#if (!GLIB_CHECK_VERSION (2, 36, 0)) + g_type_init(); +#endif + + g_test_init (&argc, &argv, NULL); + + thrift_ssl_socket_initialize_openssl(); + + g_test_add_func ("/testtransportsslsocket/CreateAndDestroy", test_ssl_create_and_destroy); + g_test_add_func ("/testtransportsslsocket/CreateAndSetProperties", test_ssl_create_and_set_properties); + g_test_add_func ("/testtransportsslsocket/OpenAndCloseNonSSLServer", test_ssl_open_and_close_non_ssl_server); + g_test_add_func ("/testtransportsslsocket/OpenAndWriteInvalidSocket", test_ssl_write_invalid_socket); + + + + + retval = g_test_run (); + + thrift_ssl_socket_finalize_openssl(); + + return retval; +} + |