/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../gen-c_glib/t_test_second_service.h" #include "../gen-c_glib/t_test_thrift_test.h" /* Handle SIGPIPE signals (indicating the server has closed the connection prematurely) by outputting an error message before exiting. */ static void sigpipe_handler (int signal_number) { THRIFT_UNUSED_VAR (signal_number); /* Flush standard output to make sure the test results so far are logged */ fflush (stdout); fputs ("Broken pipe (server closed connection prematurely)\n", stderr); fflush (stderr); /* Re-raise the signal, this time invoking the default signal handler, to terminate the program */ raise (SIGPIPE); } /* Compare two gint32 values. Used for sorting and finding integer values within a GList. */ static gint gint32_compare (gconstpointer a, gconstpointer b) { gint32 int32_a = *(gint32 *)a; gint32 int32_b = *(gint32 *)b; int result = 0; if (int32_a < int32_b) result = -1; else if (int32_a > int32_b) result = 1; return result; } int main (int argc, char **argv) { static gchar * host = NULL; static gint port = 9090; static gchar * path = NULL; static gboolean ssl = FALSE; static gchar * transport_option = NULL; static gchar * protocol_option = NULL; static gint num_tests = 1; static GOptionEntry option_entries[] ={ { "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect (=localhost)", NULL }, { "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port number to connect (=9090)", NULL }, { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path, "Unix socket domain path to connect", NULL }, { "ssl", 's', 0, G_OPTION_ARG_NONE, &ssl, "Enable SSL", NULL }, { "transport", 't', 0, G_OPTION_ARG_STRING, &transport_option, "Transport: buffered, framed (=buffered)", NULL }, { "protocol", 'r', 0, G_OPTION_ARG_STRING, &protocol_option, "Protocol: binary, compact, multi, multic (=binary)", NULL }, { "testloops", 'n', 0, G_OPTION_ARG_INT, &num_tests, "Number of tests (=1)", NULL }, { NULL } }; struct sigaction sigpipe_action; GType socket_type = THRIFT_TYPE_SOCKET; gchar *socket_name = "ip"; GType transport_type = THRIFT_TYPE_BUFFERED_TRANSPORT; gchar *transport_name = "buffered"; GType protocol_type = THRIFT_TYPE_BINARY_PROTOCOL; gchar *protocol_name = "binary"; ThriftSocket *socket = NULL; ThriftTransport *transport = NULL; ThriftProtocol *protocol = NULL; ThriftProtocol *protocol2 = NULL; // for multiplexed tests ThriftProtocol *multiplexed_protocol = NULL; TTestThriftTestIf *test_client = NULL; TTestSecondServiceIf *second_service = NULL; // for multiplexed tests struct timeval time_start, time_stop, time_elapsed; guint64 time_elapsed_usec, time_total_usec = 0; guint64 time_min_usec = G_MAXUINT64, time_max_usec = 0, time_avg_usec; GOptionContext *option_context; gboolean options_valid = TRUE; int test_num = 0; int fail_count = 0; GError *error = NULL; #if (!GLIB_CHECK_VERSION (2, 36, 0)) g_type_init (); #endif /* Configure and parse our command-line options */ option_context = g_option_context_new (NULL); g_option_context_add_main_entries (option_context, option_entries, NULL); if (!g_option_context_parse (option_context, &argc, &argv, &error)) { fprintf (stderr, "%s\n", error->message); g_clear_error (&error); g_option_context_free (option_context); return 255; } g_option_context_free (option_context); /* Set remaining default values for unspecified options */ if (host == NULL) host = g_strdup ("localhost"); /* Validate the parsed options */ if (protocol_option != NULL) { if (strncmp (protocol_option, "compact", 8) == 0) { protocol_type = THRIFT_TYPE_COMPACT_PROTOCOL; protocol_name = "compact"; } else if (strncmp (protocol_option, "multi", 6) == 0) { protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; protocol_name = "binary:multi"; } else if (strncmp (protocol_option, "multic", 7) == 0) { protocol_type = THRIFT_TYPE_MULTIPLEXED_PROTOCOL; protocol_name = "compact:multic"; } else if (strncmp (protocol_option, "binary", 7) == 0) { printf("We are going with default protocol\n"); } else { fprintf (stderr, "Unknown protocol type %s\n", protocol_option); options_valid = FALSE; } } if (transport_option != NULL) { if (strncmp (transport_option, "framed", 7) == 0) { transport_type = THRIFT_TYPE_FRAMED_TRANSPORT; transport_name = "framed"; } else if (strncmp (transport_option, "buffered", 9) != 0) { fprintf (stderr, "Unknown transport type %s\n", transport_option); options_valid = FALSE; } } if (ssl) { socket_type = THRIFT_TYPE_SSL_SOCKET; socket_name = "ip-ssl"; printf("Type name %s\n", g_type_name (socket_type)); } if (!options_valid) return 254; if (path) { printf ("Connecting (%s/%s) to: %s/%s\n", transport_name, protocol_name, socket_name, path); } else { printf ("Connecting (%s/%s) to: %s/%s:%d\n", transport_name, protocol_name, socket_name, host, port); } /* Install our SIGPIPE handler, which outputs an error message to standard error before exiting so testers can know what happened */ memset (&sigpipe_action, 0, sizeof (sigpipe_action)); sigpipe_action.sa_handler = sigpipe_handler; sigpipe_action.sa_flags = SA_RESETHAND; sigaction (SIGPIPE, &sigpipe_action, NULL); if (ssl) { thrift_ssl_socket_initialize_openssl(); } /* Establish all our connection objects */ if (path) { socket = g_object_new (socket_type, "path", path, NULL); } else { socket = g_object_new (socket_type, "hostname", host, "port", port, NULL); } if (ssl && !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket), "../keys/CA.pem")) { fprintf(stderr, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n"); g_clear_object (&socket); return 253; } transport = g_object_new (transport_type, "transport", socket, NULL); if (protocol_type == THRIFT_TYPE_MULTIPLEXED_PROTOCOL) { // TODO: A multiplexed test should also test "Second" (see Java TestServer) // The context comes from the name of the thrift file. If multiple thrift // schemas are used we have to redo the way this is done. if (strncmp(protocol_name, "binary:", 7) == 0) { multiplexed_protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL); } else if (strncmp(protocol_name, "compact:", 8) == 0) { multiplexed_protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport", transport, NULL); } else { fprintf(stderr, "Unknown multiplex protocol name: %s\n", protocol_name); g_clear_object (&transport); g_clear_object (&socket); return 252; } protocol = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, "transport", transport, "protocol", multiplexed_protocol, "service-name", "ThriftTest", NULL);; if (NULL == protocol) { g_clear_object (&multiplexed_protocol); g_clear_object (&transport); g_clear_object (&socket); return 251; } // Make a second protocol and client running on the same multiplexed transport protocol2 = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, "transport", transport, "protocol", multiplexed_protocol, "service-name", "SecondService", NULL); second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT, "input_protocol", protocol2, "output_protocol", protocol2, NULL); }else{ protocol = g_object_new (protocol_type, "transport", transport, NULL); } test_client = g_object_new (T_TEST_TYPE_THRIFT_TEST_CLIENT, "input_protocol", protocol, "output_protocol", protocol, NULL); /* Execute the actual tests */ for (test_num = 0; test_num < num_tests; ++test_num) { if (thrift_transport_open (transport, &error)) { gchar *string = NULL; gboolean boolean = 0; gint8 byte = 0; gint32 int32 = 0; gint64 int64 = 0; gdouble dub = 0; gint byte_thing, i32_thing, inner_byte_thing, inner_i32_thing; gint64 i64_thing, inner_i64_thing; TTestXtruct *xtruct_out, *xtruct_out2, *xtruct_in, *inner_xtruct_in; TTestXtruct2 *xtruct2_out, *xtruct2_in; GHashTable *map_out, *map_in, *inner_map_in; GHashTable *set_out, *set_in; gpointer key, value; gint32 *i32_key_ptr, *i32_value_ptr; GHashTableIter hash_table_iter, inner_hash_table_iter; GList *keys_out, *keys_in, *keys_elem; GArray *list_out, *list_in; TTestNumberz numberz; TTestNumberz numberz2; TTestUserId user_id, *user_id_ptr, *user_id_ptr2; TTestInsanity *insanity_out, *insanity_in; GHashTable *user_map; GHashTableIter user_map_iter; GPtrArray *xtructs; TTestXception *xception = NULL; TTestXception2 *xception2 = NULL; gboolean oneway_result; struct timeval oneway_start, oneway_end, oneway_elapsed; gint oneway_elapsed_usec; gboolean first; gint32 i, j; if (path) { printf ("Test #%d, connect %s\n", test_num + 1, path); } else { printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); } gettimeofday (&time_start, NULL); /* These test routines have been ported from the C++ test client, care being taken to ensure their output remains as close as possible to the original to facilitate diffs. For simplicity comments have been omitted, but every routine has the same basic structure: - Create and populate data structures as necessary. - Format and output (to the console) a representation of the outgoing data. - Issue the remote method call to the server. - Format and output a representation of the returned data. - Verify the returned data matches what was expected. - Deallocate any created data structures. Note the recognized values and expected behaviour of each remote method are described in ThriftTest.thrift, which you'll find in the top-level "test" folder. */ /** * VOID TEST */ printf ("testVoid()"); if (t_test_thrift_test_if_test_void (test_client, &error)) { printf (" = void\n"); } else { if(error!=NULL){ printf ("%s\n", error->message); g_error_free (error); error = NULL; } fail_count++; } /** * STRING TEST */ printf ("testString(\"Test\")"); if (t_test_thrift_test_if_test_string (test_client, &string, "Test", &error)) { printf (" = \"%s\"\n", string); if (strncmp (string, "Test", 5) != 0) fail_count++; g_free (string); string = NULL; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * Multiplexed Test - do this right in the middle of the normal Test Client run */ if (second_service) { printf ("testSecondServiceMultiplexSecondTestString(\"2nd\")"); if (t_test_second_service_if_secondtest_string (second_service, &string, "2nd", &error)) { printf (" = \"%s\"\n", string); if (strcmp (string, "testString(\"2nd\")") != 0) { ++fail_count; } g_free (string); string = NULL; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; ++fail_count; } } /** * BOOL TEST */ printf ("testByte(true)"); if (t_test_thrift_test_if_test_bool (test_client, &boolean, 1, &error)) { printf (" = %s\n", boolean ? "true" : "false"); if (boolean != 1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf ("testByte(false)"); if (t_test_thrift_test_if_test_bool (test_client, &boolean, 0, &error)) { printf (" = %s\n", boolean ? "true" : "false"); if (boolean != 0) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * BYTE TEST */ printf ("testByte(1)"); if (t_test_thrift_test_if_test_byte (test_client, &byte, 1, &error)) { printf (" = %d\n", byte); if (byte != 1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf ("testByte(-1)"); if (t_test_thrift_test_if_test_byte (test_client, &byte, -1, &error)) { printf (" = %d\n", byte); if (byte != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * I32 TEST */ printf ("testI32(-1)"); if (t_test_thrift_test_if_test_i32 (test_client, &int32, -1, &error)) { printf (" = %d\n", int32); if (int32 != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * I64 TEST */ printf ("testI64(-34359738368)"); if (t_test_thrift_test_if_test_i64 (test_client, &int64, (gint64)-34359738368, &error)) { printf (" = %" PRId64 "\n", int64); if (int64 != (gint64)-34359738368) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * DOUBLE TEST */ printf("testDouble(-5.2098523)"); if (t_test_thrift_test_if_test_double (test_client, &dub, -5.2098523, &error)) { printf (" = %f\n", dub); if ((dub - (-5.2098523)) > 0.001) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * BINARY TEST */ printf ("testBinary(empty)"); GByteArray *emptyArray = g_byte_array_new(); GByteArray *result = NULL; if (t_test_thrift_test_if_test_binary (test_client, &result, emptyArray, &error)) { GBytes *response = g_byte_array_free_to_bytes(result); // frees result result = NULL; gsize siz = g_bytes_get_size(response); if (siz == 0) { printf(" = empty\n"); } else { printf(" = not empty (%ld bytes)\n", (long)siz); ++fail_count; } g_bytes_unref(response); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_byte_array_unref(emptyArray); emptyArray = NULL; // TODO: add testBinary() with data printf ("testBinary([-128..127]) = {"); const signed char bin_data[256] = {-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, -66, -65, -64, -63, -62, -61, -60, -59, -58, -57, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127}; GByteArray *fullArray = g_byte_array_new(); g_byte_array_append(fullArray, (guint8 *)(&bin_data[0]), 256); if (t_test_thrift_test_if_test_binary (test_client, &result, fullArray, &error)) { GBytes *response = g_byte_array_free_to_bytes(result); // frees result result = NULL; gsize siz = g_bytes_get_size(response); gconstpointer ptr = g_bytes_get_data(response, &siz); if (siz == 256) { gboolean first = 1; gboolean failed = 0; int i; for (i = 0; i < 256; ++i) { if (!first) printf(","); else first = 0; int val = ((signed char *)ptr)[i]; printf("%d", val); if (!failed && val != i - 128) { failed = 1; } } printf("} "); if (failed) { printf("FAIL (bad content) size %ld OK\n", (long)siz); ++fail_count; } else { printf("OK size %ld OK\n", (long)siz); } } else { printf(" = bad size %ld\n", (long)siz); ++fail_count; } g_bytes_unref(response); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_byte_array_unref(fullArray); fullArray = NULL; /** * STRUCT TEST */ printf ("testStruct({\"Zero\", 1, -3, -5})"); xtruct_out = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", "Zero", "byte_thing", 1, "i32_thing", -3, "i64_thing", -5LL, NULL); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (t_test_thrift_test_if_test_struct (test_client, &xtruct_in, xtruct_out, &error)) { g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf (" = {\"%s\", %d, %d, %" PRId64 "}\n", string, byte_thing, i32_thing, i64_thing); if ((string == NULL || strncmp (string, "Zero", 5) != 0) || byte_thing != 1 || i32_thing != -3 || i64_thing != (gint64)-5) fail_count++; if (string) { g_free (string); string = NULL; } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } // g_clear_object(&xtruct_out); used below g_clear_object(&xtruct_in); /** * NESTED STRUCT TEST */ printf ("testNest({1, {\"Zero\", 1, -3, -5}), 5}"); xtruct2_out = g_object_new (T_TEST_TYPE_XTRUCT2, "byte_thing", 1, "struct_thing", xtruct_out, "i32_thing", 5, NULL); xtruct2_in = g_object_new (T_TEST_TYPE_XTRUCT2, NULL); if (t_test_thrift_test_if_test_nest (test_client, &xtruct2_in, xtruct2_out, &error)) { g_object_get (xtruct2_in, "byte_thing", &byte_thing, "struct_thing", &xtruct_in, "i32_thing", &i32_thing, NULL); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &inner_byte_thing, "i32_thing", &inner_i32_thing, "i64_thing", &inner_i64_thing, NULL); printf (" = {%d, {\"%s\", %d, %d, %" PRId64 "}, %d}\n", byte_thing, string, inner_byte_thing, inner_i32_thing, inner_i64_thing, i32_thing); if (byte_thing != 1 || (string == NULL || strncmp (string, "Zero", 5) != 0) || inner_byte_thing != 1 || inner_i32_thing != -3 || inner_i64_thing != (gint64)-5 || i32_thing != 5) fail_count++; if (string) { g_free(string); string = NULL; } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_clear_object(&xtruct_in); g_clear_object(&xtruct2_in); g_clear_object(&xtruct2_out); g_clear_object(&xtruct_out); /** * MAP TEST */ map_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); for (i = 0; i < 5; ++i) { i32_key_ptr = g_malloc (sizeof *i32_key_ptr); i32_value_ptr = g_malloc (sizeof *i32_value_ptr); *i32_key_ptr = i; *i32_value_ptr = i - 10; g_hash_table_insert (map_out, i32_key_ptr, i32_value_ptr); } printf ("testMap({"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); } printf ("})"); map_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_free); if (t_test_thrift_test_if_test_map (test_client, &map_in, map_out, &error)) { printf (" = {"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("%d => %d", *(gint32 *)key, *(gint32 *)value); } printf ("}\n"); if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) fail_count++; else { g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gpointer in_value = g_hash_table_lookup (map_in, key); if (in_value == NULL || *(gint32 *)in_value != *(gint32 *)value) { fail_count++; break; } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_hash_table_unref (map_out); /** * STRING MAP TEST */ map_out = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); g_hash_table_insert (map_out, "a", "2"); g_hash_table_insert (map_out, "b", "blah"); g_hash_table_insert (map_out, "some", "thing"); printf ("testStringMap({"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); } printf (")}"); map_in = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (t_test_thrift_test_if_test_string_map (test_client, &map_in, map_out, &error)) { printf (" = {"); first = TRUE; g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { if (first) first = FALSE; else printf (", "); printf ("\"%s\" => \"%s\"", (gchar *)key, (gchar *)value); } printf ("}\n"); if (g_hash_table_size (map_in) != g_hash_table_size (map_out)) fail_count++; else { g_hash_table_iter_init (&hash_table_iter, map_out); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { gpointer in_value = g_hash_table_lookup (map_in, key); if (in_value == NULL || strcmp ((gchar *)in_value, (gchar *)value) != 0) { fail_count++; break; } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_hash_table_unref (map_out); /** * SET TEST */ set_out = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); for (i = -2; i < 3; ++i) { i32_key_ptr = g_malloc (sizeof *i32_key_ptr); *i32_key_ptr = i; g_hash_table_insert (set_out, i32_key_ptr, NULL); } printf ("testSet({"); first = TRUE; keys_out = g_hash_table_get_keys (set_out); keys_elem = keys_out; while (keys_elem != NULL) { if (first) first = FALSE; else printf (", "); printf ("%d", *(gint32 *)keys_elem->data); keys_elem = keys_elem->next; } printf ("})"); set_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, NULL); if (t_test_thrift_test_if_test_set (test_client, &set_in, set_out, &error)) { printf(" = {"); first = TRUE; keys_in = g_hash_table_get_keys (set_in); keys_elem = keys_in; while (keys_elem != NULL) { if (first) first = FALSE; else printf (", "); printf ("%d", *(gint32 *)keys_elem->data); keys_elem = keys_elem->next; } printf ("}\n"); if (g_list_length (keys_in) != g_list_length (keys_out)) fail_count++; else { keys_elem = keys_out; while (keys_elem != NULL) { if (g_list_find_custom (keys_in, keys_elem->data, gint32_compare) == NULL) { fail_count++; break; } keys_elem = keys_elem->next; } } g_list_free (keys_in); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (set_in); g_list_free (keys_out); g_hash_table_unref (set_out); /** * LIST TEST */ list_out = g_array_new (FALSE, TRUE, sizeof (gint32)); for (i = -2; i < 3; ++i) { g_array_append_val (list_out, i); } printf ("testList({"); first = TRUE; for (i = 0; i < (gint32)list_out->len; ++i) { if (first) first = FALSE; else printf (", "); printf ("%d", g_array_index (list_out, gint32, i)); } printf ("})"); list_in = g_array_new (FALSE, TRUE, sizeof (gint32)); if (t_test_thrift_test_if_test_list (test_client, &list_in, list_out, &error)) { printf (" = {"); first = TRUE; for (i = 0; i < (gint32)list_in->len; ++i) { if (first) first = FALSE; else printf (", "); printf ("%d", g_array_index (list_in, gint32, i)); } printf ("}\n"); if (list_in->len != list_out->len || memcmp (list_in->data, list_out->data, list_in->len * sizeof (gint32)) != 0) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_array_unref (list_in); g_array_unref (list_out); /** * ENUM TEST */ printf("testEnum(ONE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_ONE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_ONE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(TWO)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_TWO, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_TWO) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(THREE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_THREE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_THREE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(FIVE)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_FIVE, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_FIVE) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } printf("testEnum(EIGHT)"); if (t_test_thrift_test_if_test_enum (test_client, &numberz, T_TEST_NUMBERZ_EIGHT, &error)) { printf(" = %d\n", numberz); if (numberz != T_TEST_NUMBERZ_EIGHT) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * TYPEDEF TEST */ printf ("testTypedef(309858235082523)"); if (t_test_thrift_test_if_test_typedef (test_client, &user_id, 309858235082523LL, &error)) { printf(" = %" PRId64 "\n", user_id); if (user_id != 309858235082523LL) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * NESTED MAP TEST */ printf ("testMapMap(1)"); map_in = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, (GDestroyNotify)g_hash_table_unref); if (t_test_thrift_test_if_test_map_map (test_client, &map_in, 1, &error)) { g_hash_table_iter_init (&hash_table_iter, map_in); printf (" = {"); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { printf ("%d => {", *(gint32 *)key); g_hash_table_iter_init (&inner_hash_table_iter, (GHashTable *)value); while (g_hash_table_iter_next (&inner_hash_table_iter, &key, &value)) { printf ("%d => %d, ", *(gint32 *)key, *(gint32 *)value); } printf ("}, "); } printf ("}\n"); if (g_hash_table_size (map_in) != 2) fail_count++; else { gint32 inner_keys[] = {1, 2, 3, 4}; gint32 i32_key; i32_key = -4; inner_map_in = g_hash_table_lookup (map_in, &i32_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 4) fail_count++; else { keys_in = g_hash_table_get_keys (inner_map_in); keys_in = g_list_sort (keys_in, gint32_compare); for (i = 0; i < 4; i++) { keys_elem = g_list_nth (keys_in, 3 - i); if (*(gint32 *)keys_elem->data != (-1 * inner_keys[i]) || *(gint32 *)g_hash_table_lookup (inner_map_in, keys_elem->data) != (-1 * inner_keys[i])) { fail_count++; break; } } g_list_free (keys_in); } i32_key = 4; inner_map_in = g_hash_table_lookup (map_in, &i32_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 4) fail_count++; else { keys_in = g_hash_table_get_keys (inner_map_in); keys_in = g_list_sort (keys_in, gint32_compare); for (i = 0; i < 4; i++) { keys_elem = g_list_nth (keys_in, i); if (*(gint32 *)keys_elem->data != inner_keys[i] || *(gint32 *)g_hash_table_lookup (inner_map_in, keys_elem->data) != inner_keys[i]) { fail_count++; break; } } g_list_free (keys_in); } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); /** * INSANITY TEST */ insanity_out = g_object_new (T_TEST_TYPE_INSANITY, NULL); g_object_get (insanity_out, "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_out = g_object_new (T_TEST_TYPE_XTRUCT, "string_thing", "Hello2", "byte_thing", 2, "i32_thing", 2, "i64_thing", 2LL, NULL); xtruct_out2 = 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, xtruct_out2); g_ptr_array_add (xtructs, xtruct_out); g_ptr_array_unref (xtructs); map_in = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, (GDestroyNotify)g_hash_table_unref); printf("testInsanity()"); if (t_test_thrift_test_if_test_insanity (test_client, &map_in, insanity_out, &error)) { printf (" = {"); g_hash_table_iter_init (&hash_table_iter, map_in); while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { printf ("%" PRId64 " => {", *(TTestUserId *)key); g_hash_table_iter_init (&inner_hash_table_iter, (GHashTable *)value); while (g_hash_table_iter_next (&inner_hash_table_iter, &key, &value)) { printf ("%d => {", (TTestNumberz)key); g_object_get ((TTestInsanity *)value, "userMap", &user_map, "xtructs", &xtructs, NULL); printf ("{"); g_hash_table_iter_init (&user_map_iter, user_map); while (g_hash_table_iter_next (&user_map_iter, &key, &value)) { printf ("%d => %" PRId64 ", ", (TTestNumberz)key, *(TTestUserId *)value); } printf ("}, "); g_hash_table_unref (user_map); printf("{"); for (i = 0; i < (gint32)xtructs->len; ++i) { xtruct_in = g_ptr_array_index (xtructs, i); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); printf ("{\"%s\", %d, %d, %" PRId64 "}, ", string, byte_thing, i32_thing, i64_thing); if (string != NULL) g_free (string); } printf ("}"); g_ptr_array_unref (xtructs); printf ("}, "); } printf("}, "); } printf("}\n"); if (g_hash_table_size (map_in) != 2) fail_count++; else { TTestNumberz numberz_key_values[] = { T_TEST_NUMBERZ_TWO, T_TEST_NUMBERZ_THREE }; gint user_map_values[] = { 5, 8 }; TTestUserId user_id_key; user_id_key = 1; inner_map_in = g_hash_table_lookup (map_in, &user_id_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 2) fail_count++; else { TTestNumberz numberz_key; for (i = 0; i < 2; ++i) { numberz_key = numberz_key_values[i]; insanity_in = g_hash_table_lookup (inner_map_in, (gconstpointer)numberz_key); if (insanity_in == NULL) fail_count++; else { g_object_get (insanity_in, "userMap", &user_map, "xtructs", &xtructs, NULL); if (user_map == NULL) fail_count++; else { if (g_hash_table_size (user_map) != 2) fail_count++; else { for (j = 0; j < 2; ++j) { numberz_key = (TTestNumberz)user_map_values[j]; value = g_hash_table_lookup (user_map, (gconstpointer)numberz_key); if (value == NULL || *(TTestUserId *)value != (TTestUserId)user_map_values[j]) fail_count++; } } g_hash_table_unref (user_map); } if (xtructs == NULL) fail_count++; else { if (xtructs->len != 2) fail_count++; else { xtruct_in = g_ptr_array_index (xtructs, 0); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); if ((string == NULL || strncmp (string, "Goodbye4", 9) != 0) || byte_thing != 4 || i32_thing != 4 || i64_thing != 4) fail_count++; if (string != NULL) g_free (string); xtruct_in = g_ptr_array_index (xtructs, 1); g_object_get (xtruct_in, "string_thing", &string, "byte_thing", &byte_thing, "i32_thing", &i32_thing, "i64_thing", &i64_thing, NULL); if ((string == NULL || strncmp (string, "Hello2", 7) != 0) || byte_thing != 2 || i32_thing != 2 || i64_thing != 2) fail_count++; if (string != NULL) g_free (string); } g_ptr_array_unref (xtructs); } } } } user_id_key = 2; inner_map_in = g_hash_table_lookup (map_in, &user_id_key); if (inner_map_in == NULL || g_hash_table_size (inner_map_in) != 1) fail_count++; else { insanity_in = g_hash_table_lookup (inner_map_in, (gconstpointer)T_TEST_NUMBERZ_SIX); if (insanity_in == NULL) fail_count++; else { g_object_get (insanity_in, "userMap", &user_map, "xtructs", &xtructs, NULL); if (user_map == NULL) fail_count++; else { if (g_hash_table_size (user_map) != 0) fail_count++; g_hash_table_unref (user_map); } if (xtructs == NULL) fail_count++; else { if (xtructs->len != 0) fail_count++; g_ptr_array_unref (xtructs); } } } } } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } g_hash_table_unref (map_in); g_clear_object (&insanity_out); /* test exception */ printf ("testClient.testException(\"Xception\") =>"); if (!t_test_thrift_test_if_test_exception (test_client, "Xception", &xception, &error) && xception != NULL) { g_object_get (xception, "errorCode", &int32, "message", &string, NULL); printf (" {%u, \"%s\"}\n", int32, string); g_free (string); g_clear_object (&xception); g_error_free (error); error = NULL; } else { printf (" void\nFAILURE\n"); fail_count++; if (xception != NULL) { g_object_unref (xception); xception = NULL; } if (error != NULL) { g_error_free (error); error = NULL; } } printf ("testClient.testException(\"TException\") =>"); if (!t_test_thrift_test_if_test_exception (test_client, "TException", &xception, &error) && xception == NULL && error != NULL) { printf (" Caught TException\n"); g_error_free (error); error = NULL; } else { printf (" void\nFAILURE\n"); fail_count++; g_clear_object (&xception); if (error != NULL) { g_error_free (error); error = NULL; } } printf ("testClient.testException(\"success\") =>"); if (t_test_thrift_test_if_test_exception (test_client, "success", &xception, &error)) printf (" void\n"); else { printf (" void\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_error_free (error); error = NULL; } g_assert (error == NULL); /* test multi exception */ printf ("testClient.testMultiException(\"Xception\", \"test 1\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (!t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "Xception", "test 1", &xception, &xception2, &error) && xception != NULL && xception2 == NULL) { g_object_get (xception, "errorCode", &int32, "message", &string, NULL); printf (" {%u, \"%s\"}\n", int32, string); g_free (string); g_object_unref (xception); xception = NULL; g_error_free (error); error = NULL; } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_object_unref (xtruct_in); printf ("testClient.testMultiException(\"Xception2\", \"test 2\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (!t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "Xception2", "test 2", &xception, &xception2, &error) && xception == NULL && xception2 != NULL) { g_object_get (xception2, "errorCode", &int32, "struct_thing", &inner_xtruct_in, NULL); g_object_get (inner_xtruct_in, "string_thing", &string, NULL); printf (" {%u, {\"%s\"}}\n", int32, string); g_free (string); g_clear_object (&inner_xtruct_in); g_clear_object (&xception2); g_error_free (error); error = NULL; } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_clear_object (&xtruct_in); printf ("testClient.testMultiException(\"success\", \"test 3\") =>"); xtruct_in = g_object_new (T_TEST_TYPE_XTRUCT, NULL); if (t_test_thrift_test_if_test_multi_exception (test_client, &xtruct_in, "success", "test 3", &xception, &xception2, &error) && xception == NULL && xception2 == NULL) { g_object_get (xtruct_in, "string_thing", &string, NULL); printf (" {{\"%s\"}}\n", string); g_free (string); } else { printf (" result\nFAILURE\n"); fail_count++; g_clear_object (&xception); g_clear_object (&xception2); if (error != NULL) { g_error_free (error); error = NULL; } } g_clear_object (&xtruct_in); /* test oneway void */ printf ("testClient.testOneway(1) =>"); gettimeofday (&oneway_start, NULL); oneway_result = t_test_thrift_test_if_test_oneway (test_client, 1, &error); gettimeofday (&oneway_end, NULL); timersub (&oneway_end, &oneway_start, &oneway_elapsed); oneway_elapsed_usec = oneway_elapsed.tv_sec * 1000 * 1000 + oneway_elapsed.tv_usec; if (oneway_result) { if (oneway_elapsed_usec > 200 * 1000) { printf (" FAILURE - took %.2f ms\n", (double)oneway_elapsed_usec / 1000.0); fail_count++; } else printf (" success - took %.2f ms\n", (double)oneway_elapsed_usec / 1000.0); } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } /** * redo a simple test after the oneway to make sure we aren't "off by * one" -- if the server treated oneway void like normal void, this next * test will fail since it will get the void confirmation rather than * the correct result. In this circumstance, the client will receive the * error: * * application error: Wrong method name */ /** * I32 TEST */ printf ("re-test testI32(-1)"); if (t_test_thrift_test_if_test_i32 (test_client, &int32, -1, &error)) { printf (" = %d\n", int32); if (int32 != -1) fail_count++; } else { printf ("%s\n", error->message); g_error_free (error); error = NULL; fail_count++; } gettimeofday (&time_stop, NULL); timersub (&time_stop, &time_start, &time_elapsed); time_elapsed_usec = time_elapsed.tv_sec * 1000 * 1000 + time_elapsed.tv_usec; printf("Total time: %" PRIu64 " us\n", time_elapsed_usec); time_total_usec += time_elapsed_usec; if (time_elapsed_usec < time_min_usec) time_min_usec = time_elapsed_usec; if (time_elapsed_usec > time_max_usec) time_max_usec = time_elapsed_usec; thrift_transport_close (transport, &error); } else { printf ("Connect failed: %s\n", error->message); g_error_free (error); error = NULL; goto out; } } /* All done---output statistics */ puts ("\nAll tests done."); printf("Number of failures: %d\n", fail_count); time_avg_usec = time_total_usec / num_tests; printf ("Min time: %" PRIu64 " us\n", time_min_usec); printf ("Max time: %" PRIu64 " us\n", time_max_usec); printf ("Avg time: %" PRIu64 " us\n", time_avg_usec); out: g_clear_object(&second_service); g_clear_object(&protocol2); g_clear_object(&test_client); g_clear_object(&protocol); g_clear_object(&multiplexed_protocol); g_clear_object(&transport); g_clear_object(&socket); if (ssl) { thrift_ssl_socket_finalize_openssl(); } return fail_count; }