summaryrefslogtreecommitdiff
path: root/json-glib
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2011-05-28 11:05:57 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2011-05-28 11:05:57 +0100
commit4e41d26586991d2977c846fa4871b6df39fe4106 (patch)
treeba1a406fb8d29eb36d8b6df89362df92c941d57c /json-glib
parent8d98b99b945423085232d358492e97399c9fd071 (diff)
downloadjson-glib-4e41d26586991d2977c846fa4871b6df39fe4106.tar.gz
tests: Move all tests under json-glib
The test framework should live under the json-glib directory, and not be spread across the project.
Diffstat (limited to 'json-glib')
-rw-r--r--json-glib/tests/Makefile.am53
-rw-r--r--json-glib/tests/boxed.c264
-rw-r--r--json-glib/tests/serialize-complex.c293
-rw-r--r--json-glib/tests/serialize-full.c402
-rw-r--r--json-glib/tests/serialize-simple.c166
5 files changed, 1142 insertions, 36 deletions
diff --git a/json-glib/tests/Makefile.am b/json-glib/tests/Makefile.am
index defcd2f..fea656d 100644
--- a/json-glib/tests/Makefile.am
+++ b/json-glib/tests/Makefile.am
@@ -3,6 +3,8 @@ include $(top_srcdir)/build/autotools/Makefile.am.silent
NULL =
+DISTCLEANFILES =
+
INCLUDES = \
-I$(top_srcdir) \
-I$(top_srcdir)/json-glib \
@@ -10,45 +12,24 @@ INCLUDES = \
AM_CPPFLAGS = $(JSON_DEBUG_CFLAGS) -DTESTS_DATA_DIR=\""$(top_srcdir)/json-glib/tests"\"
AM_CFLAGS = -g $(JSON_CFLAGS) $(MAINTAINER_CFLAGS)
+LDADD = ../libjson-glib-1.0.la
EXTRA_DIST += stream-load.json
-DISTCLEANFILES =
-
noinst_PROGRAMS = $(TEST_PROGS)
-progs_ldadd = $(JSON_LIBS) \
- $(top_builddir)/json-glib/libjson-glib-1.0.la
-
-TEST_PROGS += array-test
-array_test_SOURCES = array-test.c
-array_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += object-test
-object_test_SOURCES = object-test.c
-object_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += node-test
-node_test_SOURCES = node-test.c
-node_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += parser-test
-parser_test_SOURCES = parser-test.c
-parser_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += generator-test
-generator_test_SOURCES = generator-test.c
-generator_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += builder-test
-builder_test_SOURCES = builder-test.c
-builder_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += reader-test
-reader_test_SOURCES = reader-test.c
-reader_test_LDADD = $(progs_ldadd)
-
-TEST_PROGS += gvariant-test
-gvariant_test_SOURCES = gvariant-test.c
-gvariant_test_LDADD = $(progs_ldadd)
+TEST_PROGS += \
+ array-test \
+ object-test \
+ node-test \
+ parser-test \
+ generator-test \
+ builder-test \
+ reader-test \
+ gvariant-test \
+ boxed \
+ serialize-simple \
+ serialize-complex \
+ serialize-full \
+ $(NULL)
-include $(top_srcdir)/build/autotools/Makefile.am.gitignore
diff --git a/json-glib/tests/boxed.c b/json-glib/tests/boxed.c
new file mode 100644
index 0000000..deeef13
--- /dev/null
+++ b/json-glib/tests/boxed.c
@@ -0,0 +1,264 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <json-glib/json-glib.h>
+#include <json-glib/json-gobject.h>
+
+#define TEST_TYPE_BOXED (test_boxed_get_type ())
+#define TEST_TYPE_OBJECT (test_object_get_type ())
+#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OBJECT, TestObject))
+#define TEST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
+#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
+
+typedef struct _TestBoxed TestBoxed;
+typedef struct _TestObject TestObject;
+typedef struct _TestObjectClass TestObjectClass;
+
+struct _TestBoxed
+{
+ gint foo;
+ gboolean bar;
+};
+
+struct _TestObject
+{
+ GObject parent_instance;
+
+ TestBoxed blah;
+};
+
+struct _TestObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType test_object_get_type (void);
+
+/*** implementation ***/
+
+static gpointer
+test_boxed_copy (gpointer src)
+{
+ return g_slice_dup (TestBoxed, src);
+}
+
+static void
+test_boxed_free (gpointer boxed)
+{
+ if (G_LIKELY (boxed != NULL))
+ g_slice_free (TestBoxed, boxed);
+}
+
+static JsonNode *
+test_boxed_serialize (gconstpointer boxed)
+{
+ const TestBoxed *test = boxed;
+ JsonObject *object;
+ JsonNode *node;
+
+ if (boxed == NULL)
+ return json_node_new (JSON_NODE_NULL);
+
+ object = json_object_new ();
+ node = json_node_new (JSON_NODE_OBJECT);
+
+ json_object_set_int_member (object, "foo", test->foo);
+ json_object_set_boolean_member (object, "bar", test->bar);
+
+ json_node_take_object (node, object);
+
+ if (g_test_verbose ())
+ {
+ g_print ("Serialize: { foo: %" G_GINT64_FORMAT ", bar: %s }\n",
+ json_object_get_int_member (object, "foo"),
+ json_object_get_boolean_member (object, "bar") ? "true" : "false");
+ }
+
+ return node;
+}
+
+static gpointer
+test_boxed_deserialize (JsonNode *node)
+{
+ JsonObject *object;
+ TestBoxed *test;
+
+ if (json_node_get_node_type (node) != JSON_NODE_OBJECT)
+ return NULL;
+
+ object = json_node_get_object (node);
+
+ test = g_slice_new (TestBoxed);
+ test->foo = json_object_get_int_member (object, "foo");
+ test->bar = json_object_get_boolean_member (object, "bar");
+
+ if (g_test_verbose ())
+ {
+ g_print ("Deserialize: { foo: %d, bar: %s }\n",
+ test->foo,
+ test->bar ? "true" : "false");
+ }
+
+ return test;
+}
+
+GType
+test_boxed_get_type (void)
+{
+ static GType b_type = 0;
+
+ if (G_UNLIKELY (b_type == 0))
+ {
+ b_type = g_boxed_type_register_static ("TestBoxed",
+ test_boxed_copy,
+ test_boxed_free);
+
+ if (g_test_verbose ())
+ g_print ("Registering transform functions\n");
+
+ json_boxed_register_serialize_func (b_type, JSON_NODE_OBJECT,
+ test_boxed_serialize);
+ json_boxed_register_deserialize_func (b_type, JSON_NODE_OBJECT,
+ test_boxed_deserialize);
+ }
+
+ return b_type;
+}
+
+enum
+{
+ PROP_0,
+
+ PROP_BLAH
+};
+
+G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
+
+static void
+test_object_finalize (GObject *gobject)
+{
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
+}
+
+static void
+test_object_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_BLAH:
+ {
+ const TestBoxed *blah = g_value_get_boxed (value);
+
+ TEST_OBJECT (gobject)->blah = *blah;
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_BLAH:
+ g_value_set_boxed (value, &(TEST_OBJECT (gobject)->blah));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_class_init (TestObjectClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = test_object_set_property;
+ gobject_class->get_property = test_object_get_property;
+ gobject_class->finalize = test_object_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_BLAH,
+ g_param_spec_boxed ("blah", "Blah", "Blah",
+ TEST_TYPE_BOXED,
+ G_PARAM_READWRITE));
+}
+
+static void
+test_object_init (TestObject *object)
+{
+ object->blah.foo = 0;
+ object->blah.bar = FALSE;
+}
+
+static const gchar *serialize_data =
+"{\n"
+" \"blah\" : {\n"
+" \"foo\" : 42,\n"
+" \"bar\" : true\n"
+" }\n"
+"}";
+
+static void
+test_serialize_boxed (void)
+{
+ TestBoxed boxed = { 42, TRUE };
+ GObject *obj;
+ gchar *data;
+ gsize len;
+
+ obj = g_object_new (TEST_TYPE_OBJECT, "blah", &boxed, NULL);
+
+ data = json_gobject_to_data (obj, &len);
+
+ g_assert_cmpint (len, ==, strlen (serialize_data));
+ g_assert_cmpstr (data, ==, serialize_data);
+
+ if (g_test_verbose ())
+ g_print ("TestObject:\n%s\n", data);
+
+ g_free (data);
+ g_object_unref (obj);
+}
+
+static void
+test_deserialize_boxed (void)
+{
+
+ GObject *obj;
+
+ obj = json_gobject_from_data (TEST_TYPE_OBJECT, serialize_data, -1, NULL);
+ g_assert (TEST_IS_OBJECT (obj));
+ g_assert_cmpint (TEST_OBJECT (obj)->blah.foo, ==, 42);
+ g_assert (TEST_OBJECT (obj)->blah.bar);
+
+ g_object_unref (obj);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/boxed/serialize-property", test_serialize_boxed);
+ g_test_add_func ("/boxed/deserialize-property", test_deserialize_boxed);
+
+ return g_test_run ();
+}
diff --git a/json-glib/tests/serialize-complex.c b/json-glib/tests/serialize-complex.c
new file mode 100644
index 0000000..f577761
--- /dev/null
+++ b/json-glib/tests/serialize-complex.c
@@ -0,0 +1,293 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <json-glib/json-glib.h>
+#include <json-glib/json-gobject.h>
+
+#define TEST_TYPE_BOXED (test_boxed_get_type ())
+#define TEST_TYPE_OBJECT (test_object_get_type ())
+#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OBJECT, TestObject))
+#define TEST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
+#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
+
+typedef struct _TestBoxed TestBoxed;
+typedef struct _TestObject TestObject;
+typedef struct _TestObjectClass TestObjectClass;
+
+struct _TestBoxed
+{
+ gint foo;
+ gboolean bar;
+};
+
+struct _TestObject
+{
+ GObject parent_instance;
+
+ gint foo;
+ gboolean bar;
+ gchar *baz;
+ TestBoxed blah;
+};
+
+struct _TestObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType test_object_get_type (void);
+
+/*** implementation ***/
+
+static TestBoxed *
+test_boxed_copy (const TestBoxed *src)
+{
+ TestBoxed *copy = g_slice_new (TestBoxed);
+
+ *copy = *src;
+
+ return copy;
+}
+
+static void
+test_boxed_free (TestBoxed *boxed)
+{
+ if (G_LIKELY (boxed))
+ {
+ g_slice_free (TestBoxed, boxed);
+ }
+}
+
+GType
+test_boxed_get_type (void)
+{
+ static GType b_type = 0;
+
+ if (G_UNLIKELY (b_type == 0))
+ b_type = g_boxed_type_register_static ("TestBoxed",
+ (GBoxedCopyFunc) test_boxed_copy,
+ (GBoxedFreeFunc) test_boxed_free);
+
+ return b_type;
+}
+
+enum
+{
+ PROP_0,
+
+ PROP_FOO,
+ PROP_BAR,
+ PROP_BAZ,
+ PROP_BLAH
+};
+
+static JsonSerializableIface *serializable_iface = NULL;
+
+static void json_serializable_iface_init (gpointer g_iface);
+
+G_DEFINE_TYPE_WITH_CODE (TestObject, test_object, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
+ json_serializable_iface_init));
+
+static JsonNode *
+test_object_serialize_property (JsonSerializable *serializable,
+ const gchar *name,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ JsonNode *retval = NULL;
+
+ if (strcmp (name, "blah") == 0)
+ {
+ TestBoxed *boxed;
+ JsonObject *obj;
+ JsonNode *val;
+
+ retval = json_node_new (JSON_NODE_OBJECT);
+ obj = json_object_new ();
+
+ boxed = g_value_get_boxed (value);
+
+ val = json_node_new (JSON_NODE_VALUE);
+ json_node_set_int (val, boxed->foo);
+ json_object_set_member (obj, "foo", val);
+
+ val = json_node_new (JSON_NODE_VALUE);
+ json_node_set_boolean (val, boxed->bar);
+ json_object_set_member (obj, "bar", val);
+
+ json_node_take_object (retval, obj);
+ }
+ else
+ retval = serializable_iface->serialize_property (serializable,
+ name,
+ value, pspec);
+
+ return retval;
+}
+
+static void
+json_serializable_iface_init (gpointer g_iface)
+{
+ JsonSerializableIface *iface = g_iface;
+
+ serializable_iface = g_type_default_interface_peek (JSON_TYPE_SERIALIZABLE);
+
+ iface->serialize_property = test_object_serialize_property;
+}
+
+static void
+test_object_finalize (GObject *gobject)
+{
+ g_free (TEST_OBJECT (gobject)->baz);
+
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
+}
+
+static void
+test_object_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ TEST_OBJECT (gobject)->foo = g_value_get_int (value);
+ break;
+ case PROP_BAR:
+ TEST_OBJECT (gobject)->bar = g_value_get_boolean (value);
+ break;
+ case PROP_BAZ:
+ g_free (TEST_OBJECT (gobject)->baz);
+ TEST_OBJECT (gobject)->baz = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ g_value_set_int (value, TEST_OBJECT (gobject)->foo);
+ break;
+ case PROP_BAR:
+ g_value_set_boolean (value, TEST_OBJECT (gobject)->bar);
+ break;
+ case PROP_BAZ:
+ g_value_set_string (value, TEST_OBJECT (gobject)->baz);
+ break;
+ case PROP_BLAH:
+ g_value_set_boxed (value, &(TEST_OBJECT (gobject)->blah));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_class_init (TestObjectClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = test_object_set_property;
+ gobject_class->get_property = test_object_get_property;
+ gobject_class->finalize = test_object_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_FOO,
+ g_param_spec_int ("foo", "Foo", "Foo",
+ 0, G_MAXINT, 42,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BAR,
+ g_param_spec_boolean ("bar", "Bar", "Bar",
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BAZ,
+ g_param_spec_string ("baz", "Baz", "Baz",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BLAH,
+ g_param_spec_boxed ("blah", "Blah", "Blah",
+ TEST_TYPE_BOXED,
+ G_PARAM_READABLE));
+}
+
+static void
+test_object_init (TestObject *object)
+{
+ object->foo = 42;
+ object->bar = TRUE;
+ object->baz = g_strdup ("Test");
+
+ object->blah.foo = object->foo;
+ object->blah.bar = object->bar;
+}
+
+static void
+test_serialize (void)
+{
+ TestObject *obj = g_object_new (TEST_TYPE_OBJECT, NULL);
+ JsonParser *parser = json_parser_new ();
+ GError *error = NULL;
+ JsonObject *object;
+ JsonNode *node;
+ gchar *data;
+ gsize len;
+
+ data = json_gobject_to_data (G_OBJECT (obj), &len);
+
+ g_assert_cmpint (len, >, 0);
+ if (g_test_verbose ())
+ g_print ("TestObject:\n%s\n", data);
+
+ parser = json_parser_new ();
+ json_parser_load_from_data (parser, data, -1, &error);
+ g_assert (error == NULL);
+
+ node = json_parser_get_root (parser);
+ g_assert (json_node_get_node_type (node) == JSON_NODE_OBJECT);
+
+ object = json_node_get_object (node);
+ g_assert_cmpint (json_object_get_int_member (object, "foo"), ==, 42);
+ g_assert (json_object_get_boolean_member (object, "bar"));
+ g_assert_cmpstr (json_object_get_string_member (object, "baz"), ==, "Test");
+
+ node = json_object_get_member (object, "blah");
+ g_assert (json_node_get_node_type (node) == JSON_NODE_OBJECT);
+
+ object = json_node_get_object (node);
+ g_assert_cmpint (json_object_get_int_member (object, "foo"), ==, 42);
+ g_assert (json_object_get_boolean_member (object, "bar"));
+
+ g_free (data);
+ g_object_unref (parser);
+ g_object_unref (obj);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/serialize/gobject-boxed", test_serialize);
+
+ return g_test_run ();
+}
diff --git a/json-glib/tests/serialize-full.c b/json-glib/tests/serialize-full.c
new file mode 100644
index 0000000..704fb18
--- /dev/null
+++ b/json-glib/tests/serialize-full.c
@@ -0,0 +1,402 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <json-glib/json-glib.h>
+#include <json-glib/json-gobject.h>
+
+#define TEST_TYPE_ENUM (test_enum_get_type ())
+#define TEST_TYPE_BOXED (test_boxed_get_type ())
+#define TEST_TYPE_OBJECT (test_object_get_type ())
+#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OBJECT, TestObject))
+#define TEST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
+#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
+
+typedef enum {
+ TEST_ENUM_FOO,
+ TEST_ENUM_BAR,
+ TEST_ENUM_BAZ
+} TestEnum;
+
+typedef struct _TestBoxed TestBoxed;
+typedef struct _TestObject TestObject;
+typedef struct _TestObjectClass TestObjectClass;
+
+struct _TestBoxed
+{
+ gint foo;
+ gboolean bar;
+};
+
+struct _TestObject
+{
+ GObject parent_instance;
+
+ gint foo;
+ gboolean bar;
+ gchar *baz;
+ TestBoxed blah;
+ TestEnum meh;
+ gchar **mah;
+
+ TestObject *test;
+};
+
+struct _TestObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType test_object_get_type (void);
+
+/*** implementation ***/
+
+static TestBoxed *
+test_boxed_copy (const TestBoxed *src)
+{
+ TestBoxed *copy = g_slice_new (TestBoxed);
+
+ *copy = *src;
+
+ return copy;
+}
+
+static void
+test_boxed_free (TestBoxed *boxed)
+{
+ if (G_LIKELY (boxed))
+ {
+ g_slice_free (TestBoxed, boxed);
+ }
+}
+
+GType
+test_boxed_get_type (void)
+{
+ static GType b_type = 0;
+
+ if (G_UNLIKELY (b_type == 0))
+ b_type = g_boxed_type_register_static ("TestBoxed",
+ (GBoxedCopyFunc) test_boxed_copy,
+ (GBoxedFreeFunc) test_boxed_free);
+
+ return b_type;
+}
+
+GType
+test_enum_get_type (void)
+{
+ static GType e_type = 0;
+
+ if (G_UNLIKELY (e_type == 0))
+ {
+ static const GEnumValue values[] = {
+ { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
+ { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
+ { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
+ { 0, NULL, NULL }
+ };
+
+ e_type = g_enum_register_static ("TestEnum", values);
+ }
+
+ return e_type;
+}
+
+enum
+{
+ PROP_0,
+
+ PROP_FOO,
+ PROP_BAR,
+ PROP_BAZ,
+ PROP_BLAH,
+ PROP_MEH,
+ PROP_MAH,
+ PROP_TEST
+};
+
+static void json_serializable_iface_init (gpointer g_iface);
+
+G_DEFINE_TYPE_WITH_CODE (TestObject, test_object, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
+ json_serializable_iface_init));
+
+static JsonNode *
+test_object_serialize_property (JsonSerializable *serializable,
+ const gchar *name,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ JsonNode *retval;
+
+ if (strcmp (name, "blah") == 0)
+ {
+ TestBoxed *boxed;
+ JsonObject *obj;
+
+ retval = json_node_new (JSON_NODE_OBJECT);
+ obj = json_object_new ();
+
+ boxed = g_value_get_boxed (value);
+
+ json_object_set_int_member (obj, "foo", boxed->foo);
+ json_object_set_boolean_member (obj, "bar", boxed->bar);
+
+ json_node_take_object (retval, obj);
+
+ test_boxed_free (boxed);
+ }
+ else
+ {
+ GValue copy = { 0, };
+
+ retval = json_node_new (JSON_NODE_VALUE);
+
+ g_value_init (&copy, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_value_copy (value, &copy);
+ json_node_set_value (retval, &copy);
+ g_value_unset (&copy);
+ }
+
+ return retval;
+}
+
+static void
+json_serializable_iface_init (gpointer g_iface)
+{
+ JsonSerializableIface *iface = g_iface;
+
+ iface->serialize_property = test_object_serialize_property;
+}
+
+static void
+test_object_finalize (GObject *gobject)
+{
+ g_free (TEST_OBJECT (gobject)->baz);
+ g_strfreev (TEST_OBJECT (gobject)->mah);
+
+ if (TEST_OBJECT (gobject)->test != NULL)
+ g_object_unref (TEST_OBJECT (gobject)->test);
+
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
+}
+
+static void
+test_object_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ TEST_OBJECT (gobject)->foo = g_value_get_int (value);
+ break;
+
+ case PROP_BAR:
+ TEST_OBJECT (gobject)->bar = g_value_get_boolean (value);
+ break;
+
+ case PROP_BAZ:
+ g_free (TEST_OBJECT (gobject)->baz);
+ TEST_OBJECT (gobject)->baz = g_value_dup_string (value);
+ break;
+
+ case PROP_MEH:
+ TEST_OBJECT (gobject)->meh = g_value_get_enum (value);
+ break;
+
+ case PROP_MAH:
+ TEST_OBJECT (gobject)->mah = g_strdupv (g_value_get_boxed (value));
+ break;
+
+ case PROP_TEST:
+ TEST_OBJECT (gobject)->test = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ g_value_set_int (value, TEST_OBJECT (gobject)->foo);
+ break;
+
+ case PROP_BAR:
+ g_value_set_boolean (value, TEST_OBJECT (gobject)->bar);
+ break;
+
+ case PROP_BAZ:
+ g_value_set_string (value, TEST_OBJECT (gobject)->baz);
+ break;
+
+ case PROP_BLAH:
+ g_value_set_boxed (value, &(TEST_OBJECT (gobject)->blah));
+ break;
+
+ case PROP_MEH:
+ g_value_set_enum (value, TEST_OBJECT (gobject)->meh);
+ break;
+
+ case PROP_MAH:
+ g_value_set_boxed (value, TEST_OBJECT (gobject)->mah);
+ break;
+
+ case PROP_TEST:
+ g_value_set_object (value, TEST_OBJECT (gobject)->test);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_class_init (TestObjectClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = test_object_set_property;
+ gobject_class->get_property = test_object_get_property;
+ gobject_class->finalize = test_object_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_FOO,
+ g_param_spec_int ("foo", "Foo", "Foo",
+ 0, G_MAXINT, 42,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BAR,
+ g_param_spec_boolean ("bar", "Bar", "Bar",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (gobject_class,
+ PROP_BAZ,
+ g_param_spec_string ("baz", "Baz", "Baz",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BLAH,
+ g_param_spec_boxed ("blah", "Blah", "Blah",
+ TEST_TYPE_BOXED,
+ G_PARAM_READABLE));
+ g_object_class_install_property (gobject_class,
+ PROP_MEH,
+ g_param_spec_enum ("meh", "Meh", "Meh",
+ TEST_TYPE_ENUM,
+ TEST_ENUM_BAR,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_MAH,
+ g_param_spec_boxed ("mah", "Mah", "Mah",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_TEST,
+ g_param_spec_object ("test", "Test", "Test",
+ TEST_TYPE_OBJECT,
+ G_PARAM_READWRITE));
+}
+
+static void
+test_object_init (TestObject *object)
+{
+ object->foo = 0;
+ object->bar = FALSE;
+ object->baz = NULL;
+
+ object->blah.foo = object->foo;
+ object->blah.bar = object->bar;
+
+ object->meh = TEST_ENUM_BAR;
+
+ object->mah = NULL;
+
+ object->test = NULL;
+}
+
+static const gchar *var_test =
+"{\n"
+" \"foo\" : 42,\n"
+" \"bar\" : true,\n"
+" \"baz\" : \"hello\",\n"
+" \"meh\" : \"baz\",\n"
+" \"mah\" : [ \"hello\", \", \", \"world\", \"!\" ],\n"
+" \"test\" : {\n"
+" \"bar\" : true,\n"
+" \"baz\" : \"world\",\n"
+" \"meh\" : \"foo\"\n"
+" }\n"
+"}";
+
+static void
+test_deserialize (void)
+{
+ TestObject *test;
+ GObject *object;
+ GError *error;
+ gchar *str;
+
+ error = NULL;
+ object = json_gobject_from_data (TEST_TYPE_OBJECT, var_test, -1, &error);
+ if (error)
+ g_error ("*** Unable to parse buffer: %s\n", error->message);
+
+ if (g_test_verbose ())
+ g_print ("*** TestObject ***\n"
+ " foo: %s\n"
+ " bar: %s\n"
+ " baz: %s\n"
+ " meh: %s\n",
+ TEST_OBJECT (object)->foo == 42 ? "<true>" : "<false>",
+ TEST_OBJECT (object)->bar == TRUE ? "<true>" : "<false>",
+ TEST_OBJECT (object)->baz != NULL ? "<true>" : "<false>",
+ TEST_OBJECT (object)->meh == TEST_ENUM_BAZ ? "<true>" : "<false>");
+
+ g_assert_cmpint (TEST_OBJECT (object)->foo, ==, 42);
+ g_assert (TEST_OBJECT (object)->bar);
+ g_assert_cmpstr (TEST_OBJECT (object)->baz, ==, "hello");
+ g_assert_cmpint (TEST_OBJECT (object)->meh, ==, TEST_ENUM_BAZ);
+
+ g_assert (TEST_OBJECT (object)->mah != NULL);
+ g_assert_cmpint (g_strv_length (TEST_OBJECT (object)->mah), ==, 4);
+
+ str = g_strjoinv (NULL, TEST_OBJECT (object)->mah);
+ g_assert_cmpstr (str, ==, "hello, world!");
+ g_free (str);
+
+ g_assert (TEST_IS_OBJECT (TEST_OBJECT (object)->test));
+ test = TEST_OBJECT (TEST_OBJECT (object)->test);
+ g_assert (test->bar);
+ g_assert_cmpstr (test->baz, ==, "world");
+ g_assert_cmpint (test->meh, ==, TEST_ENUM_FOO);
+
+ g_object_unref (object);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/deserialize/json-to-gobject", test_deserialize);
+
+ return g_test_run ();
+}
diff --git a/json-glib/tests/serialize-simple.c b/json-glib/tests/serialize-simple.c
new file mode 100644
index 0000000..42af6fb
--- /dev/null
+++ b/json-glib/tests/serialize-simple.c
@@ -0,0 +1,166 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <glib-object.h>
+
+#include <json-glib/json-glib.h>
+#include <json-glib/json-gobject.h>
+
+#define TEST_TYPE_OBJECT (test_object_get_type ())
+#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OBJECT, TestObject))
+#define TEST_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
+#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
+#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
+
+typedef struct _TestObject TestObject;
+typedef struct _TestObjectClass TestObjectClass;
+
+struct _TestObject
+{
+ GObject parent_instance;
+
+ gint foo;
+ gboolean bar;
+ gchar *baz;
+};
+
+struct _TestObjectClass
+{
+ GObjectClass parent_class;
+};
+
+GType test_object_get_type (void);
+
+/*** implementation ***/
+
+enum
+{
+ PROP_0,
+
+ PROP_FOO,
+ PROP_BAR,
+ PROP_BAZ
+};
+
+G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT);
+
+static void
+test_object_finalize (GObject *gobject)
+{
+ g_free (TEST_OBJECT (gobject)->baz);
+
+ G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
+}
+
+static void
+test_object_set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ TEST_OBJECT (gobject)->foo = g_value_get_int (value);
+ break;
+ case PROP_BAR:
+ TEST_OBJECT (gobject)->bar = g_value_get_boolean (value);
+ break;
+ case PROP_BAZ:
+ g_free (TEST_OBJECT (gobject)->baz);
+ TEST_OBJECT (gobject)->baz = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (prop_id)
+ {
+ case PROP_FOO:
+ g_value_set_int (value, TEST_OBJECT (gobject)->foo);
+ break;
+ case PROP_BAR:
+ g_value_set_boolean (value, TEST_OBJECT (gobject)->bar);
+ break;
+ case PROP_BAZ:
+ g_value_set_string (value, TEST_OBJECT (gobject)->baz);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+ }
+}
+
+static void
+test_object_class_init (TestObjectClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->set_property = test_object_set_property;
+ gobject_class->get_property = test_object_get_property;
+ gobject_class->finalize = test_object_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_FOO,
+ g_param_spec_int ("foo", "Foo", "Foo",
+ 0, G_MAXINT, 42,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BAR,
+ g_param_spec_boolean ("bar", "Bar", "Bar",
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_BAZ,
+ g_param_spec_string ("baz", "Baz", "Baz",
+ NULL,
+ G_PARAM_READWRITE));
+}
+
+static void
+test_object_init (TestObject *object)
+{
+ object->foo = 42;
+ object->bar = FALSE;
+ object->baz = g_strdup ("Test");
+}
+
+static void
+test_serialize (void)
+{
+ TestObject *obj = g_object_new (TEST_TYPE_OBJECT, "bar", TRUE, NULL);
+ gchar *data;
+ gsize len;
+
+ data = json_gobject_to_data (G_OBJECT (obj), &len);
+
+ g_assert (data != NULL);
+ g_assert_cmpint (len, >, 0);
+ g_assert_cmpint (len, ==, strlen (data));
+
+ if (g_test_verbose ())
+ g_print ("TestObject:\n%s\n", data);
+
+ g_free (data);
+ g_object_unref (obj);
+}
+
+int
+main (int argc,
+ char *argv[])
+{
+ g_type_init ();
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/serialize/gobject", test_serialize);
+
+ return g_test_run ();
+}