Initial Import
[profile/ivi/json-glib.git] / json-glib / tests / serialize-full.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 #include <glib-object.h>
6
7 #include <json-glib/json-glib.h>
8 #include <json-glib/json-gobject.h>
9
10 #define TEST_TYPE_ENUM                  (test_enum_get_type ())
11 #define TEST_TYPE_BOXED                 (test_boxed_get_type ())
12 #define TEST_TYPE_OBJECT                (test_object_get_type ())
13 #define TEST_OBJECT(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_OBJECT, TestObject))
14 #define TEST_IS_OBJECT(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_OBJECT))
15 #define TEST_OBJECT_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
16 #define TEST_IS_OBJECT_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
17 #define TEST_OBJECT_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
18
19 typedef enum {
20   TEST_ENUM_FOO,
21   TEST_ENUM_BAR,
22   TEST_ENUM_BAZ
23 } TestEnum;
24
25 typedef struct _TestBoxed               TestBoxed;
26 typedef struct _TestObject              TestObject;
27 typedef struct _TestObjectClass         TestObjectClass;
28
29 struct _TestBoxed
30 {
31   gint foo;
32   gboolean bar;
33 };
34
35 struct _TestObject
36 {
37   GObject parent_instance;
38
39   gint foo;
40   gboolean bar;
41   gchar *baz;
42   TestBoxed blah;
43   TestEnum meh;
44   gchar **mah;
45
46   TestObject *test;
47 };
48
49 struct _TestObjectClass
50 {
51   GObjectClass parent_class;
52 };
53
54 GType test_object_get_type (void);
55
56 /*** implementation ***/
57
58 static TestBoxed *
59 test_boxed_copy (const TestBoxed *src)
60 {
61   TestBoxed *copy = g_slice_new (TestBoxed);
62
63   *copy = *src;
64
65   return copy;
66 }
67
68 static void
69 test_boxed_free (TestBoxed *boxed)
70 {
71   if (G_LIKELY (boxed))
72     {
73       g_slice_free (TestBoxed, boxed);
74     }
75 }
76
77 GType
78 test_boxed_get_type (void)
79 {
80   static GType b_type = 0;
81
82   if (G_UNLIKELY (b_type == 0))
83     b_type = g_boxed_type_register_static ("TestBoxed",
84                                            (GBoxedCopyFunc) test_boxed_copy,
85                                            (GBoxedFreeFunc) test_boxed_free);
86
87   return b_type;
88 }
89
90 GType
91 test_enum_get_type (void)
92 {
93   static GType e_type = 0;
94
95   if (G_UNLIKELY (e_type == 0))
96     {
97       static const GEnumValue values[] = {
98         { TEST_ENUM_FOO, "TEST_ENUM_FOO", "foo" },
99         { TEST_ENUM_BAR, "TEST_ENUM_BAR", "bar" },
100         { TEST_ENUM_BAZ, "TEST_ENUM_BAZ", "baz" },
101         { 0, NULL, NULL }
102       };
103
104       e_type = g_enum_register_static ("TestEnum", values);
105     }
106
107   return e_type;
108 }
109
110 enum
111 {
112   PROP_0,
113
114   PROP_FOO,
115   PROP_BAR,
116   PROP_BAZ,
117   PROP_BLAH,
118   PROP_MEH,
119   PROP_MAH,
120   PROP_TEST
121 };
122
123 static void json_serializable_iface_init (gpointer g_iface);
124
125 G_DEFINE_TYPE_WITH_CODE (TestObject, test_object, G_TYPE_OBJECT,
126                          G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
127                                                 json_serializable_iface_init));
128
129 static JsonNode *
130 test_object_serialize_property (JsonSerializable *serializable,
131                                 const gchar      *name,
132                                 const GValue     *value,
133                                 GParamSpec       *pspec)
134 {
135   JsonNode *retval;
136
137   if (strcmp (name, "blah") == 0)
138     {
139       TestBoxed *boxed;
140       JsonObject *obj;
141
142       retval = json_node_new (JSON_NODE_OBJECT);
143       obj = json_object_new ();
144       
145       boxed = g_value_get_boxed (value);
146
147       json_object_set_int_member (obj, "foo", boxed->foo);
148       json_object_set_boolean_member (obj, "bar", boxed->bar);
149
150       json_node_take_object (retval, obj);
151
152       test_boxed_free (boxed);
153     }
154   else
155     {
156       GValue copy = { 0, };
157
158       retval = json_node_new (JSON_NODE_VALUE);
159
160       g_value_init (&copy, G_PARAM_SPEC_VALUE_TYPE (pspec));
161       g_value_copy (value, &copy);
162       json_node_set_value (retval, &copy);
163       g_value_unset (&copy);
164     }
165
166   return retval;
167 }
168
169 static void
170 json_serializable_iface_init (gpointer g_iface)
171 {
172   JsonSerializableIface *iface = g_iface;
173
174   iface->serialize_property = test_object_serialize_property;
175 }
176
177 static void
178 test_object_finalize (GObject *gobject)
179 {
180   g_free (TEST_OBJECT (gobject)->baz);
181   g_strfreev (TEST_OBJECT (gobject)->mah);
182
183   if (TEST_OBJECT (gobject)->test != NULL)
184     g_object_unref (TEST_OBJECT (gobject)->test);
185
186   G_OBJECT_CLASS (test_object_parent_class)->finalize (gobject);
187 }
188
189 static void
190 test_object_set_property (GObject      *gobject,
191                           guint         prop_id,
192                           const GValue *value,
193                           GParamSpec   *pspec)
194 {
195   switch (prop_id)
196     {
197     case PROP_FOO:
198       TEST_OBJECT (gobject)->foo = g_value_get_int (value);
199       break;
200
201     case PROP_BAR:
202       TEST_OBJECT (gobject)->bar = g_value_get_boolean (value);
203       break;
204
205     case PROP_BAZ:
206       g_free (TEST_OBJECT (gobject)->baz);
207       TEST_OBJECT (gobject)->baz = g_value_dup_string (value);
208       break;
209
210     case PROP_MEH:
211       TEST_OBJECT (gobject)->meh = g_value_get_enum (value);
212       break;
213
214     case PROP_MAH:
215       TEST_OBJECT (gobject)->mah = g_strdupv (g_value_get_boxed (value));
216       break;
217
218     case PROP_TEST:
219       TEST_OBJECT (gobject)->test = g_value_dup_object (value);
220       break;
221
222     default:
223       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
224     }
225 }
226
227 static void
228 test_object_get_property (GObject    *gobject,
229                           guint       prop_id,
230                           GValue     *value,
231                           GParamSpec *pspec)
232 {
233   switch (prop_id)
234     {
235     case PROP_FOO:
236       g_value_set_int (value, TEST_OBJECT (gobject)->foo);
237       break;
238
239     case PROP_BAR:
240       g_value_set_boolean (value, TEST_OBJECT (gobject)->bar);
241       break;
242
243     case PROP_BAZ:
244       g_value_set_string (value, TEST_OBJECT (gobject)->baz);
245       break;
246
247     case PROP_BLAH:
248       g_value_set_boxed (value, &(TEST_OBJECT (gobject)->blah));
249       break;
250
251     case PROP_MEH:
252       g_value_set_enum (value, TEST_OBJECT (gobject)->meh);
253       break;
254
255     case PROP_MAH:
256       g_value_set_boxed (value, TEST_OBJECT (gobject)->mah);
257       break;
258
259     case PROP_TEST:
260       g_value_set_object (value, TEST_OBJECT (gobject)->test);
261       break;
262
263     default:
264       G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
265     }
266 }
267
268 static void
269 test_object_class_init (TestObjectClass *klass)
270 {
271   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
272
273   gobject_class->set_property = test_object_set_property;
274   gobject_class->get_property = test_object_get_property;
275   gobject_class->finalize = test_object_finalize;
276
277   g_object_class_install_property (gobject_class,
278                                    PROP_FOO,
279                                    g_param_spec_int ("foo", "Foo", "Foo",
280                                                      0, G_MAXINT, 42,
281                                                      G_PARAM_READWRITE));
282   g_object_class_install_property (gobject_class,
283                                    PROP_BAR,
284                                    g_param_spec_boolean ("bar", "Bar", "Bar",
285                                                          FALSE,
286                                                          G_PARAM_READWRITE |
287                                                          G_PARAM_CONSTRUCT_ONLY));
288   g_object_class_install_property (gobject_class,
289                                    PROP_BAZ,
290                                    g_param_spec_string ("baz", "Baz", "Baz",
291                                                         NULL,
292                                                         G_PARAM_READWRITE));
293   g_object_class_install_property (gobject_class,
294                                    PROP_BLAH,
295                                    g_param_spec_boxed ("blah", "Blah", "Blah",
296                                                        TEST_TYPE_BOXED,
297                                                        G_PARAM_READABLE));
298   g_object_class_install_property (gobject_class,
299                                    PROP_MEH,
300                                    g_param_spec_enum ("meh", "Meh", "Meh",
301                                                       TEST_TYPE_ENUM,
302                                                       TEST_ENUM_BAR,
303                                                       G_PARAM_READWRITE |
304                                                       G_PARAM_CONSTRUCT));
305   g_object_class_install_property (gobject_class,
306                                    PROP_MAH,
307                                    g_param_spec_boxed ("mah", "Mah", "Mah",
308                                                        G_TYPE_STRV,
309                                                        G_PARAM_READWRITE));
310   g_object_class_install_property (gobject_class,
311                                    PROP_TEST,
312                                    g_param_spec_object ("test", "Test", "Test",
313                                                         TEST_TYPE_OBJECT,
314                                                         G_PARAM_READWRITE));
315 }
316
317 static void
318 test_object_init (TestObject *object)
319 {
320   object->foo = 0;
321   object->bar = FALSE;
322   object->baz = NULL; 
323
324   object->blah.foo = object->foo;
325   object->blah.bar = object->bar;
326
327   object->meh = TEST_ENUM_BAR;
328
329   object->mah = NULL;
330
331   object->test = NULL;
332 }
333
334 static const gchar *var_test =
335 "{\n"
336 "  \"foo\"  : 42,\n"
337 "  \"bar\"  : true,\n"
338 "  \"baz\"  : \"hello\",\n"
339 "  \"meh\"  : \"baz\",\n"
340 "  \"mah\"  : [ \"hello\", \", \", \"world\", \"!\" ],\n"
341 "  \"test\" : {\n"
342 "    \"bar\" : true,\n"
343 "    \"baz\" : \"world\",\n"
344 "    \"meh\" : \"foo\"\n"
345 "  }\n"
346 "}";
347
348 static void
349 test_deserialize (void)
350 {
351   TestObject *test;
352   GObject *object;
353   GError *error;
354   gchar *str;
355
356   error = NULL;
357   object = json_gobject_from_data (TEST_TYPE_OBJECT, var_test, -1, &error);
358   if (error)
359     g_error ("*** Unable to parse buffer: %s\n", error->message);
360
361   if (g_test_verbose ())
362     g_print ("*** TestObject ***\n"
363              " foo: %s\n"
364              " bar: %s\n"
365              " baz: %s\n"
366              " meh: %s\n",
367              TEST_OBJECT (object)->foo == 42            ? "<true>" : "<false>",
368              TEST_OBJECT (object)->bar == TRUE          ? "<true>" : "<false>",
369              TEST_OBJECT (object)->baz != NULL          ? "<true>" : "<false>",
370              TEST_OBJECT (object)->meh == TEST_ENUM_BAZ ? "<true>" : "<false>");
371
372   g_assert_cmpint (TEST_OBJECT (object)->foo, ==, 42);
373   g_assert (TEST_OBJECT (object)->bar);
374   g_assert_cmpstr (TEST_OBJECT (object)->baz, ==, "hello");
375   g_assert_cmpint (TEST_OBJECT (object)->meh, ==, TEST_ENUM_BAZ);
376
377   g_assert (TEST_OBJECT (object)->mah != NULL);
378   g_assert_cmpint (g_strv_length (TEST_OBJECT (object)->mah), ==, 4);
379
380   str = g_strjoinv (NULL, TEST_OBJECT (object)->mah);
381   g_assert_cmpstr (str, ==, "hello, world!");
382   g_free (str);
383
384   g_assert (TEST_IS_OBJECT (TEST_OBJECT (object)->test));
385   test = TEST_OBJECT (TEST_OBJECT (object)->test);
386   g_assert (test->bar);
387   g_assert_cmpstr (test->baz, ==, "world");
388   g_assert_cmpint (test->meh, ==, TEST_ENUM_FOO);
389
390   g_object_unref (object);
391 }
392
393 int
394 main (int   argc,
395       char *argv[])
396 {
397   g_type_init ();
398   g_test_init (&argc, &argv, NULL);
399
400   g_test_add_func ("/deserialize/json-to-gobject", test_deserialize);
401
402   return g_test_run ();
403 }