THRIFT-2685 c_glib: Include in integration test suite

Patch: Simon South
diff --git a/.gitignore b/.gitignore
index a3344b7..e0b36f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -207,6 +207,7 @@
 /stamp-h1
 /test/status.html
 /test/c_glib/test_client
+/test/c_glib/test_server
 /test/cpp/StressTest
 /test/cpp/StressTestNonBlocking
 /test/cpp/TestClient
diff --git a/test/c_glib/Makefile.am b/test/c_glib/Makefile.am
index 1dc8c16..de23cb9 100755
--- a/test/c_glib/Makefile.am
+++ b/test/c_glib/Makefile.am
@@ -29,7 +29,8 @@
 libtestcglib_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la
 
 check_PROGRAMS = \
-	test_client
+	test_client \
+	test_server
 
 test_client_SOURCES = \
 	src/test_client.c
@@ -38,6 +39,15 @@
 	libtestcglib.la \
 	$(top_builddir)/lib/c_glib/libthrift_c_glib.la
 
+test_server_SOURCES = \
+	src/thrift_test_handler.c \
+	src/thrift_test_handler.h \
+	src/test_server.c
+
+test_server_LDADD = \
+	libtestcglib.la \
+	$(top_builddir)/lib/c_glib/libthrift_c_glib.la
+
 #
 # Common thrift code generation rules
 #
@@ -55,4 +65,7 @@
 	$(RM) -r gen-c_glib
 
 EXTRA_DIST = \
-	src/test_client.c
+	src/test_client.c \
+	src/thrift_test_handler.c \
+	src/thrift_test_handler.h \
+	src/test_server.c
diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c
index 2a66795..59f4157 100644
--- a/test/c_glib/src/test_client.c
+++ b/test/c_glib/src/test_client.c
@@ -38,7 +38,8 @@
    connection prematurely) by outputting an error message before
    exiting. */
 static void
-sigpipe_handler (int signal_number) {
+sigpipe_handler (int signal_number)
+{
   THRIFT_UNUSED_VAR (signal_number);
 
   /* Flush standard output to make sure the test results so far are
@@ -56,7 +57,8 @@
 /* Compare two gint32 values. Used for sorting and finding integer
    values within a GList. */
 static gint
-gint32_compare (gconstpointer a, gconstpointer b) {
+gint32_compare (gconstpointer a, gconstpointer b)
+{
   gint32 int32_a = *(gint32 *)a;
   gint32 int32_b = *(gint32 *)b;
   int result = 0;
@@ -70,7 +72,8 @@
 }
 
 int
-main (int argc, char **argv) {
+main (int argc, char **argv)
+{
   static gchar *host = NULL;
   static gint   port = 9090;
   static gchar *transport_option = NULL;
@@ -115,15 +118,19 @@
   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) == FALSE) {
+  if (!g_option_context_parse (option_context,
+                               &argc,
+                               &argv,
+                               &error)) {
     fprintf (stderr, "%s\n", error->message);
     return 255;
   }
@@ -151,7 +158,7 @@
     }
   }
 
-  if (options_valid == FALSE)
+  if (!options_valid)
     return 254;
 
   printf ("Connecting (%s/%s) to: %s:%d\n",
@@ -186,7 +193,7 @@
 
   /* Execute the actual tests */
   for (test_num = 0; test_num < num_tests; ++test_num) {
-    if (thrift_transport_open (transport, &error) == TRUE) {
+    if (thrift_transport_open (transport, &error)) {
       gchar  *string = NULL;
       gint8   byte   = 0;
       gint32  int32  = 0;
@@ -258,7 +265,7 @@
        * VOID TEST
        */
       printf ("testVoid()");
-      if (t_test_thrift_test_if_test_void (test_client, &error) == TRUE) {
+      if (t_test_thrift_test_if_test_void (test_client, &error)) {
         printf (" = void\n");
       }
       else {
@@ -276,7 +283,7 @@
       if (t_test_thrift_test_if_test_string (test_client,
                                              &string,
                                              "Test",
-                                             &error) == TRUE) {
+                                             &error)) {
         printf (" = \"%s\"\n", string);
         if (strncmp (string, "Test", 5) != 0)
           fail_count++;
@@ -299,7 +306,7 @@
       if (t_test_thrift_test_if_test_byte (test_client,
                                            &byte,
                                            1,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf (" = %d\n", byte);
         if (byte != 1)
           fail_count++;
@@ -319,7 +326,7 @@
       if (t_test_thrift_test_if_test_i32 (test_client,
                                           &int32,
                                           -1,
-                                          &error) == TRUE) {
+                                          &error)) {
         printf (" = %d\n", int32);
         if (int32 != -1)
           fail_count++;
@@ -339,7 +346,7 @@
       if (t_test_thrift_test_if_test_i64 (test_client,
                                           &int64,
                                           (gint64)-34359738368,
-                                          &error) == TRUE) {
+                                          &error)) {
         printf (" = %" PRId64 "\n", int64);
         if (int64 != (gint64)-34359738368)
           fail_count++;
@@ -359,7 +366,7 @@
       if (t_test_thrift_test_if_test_double (test_client,
                                              &dub,
                                              -5.2098523,
-                                             &error) == TRUE) {
+                                             &error)) {
         printf (" = %f\n", dub);
         if ((dub - (-5.2098523)) > 0.001)
           fail_count++;
@@ -387,7 +394,7 @@
       if (t_test_thrift_test_if_test_struct (test_client,
                                              &xtruct_in,
                                              xtruct_out,
-                                             &error) == TRUE) {
+                                             &error)) {
         g_object_get (xtruct_in,
                       "string_thing", &string,
                       "byte_thing",   &byte_thing,
@@ -429,7 +436,7 @@
       if (t_test_thrift_test_if_test_nest (test_client,
                                            &xtruct2_in,
                                            xtruct2_out,
-                                           &error) == TRUE) {
+                                           &error)) {
         g_object_get (xtruct2_in,
                       "byte_thing",   &byte_thing,
                       "struct_thing", &xtruct_in,
@@ -491,8 +498,8 @@
       g_hash_table_iter_init (&hash_table_iter, map_out);
       while (g_hash_table_iter_next (&hash_table_iter,
                                      &key,
-                                     &value) == TRUE) {
-        if (first == TRUE)
+                                     &value)) {
+        if (first)
           first = FALSE;
         else
           printf (", ");
@@ -509,14 +516,14 @@
       if (t_test_thrift_test_if_test_map (test_client,
                                           &map_in,
                                           map_out,
-                                          &error) == TRUE) {
+                                          &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) == TRUE) {
-          if (first == TRUE)
+                                       &value)) {
+          if (first)
             first = FALSE;
           else
             printf (", ");
@@ -531,7 +538,7 @@
           g_hash_table_iter_init (&hash_table_iter, map_out);
           while (g_hash_table_iter_next (&hash_table_iter,
                                          &key,
-                                         &value) == TRUE) {
+                                         &value)) {
             gpointer in_value = g_hash_table_lookup (map_in, key);
             if (in_value == NULL ||
                 *(gint32 *)in_value != *(gint32 *)value) {
@@ -567,8 +574,8 @@
       g_hash_table_iter_init (&hash_table_iter, map_out);
       while (g_hash_table_iter_next (&hash_table_iter,
                                      &key,
-                                     &value) == TRUE) {
-        if (first == TRUE)
+                                     &value)) {
+        if (first)
           first = FALSE;
         else
           printf (", ");
@@ -585,14 +592,14 @@
       if (t_test_thrift_test_if_test_string_map (test_client,
                                                  &map_in,
                                                  map_out,
-                                                 &error) == TRUE) {
+                                                 &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) == TRUE) {
-          if (first == TRUE)
+                                       &value)) {
+          if (first)
             first = FALSE;
           else
             printf (", ");
@@ -607,7 +614,7 @@
           g_hash_table_iter_init (&hash_table_iter, map_out);
           while (g_hash_table_iter_next (&hash_table_iter,
                                          &key,
-                                         &value) == TRUE) {
+                                         &value)) {
             gpointer in_value = g_hash_table_lookup (map_in, key);
             if (in_value == NULL ||
                 strcmp ((gchar *)in_value, (gchar *)value) != 0) {
@@ -643,7 +650,7 @@
       keys_out = g_hash_table_get_keys (set_out);
       keys_elem = keys_out;
       while (keys_elem != NULL) {
-        if (first == TRUE)
+        if (first)
           first = FALSE;
         else
           printf (", ");
@@ -659,13 +666,13 @@
       if (t_test_thrift_test_if_test_set (test_client,
                                           &set_in,
                                           set_out,
-                                          &error) == TRUE) {
+                                          &error)) {
         printf(" = {");
         first = TRUE;
         keys_in = g_hash_table_get_keys (set_in);
         keys_elem = keys_in;
         while (keys_elem != NULL) {
-          if (first == TRUE)
+          if (first)
             first = FALSE;
           else
             printf (", ");
@@ -716,7 +723,7 @@
       printf ("testList({");
       first = TRUE;
       for (i = 0; i < (gint32)list_out->len; ++i) {
-        if (first == TRUE)
+        if (first)
           first = FALSE;
         else
           printf (", ");
@@ -730,11 +737,11 @@
       if (t_test_thrift_test_if_test_list (test_client,
                                            &list_in,
                                            list_out,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf (" = {");
         first = TRUE;
         for (i = 0; i < (gint32)list_in->len; ++i) {
-          if (first == TRUE)
+          if (first)
             first = FALSE;
           else
             printf (", ");
@@ -767,7 +774,7 @@
       if (t_test_thrift_test_if_test_enum (test_client,
                                            &numberz,
                                            T_TEST_NUMBERZ_ONE,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf(" = %d\n", numberz);
         if (numberz != T_TEST_NUMBERZ_ONE)
           fail_count++;
@@ -784,7 +791,7 @@
       if (t_test_thrift_test_if_test_enum (test_client,
                                            &numberz,
                                            T_TEST_NUMBERZ_TWO,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf(" = %d\n", numberz);
         if (numberz != T_TEST_NUMBERZ_TWO)
           fail_count++;
@@ -801,7 +808,7 @@
       if (t_test_thrift_test_if_test_enum (test_client,
                                            &numberz,
                                            T_TEST_NUMBERZ_THREE,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf(" = %d\n", numberz);
         if (numberz != T_TEST_NUMBERZ_THREE)
           fail_count++;
@@ -818,7 +825,7 @@
       if (t_test_thrift_test_if_test_enum (test_client,
                                            &numberz,
                                            T_TEST_NUMBERZ_FIVE,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf(" = %d\n", numberz);
         if (numberz != T_TEST_NUMBERZ_FIVE)
           fail_count++;
@@ -835,7 +842,7 @@
       if (t_test_thrift_test_if_test_enum (test_client,
                                            &numberz,
                                            T_TEST_NUMBERZ_EIGHT,
-                                           &error) == TRUE) {
+                                           &error)) {
         printf(" = %d\n", numberz);
         if (numberz != T_TEST_NUMBERZ_EIGHT)
           fail_count++;
@@ -855,7 +862,7 @@
       if (t_test_thrift_test_if_test_typedef (test_client,
                                               &user_id,
                                               309858235082523LL,
-                                              &error) == TRUE) {
+                                              &error)) {
         printf(" = %" PRId64 "\n", user_id);
         if (user_id != 309858235082523LL)
           fail_count++;
@@ -879,20 +886,20 @@
       if (t_test_thrift_test_if_test_map_map (test_client,
                                               &map_in,
                                               1,
-                                              &error) == TRUE) {
+                                              &error)) {
         g_hash_table_iter_init (&hash_table_iter, map_in);
 
         printf (" = {");
         while (g_hash_table_iter_next (&hash_table_iter,
                                        &key,
-                                       &value) == TRUE) {
+                                       &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) == TRUE) {
+                                         &value)) {
             printf ("%d => %d, ", *(gint32 *)key, *(gint32 *)value);
           }
 
@@ -984,7 +991,7 @@
                                  "string_thing", "Truck",
                                  "byte_thing",   8,
                                  "i32_thing",    8,
-                                 "i64_thing",    8,
+                                 "i64_thing",    8LL,
                                  NULL);
       g_ptr_array_add (xtructs, xtruct_out);
       g_ptr_array_unref (xtructs);
@@ -998,19 +1005,19 @@
       if (t_test_thrift_test_if_test_insanity (test_client,
                                                &map_in,
                                                insanity_out,
-                                               &error) == TRUE) {
+                                               &error)) {
         printf (" = {");
         g_hash_table_iter_init (&hash_table_iter, map_in);
         while (g_hash_table_iter_next (&hash_table_iter,
                                        &key,
-                                       &value) == TRUE) {
+                                       &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) == TRUE) {
+                                         &value)) {
             printf ("%d => {", (TTestNumberz)key);
 
             g_object_get ((TTestInsanity *)value,
@@ -1022,7 +1029,7 @@
             g_hash_table_iter_init (&user_map_iter, user_map);
             while (g_hash_table_iter_next (&user_map_iter,
                                            &key,
-                                           &value) == TRUE) {
+                                           &value)) {
               printf ("%d => %" PRId64 ", ",
                       (TTestNumberz)key,
                       *(TTestUserId *)value);
@@ -1204,10 +1211,10 @@
 
       /* test exception */
       printf ("testClient.testException(\"Xception\") =>");
-      if (t_test_thrift_test_if_test_exception (test_client,
-                                                "Xception",
-                                                &xception,
-                                                &error) == FALSE &&
+      if (!t_test_thrift_test_if_test_exception (test_client,
+                                                 "Xception",
+                                                 &xception,
+                                                 &error) &&
           xception != NULL) {
         g_object_get (xception,
                       "errorCode", &int32,
@@ -1238,10 +1245,10 @@
       }
 
       printf ("testClient.testException(\"TException\") =>");
-      if (t_test_thrift_test_if_test_exception (test_client,
-                                                "TException",
-                                                &xception,
-                                                &error) == FALSE &&
+      if (!t_test_thrift_test_if_test_exception (test_client,
+                                                 "TException",
+                                                 &xception,
+                                                 &error) &&
           xception == NULL &&
           error != NULL) {
         printf ("  Caught TException\n");
@@ -1268,7 +1275,7 @@
       if (t_test_thrift_test_if_test_exception (test_client,
                                                 "success",
                                                 &xception,
-                                                &error) == TRUE)
+                                                &error))
         printf ("  void\n");
       else {
         printf ("  void\nFAILURE\n");
@@ -1288,13 +1295,13 @@
       /* 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) == FALSE &&
+      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,
@@ -1333,13 +1340,13 @@
 
       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) == FALSE &&
+      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,
@@ -1390,7 +1397,7 @@
                                                       "test 3",
                                                       &xception,
                                                       &xception2,
-                                                      &error) == TRUE &&
+                                                      &error) &&
           xception == NULL &&
           xception2 == NULL) {
         g_object_get (xtruct_in,
@@ -1431,7 +1438,7 @@
       oneway_elapsed_usec =
         oneway_elapsed.tv_sec * 1000 * 1000 + oneway_elapsed.tv_usec;
 
-      if (oneway_result == TRUE) {
+      if (oneway_result) {
         if (oneway_elapsed_usec > 200 * 1000) {
           printf ("  FAILURE - took %.2f ms\n",
                   (double)oneway_elapsed_usec / 1000.0);
@@ -1465,7 +1472,7 @@
       if (t_test_thrift_test_if_test_i32 (test_client,
                                           &int32,
                                           -1,
-                                          &error) == TRUE) {
+                                          &error)) {
         printf (" = %d\n", int32);
         if (int32 != -1)
           fail_count++;
diff --git a/test/c_glib/src/test_server.c b/test/c_glib/src/test_server.c
new file mode 100644
index 0000000..13eec27
--- /dev/null
+++ b/test/c_glib/src/test_server.c
@@ -0,0 +1,207 @@
+/*
+ * 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 <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/protocol/thrift_binary_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.h>
+#include <thrift/c_glib/transport/thrift_buffered_transport_factory.h>
+#include <thrift/c_glib/transport/thrift_framed_transport.h>
+#include <thrift/c_glib/transport/thrift_framed_transport_factory.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_transport.h>
+#include <thrift/c_glib/transport/thrift_transport_factory.h>
+
+#include "../gen-c_glib/t_test_thrift_test.h"
+
+#include "thrift_test_handler.h"
+
+/* Our server object, declared globally so it is accessible within the SIGINT
+   signal handler */
+ThriftServer *server = NULL;
+
+/* A flag that indicates whether the server was interrupted with SIGINT
+   (i.e. Ctrl-C) so we can tell whether its termination was abnormal */
+gboolean sigint_received = FALSE;
+
+/* Handle SIGINT ("Ctrl-C") signals by gracefully stopping the server */
+static void
+sigint_handler (int signal_number)
+{
+  THRIFT_UNUSED_VAR (signal_number);
+
+  /* Take note we were called */
+  sigint_received = TRUE;
+
+  /* Shut down the server gracefully */
+  if (server != NULL)
+    thrift_server_stop (server);
+}
+
+int
+main (int argc, char **argv)
+{
+  static gint   port = 9090;
+  static gchar *server_type_option = NULL;
+  static gchar *transport_option = NULL;
+  static gchar *protocol_option = NULL;
+
+  static
+    GOptionEntry option_entries[] = {
+    { "port",            0, 0, G_OPTION_ARG_INT,      &port,
+      "Port number to connect (=9090)", NULL },
+    { "server-type",     0, 0, G_OPTION_ARG_STRING,   &server_type_option,
+      "Type of server: simple (=simple)", NULL },
+    { "transport",       0, 0, G_OPTION_ARG_STRING,   &transport_option,
+      "Transport: buffered, framed (=buffered)", NULL },
+    { "protocol",        0, 0, G_OPTION_ARG_STRING,   &protocol_option,
+      "Protocol: binary (=binary)", NULL },
+    { NULL }
+  };
+
+  gchar *server_name            = "simple";
+  gchar *transport_name         = "buffered";
+  GType  transport_factory_type = THRIFT_TYPE_BUFFERED_TRANSPORT_FACTORY;
+  gchar *protocol_name          = "binary";
+  GType  protocol_factory_type  = THRIFT_TYPE_BINARY_PROTOCOL_FACTORY;
+
+  TTestThriftTestHandler *handler;
+  ThriftProcessor        *processor;
+  ThriftServerTransport  *server_transport;
+  ThriftTransportFactory *transport_factory;
+  ThriftProtocolFactory  *protocol_factory;
+
+  struct sigaction sigint_action;
+
+  GOptionContext *option_context;
+  gboolean        options_valid = TRUE;
+
+  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) == FALSE) {
+    fprintf (stderr, "%s\n", error->message);
+    return 255;
+  }
+  g_option_context_free (option_context);
+
+  /* Validate the parsed options */
+  if (server_type_option != NULL &&
+      strncmp (server_type_option, "simple", 7) != 0) {
+    fprintf (stderr, "Unknown server type %s\n", protocol_option);
+    options_valid = FALSE;
+  }
+
+  if (protocol_option != NULL &&
+      strncmp (protocol_option, "binary", 7) != 0) {
+    fprintf (stderr, "Unknown protocol type %s\n", protocol_option);
+    options_valid = FALSE;
+  }
+
+  if (transport_option != NULL) {
+    if (strncmp (transport_option, "framed", 7) == 0) {
+      transport_factory_type = THRIFT_TYPE_FRAMED_TRANSPORT_FACTORY;
+      transport_name = "framed";
+    }
+    else if (strncmp (transport_option, "buffered", 9) != 0) {
+      fprintf (stderr, "Unknown transport type %s\n", transport_option);
+      options_valid = FALSE;
+    }
+  }
+
+  if (!options_valid)
+    return 254;
+
+  /* Establish all our connection objects */
+  handler           = g_object_new (TYPE_THRIFT_TEST_HANDLER,
+                                    NULL);
+  processor         = g_object_new (T_TEST_TYPE_THRIFT_TEST_PROCESSOR,
+                                    "handler", handler,
+                                    NULL);
+  server_transport  = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
+                                    "port", port,
+                                    NULL);
+  transport_factory = g_object_new (transport_factory_type,
+                                    NULL);
+  protocol_factory  = g_object_new (protocol_factory_type,
+                                    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);
+
+  /* Install our SIGINT handler, which handles Ctrl-C being pressed by stopping
+     the server gracefully */
+  memset (&sigint_action, 0, sizeof (sigint_action));
+  sigint_action.sa_handler = sigint_handler;
+  sigint_action.sa_flags = SA_RESETHAND;
+  sigaction (SIGINT, &sigint_action, NULL);
+
+  printf ("Starting \"%s\" server (%s/%s) listen on: %d\n",
+          server_name,
+          transport_name,
+          protocol_name,
+          port);
+  fflush (stdout);
+
+  /* Serve clients until SIGINT is received (Ctrl-C is pressed) */
+  thrift_server_serve (server, &error);
+
+  /* If the server stopped for any reason other than being interrupted by the
+     user, report the error */
+  if (!sigint_received) {
+    g_message ("thrift_server_serve: %s",
+               error != NULL ? error->message : "(null)");
+    g_clear_error (&error);
+  }
+
+  puts ("done.");
+
+  g_object_unref (server);
+  g_object_unref (protocol_factory);
+  g_object_unref (transport_factory);
+  g_object_unref (server_transport);
+  g_object_unref (processor);
+  g_object_unref (handler);
+
+  return 0;
+}
diff --git a/test/c_glib/src/thrift_test_handler.c b/test/c_glib/src/thrift_test_handler.c
new file mode 100644
index 0000000..596e615
--- /dev/null
+++ b/test/c_glib/src/thrift_test_handler.c
@@ -0,0 +1,838 @@
+/*
+ * 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 <inttypes.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <thrift/c_glib/thrift.h>
+#include <thrift/c_glib/thrift_application_exception.h>
+
+#include "thrift_test_handler.h"
+
+/* A handler that implements the TTestThriftTestIf interface */
+
+G_DEFINE_TYPE (ThriftTestHandler,
+               thrift_test_handler,
+               T_TEST_TYPE_THRIFT_TEST_HANDLER);
+
+gboolean
+thrift_test_handler_test_void (TTestThriftTestIf  *iface,
+                               GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testVoid()\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_string (TTestThriftTestIf  *iface,
+                                 gchar             **_return,
+                                 const gchar        *thing,
+                                 GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testString(\"%s\")\n", thing);
+  *_return = g_strdup (thing);
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_byte (TTestThriftTestIf  *iface,
+                               gint8              *_return,
+                               const gint8         thing,
+                               GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testByte(%d)\n", (gint)thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_i32 (TTestThriftTestIf  *iface,
+                              gint32             *_return,
+                              const gint32        thing,
+                              GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testI32(%d)\n", thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_i64 (TTestThriftTestIf  *iface,
+                              gint64             *_return,
+                              const gint64        thing,
+                              GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testI64(%" PRId64 ")\n", thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_double (TTestThriftTestIf  *iface,
+                                 gdouble            *_return,
+                                 const gdouble       thing,
+                                 GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testDouble(%f)\n", thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_struct (TTestThriftTestIf  *iface,
+                                 TTestXtruct       **_return,
+                                 const TTestXtruct  *thing,
+                                 GError            **error)
+{
+  gchar *string_thing = NULL;
+  gint   byte_thing;
+  gint   i32_thing;
+  gint64 i64_thing;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  g_object_get ((TTestXtruct *)thing,
+                "string_thing", &string_thing,
+                "byte_thing",   &byte_thing,
+                "i32_thing",    &i32_thing,
+                "i64_thing",    &i64_thing,
+                NULL);
+
+  printf ("testStruct({\"%s\", %d, %d, %" PRId64 "})\n",
+          string_thing,
+          (gint)byte_thing,
+          i32_thing,
+          i64_thing);
+
+  g_object_set (*_return,
+                "string_thing", string_thing,
+                "byte_thing",   byte_thing,
+                "i32_thing",    i32_thing,
+                "i64_thing",    i64_thing,
+                NULL);
+
+  if (string_thing != NULL)
+    g_free (string_thing);
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_nest (TTestThriftTestIf   *iface,
+                               TTestXtruct2       **_return,
+                               const TTestXtruct2  *thing,
+                               GError             **error)
+{
+  gchar *inner_string_thing = NULL;
+  gint   byte_thing, inner_byte_thing;
+  gint   i32_thing, inner_i32_thing;
+  gint64 inner_i64_thing;
+  TTestXtruct *struct_thing;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  g_object_get ((TTestXtruct2 *)thing,
+                "byte_thing",   &byte_thing,
+                "struct_thing", &struct_thing,
+                "i32_thing",    &i32_thing,
+                NULL);
+  g_object_get (struct_thing,
+                "string_thing", &inner_string_thing,
+                "byte_thing",   &inner_byte_thing,
+                "i32_thing",    &inner_i32_thing,
+                "i64_thing",    &inner_i64_thing,
+                NULL);
+
+  printf ("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n",
+          byte_thing,
+          inner_string_thing,
+          inner_byte_thing,
+          inner_i32_thing,
+          inner_i64_thing,
+          i32_thing);
+
+  g_object_set (*_return,
+                "byte_thing",   byte_thing,
+                "struct_thing", struct_thing,
+                "i32_thing",    i32_thing,
+                NULL);
+
+  if (inner_string_thing != NULL)
+    g_free (inner_string_thing);
+  g_object_unref (struct_thing);
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_map (TTestThriftTestIf  *iface,
+                              GHashTable        **_return,
+                              const GHashTable   *thing,
+                              GError            **error)
+{
+  GHashTableIter hash_table_iter;
+  gpointer key;
+  gpointer value;
+  gboolean first = TRUE;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testMap({");
+  g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
+  while (g_hash_table_iter_next (&hash_table_iter,
+                                 &key,
+                                 &value)) {
+    gint32 *new_key;
+    gint32 *new_value;
+
+    if (first)
+      first = FALSE;
+    else
+      printf (", ");
+
+    printf ("%d => %d", *(gint32 *)key, *(gint32 *)value);
+
+    new_key = g_malloc (sizeof *new_key);
+    *new_key = *(gint32 *)key;
+    new_value = g_malloc (sizeof *new_value);
+    *new_value = *(gint32 *)value;
+    g_hash_table_insert (*_return, new_key, new_value);
+  }
+  printf ("})\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_string_map (TTestThriftTestIf  *iface,
+                                     GHashTable        **_return,
+                                     const GHashTable   *thing,
+                                     GError            **error)
+{
+  GHashTableIter hash_table_iter;
+  gpointer key;
+  gpointer value;
+  gboolean first = TRUE;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testStringMap({");
+  g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
+  while (g_hash_table_iter_next (&hash_table_iter,
+                                 &key,
+                                 &value)) {
+    gchar *new_key;
+    gchar *new_value;
+
+    if (first)
+      first = FALSE;
+    else
+      printf (", ");
+
+    printf ("%s => %s", (gchar *)key, (gchar *)value);
+
+    new_key = g_strdup ((gchar *)key);
+    new_value = g_strdup ((gchar *)value);
+    g_hash_table_insert (*_return, new_key, new_value);
+  }
+  printf ("})\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_set (TTestThriftTestIf  *iface,
+                              GHashTable        **_return,
+                              const GHashTable   *thing,
+                              GError            **error)
+{
+  GHashTableIter hash_table_iter;
+  gpointer key;
+  gboolean first = TRUE;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testSet({");
+  g_hash_table_iter_init (&hash_table_iter, (GHashTable *)thing);
+  while (g_hash_table_iter_next (&hash_table_iter,
+                                 &key,
+                                 NULL)) {
+    gint32 *new_key;
+
+    if (first)
+      first = FALSE;
+    else
+      printf (", ");
+
+    printf ("%d", *(gint32 *)key);
+
+    new_key = g_malloc (sizeof *new_key);
+    *new_key = *(gint32 *)key;
+    g_hash_table_insert (*_return, new_key, NULL);
+  }
+  printf ("})\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_list (TTestThriftTestIf  *iface,
+                               GArray            **_return,
+                               const GArray       *thing,
+                               GError            **error)
+{
+  guint i;
+  gboolean first = TRUE;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testList({");
+  for (i = 0; i < thing->len; i += 1) {
+    gint32 value;
+    gint32 *new_value;
+
+    if (first)
+      first = FALSE;
+    else
+      printf (", ");
+
+    value = g_array_index (thing, gint32, i);
+    printf ("%d", value);
+
+    new_value = g_malloc (sizeof *new_value);
+    *new_value = value;
+    g_array_append_val (*_return, *new_value);
+  }
+  printf ("})\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_enum (TTestThriftTestIf   *iface,
+                               TTestNumberz        *_return,
+                               const TTestNumberz   thing,
+                               GError             **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testEnum(%d)\n", thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_typedef (TTestThriftTestIf  *iface,
+                                  TTestUserId        *_return,
+                                  const TTestUserId   thing,
+                                  GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testTypedef(%" PRId64 ")\n", thing);
+  *_return = thing;
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_map_map (TTestThriftTestIf  *iface,
+                                  GHashTable        **_return,
+                                  const gint32        hello,
+                                  GError            **error)
+{
+  GHashTable *positive;
+  GHashTable *negative;
+  gint32 *key;
+  gint32 *value;
+  guint i;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testMapMap(%d)\n", hello);
+
+  positive = g_hash_table_new_full (g_int_hash,
+                                    g_int_equal,
+                                    g_free,
+                                    g_free);
+  negative = g_hash_table_new_full (g_int_hash,
+                                    g_int_equal,
+                                    g_free,
+                                    g_free);
+
+  for (i = 1; i < 5; i += 1) {
+    key = g_malloc (sizeof *key);
+    value = g_malloc (sizeof *value);
+    *key = i;
+    *value = i;
+    g_hash_table_insert (positive, key, value);
+
+    key = g_malloc (sizeof *key);
+    value = g_malloc (sizeof *value);
+    *key = -i;
+    *value = -i;
+    g_hash_table_insert (negative, key, value);
+  }
+
+  key = g_malloc (sizeof *key);
+  *key = 4;
+  g_hash_table_insert (*_return, key, positive);
+
+  key = g_malloc (sizeof *key);
+  *key = -4;
+  g_hash_table_insert (*_return, key, negative);
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_insanity (TTestThriftTestIf    *iface,
+                                   GHashTable          **_return,
+                                   const TTestInsanity  *argument,
+                                   GError              **error)
+{
+  TTestXtruct *hello;
+  TTestXtruct *goodbye;
+  TTestXtruct *xtruct_in;
+
+  gchar *string_thing = NULL;
+  gint   byte_thing;
+  gint   i32_thing;
+  gint64 i64_thing;
+
+  GPtrArray *xtructs;
+
+  TTestInsanity *crazy;
+  TTestInsanity *looney;
+
+  GHashTable *user_map;
+  GHashTable *first_map;
+  GHashTable *second_map;
+
+  GHashTableIter hash_table_iter;
+  GHashTableIter inner_hash_table_iter;
+  GHashTableIter user_map_iter;
+
+  gpointer key;
+  gpointer value;
+
+  TTestUserId *user_id;
+
+  guint i;
+
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (argument);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testInsanity()\n");
+
+  hello = g_object_new (T_TEST_TYPE_XTRUCT,
+                        "string_thing", "Hello2",
+                        "byte_thing",   2,
+                        "i32_thing",    2,
+                        "i64_thing",    2,
+                        NULL);
+
+  goodbye = g_object_new (T_TEST_TYPE_XTRUCT,
+                          "string_thing", "Goodbye4",
+                          "byte_thing",   4,
+                          "i32_thing",    4,
+                          "i64_thing",    4,
+                          NULL);
+
+  crazy = g_object_new (T_TEST_TYPE_INSANITY, NULL);
+  g_object_get (crazy,
+                "userMap", &user_map,
+                "xtructs", &xtructs,
+                NULL);
+
+  user_id = g_malloc(sizeof *user_id);
+  *user_id = 8;
+  g_hash_table_insert (user_map,
+                       GINT_TO_POINTER (T_TEST_NUMBERZ_EIGHT),
+                       user_id);
+
+  g_ptr_array_add (xtructs, goodbye);
+
+  user_id = g_malloc(sizeof *user_id);
+  *user_id = 5;
+  g_hash_table_insert (user_map,
+                       GINT_TO_POINTER (T_TEST_NUMBERZ_FIVE),
+                       user_id);
+
+  g_ptr_array_add (xtructs, hello);
+
+  g_hash_table_unref (user_map);
+  g_ptr_array_unref (xtructs);
+
+  first_map = g_hash_table_new_full (g_direct_hash,
+                                     g_direct_equal,
+                                     NULL,
+                                     g_object_unref);
+  second_map = g_hash_table_new_full (g_direct_hash,
+                                      g_direct_equal,
+                                      NULL,
+                                      g_object_unref);
+
+  g_hash_table_insert (first_map,
+                       GINT_TO_POINTER (T_TEST_NUMBERZ_TWO),
+                       crazy);
+  g_hash_table_insert (first_map,
+                       GINT_TO_POINTER (T_TEST_NUMBERZ_THREE),
+                       crazy);
+
+  /* Increment crazy's ref count since first_map now holds two
+     references to it and would otherwise attempt to deallocate it
+     twice during destruction. We do this instead of creating a copy
+     of crazy in order to mimic the C++ implementation (and since,
+     frankly, the world needs less crazy, not more). */
+  g_object_ref (crazy);
+
+  looney = g_object_new (T_TEST_TYPE_INSANITY, NULL);
+  g_hash_table_insert (second_map,
+                       GINT_TO_POINTER (T_TEST_NUMBERZ_SIX),
+                       looney);
+
+  user_id = g_malloc (sizeof *user_id);
+  *user_id = 1;
+  g_hash_table_insert (*_return, user_id, first_map);
+
+  user_id = g_malloc (sizeof *user_id);
+  *user_id = 2;
+  g_hash_table_insert (*_return, user_id, second_map);
+
+  printf ("return");
+  printf (" = {");
+  g_hash_table_iter_init (&hash_table_iter, *_return);
+  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 < xtructs->len; ++i) {
+        xtruct_in = g_ptr_array_index (xtructs, i);
+        g_object_get (xtruct_in,
+                      "string_thing", &string_thing,
+                      "byte_thing",   &byte_thing,
+                      "i32_thing",    &i32_thing,
+                      "i64_thing",    &i64_thing,
+                      NULL);
+
+        printf ("{\"%s\", %d, %d, %" PRId64 "}, ",
+                string_thing,
+                byte_thing,
+                i32_thing,
+                i64_thing);
+      }
+      printf ("}");
+      g_ptr_array_unref (xtructs);
+
+      printf ("}, ");
+    }
+    printf ("}, ");
+  }
+  printf ("}\n");
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_multi (TTestThriftTestIf   *iface,
+                                TTestXtruct        **_return,
+                                const gint8          arg0,
+                                const gint32         arg1,
+                                const gint64         arg2,
+                                const GHashTable    *arg3,
+                                const TTestNumberz   arg4,
+                                const TTestUserId    arg5,
+                                GError             **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+  THRIFT_UNUSED_VAR (arg3);
+  THRIFT_UNUSED_VAR (arg4);
+  THRIFT_UNUSED_VAR (arg5);
+
+  printf ("testMulti()\n");
+
+  g_object_set (*_return,
+                "string_thing", g_strdup ("Hello2"),
+                "byte_thing",   arg0,
+                "i32_thing",    arg1,
+                "i64_thing",    arg2,
+                NULL);
+
+  return TRUE;
+}
+
+gboolean
+thrift_test_handler_test_exception (TTestThriftTestIf  *iface,
+                                    const gchar        *arg,
+                                    TTestXception     **err1,
+                                    GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+
+  TTestXtruct *xtruct;
+  gboolean result;
+
+  printf ("testException(%s)\n", arg);
+
+  /* Unlike argument objects, exception objects are not pre-created */
+  g_assert (*err1 == NULL);
+
+  if (strncmp (arg, "Xception", 9) == 0) {
+    /* "Throw" a custom exception: Set the corresponding exception
+       argument, set *error to NULL and return FALSE */
+    *err1 = g_object_new (T_TEST_TYPE_XCEPTION,
+                          "errorCode", 1001,
+                          "message",   g_strdup (arg),
+                          NULL);
+    *error = NULL;
+    result = FALSE;
+  }
+  else if (strncmp (arg, "TException", 11) == 0) {
+    /* "Throw" a generic TException (ThriftApplicationException): Set
+       all exception arguments to NULL, set *error and return FALSE */
+    *err1 = NULL;
+    g_set_error (error,
+                 thrift_application_exception_error_quark (),
+                 THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN,
+                 "Default TException.");
+    result = FALSE;
+  }
+  else {
+    *err1 = NULL;
+    *error = NULL;
+
+    /* This code is duplicated from the C++ test suite, though it
+       appears to serve no purpose */
+    xtruct = g_object_new (T_TEST_TYPE_XTRUCT,
+                           "string_thing", g_strdup (arg),
+                           NULL);
+    g_object_unref (xtruct);
+
+    result = TRUE;
+  }
+
+  return result;
+}
+
+gboolean
+thrift_test_handler_test_multi_exception (TTestThriftTestIf  *iface,
+                                          TTestXtruct       **_return,
+                                          const gchar        *arg0,
+                                          const gchar        *arg1,
+                                          TTestXception     **err1,
+                                          TTestXception2    **err2,
+                                          GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  TTestXtruct *struct_thing;
+  gboolean result;
+
+  printf ("testMultiException(%s, %s)\n", arg0, arg1);
+
+  g_assert (*err1 == NULL);
+  g_assert (*err2 == NULL);
+
+  if (strncmp (arg0, "Xception", 9) == 0) {
+    *err1 = g_object_new (T_TEST_TYPE_XCEPTION,
+                          "errorCode", 1001,
+                          "message",   g_strdup ("This is an Xception"),
+                          NULL);
+    result = FALSE;
+  }
+  else if (strncmp (arg0, "Xception2", 10) == 0) {
+    *err2 = g_object_new (T_TEST_TYPE_XCEPTION2,
+                          "errorCode", 2002);
+
+    g_object_get (*err2,
+                  "struct_thing", &struct_thing,
+                  NULL);
+    g_object_set (struct_thing,
+                  "string_thing", g_strdup ("This is an Xception2"),
+                  NULL);
+    g_object_set (*err2,
+                  "struct_thing", struct_thing,
+                  NULL);
+    g_object_unref (struct_thing);
+
+    result = FALSE;
+  }
+  else {
+    g_object_set (*_return,
+                  "string_thing", g_strdup (arg1),
+                  NULL);
+    result = TRUE;
+  }
+
+  return result;
+}
+
+gboolean
+thrift_test_handler_test_oneway (TTestThriftTestIf  *iface,
+                                 const gint32        secondsToSleep,
+                                 GError            **error)
+{
+  THRIFT_UNUSED_VAR (iface);
+  THRIFT_UNUSED_VAR (error);
+
+  printf ("testOneway(%d): Sleeping...\n", secondsToSleep);
+  sleep (secondsToSleep);
+  printf ("testOneway(%d): done sleeping!\n", secondsToSleep);
+
+  return TRUE;
+}
+
+static void
+thrift_test_handler_init (ThriftTestHandler *self)
+{
+  THRIFT_UNUSED_VAR (self);
+}
+
+static void
+thrift_test_handler_class_init (ThriftTestHandlerClass *klass)
+{
+  TTestThriftTestHandlerClass *base_class =
+    T_TEST_THRIFT_TEST_HANDLER_CLASS (klass);
+
+  base_class->test_void =
+    klass->test_void =
+    thrift_test_handler_test_void;
+  base_class->test_string =
+    klass->test_string =
+    thrift_test_handler_test_string;
+  base_class->test_byte =
+    klass->test_byte =
+    thrift_test_handler_test_byte;
+  base_class->test_i32 =
+    klass->test_i32 =
+    thrift_test_handler_test_i32;
+  base_class->test_i64 =
+    klass->test_i64 =
+    thrift_test_handler_test_i64;
+  base_class->test_double =
+    klass->test_double =
+    thrift_test_handler_test_double;
+  base_class->test_struct =
+    klass->test_struct =
+    thrift_test_handler_test_struct;
+  base_class->test_nest =
+    klass->test_nest =
+    thrift_test_handler_test_nest;
+  base_class->test_map =
+    klass->test_map =
+    thrift_test_handler_test_map;
+  base_class->test_string_map =
+    klass->test_string_map =
+    thrift_test_handler_test_string_map;
+  base_class->test_set =
+    klass->test_set =
+    thrift_test_handler_test_set;
+  base_class->test_list =
+    klass->test_list =
+    thrift_test_handler_test_list;
+  base_class->test_enum =
+    klass->test_enum =
+    thrift_test_handler_test_enum;
+  base_class->test_typedef =
+    klass->test_typedef =
+    thrift_test_handler_test_typedef;
+  base_class->test_map_map =
+    klass->test_map_map =
+    thrift_test_handler_test_map_map;
+  base_class->test_insanity =
+    klass->test_insanity =
+    thrift_test_handler_test_insanity;
+  base_class->test_multi =
+    klass->test_multi =
+    thrift_test_handler_test_multi;
+  base_class->test_exception =
+    klass->test_exception =
+    thrift_test_handler_test_exception;
+  base_class->test_multi_exception =
+    klass->test_multi_exception =
+    thrift_test_handler_test_multi_exception;
+  base_class->test_oneway =
+    klass->test_oneway =
+    thrift_test_handler_test_oneway;
+}
diff --git a/test/c_glib/src/thrift_test_handler.h b/test/c_glib/src/thrift_test_handler.h
new file mode 100644
index 0000000..a34f90a
--- /dev/null
+++ b/test/c_glib/src/thrift_test_handler.h
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+#ifndef _THRIFT_TEST_HANDLER_H
+#define _THRIFT_TEST_HANDLER_H
+
+#include <glib-object.h>
+#include <stdio.h>
+
+#include "../gen-c_glib/t_test_thrift_test.h"
+
+G_BEGIN_DECLS
+
+/* A handler that implements the TTestThriftTestIf interface */
+
+#define TYPE_THRIFT_TEST_HANDLER (thrift_test_handler_get_type ())
+
+#define THRIFT_TEST_HANDLER(obj)                                \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj),                           \
+                               TYPE_THRIFT_TEST_HANDLER,        \
+                               ThriftTestHandler))
+#define IS_THRIFT_TEST_HANDLER(obj)                             \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                           \
+                               TYPE_THRIFT_TEST_HANDLER))
+#define THRIFT_TEST_HANDLER_CLASS(c)                    \
+  (G_TYPE_CHECK_CLASS_CAST ((c),                        \
+                            TYPE_THRIFT_TEST_HANDLER,   \
+                            ThriftTestHandlerClass))
+#define IS_THRIFT_TEST_HANDLER_CLASS(c)                 \
+  (G_TYPE_CHECK_CLASS_TYPE ((c),                        \
+                            TYPE_THRIFT_TEST_HANDLER))
+#define THRIFT_TEST_HANDLER_GET_CLASS(obj)              \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj),                    \
+                              TYPE_THRIFT_TEST_HANDLER, \
+                              ThriftTestHandlerClass))
+
+typedef struct _ThriftTestHandler ThriftTestHandler;
+typedef struct _ThriftTestHandlerClass ThriftTestHandlerClass;
+
+struct _ThriftTestHandler {
+  TTestThriftTestHandler parent;
+};
+
+struct _ThriftTestHandlerClass {
+  TTestThriftTestHandlerClass parent;
+
+  gboolean (*test_void)            (TTestThriftTestIf    *iface,
+                                    GError              **error);
+  gboolean (*test_string)          (TTestThriftTestIf    *iface,
+                                    gchar               **_return,
+                                    const gchar          *thing,
+                                    GError              **error);
+  gboolean (*test_byte)            (TTestThriftTestIf    *iface,
+                                    gint8*_return,
+                                    const gint8           thing,
+                                    GError              **error);
+  gboolean (*test_i32)             (TTestThriftTestIf    *iface,
+                                    gint32*_return,
+                                    const gint32          thing,
+                                    GError              **error);
+  gboolean (*test_i64)             (TTestThriftTestIf    *iface,
+                                    gint64*_return,
+                                    const gint64          thing,
+                                    GError              **error);
+  gboolean (*test_double)          (TTestThriftTestIf    *iface,
+                                    gdouble*_return,
+                                    const gdouble         thing,
+                                    GError              **error);
+  gboolean (*test_struct)          (TTestThriftTestIf    *iface,
+                                    TTestXtruct         **_return,
+                                    const TTestXtruct    *thing,
+                                    GError              **error);
+  gboolean (*test_nest)            (TTestThriftTestIf    *iface,
+                                    TTestXtruct2        **_return,
+                                    const TTestXtruct2   *thing,
+                                    GError              **error);
+  gboolean (*test_map)             (TTestThriftTestIf    *iface,
+                                    GHashTable          **_return,
+                                    const GHashTable     *thing,
+                                    GError              **error);
+  gboolean (*test_string_map)      (TTestThriftTestIf    *iface,
+                                    GHashTable          **_return,
+                                    const GHashTable     *thing,
+                                    GError              **error);
+  gboolean (*test_set)             (TTestThriftTestIf    *iface,
+                                    GHashTable          **_return,
+                                    const GHashTable     *thing,
+                                    GError              **error);
+  gboolean (*test_list)            (TTestThriftTestIf    *iface,
+                                    GArray              **_return,
+                                    const GArray         *thing,
+                                    GError              **error);
+  gboolean (*test_enum)            (TTestThriftTestIf    *iface,
+                                    TTestNumberz*_return,
+                                    const TTestNumberz    thing,
+                                    GError              **error);
+  gboolean (*test_typedef)         (TTestThriftTestIf    *iface,
+                                    TTestUserId*_return,
+                                    const TTestUserId     thing,
+                                    GError              **error);
+  gboolean (*test_map_map)         (TTestThriftTestIf    *iface,
+                                    GHashTable          **_return,
+                                    const gint32          hello,
+                                    GError              **error);
+  gboolean (*test_insanity)        (TTestThriftTestIf    *iface,
+                                    GHashTable          **_return,
+                                    const TTestInsanity  *argument,
+                                    GError              **error);
+  gboolean (*test_multi)           (TTestThriftTestIf    *iface,
+                                    TTestXtruct         **_return,
+                                    const gint8           arg0,
+                                    const gint32          arg1,
+                                    const gint64          arg2,
+                                    const GHashTable     *arg3,
+                                    const TTestNumberz    arg4,
+                                    const TTestUserId     arg5,
+                                    GError              **error);
+  gboolean (*test_exception)       (TTestThriftTestIf    *iface,
+                                    const gchar          *arg,
+                                    TTestXception       **err1,
+                                    GError              **error);
+  gboolean (*test_multi_exception) (TTestThriftTestIf    *iface,
+                                    TTestXtruct         **_return,
+                                    const gchar          *arg0,
+                                    const gchar          *arg1,
+                                    TTestXception       **err1,
+                                    TTestXception2      **err2,
+                                    GError              **error);
+  gboolean (*test_oneway)          (TTestThriftTestIf    *iface,
+                                    const gint32          secondsToSleep,
+                                    GError              **error);
+};
+
+/* Used by THRIFT_TEST_HANDLER_GET_TYPE */
+GType thrift_test_handler_get_type (void);
+
+gboolean thrift_test_handler_test_void            (TTestThriftTestIf    *iface,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_string          (TTestThriftTestIf    *iface,
+                                                   gchar               **_return,
+                                                   const gchar          *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_byte            (TTestThriftTestIf    *iface,
+                                                   gint8*_return,
+                                                   const gint8           thing,
+                                                   GError              **error);
+gboolean t_test_thrift_test_if_test_i32           (TTestThriftTestIf    *iface,
+                                                   gint32*_return,
+                                                   const gint32          thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_i64             (TTestThriftTestIf    *iface,
+                                                   gint64*_return,
+                                                   const gint64          thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_double          (TTestThriftTestIf    *iface,
+                                                   gdouble*_return,
+                                                   const gdouble         thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_struct          (TTestThriftTestIf    *iface,
+                                                   TTestXtruct         **_return,
+                                                   const TTestXtruct    *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_nest            (TTestThriftTestIf    *iface,
+                                                   TTestXtruct2        **_return,
+                                                   const TTestXtruct2   *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_map             (TTestThriftTestIf    *iface,
+                                                   GHashTable          **_return,
+                                                   const GHashTable     *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_string_map      (TTestThriftTestIf    *iface,
+                                                   GHashTable          **_return,
+                                                   const GHashTable     *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_set             (TTestThriftTestIf    *iface,
+                                                   GHashTable          **_return,
+                                                   const GHashTable     *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_list            (TTestThriftTestIf    *iface,
+                                                   GArray              **_return,
+                                                   const GArray         *thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_typedef         (TTestThriftTestIf    *iface,
+                                                   TTestUserId*_return,
+                                                   const TTestUserId     thing,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_map_map         (TTestThriftTestIf    *iface,
+                                                   GHashTable          **_return,
+                                                   const gint32          hello,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_insanity        (TTestThriftTestIf    *iface,
+                                                   GHashTable          **_return,
+                                                   const TTestInsanity  *argument,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_multi           (TTestThriftTestIf    *iface,
+                                                   TTestXtruct         **_return,
+                                                   const gint8           arg0,
+                                                   const gint32          arg1,
+                                                   const gint64          arg2,
+                                                   const GHashTable     *arg3,
+                                                   const TTestNumberz    arg4,
+                                                   const TTestUserId     arg5,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_exception       (TTestThriftTestIf    *iface,
+                                                   const gchar          *arg,
+                                                   TTestXception       **err1,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_multi_exception (TTestThriftTestIf    *iface,
+                                                   TTestXtruct         **_return,
+                                                   const gchar          *arg0,
+                                                   const gchar          *arg1,
+                                                   TTestXception       **err1,
+                                                   TTestXception2      **err2,
+                                                   GError              **error);
+gboolean thrift_test_handler_test_oneway          (TTestThriftTestIf    *iface,
+                                                   const gint32          secondsToSleep,
+                                                   GError              **error);
+
+G_END_DECLS
+
+#endif /* _THRIFT_TEST_HANDLER_H */
diff --git a/test/test.sh b/test/test.sh
index f7e119d..edb2237 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -288,6 +288,23 @@
   done
 done
 
+######### c_glib client - c_glib server ##############
+for proto in ${c_glib_protocols}; do
+  for trans in ${c_glib_transports}; do
+    for sock in ${c_glib_sockets}; do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+        "domain" ) extraparam="--domain-socket=/tmp/ThriftTest.thrift";;
+      esac
+      do_test "c_glib-c_glib" "${proto}" "${trans}-${sock}" \
+              "c_glib/test_client --protocol=${proto}  --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "c_glib/test_server --protocol=${proto}  --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "2" "0.1"
+    done
+  done
+done
+
 ######### c_glib client - cpp server ##############
 for proto in $(intersection "${c_glib_protocols}" "${cpp_protocols}"); do
   for trans in $(intersection "${c_glib_transports}" "${cpp_transports}"); do
@@ -305,6 +322,23 @@
   done
 done
 
+######### cpp client - c_glib server ##############
+for proto in $(intersection "${cpp_protocols}" "${c_glib_protocols}"); do
+  for trans in $(intersection "${cpp_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${cpp_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+        "domain" ) extraparam="--domain-socket=/tmp/ThriftTest.thrift";;
+      esac
+      do_test "cpp-c_glib" "${proto}" "${trans}-${sock}" \
+              "cpp/TestClient --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}"\
+              "c_glib/test_server --protocol=${proto}  --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "2" "0.1"
+    done
+  done
+done
+
 ######### c_glib client - java server ##############
 for proto in $(intersection "${c_glib_protocols}" "${java_protocols}"); do
   for trans in $(intersection "${c_glib_transports}" "${java_server_transports}"); do
@@ -321,6 +355,22 @@
   done
 done
 
+######### java client - c_glib server ##############
+for proto in $(intersection "${java_protocols}" "${c_glib_protocols}"); do
+  for trans in $(intersection "${java_client_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${java_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "java-c_glib" "${proto}" "${trans}-${sock}" \
+              "ant -f  ../lib/java/build.xml -Dno-gen-thrift=\"\" -Dtestargs \"--protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}\" run-testclient" \
+              "c_glib/test_server --protocol=${proto}  --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "5" "0.1"
+    done
+  done
+done
+
 
 NODE_TEST_DIR=${BASEDIR}/../lib/nodejs/test
 export NODE_PATH=${NODE_TEST_DIR}:${NODE_TEST_DIR}/../lib:${NODE_PATH}
@@ -404,6 +454,22 @@
   done
 done
 
+######### nodejs client - c_glib server ##############
+for proto in $(intersection "${nodejs_protocols}" "${c_glib_protocols}"); do
+  for trans in $(intersection "${nodejs_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${nodejs_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "nodejs-c_glib" "${proto}" "${trans}-${sock}" \
+              "node ${NODE_TEST_DIR}/client.js -p ${proto} -t ${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "c_glib/test_server --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "5" "0.1"
+    done
+  done
+done
+
 ######### c_glib client - nodejs server ##############
 for proto in $(intersection "${c_glib_protocols}" "${nodejs_protocols}"); do
   for trans in $(intersection "${c_glib_transports}" "${nodejs_transports}"); do
@@ -569,6 +635,35 @@
     done
   done
 
+######### py client - c_glib server ##############
+for proto in $(intersection "${py_protocols}" "${c_glib_protocols}"); do
+  for trans in $(intersection "${py_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${py_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "py-c_glib" "${proto}" "${trans}-${sock}" \
+              "py/TestClient.py --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} --host=localhost --genpydir=gen-py ${extraparam}" \
+              "c_glib/test_server --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "10" "0.1"
+    done
+  done
+done
+
+for trans in $(intersection "${py_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${py_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "py-c_glib" "accel-binary" "${trans}-${sock}" \
+              "py/TestClient.py --protocol=accel --transport=${trans} --port=${THRIFT_TEST_PORT} --host=localhost --genpydir=gen-py ${extraparam}" \
+              "c_glib/test_server --protocol=binary --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "10" "0.1"
+    done
+  done
+
 ######### c_glib client - py server ##############
 for proto in $(intersection "${c_glib_protocols}" "${py_protocols}"); do
   for trans in $(intersection "${c_glib_transports}" "${py_transports}"); do
@@ -585,6 +680,19 @@
   done
 done
 
+for trans in $(intersection "${c_glib_transports}" "${py_transports}"); do
+    for sock in $(intersection "${c_glib_sockets}" "${py_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "c_glib-py" "binary-accel" "${trans}-${sock}" \
+              "c_glib/test_client --protocol=binary --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "py/TestServer.py --protocol=accel --transport=${trans} --port=${THRIFT_TEST_PORT} --genpydir=gen-py TSimpleServer ${extraparam}" \
+              "10" "2"
+    done
+  done
+
 ######### py client - nodejs server ##############
 for proto in $(intersection "${py_protocols}" "${nodejs_protocols}"); do
   for trans in $(intersection "${py_transports}" "${nodejs_transports}"); do
@@ -792,6 +900,35 @@
     done
   done
 
+######### ruby client - c_glib server ##############
+for proto in $(intersection "${ruby_protocols}" "${c_glib_protocols}"); do
+  for trans in $(intersection "${ruby_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${ruby_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "ruby-c_glib" "${proto}" "${trans}-${sock}" \
+              "ruby rb/integration/TestClient.rb --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "c_glib/test_server --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "5" "0.1"
+    done
+  done
+done
+
+for trans in $(intersection "${ruby_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${ruby_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "ruby-c_glib" "accel-binary" "${trans}-${sock}" \
+              "ruby rb/integration/TestClient.rb --protocol=accel --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "c_glib/test_server --protocol=binary --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "5" "0.1"
+    done
+  done
+
 ######### c_glib client - ruby server ##############
 for proto in $(intersection "${c_glib_protocols}" "${ruby_protocols}"); do
   for trans in $(intersection "${c_glib_transports}" "${ruby_transports}"); do
@@ -808,6 +945,19 @@
   done
 done
 
+for trans in $(intersection "${c_glib_transports}" "${ruby_transports}"); do
+    for sock in $(intersection "${c_glib_sockets}" "${ruby_sockets}"); do
+      case "$sock" in
+        "ip" ) extraparam="";;
+        "ip-ssl" ) extraparam="--ssl";;
+      esac
+      do_test "c_glib-ruby" "binary-accel" "${trans}-${sock}" \
+              "c_glib/test_client --protocol=binary --transport=${trans} --port=${THRIFT_TEST_PORT} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "ruby rb/integration/TestServer.rb --protocol=accel --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "5" "5"
+    done
+  done
+
 ######### ruby client - nodejs server ##############
 for proto in $(intersection "${ruby_protocols}" "${nodejs_protocols}"); do
   for trans in $(intersection "${ruby_transports}" "${nodejs_transports}"); do
@@ -1017,6 +1167,23 @@
   done
 done
 
+######### hs client - c_glib server ###############
+for proto in $(intersection "${hs_protocols}" "${c_glib_protocols}"); do
+  for trans in  $(intersection "${hs_transports}" "${c_glib_transports}"); do
+    for sock in $(intersection "${hs_sockets}" "${c_glib_sockets}"); do
+      case "$sock" in
+       "ip" )     extraparam="";;
+       "ip-ssl" ) extraparam="--ssl";;
+       "domain" ) extraparam="--domain-socket=/tmp/ThriftTest.thrift";;
+      esac
+      do_test "hs-c_glib"   "${proto}" "${trans}-${sock}" \
+              "hs/TestClient --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "c_glib/test_server --protocol=${proto} --transport=${trans} --port=${THRIFT_TEST_PORT} ${extraparam}" \
+              "2" "0.1"
+    done
+  done
+done
+
 ######### c_glib client - hs server ###############
 for proto in $(intersection "${c_glib_protocols}" "${hs_protocols}"); do
   for trans in  $(intersection "${c_glib_transports}" "${hs_transports}"); do