THRIFT-2636 c_glib: ThriftApplicationException: Expose "type" and "message" properties
Patch: Simon South
diff --git a/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c b/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c
index 64bd87a..1234cae 100644
--- a/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c
+++ b/lib/c_glib/src/thrift/c_glib/thrift_application_exception.c
@@ -20,6 +20,14 @@
#include "thrift_application_exception.h"
#include <thrift/c_glib/protocol/thrift_protocol.h>
+/* object properties */
+enum _ThriftApplicationExceptionProperties
+{
+ PROP_0,
+ PROP_THRIFT_APPLICATION_EXCEPTION_TYPE,
+ PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE
+};
+
G_DEFINE_TYPE(ThriftApplicationException, thrift_application_exception, THRIFT_TYPE_STRUCT)
gint32
@@ -161,6 +169,55 @@
return g_quark_from_static_string (THRIFT_APPLICATION_EXCEPTION_ERROR_DOMAIN);
}
+static void
+thrift_application_exception_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object);
+
+ switch (property_id)
+ {
+ case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE:
+ g_value_set_int (value, tae->type);
+ break;
+ case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE:
+ g_value_set_string (value, tae->message);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+thrift_application_exception_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ThriftApplicationException *tae = THRIFT_APPLICATION_EXCEPTION (object);
+
+ switch (property_id)
+ {
+ case PROP_THRIFT_APPLICATION_EXCEPTION_TYPE:
+ tae->type = g_value_get_int (value);
+ tae->__isset_type = TRUE;
+ break;
+ case PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE:
+ if (tae->message != NULL)
+ g_free (tae->message);
+
+ tae->message = g_value_dup_string (value);
+ tae->__isset_message = TRUE;
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
void
thrift_application_exception_init (ThriftApplicationException *object)
{
@@ -185,9 +242,36 @@
{
GObjectClass *gobject_class = G_OBJECT_CLASS(class);
ThriftStructClass *cls = THRIFT_STRUCT_CLASS(class);
+ GParamSpec *param_spec;
cls->read = thrift_application_exception_read;
cls->write = thrift_application_exception_write;
gobject_class->finalize = thrift_application_exception_finalize;
+ gobject_class->get_property = thrift_application_exception_get_property;
+ gobject_class->set_property = thrift_application_exception_set_property;
+
+ param_spec = g_param_spec_int ("type",
+ "Exception type",
+ "The type of the exception, one of the "
+ "values defined by the "
+ "ThriftApplicationExceptionError "
+ "enumeration.",
+ 0,
+ THRIFT_APPLICATION_EXCEPTION_ERROR_N - 1,
+ 0,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class,
+ PROP_THRIFT_APPLICATION_EXCEPTION_TYPE,
+ param_spec);
+
+ param_spec = g_param_spec_string ("message",
+ "Exception message",
+ "A string describing the exception that "
+ "occurred.",
+ NULL,
+ G_PARAM_READWRITE);
+ g_object_class_install_property (gobject_class,
+ PROP_THRIFT_APPLICATION_EXCEPTION_MESSAGE,
+ param_spec);
}
diff --git a/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h b/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h
index ba3e97b..733f793 100644
--- a/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h
+++ b/lib/c_glib/src/thrift/c_glib/thrift_application_exception.h
@@ -43,7 +43,7 @@
{
ThriftStruct parent;
- /* public */
+ /* private */
gint32 type;
gboolean __isset_type;
gchar *message;
@@ -72,7 +72,9 @@
THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR,
THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM,
THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL,
- THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE
+ THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE,
+
+ THRIFT_APPLICATION_EXCEPTION_ERROR_N
} ThriftApplicationExceptionError;
/* define error domain for GError */
diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am
index 7fed8e8..25f474a 100755
--- a/lib/c_glib/test/Makefile.am
+++ b/lib/c_glib/test/Makefile.am
@@ -26,6 +26,7 @@
CXXFLAGS = -g
check_PROGRAMS = \
+ testapplicationexception \
testtransportsocket \
testbinaryprotocol \
testbufferedtransport \
@@ -41,6 +42,13 @@
check_PROGRAMS += testthrifttestclient
endif
+testapplicationexception_SOURCES = testapplicationexception.c
+testapplicationexception_LDADD = \
+ ../libthrift_c_glib_la-thrift_application_exception.o \
+ ../libthrift_c_glib_la-thrift_protocol.o \
+ ../libthrift_c_glib_la-thrift_struct.o \
+ ../libthrift_c_glib_la-thrift_transport.o
+
testtransportsocket_SOURCES = testtransportsocket.c
testtransportsocket_LDADD = \
../libthrift_c_glib_la-thrift_transport.o \
diff --git a/lib/c_glib/test/testapplicationexception.c b/lib/c_glib/test/testapplicationexception.c
new file mode 100644
index 0000000..2481340
--- /dev/null
+++ b/lib/c_glib/test/testapplicationexception.c
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include <thrift/c_glib/thrift_application_exception.h>
+
+static void
+test_create_and_destroy (void)
+{
+ GObject *object = NULL;
+
+ /* A ThriftApplicationException can be created... */
+ object = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);
+
+ g_assert (object != NULL);
+ g_assert (THRIFT_IS_APPLICATION_EXCEPTION (object));
+
+ /* ...and destroyed */
+ g_object_unref (object);
+}
+
+static void
+test_initialize (void)
+{
+ ThriftApplicationException *xception = NULL;
+ gint32 type = THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR;
+ gchar *message = "Exception message";
+ gint32 retrieved_type = 0;
+ gchar *retrieved_message = NULL;
+
+ /* A ThriftApplicationException has "type" and "message" properties that can
+ be initialized at object creation */
+ xception =
+ g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION,
+ "type", type,
+ "message", message,
+ NULL);
+
+ g_assert (xception != NULL);
+
+ /* A ThriftApplicationException's properties can be retrieved */
+ g_object_get (xception,
+ "type", &retrieved_type,
+ "message", &retrieved_message,
+ NULL);
+
+ g_assert (retrieved_type == type);
+ g_assert (retrieved_message != NULL);
+ g_assert_cmpstr (retrieved_message, ==, message);
+
+ g_free (retrieved_message);
+ g_object_unref (xception);
+}
+
+static void
+test_properties_test (void)
+{
+ ThriftApplicationException *xception = NULL;
+ gint32 retrieved_type;
+
+ xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);
+
+#define TEST_TYPE_VALUE(_type) \
+ retrieved_type = -1; \
+ g_object_set (xception, "type", _type, NULL); \
+ g_object_get (xception, "type", &retrieved_type, NULL); \
+ g_assert_cmpint (retrieved_type, ==, _type);
+
+ /* The "type" property can be set to any valid Thrift exception type */
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN_METHOD);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_MESSAGE_TYPE);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_WRONG_METHOD_NAME);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_BAD_SEQUENCE_ID);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_MISSING_RESULT);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INTERNAL_ERROR);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_PROTOCOL_ERROR);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_TRANSFORM);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_INVALID_PROTOCOL);
+ TEST_TYPE_VALUE (THRIFT_APPLICATION_EXCEPTION_ERROR_UNSUPPORTED_CLIENT_TYPE);
+
+/* "g_test_expect_message" is required for the property range tests below but is
+ not present in GLib before version 2.34 */
+#if (GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION >= 34)
+ g_object_set (xception,
+ "type", THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN,
+ NULL);
+
+ /* The "type" property cannot be set to a value too low (less than zero) */
+ g_test_expect_message ("GLib-GObject",
+ G_LOG_LEVEL_WARNING,
+ "value*out of range*type*");
+ g_object_set (xception, "type", -1, NULL);
+ g_test_assert_expected_messages ();
+
+ g_object_get (xception, "type", &retrieved_type, NULL);
+ g_assert_cmpint (retrieved_type, !=, -1);
+ g_assert_cmpint (retrieved_type,
+ ==,
+ THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN);
+
+ /* The "type" property cannot be set to a value too high (greater than the
+ highest defined exception-type value) */
+ g_test_expect_message ("GLib-GObject",
+ G_LOG_LEVEL_WARNING,
+ "value*out of range*type*");
+ g_object_set (xception, "type", THRIFT_APPLICATION_EXCEPTION_ERROR_N, NULL);
+ g_test_assert_expected_messages ();
+
+ g_object_get (xception, "type", &retrieved_type, NULL);
+ g_assert_cmpint (retrieved_type, !=, THRIFT_APPLICATION_EXCEPTION_ERROR_N);
+ g_assert_cmpint (retrieved_type,
+ ==,
+ THRIFT_APPLICATION_EXCEPTION_ERROR_UNKNOWN);
+#endif
+
+ g_object_unref (xception);
+}
+
+static void
+test_properties_message (void)
+{
+ ThriftApplicationException *xception = NULL;
+ gchar *message = "Exception message";
+ gchar *retrieved_message;
+
+ xception = g_object_new (THRIFT_TYPE_APPLICATION_EXCEPTION, NULL);
+
+ /* The "message" property can be set to NULL */
+ g_object_set (xception, "message", NULL, NULL);
+ g_object_get (xception, "message", &retrieved_message, NULL);
+ g_assert (retrieved_message == NULL);
+
+ /* The "message" property can be set to a valid string */
+ g_object_set (xception, "message", message, NULL);
+ g_object_get (xception, "message", &retrieved_message, NULL);
+ g_assert_cmpint (strcmp (retrieved_message, message), ==, 0);
+
+ g_free (retrieved_message);
+ g_object_unref (xception);
+}
+
+int
+main (int argc, char **argv)
+{
+#if (GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION < 36)
+ g_type_init ();
+#endif
+
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/testapplicationexception/CreateAndDestroy",
+ test_create_and_destroy);
+ g_test_add_func ("/testapplicationexception/Initialize",
+ test_initialize);
+ g_test_add_func ("/testapplicationexception/Properties/test",
+ test_properties_test);
+ g_test_add_func ("/testapplicationexception/Properties/message",
+ test_properties_message);
+
+ return g_test_run ();
+}