2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
20 #include <glib-object.h>
28 #include <thrift/c_glib/thrift.h>
29 #include <thrift/c_glib/protocol/thrift_binary_protocol.h>
30 #include <thrift/c_glib/protocol/thrift_compact_protocol.h>
31 #include <thrift/c_glib/protocol/thrift_multiplexed_protocol.h>
32 #include <thrift/c_glib/transport/thrift_buffered_transport.h>
33 #include <thrift/c_glib/transport/thrift_framed_transport.h>
34 #include <thrift/c_glib/transport/thrift_ssl_socket.h>
35 #include <thrift/c_glib/transport/thrift_socket.h>
36 #include <thrift/c_glib/transport/thrift_transport.h>
38 #include "../gen-c_glib/t_test_second_service.h"
39 #include "../gen-c_glib/t_test_thrift_test.h"
41 /* Handle SIGPIPE signals (indicating the server has closed the
42 connection prematurely) by outputting an error message before
45 sigpipe_handler (int signal_number
)
47 THRIFT_UNUSED_VAR (signal_number
);
49 /* Flush standard output to make sure the test results so far are
53 fputs ("Broken pipe (server closed connection prematurely)\n", stderr
);
56 /* Re-raise the signal, this time invoking the default signal
57 handler, to terminate the program */
61 /* Compare two gint32 values. Used for sorting and finding integer
62 values within a GList. */
64 gint32_compare (gconstpointer a
, gconstpointer b
)
66 gint32 int32_a
= *(gint32
*)a
;
67 gint32 int32_b
= *(gint32
*)b
;
70 if (int32_a
< int32_b
)
72 else if (int32_a
> int32_b
)
79 * It gets a multiplexed protocol which uses a concrete protocol underneath
80 * @param protocol_name the fully qualified protocol path (e.g. "binary:multi")
81 * @param transport the underlying transport
82 * @param service_name the single supported service name
83 * @todo need to allow multiple services to fully test multiplexed
84 * @return a multiplexed protocol wrapping the correct underlying protocol
87 get_multiplexed_protocol(gchar
*protocol_name
, ThriftTransport
*transport
, gchar
*service_name
)
89 ThriftProtocol
* multiplexed_protocol
= NULL
;
91 if ( strncmp(protocol_name
, "binary:", 7) == 0) {
92 multiplexed_protocol
= g_object_new (THRIFT_TYPE_BINARY_PROTOCOL
,
93 "transport", transport
,
95 } else if ( strncmp(protocol_name
, "compact:", 8) == 0) {
96 multiplexed_protocol
= g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL
,
97 "transport", transport
,
100 fprintf(stderr
, "Unknown multiplex protocol name: %s\n", protocol_name
);
104 return g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL
,
105 "transport", transport
,
106 "protocol", multiplexed_protocol
,
107 "service-name", service_name
,
112 main (int argc
, char **argv
)
114 static gchar
* host
= NULL
;
115 static gint port
= 9090;
116 static gchar
* path
= NULL
;
117 static gboolean ssl
= FALSE
;
118 static gchar
* transport_option
= NULL
;
119 static gchar
* protocol_option
= NULL
;
120 static gint num_tests
= 1;
123 GOptionEntry option_entries
[] ={
124 { "host", 'h', 0, G_OPTION_ARG_STRING
, &host
,
125 "Host to connect (=localhost)", NULL
},
126 { "port", 'p', 0, G_OPTION_ARG_INT
, &port
,
127 "Port number to connect (=9090)", NULL
},
128 { "domain-socket", 0, 0, G_OPTION_ARG_STRING
, &path
,
129 "Unix socket domain path to connect", NULL
},
130 { "ssl", 's', 0, G_OPTION_ARG_NONE
, &ssl
,
131 "Enable SSL", NULL
},
132 { "transport", 't', 0, G_OPTION_ARG_STRING
, &transport_option
,
133 "Transport: buffered, framed (=buffered)", NULL
},
134 { "protocol", 'r', 0, G_OPTION_ARG_STRING
, &protocol_option
,
135 "Protocol: binary, compact, multi, multic (=binary)", NULL
},
136 { "testloops", 'n', 0, G_OPTION_ARG_INT
, &num_tests
,
137 "Number of tests (=1)", NULL
},
141 struct sigaction sigpipe_action
;
143 GType socket_type
= THRIFT_TYPE_SOCKET
;
144 gchar
*socket_name
= "ip";
145 GType transport_type
= THRIFT_TYPE_BUFFERED_TRANSPORT
;
146 gchar
*transport_name
= "buffered";
147 GType protocol_type
= THRIFT_TYPE_BINARY_PROTOCOL
;
148 gchar
*protocol_name
= "binary";
150 ThriftSocket
*socket
= NULL
;
151 ThriftTransport
*transport
= NULL
;
152 ThriftProtocol
*protocol
= NULL
;
153 ThriftProtocol
*protocol2
= NULL
; // for multiplexed tests
155 TTestThriftTestIf
*test_client
= NULL
;
156 TTestSecondServiceIf
*second_service
= NULL
; // for multiplexed tests
158 struct timeval time_start
, time_stop
, time_elapsed
;
159 guint64 time_elapsed_usec
, time_total_usec
= 0;
160 guint64 time_min_usec
= G_MAXUINT64
, time_max_usec
= 0, time_avg_usec
;
162 GOptionContext
*option_context
;
163 gboolean options_valid
= TRUE
;
166 GError
*error
= NULL
;
168 #if (!GLIB_CHECK_VERSION (2, 36, 0))
172 /* Configure and parse our command-line options */
173 option_context
= g_option_context_new (NULL
);
174 g_option_context_add_main_entries (option_context
,
177 if (!g_option_context_parse (option_context
,
181 fprintf (stderr
, "%s\n", error
->message
);
184 g_option_context_free (option_context
);
186 /* Set remaining default values for unspecified options */
188 host
= g_strdup ("localhost");
190 /* Validate the parsed options */
191 if (protocol_option
!= NULL
) {
192 if (strncmp (protocol_option
, "compact", 8) == 0) {
193 protocol_type
= THRIFT_TYPE_COMPACT_PROTOCOL
;
194 protocol_name
= "compact";
196 else if (strncmp (protocol_option
, "multi", 6) == 0) {
197 protocol_type
= THRIFT_TYPE_MULTIPLEXED_PROTOCOL
;
198 protocol_name
= "binary:multi";
200 else if (strncmp (protocol_option
, "multic", 7) == 0) {
201 protocol_type
= THRIFT_TYPE_MULTIPLEXED_PROTOCOL
;
202 protocol_name
= "compact:multic";
204 else if (strncmp (protocol_option
, "binary", 7) == 0) {
205 printf("We are going with default protocol\n");
208 fprintf (stderr
, "Unknown protocol type %s\n", protocol_option
);
209 options_valid
= FALSE
;
213 if (transport_option
!= NULL
) {
214 if (strncmp (transport_option
, "framed", 7) == 0) {
215 transport_type
= THRIFT_TYPE_FRAMED_TRANSPORT
;
216 transport_name
= "framed";
218 else if (strncmp (transport_option
, "buffered", 9) != 0) {
219 fprintf (stderr
, "Unknown transport type %s\n", transport_option
);
220 options_valid
= FALSE
;
225 socket_type
= THRIFT_TYPE_SSL_SOCKET
;
226 socket_name
= "ip-ssl";
227 printf("Type name %s\n", g_type_name (socket_type
));
234 printf ("Connecting (%s/%s) to: %s/%s\n",
240 printf ("Connecting (%s/%s) to: %s/%s:%d\n",
248 /* Install our SIGPIPE handler, which outputs an error message to
249 standard error before exiting so testers can know what
251 memset (&sigpipe_action
, 0, sizeof (sigpipe_action
));
252 sigpipe_action
.sa_handler
= sigpipe_handler
;
253 sigpipe_action
.sa_flags
= SA_RESETHAND
;
254 sigaction (SIGPIPE
, &sigpipe_action
, NULL
);
257 thrift_ssl_socket_initialize_openssl();
260 /* Establish all our connection objects */
262 socket
= g_object_new (socket_type
,
266 socket
= g_object_new (socket_type
,
272 if (ssl
&& !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket
), "../keys/CA.pem")) {
273 fprintf(stderr
, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n");
274 g_clear_object (&socket
);
278 transport
= g_object_new (transport_type
,
282 if(protocol_type
==THRIFT_TYPE_MULTIPLEXED_PROTOCOL
) {
283 // TODO: A multiplexed test should also test "Second" (see Java TestServer)
284 // The context comes from the name of the thrift file. If multiple thrift
285 // schemas are used we have to redo the way this is done.
286 protocol
= get_multiplexed_protocol(protocol_name
, transport
, "ThriftTest");
287 if (NULL
== protocol
) {
288 g_clear_object (&transport
);
289 g_clear_object (&socket
);
293 // Make a second protocol and client running on the same multiplexed transport
294 protocol2
= get_multiplexed_protocol(protocol_name
, transport
, "SecondService");
295 second_service
= g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT
,
296 "input_protocol", protocol2
,
297 "output_protocol", protocol2
,
301 protocol
= g_object_new (protocol_type
,
302 "transport", transport
,
306 test_client
= g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT
,
307 "input_protocol", protocol
,
308 "output_protocol", protocol
,
311 /* Execute the actual tests */
312 for (test_num
= 0; test_num
< num_tests
; ++test_num
) {
313 if (thrift_transport_open (transport
, &error
)) {
314 gchar
*string
= NULL
;
315 gboolean boolean
= 0;
321 gint byte_thing
, i32_thing
, inner_byte_thing
, inner_i32_thing
;
322 gint64 i64_thing
, inner_i64_thing
;
324 TTestXtruct
*xtruct_out
, *xtruct_out2
, *xtruct_in
, *inner_xtruct_in
;
325 TTestXtruct2
*xtruct2_out
, *xtruct2_in
;
327 GHashTable
*map_out
, *map_in
, *inner_map_in
;
328 GHashTable
*set_out
, *set_in
;
330 gint32
*i32_key_ptr
, *i32_value_ptr
;
331 GHashTableIter hash_table_iter
, inner_hash_table_iter
;
332 GList
*keys_out
, *keys_in
, *keys_elem
;
334 GArray
*list_out
, *list_in
;
336 TTestNumberz numberz
;
337 TTestNumberz numberz2
;
339 TTestUserId user_id
, *user_id_ptr
, *user_id_ptr2
;
341 TTestInsanity
*insanity_out
, *insanity_in
;
342 GHashTable
*user_map
;
343 GHashTableIter user_map_iter
;
346 TTestXception
*xception
= NULL
;
347 TTestXception2
*xception2
= NULL
;
349 gboolean oneway_result
;
350 struct timeval oneway_start
, oneway_end
, oneway_elapsed
;
351 gint oneway_elapsed_usec
;
357 printf ("Test #%d, connect %s\n", test_num
+ 1, path
);
359 printf ("Test #%d, connect %s:%d\n", test_num
+ 1, host
, port
);
361 gettimeofday (&time_start
, NULL
);
363 /* These test routines have been ported from the C++ test
364 client, care being taken to ensure their output remains as
365 close as possible to the original to facilitate diffs.
367 For simplicity comments have been omitted, but every routine
368 has the same basic structure:
370 - Create and populate data structures as necessary.
372 - Format and output (to the console) a representation of the
375 - Issue the remote method call to the server.
377 - Format and output a representation of the returned data.
379 - Verify the returned data matches what was expected.
381 - Deallocate any created data structures.
383 Note the recognized values and expected behaviour of each
384 remote method are described in ThriftTest.thrift, which
385 you'll find in the top-level "test" folder. */
390 printf ("testVoid()");
391 if (t_test_thrift_test_if_test_void (test_client
, &error
)) {
392 printf (" = void\n");
396 printf ("%s\n", error
->message
);
397 g_error_free (error
);
406 printf ("testString(\"Test\")");
407 if (t_test_thrift_test_if_test_string (test_client
,
411 printf (" = \"%s\"\n", string
);
412 if (strncmp (string
, "Test", 5) != 0)
419 printf ("%s\n", error
->message
);
420 g_error_free (error
);
427 * Multiplexed Test - do this right in the middle of the normal Test Client run
429 if (second_service
) {
430 printf ("testSecondServiceMultiplexSecondTestString(\"2nd\")");
431 if (t_test_second_service_if_secondtest_string (second_service
,
435 printf (" = \"%s\"\n", string
);
436 if (strcmp (string
, "testString(\"2nd\")") != 0) {
443 printf ("%s\n", error
->message
);
444 g_error_free (error
);
454 printf ("testByte(true)");
455 if (t_test_thrift_test_if_test_bool (test_client
,
459 printf (" = %s\n", boolean
? "true" : "false");
464 printf ("%s\n", error
->message
);
465 g_error_free (error
);
470 printf ("testByte(false)");
471 if (t_test_thrift_test_if_test_bool (test_client
,
475 printf (" = %s\n", boolean
? "true" : "false");
480 printf ("%s\n", error
->message
);
481 g_error_free (error
);
490 printf ("testByte(1)");
491 if (t_test_thrift_test_if_test_byte (test_client
,
495 printf (" = %d\n", byte
);
500 printf ("%s\n", error
->message
);
501 g_error_free (error
);
506 printf ("testByte(-1)");
507 if (t_test_thrift_test_if_test_byte (test_client
,
511 printf (" = %d\n", byte
);
516 printf ("%s\n", error
->message
);
517 g_error_free (error
);
526 printf ("testI32(-1)");
527 if (t_test_thrift_test_if_test_i32 (test_client
,
531 printf (" = %d\n", int32
);
536 printf ("%s\n", error
->message
);
537 g_error_free (error
);
546 printf ("testI64(-34359738368)");
547 if (t_test_thrift_test_if_test_i64 (test_client
,
549 (gint64
)-34359738368,
551 printf (" = %" PRId64
"\n", int64
);
552 if (int64
!= (gint64
)-34359738368)
556 printf ("%s\n", error
->message
);
557 g_error_free (error
);
566 printf("testDouble(-5.2098523)");
567 if (t_test_thrift_test_if_test_double (test_client
,
571 printf (" = %f\n", dub
);
572 if ((dub
- (-5.2098523)) > 0.001)
576 printf ("%s\n", error
->message
);
577 g_error_free (error
);
586 printf ("testBinary(empty)");
587 GByteArray
*emptyArray
= g_byte_array_new();
588 GByteArray
*result
= NULL
;
589 if (t_test_thrift_test_if_test_binary (test_client
,
593 GBytes
*response
= g_byte_array_free_to_bytes(result
); // frees result
595 gsize siz
= g_bytes_get_size(response
);
597 printf(" = empty\n");
599 printf(" = not empty (%ld bytes)\n", (long)siz
);
602 g_bytes_unref(response
);
604 printf ("%s\n", error
->message
);
605 g_error_free (error
);
610 g_byte_array_unref(emptyArray
);
613 // TODO: add testBinary() with data
614 printf ("testBinary([-128..127]) = {");
615 const signed char bin_data
[256]
616 = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114,
617 -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99,
618 -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84,
619 -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69,
620 -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54,
621 -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39,
622 -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24,
623 -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9,
624 -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6,
625 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
626 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
627 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
628 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
629 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
630 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
631 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
632 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
634 GByteArray
*fullArray
= g_byte_array_new();
635 g_byte_array_append(fullArray
, (guint8
*)(&bin_data
[0]), 256);
636 if (t_test_thrift_test_if_test_binary (test_client
,
640 GBytes
*response
= g_byte_array_free_to_bytes(result
); // frees result
642 gsize siz
= g_bytes_get_size(response
);
643 gconstpointer ptr
= g_bytes_get_data(response
, &siz
);
649 for (i
= 0; i
< 256; ++i
) {
654 int val
= ((signed char *)ptr
)[i
];
656 if (!failed
&& val
!= i
- 128) {
662 printf("FAIL (bad content) size %ld OK\n", (long)siz
);
665 printf("OK size %ld OK\n", (long)siz
);
668 printf(" = bad size %ld\n", (long)siz
);
671 g_bytes_unref(response
);
673 printf ("%s\n", error
->message
);
674 g_error_free (error
);
679 g_byte_array_unref(fullArray
);
685 printf ("testStruct({\"Zero\", 1, -3, -5})");
686 xtruct_out
= g_object_new (T_TEST_TYPE_XTRUCT
,
687 "string_thing", "Zero",
692 xtruct_in
= g_object_new (T_TEST_TYPE_XTRUCT
, NULL
);
694 if (t_test_thrift_test_if_test_struct (test_client
,
698 g_object_get (xtruct_in
,
699 "string_thing", &string
,
700 "byte_thing", &byte_thing
,
701 "i32_thing", &i32_thing
,
702 "i64_thing", &i64_thing
,
705 printf (" = {\"%s\", %d, %d, %" PRId64
"}\n",
710 if ((string
== NULL
|| strncmp (string
, "Zero", 5) != 0) ||
713 i64_thing
!= (gint64
)-5)
722 printf ("%s\n", error
->message
);
723 g_error_free (error
);
728 // g_clear_object(&xtruct_out); used below
729 g_clear_object(&xtruct_in
);
734 printf ("testNest({1, {\"Zero\", 1, -3, -5}), 5}");
735 xtruct2_out
= g_object_new (T_TEST_TYPE_XTRUCT2
,
737 "struct_thing", xtruct_out
,
740 xtruct2_in
= g_object_new (T_TEST_TYPE_XTRUCT2
, NULL
);
742 if (t_test_thrift_test_if_test_nest (test_client
,
746 g_object_get (xtruct2_in
,
747 "byte_thing", &byte_thing
,
748 "struct_thing", &xtruct_in
,
749 "i32_thing", &i32_thing
,
751 g_object_get (xtruct_in
,
752 "string_thing", &string
,
753 "byte_thing", &inner_byte_thing
,
754 "i32_thing", &inner_i32_thing
,
755 "i64_thing", &inner_i64_thing
,
758 printf (" = {%d, {\"%s\", %d, %d, %" PRId64
"}, %d}\n",
765 if (byte_thing
!= 1 ||
766 (string
== NULL
|| strncmp (string
, "Zero", 5) != 0) ||
767 inner_byte_thing
!= 1 ||
768 inner_i32_thing
!= -3 ||
769 inner_i64_thing
!= (gint64
)-5 ||
779 printf ("%s\n", error
->message
);
780 g_error_free (error
);
786 g_clear_object(&xtruct_in
);
787 g_clear_object(&xtruct2_in
);
788 g_clear_object(&xtruct2_out
);
789 g_clear_object(&xtruct_out
);
794 map_out
= g_hash_table_new_full (g_int_hash
,
798 for (i
= 0; i
< 5; ++i
) {
799 i32_key_ptr
= g_malloc (sizeof *i32_key_ptr
);
800 i32_value_ptr
= g_malloc (sizeof *i32_value_ptr
);
803 *i32_value_ptr
= i
- 10;
805 g_hash_table_insert (map_out
, i32_key_ptr
, i32_value_ptr
);
807 printf ("testMap({");
809 g_hash_table_iter_init (&hash_table_iter
, map_out
);
810 while (g_hash_table_iter_next (&hash_table_iter
,
818 printf ("%d => %d", *(gint32
*)key
, *(gint32
*)value
);
822 map_in
= g_hash_table_new_full (g_int_hash
,
827 if (t_test_thrift_test_if_test_map (test_client
,
833 g_hash_table_iter_init (&hash_table_iter
, map_in
);
834 while (g_hash_table_iter_next (&hash_table_iter
,
842 printf ("%d => %d", *(gint32
*)key
, *(gint32
*)value
);
846 if (g_hash_table_size (map_in
) != g_hash_table_size (map_out
))
849 g_hash_table_iter_init (&hash_table_iter
, map_out
);
850 while (g_hash_table_iter_next (&hash_table_iter
,
853 gpointer in_value
= g_hash_table_lookup (map_in
, key
);
854 if (in_value
== NULL
||
855 *(gint32
*)in_value
!= *(gint32
*)value
) {
863 printf ("%s\n", error
->message
);
864 g_error_free (error
);
870 g_hash_table_unref (map_in
);
871 g_hash_table_unref (map_out
);
876 map_out
= g_hash_table_new_full (g_str_hash
,
880 g_hash_table_insert (map_out
, "a", "2");
881 g_hash_table_insert (map_out
, "b", "blah");
882 g_hash_table_insert (map_out
, "some", "thing");
883 printf ("testStringMap({");
885 g_hash_table_iter_init (&hash_table_iter
, map_out
);
886 while (g_hash_table_iter_next (&hash_table_iter
,
894 printf ("\"%s\" => \"%s\"", (gchar
*)key
, (gchar
*)value
);
898 map_in
= g_hash_table_new_full (g_str_hash
,
903 if (t_test_thrift_test_if_test_string_map (test_client
,
909 g_hash_table_iter_init (&hash_table_iter
, map_in
);
910 while (g_hash_table_iter_next (&hash_table_iter
,
918 printf ("\"%s\" => \"%s\"", (gchar
*)key
, (gchar
*)value
);
922 if (g_hash_table_size (map_in
) != g_hash_table_size (map_out
))
925 g_hash_table_iter_init (&hash_table_iter
, map_out
);
926 while (g_hash_table_iter_next (&hash_table_iter
,
929 gpointer in_value
= g_hash_table_lookup (map_in
, key
);
930 if (in_value
== NULL
||
931 strcmp ((gchar
*)in_value
, (gchar
*)value
) != 0) {
939 printf ("%s\n", error
->message
);
940 g_error_free (error
);
946 g_hash_table_unref (map_in
);
947 g_hash_table_unref (map_out
);
952 set_out
= g_hash_table_new_full (g_int_hash
, g_int_equal
, g_free
, NULL
);
953 for (i
= -2; i
< 3; ++i
) {
954 i32_key_ptr
= g_malloc (sizeof *i32_key_ptr
);
957 g_hash_table_insert (set_out
, i32_key_ptr
, NULL
);
959 printf ("testSet({");
961 keys_out
= g_hash_table_get_keys (set_out
);
962 keys_elem
= keys_out
;
963 while (keys_elem
!= NULL
) {
969 printf ("%d", *(gint32
*)keys_elem
->data
);
971 keys_elem
= keys_elem
->next
;
975 set_in
= g_hash_table_new_full (g_int_hash
, g_int_equal
, g_free
, NULL
);
977 if (t_test_thrift_test_if_test_set (test_client
,
983 keys_in
= g_hash_table_get_keys (set_in
);
985 while (keys_elem
!= NULL
) {
991 printf ("%d", *(gint32
*)keys_elem
->data
);
993 keys_elem
= keys_elem
->next
;
997 if (g_list_length (keys_in
) != g_list_length (keys_out
))
1000 keys_elem
= keys_out
;
1001 while (keys_elem
!= NULL
) {
1002 if (g_list_find_custom (keys_in
,
1004 gint32_compare
) == NULL
) {
1009 keys_elem
= keys_elem
->next
;
1013 g_list_free (keys_in
);
1016 printf ("%s\n", error
->message
);
1017 g_error_free (error
);
1023 g_hash_table_unref (set_in
);
1024 g_list_free (keys_out
);
1025 g_hash_table_unref (set_out
);
1030 list_out
= g_array_new (FALSE
, TRUE
, sizeof (gint32
));
1031 for (i
= -2; i
< 3; ++i
) {
1032 g_array_append_val (list_out
, i
);
1034 printf ("testList({");
1036 for (i
= 0; i
< (gint32
)list_out
->len
; ++i
) {
1042 printf ("%d", g_array_index (list_out
, gint32
, i
));
1046 list_in
= g_array_new (FALSE
, TRUE
, sizeof (gint32
));
1048 if (t_test_thrift_test_if_test_list (test_client
,
1054 for (i
= 0; i
< (gint32
)list_in
->len
; ++i
) {
1060 printf ("%d", g_array_index (list_in
, gint32
, i
));
1064 if (list_in
->len
!= list_out
->len
||
1065 memcmp (list_in
->data
,
1067 list_in
->len
* sizeof (gint32
)) != 0)
1071 printf ("%s\n", error
->message
);
1072 g_error_free (error
);
1078 g_array_unref (list_in
);
1079 g_array_unref (list_out
);
1084 printf("testEnum(ONE)");
1085 if (t_test_thrift_test_if_test_enum (test_client
,
1089 printf(" = %d\n", numberz
);
1090 if (numberz
!= T_TEST_NUMBERZ_ONE
)
1094 printf ("%s\n", error
->message
);
1095 g_error_free (error
);
1101 printf("testEnum(TWO)");
1102 if (t_test_thrift_test_if_test_enum (test_client
,
1106 printf(" = %d\n", numberz
);
1107 if (numberz
!= T_TEST_NUMBERZ_TWO
)
1111 printf ("%s\n", error
->message
);
1112 g_error_free (error
);
1118 printf("testEnum(THREE)");
1119 if (t_test_thrift_test_if_test_enum (test_client
,
1121 T_TEST_NUMBERZ_THREE
,
1123 printf(" = %d\n", numberz
);
1124 if (numberz
!= T_TEST_NUMBERZ_THREE
)
1128 printf ("%s\n", error
->message
);
1129 g_error_free (error
);
1135 printf("testEnum(FIVE)");
1136 if (t_test_thrift_test_if_test_enum (test_client
,
1138 T_TEST_NUMBERZ_FIVE
,
1140 printf(" = %d\n", numberz
);
1141 if (numberz
!= T_TEST_NUMBERZ_FIVE
)
1145 printf ("%s\n", error
->message
);
1146 g_error_free (error
);
1152 printf("testEnum(EIGHT)");
1153 if (t_test_thrift_test_if_test_enum (test_client
,
1155 T_TEST_NUMBERZ_EIGHT
,
1157 printf(" = %d\n", numberz
);
1158 if (numberz
!= T_TEST_NUMBERZ_EIGHT
)
1162 printf ("%s\n", error
->message
);
1163 g_error_free (error
);
1172 printf ("testTypedef(309858235082523)");
1173 if (t_test_thrift_test_if_test_typedef (test_client
,
1177 printf(" = %" PRId64
"\n", user_id
);
1178 if (user_id
!= 309858235082523LL)
1182 printf ("%s\n", error
->message
);
1183 g_error_free (error
);
1192 printf ("testMapMap(1)");
1193 map_in
= g_hash_table_new_full (g_int_hash
,
1196 (GDestroyNotify
)g_hash_table_unref
);
1197 if (t_test_thrift_test_if_test_map_map (test_client
,
1201 g_hash_table_iter_init (&hash_table_iter
, map_in
);
1204 while (g_hash_table_iter_next (&hash_table_iter
,
1207 printf ("%d => {", *(gint32
*)key
);
1209 g_hash_table_iter_init (&inner_hash_table_iter
,
1210 (GHashTable
*)value
);
1211 while (g_hash_table_iter_next (&inner_hash_table_iter
,
1214 printf ("%d => %d, ", *(gint32
*)key
, *(gint32
*)value
);
1221 if (g_hash_table_size (map_in
) != 2)
1224 gint32 inner_keys
[] = {1, 2, 3, 4};
1228 inner_map_in
= g_hash_table_lookup (map_in
, &i32_key
);
1229 if (inner_map_in
== NULL
||
1230 g_hash_table_size (inner_map_in
) != 4)
1233 keys_in
= g_hash_table_get_keys (inner_map_in
);
1234 keys_in
= g_list_sort (keys_in
, gint32_compare
);
1236 for (i
= 0; i
< 4; i
++) {
1237 keys_elem
= g_list_nth (keys_in
, 3 - i
);
1239 if (*(gint32
*)keys_elem
->data
!= (-1 * inner_keys
[i
]) ||
1240 *(gint32
*)g_hash_table_lookup (inner_map_in
,
1242 (-1 * inner_keys
[i
])) {
1248 g_list_free (keys_in
);
1252 inner_map_in
= g_hash_table_lookup (map_in
, &i32_key
);
1253 if (inner_map_in
== NULL
||
1254 g_hash_table_size (inner_map_in
) != 4)
1257 keys_in
= g_hash_table_get_keys (inner_map_in
);
1258 keys_in
= g_list_sort (keys_in
, gint32_compare
);
1260 for (i
= 0; i
< 4; i
++) {
1261 keys_elem
= g_list_nth (keys_in
, i
);
1263 if (*(gint32
*)keys_elem
->data
!= inner_keys
[i
] ||
1264 *(gint32
*)g_hash_table_lookup (inner_map_in
,
1272 g_list_free (keys_in
);
1277 printf ("%s\n", error
->message
);
1278 g_error_free (error
);
1284 g_hash_table_unref (map_in
);
1289 insanity_out
= g_object_new (T_TEST_TYPE_INSANITY
, NULL
);
1290 g_object_get (insanity_out
,
1291 "userMap", &user_map
,
1292 "xtructs", &xtructs
,
1295 numberz
= T_TEST_NUMBERZ_FIVE
;
1296 numberz2
= T_TEST_NUMBERZ_EIGHT
;
1297 user_id_ptr
= g_malloc (sizeof *user_id_ptr
);
1299 user_id_ptr2
= g_malloc (sizeof *user_id_ptr
);
1301 g_hash_table_insert (user_map
, (gpointer
)numberz
, user_id_ptr
);
1302 g_hash_table_insert (user_map
, (gpointer
)numberz2
, user_id_ptr2
);
1303 g_hash_table_unref (user_map
);
1305 xtruct_out
= g_object_new (T_TEST_TYPE_XTRUCT
,
1306 "string_thing", "Hello2",
1311 xtruct_out2
= g_object_new (T_TEST_TYPE_XTRUCT
,
1312 "string_thing", "Goodbye4",
1317 g_ptr_array_add (xtructs
, xtruct_out2
);
1318 g_ptr_array_add (xtructs
, xtruct_out
);
1319 g_ptr_array_unref (xtructs
);
1321 map_in
= g_hash_table_new_full (g_int64_hash
,
1324 (GDestroyNotify
)g_hash_table_unref
);
1326 printf("testInsanity()");
1327 if (t_test_thrift_test_if_test_insanity (test_client
,
1332 g_hash_table_iter_init (&hash_table_iter
, map_in
);
1333 while (g_hash_table_iter_next (&hash_table_iter
,
1336 printf ("%" PRId64
" => {", *(TTestUserId
*)key
);
1338 g_hash_table_iter_init (&inner_hash_table_iter
,
1339 (GHashTable
*)value
);
1340 while (g_hash_table_iter_next (&inner_hash_table_iter
,
1343 printf ("%d => {", (TTestNumberz
)key
);
1345 g_object_get ((TTestInsanity
*)value
,
1346 "userMap", &user_map
,
1347 "xtructs", &xtructs
,
1351 g_hash_table_iter_init (&user_map_iter
, user_map
);
1352 while (g_hash_table_iter_next (&user_map_iter
,
1355 printf ("%d => %" PRId64
", ",
1357 *(TTestUserId
*)value
);
1360 g_hash_table_unref (user_map
);
1363 for (i
= 0; i
< (gint32
)xtructs
->len
; ++i
) {
1364 xtruct_in
= g_ptr_array_index (xtructs
, i
);
1365 g_object_get (xtruct_in
,
1366 "string_thing", &string
,
1367 "byte_thing", &byte_thing
,
1368 "i32_thing", &i32_thing
,
1369 "i64_thing", &i64_thing
,
1372 printf ("{\"%s\", %d, %d, %" PRId64
"}, ",
1379 g_ptr_array_unref (xtructs
);
1387 if (g_hash_table_size (map_in
) != 2)
1390 TTestNumberz numberz_key_values
[] = {
1391 T_TEST_NUMBERZ_TWO
, T_TEST_NUMBERZ_THREE
1393 gint user_map_values
[] = { 5, 8 };
1394 TTestUserId user_id_key
;
1397 inner_map_in
= g_hash_table_lookup (map_in
, &user_id_key
);
1398 if (inner_map_in
== NULL
||
1399 g_hash_table_size (inner_map_in
) != 2)
1402 TTestNumberz numberz_key
;
1404 for (i
= 0; i
< 2; ++i
) {
1405 numberz_key
= numberz_key_values
[i
];
1407 g_hash_table_lookup (inner_map_in
,
1408 (gconstpointer
)numberz_key
);
1409 if (insanity_in
== NULL
)
1412 g_object_get (insanity_in
,
1413 "userMap", &user_map
,
1414 "xtructs", &xtructs
,
1417 if (user_map
== NULL
)
1420 if (g_hash_table_size (user_map
) != 2)
1423 for (j
= 0; j
< 2; ++j
) {
1424 numberz_key
= (TTestNumberz
)user_map_values
[j
];
1427 g_hash_table_lookup (user_map
,
1428 (gconstpointer
)numberz_key
);
1429 if (value
== NULL
||
1430 *(TTestUserId
*)value
!= (TTestUserId
)user_map_values
[j
])
1435 g_hash_table_unref (user_map
);
1438 if (xtructs
== NULL
)
1441 if (xtructs
->len
!= 2)
1444 xtruct_in
= g_ptr_array_index (xtructs
, 0);
1445 g_object_get (xtruct_in
,
1446 "string_thing", &string
,
1447 "byte_thing", &byte_thing
,
1448 "i32_thing", &i32_thing
,
1449 "i64_thing", &i64_thing
,
1451 if ((string
== NULL
||
1452 strncmp (string
, "Goodbye4", 9) != 0) ||
1461 xtruct_in
= g_ptr_array_index (xtructs
, 1);
1462 g_object_get (xtruct_in
,
1463 "string_thing", &string
,
1464 "byte_thing", &byte_thing
,
1465 "i32_thing", &i32_thing
,
1466 "i64_thing", &i64_thing
,
1468 if ((string
== NULL
||
1469 strncmp (string
, "Hello2", 7) != 0) ||
1479 g_ptr_array_unref (xtructs
);
1486 inner_map_in
= g_hash_table_lookup (map_in
, &user_id_key
);
1487 if (inner_map_in
== NULL
||
1488 g_hash_table_size (inner_map_in
) != 1)
1492 g_hash_table_lookup (inner_map_in
,
1493 (gconstpointer
)T_TEST_NUMBERZ_SIX
);
1494 if (insanity_in
== NULL
)
1497 g_object_get (insanity_in
,
1498 "userMap", &user_map
,
1499 "xtructs", &xtructs
,
1502 if (user_map
== NULL
)
1505 if (g_hash_table_size (user_map
) != 0)
1508 g_hash_table_unref (user_map
);
1511 if (xtructs
== NULL
)
1514 if (xtructs
->len
!= 0)
1517 g_ptr_array_unref (xtructs
);
1524 printf ("%s\n", error
->message
);
1525 g_error_free (error
);
1531 g_hash_table_unref (map_in
);
1532 g_clear_object (&insanity_out
);
1534 /* test exception */
1535 printf ("testClient.testException(\"Xception\") =>");
1536 if (!t_test_thrift_test_if_test_exception (test_client
,
1541 g_object_get (xception
,
1542 "errorCode", &int32
,
1545 printf (" {%u, \"%s\"}\n", int32
, string
);
1548 g_clear_object (&xception
);
1550 g_error_free (error
);
1554 printf (" void\nFAILURE\n");
1557 if (xception
!= NULL
) {
1558 g_object_unref (xception
);
1562 if (error
!= NULL
) {
1563 g_error_free (error
);
1568 printf ("testClient.testException(\"TException\") =>");
1569 if (!t_test_thrift_test_if_test_exception (test_client
,
1575 printf (" Caught TException\n");
1577 g_error_free (error
);
1581 printf (" void\nFAILURE\n");
1584 g_clear_object (&xception
);
1586 if (error
!= NULL
) {
1587 g_error_free (error
);
1592 printf ("testClient.testException(\"success\") =>");
1593 if (t_test_thrift_test_if_test_exception (test_client
,
1599 printf (" void\nFAILURE\n");
1602 g_clear_object (&xception
);
1604 g_error_free (error
);
1608 g_assert (error
== NULL
);
1610 /* test multi exception */
1611 printf ("testClient.testMultiException(\"Xception\", \"test 1\") =>");
1612 xtruct_in
= g_object_new (T_TEST_TYPE_XTRUCT
, NULL
);
1613 if (!t_test_thrift_test_if_test_multi_exception (test_client
,
1621 xception2
== NULL
) {
1622 g_object_get (xception
,
1623 "errorCode", &int32
,
1626 printf (" {%u, \"%s\"}\n", int32
, string
);
1629 g_object_unref (xception
);
1632 g_error_free (error
);
1636 printf (" result\nFAILURE\n");
1639 g_clear_object (&xception
);
1640 g_clear_object (&xception2
);
1642 if (error
!= NULL
) {
1643 g_error_free (error
);
1647 g_object_unref (xtruct_in
);
1649 printf ("testClient.testMultiException(\"Xception2\", \"test 2\") =>");
1650 xtruct_in
= g_object_new (T_TEST_TYPE_XTRUCT
, NULL
);
1651 if (!t_test_thrift_test_if_test_multi_exception (test_client
,
1659 xception2
!= NULL
) {
1660 g_object_get (xception2
,
1661 "errorCode", &int32
,
1662 "struct_thing", &inner_xtruct_in
,
1664 g_object_get (inner_xtruct_in
,
1665 "string_thing", &string
,
1667 printf (" {%u, {\"%s\"}}\n", int32
, string
);
1670 g_clear_object (&inner_xtruct_in
);
1671 g_clear_object (&xception2
);
1673 g_error_free (error
);
1677 printf (" result\nFAILURE\n");
1680 g_clear_object (&xception
);
1681 g_clear_object (&xception2
);
1683 if (error
!= NULL
) {
1684 g_error_free (error
);
1688 g_clear_object (&xtruct_in
);
1690 printf ("testClient.testMultiException(\"success\", \"test 3\") =>");
1691 xtruct_in
= g_object_new (T_TEST_TYPE_XTRUCT
, NULL
);
1692 if (t_test_thrift_test_if_test_multi_exception (test_client
,
1700 xception2
== NULL
) {
1701 g_object_get (xtruct_in
,
1702 "string_thing", &string
,
1704 printf (" {{\"%s\"}}\n", string
);
1708 printf (" result\nFAILURE\n");
1711 g_clear_object (&xception
);
1712 g_clear_object (&xception2
);
1714 if (error
!= NULL
) {
1715 g_error_free (error
);
1719 g_clear_object (&xtruct_in
);
1721 /* test oneway void */
1722 printf ("testClient.testOneway(1) =>");
1723 gettimeofday (&oneway_start
, NULL
);
1724 oneway_result
= t_test_thrift_test_if_test_oneway (test_client
,
1727 gettimeofday (&oneway_end
, NULL
);
1728 timersub (&oneway_end
, &oneway_start
, &oneway_elapsed
);
1729 oneway_elapsed_usec
=
1730 oneway_elapsed
.tv_sec
* 1000 * 1000 + oneway_elapsed
.tv_usec
;
1732 if (oneway_result
) {
1733 if (oneway_elapsed_usec
> 200 * 1000) {
1734 printf (" FAILURE - took %.2f ms\n",
1735 (double)oneway_elapsed_usec
/ 1000.0);
1739 printf (" success - took %.2f ms\n",
1740 (double)oneway_elapsed_usec
/ 1000.0);
1743 printf ("%s\n", error
->message
);
1744 g_error_free (error
);
1751 * redo a simple test after the oneway to make sure we aren't "off by
1752 * one" -- if the server treated oneway void like normal void, this next
1753 * test will fail since it will get the void confirmation rather than
1754 * the correct result. In this circumstance, the client will receive the
1757 * application error: Wrong method name
1762 printf ("re-test testI32(-1)");
1763 if (t_test_thrift_test_if_test_i32 (test_client
,
1767 printf (" = %d\n", int32
);
1772 printf ("%s\n", error
->message
);
1773 g_error_free (error
);
1779 gettimeofday (&time_stop
, NULL
);
1780 timersub (&time_stop
, &time_start
, &time_elapsed
);
1782 time_elapsed
.tv_sec
* 1000 * 1000 + time_elapsed
.tv_usec
;
1784 printf("Total time: %" PRIu64
" us\n", time_elapsed_usec
);
1786 time_total_usec
+= time_elapsed_usec
;
1787 if (time_elapsed_usec
< time_min_usec
)
1788 time_min_usec
= time_elapsed_usec
;
1789 if (time_elapsed_usec
> time_max_usec
)
1790 time_max_usec
= time_elapsed_usec
;
1792 thrift_transport_close (transport
, &error
);
1795 printf ("Connect failed: %s\n", error
->message
);
1796 g_error_free (error
);
1803 /* All done---output statistics */
1804 puts ("\nAll tests done.");
1805 printf("Number of failures: %d\n", fail_count
);
1807 time_avg_usec
= time_total_usec
/ num_tests
;
1809 printf ("Min time: %" PRIu64
" us\n", time_min_usec
);
1810 printf ("Max time: %" PRIu64
" us\n", time_max_usec
);
1811 printf ("Avg time: %" PRIu64
" us\n", time_avg_usec
);
1813 g_clear_object(&second_service
);
1814 g_clear_object(&protocol2
);
1815 g_clear_object(&test_client
);
1816 g_clear_object(&protocol
);
1817 g_clear_object(&transport
);
1818 g_clear_object(&socket
);
1821 thrift_ssl_socket_finalize_openssl();