THRIFT-3464 Fix several defects in c_glib code generator
Client: c_glib compiler
Patch: Nobuaki Sukegawa

This closes #724
diff --git a/lib/c_glib/test/CMakeLists.txt b/lib/c_glib/test/CMakeLists.txt
index 61dc490..48a30d0 100644
--- a/lib/c_glib/test/CMakeLists.txt
+++ b/lib/c_glib/test/CMakeLists.txt
@@ -28,6 +28,8 @@
 # Create the thrift C test library
 set(testgenc_SOURCES
     gen-c_glib/t_test_debug_proto_test_types.c
+    gen-c_glib/t_test_enum_test_types.c
+    gen-c_glib/t_test_enum_test_service.c
     gen-c_glib/t_test_empty_service.c
     gen-c_glib/t_test_inherited.c
     gen-c_glib/t_test_optional_required_test_types.c
@@ -38,6 +40,8 @@
     gen-c_glib/t_test_thrift_test.c
     gen-c_glib/t_test_thrift_test_types.c
     gen-c_glib/t_test_debug_proto_test_types.h
+    gen-c_glib/t_test_enum_test_types.h
+    gen-c_glib/t_test_enum_test_service.h
     gen-c_glib/t_test_empty_service.h
     gen-c_glib/t_test_inherited.h
     gen-c_glib/t_test_optional_required_test_types.h
@@ -146,6 +150,14 @@
 )
 
 add_custom_command(OUTPUT
+    gen-c_glib/t_test_enum_test_types.c
+    gen-c_glib/t_test_enum_test_types.h
+    gen-c_glib/t_test_enum_test_service.c
+    gen-c_glib/t_test_enum_test_service.h
+    COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/EnumTest.thrift
+)
+
+add_custom_command(OUTPUT
     gen-c_glib/t_test_optional_required_test_types.c
     gen-c_glib/t_test_optional_required_test_types.h
     COMMAND ${THRIFT_COMPILER} --gen c_glib ${PROJECT_SOURCE_DIR}/test/OptionalRequiredTest.thrift
diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am
index 555380c..4d35f2a 100755
--- a/lib/c_glib/test/Makefile.am
+++ b/lib/c_glib/test/Makefile.am
@@ -169,6 +169,8 @@
 nodist_libtestgenc_la_SOURCES = \
         gen-c_glib/t_test_container_test_types.c \
         gen-c_glib/t_test_debug_proto_test_types.c \
+        gen-c_glib/t_test_enum_test_types.c \
+        gen-c_glib/t_test_enum_test_service.c \
         gen-c_glib/t_test_empty_service.c \
         gen-c_glib/t_test_inherited.c \
         gen-c_glib/t_test_optional_required_test_types.c \
@@ -181,6 +183,8 @@
         gen-c_glib/t_test_thrift_test_types.c \
         gen-c_glib/t_test_container_test_types.h \
         gen-c_glib/t_test_debug_proto_test_types.h \
+        gen-c_glib/t_test_enum_test_types.h \
+        gen-c_glib/t_test_enum_test_service.h \
         gen-c_glib/t_test_empty_service.h \
         gen-c_glib/t_test_inherited.h \
         gen-c_glib/t_test_optional_required_test_types.h \
@@ -211,6 +215,9 @@
 gen-c_glib/t_test_debug_proto_test_types.c gen-c_glib/t_test_debug_proto_test_types.h gen-c_glib/t_test_empty_service.c gen-c_glib/t_test_empty_service.h gen-c_glib/t_test_inherited.c gen-c_glib/t_test_inherited.h gen-c_glib/t_test_reverse_order_service.c gen-c_glib/t_test_reverse_order_service.h gen-c_glib/t_test_service_for_exception_with_a_map.c gen-c_glib/t_test_service_for_exception_with_a_map.h gen-c_glib/t_test_srv.c gen-c_glib/t_test_srv.h: ../../../test/DebugProtoTest.thrift
 	$(THRIFT) --gen c_glib $<
 
+gen-c_glib/t_test_enum_test_types.c gen-c_glib/t_test_enum_test_types.h gen-c_glib/t_test_enum_test_service.c gen-c_glib/t_test_enum_test_service.h : ../../../test/EnumTest.thrift
+	$(THRIFT) --gen c_glib $<
+
 gen-c_glib/t_test_optional_required_test_types.c gen-c_glib/t_test_optional_required_test_types.h: ../../../test/OptionalRequiredTest.thrift
 	$(THRIFT) --gen c_glib $<
 
diff --git a/lib/c_glib/test/testoptionalrequired.c b/lib/c_glib/test/testoptionalrequired.c
index ae0c3d2..cfc96a2 100755
--- a/lib/c_glib/test/testoptionalrequired.c
+++ b/lib/c_glib/test/testoptionalrequired.c
@@ -187,6 +187,26 @@
   g_object_unref (t3);
 }
 
+static void
+test_non_set_binary (void)
+{
+  TTestBinaries *b1 = NULL;
+  TTestBinaries *b2 = NULL;
+  GError *error = NULL;
+
+  b1 = g_object_new (T_TEST_TYPE_BINARIES, NULL);
+  b2 = g_object_new (T_TEST_TYPE_BINARIES, NULL);
+
+  write_to_read (THRIFT_STRUCT (b1), THRIFT_STRUCT (b2), NULL, &error);
+  g_assert(!error);
+  write_to_read (THRIFT_STRUCT (b2), THRIFT_STRUCT (b1), NULL, &error);
+  g_assert(!error);
+  // OK. No segfault
+
+  g_object_unref (b1);
+  g_object_unref (b2);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -202,6 +222,7 @@
   g_test_add_func ("/testoptionalrequired/Tricky2", test_tricky2);
   g_test_add_func ("/testoptionalrequired/Tricky3", test_tricky3);
   g_test_add_func ("/testoptionalrequired/Tricky4", test_tricky4);
+  g_test_add_func ("/testoptionalrequired/Binary", test_non_set_binary);
 
   return g_test_run ();
 }
diff --git a/lib/c_glib/test/testserialization.c b/lib/c_glib/test/testserialization.c
index 0ece2ad..9fc6357 100644
--- a/lib/c_glib/test/testserialization.c
+++ b/lib/c_glib/test/testserialization.c
@@ -3,6 +3,53 @@
 #include <thrift/c_glib/transport/thrift_memory_buffer.h>
 #include <thrift/c_glib/transport/thrift_transport.h>
 #include "gen-c_glib/t_test_debug_proto_test_types.h"
+#include "gen-c_glib/t_test_enum_test_types.h"
+
+static void enum_constants_read_write() {
+  GError* error = NULL;
+  ThriftTransport* transport
+      = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, NULL));
+  ThriftProtocol* protocol
+      = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
+  TTestEnumTestStruct* src = T_TEST_ENUM_TEST;
+  TTestEnumTestStruct* dst = g_object_new(T_TEST_TYPE_ENUM_TEST_STRUCT, NULL);
+  TTestEnumTestStructClass* cls = T_TEST_ENUM_TEST_STRUCT_GET_CLASS(src);
+
+  int write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error);
+  g_assert(!error);
+  g_assert(write_len > 0);
+
+  int read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error);
+  g_assert(!error);
+  g_assert_cmpint(write_len, ==, read_len);
+
+  g_object_unref(dst);
+  g_object_unref(protocol);
+  g_object_unref(transport);
+}
+
+static void struct_constants_read_write() {
+  GError* error = NULL;
+  ThriftTransport* transport
+      = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 4096, NULL));
+  ThriftProtocol* protocol
+      = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
+  TTestCompactProtoTestStruct* src = T_TEST_COMPACT_TEST;
+  TTestCompactProtoTestStruct* dst = g_object_new(T_TEST_TYPE_COMPACT_PROTO_TEST_STRUCT, NULL);
+  TTestCompactProtoTestStructClass* cls = T_TEST_COMPACT_PROTO_TEST_STRUCT_GET_CLASS(src);
+
+  int write_len = THRIFT_STRUCT_CLASS(cls)->write(THRIFT_STRUCT(src), protocol, &error);
+  g_assert(!error);
+  g_assert(write_len > 0);
+
+  int read_len = THRIFT_STRUCT_CLASS(cls)->read(THRIFT_STRUCT(dst), protocol, &error);
+  g_assert(!error);
+  g_assert_cmpint(write_len, ==, read_len);
+
+  g_object_unref(dst);
+  g_object_unref(protocol);
+  g_object_unref(transport);
+}
 
 static void struct_read_write_length_should_equal() {
   GError* error = NULL;
@@ -36,5 +83,7 @@
 
   g_test_add_func("/testserialization/StructReadWriteLengthShouldEqual",
                   struct_read_write_length_should_equal);
+  g_test_add_func("/testserialization/StructConstants", struct_constants_read_write);
+  g_test_add_func("/testserialization/EnumConstants", enum_constants_read_write);
   return g_test_run();
 }