1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <math.h>
21 #include <string.h>
22 #include <glib-object.h>
23 
24 #ifndef M_PI
25 #define M_PI 3.1415926535897932385
26 #endif
27 
28 #include <thrift/c_glib/protocol/thrift_protocol.h>
29 #include <thrift/c_glib/protocol/thrift_binary_protocol.h>
30 
31 #include "gen-c_glib/t_test_debug_proto_test_types.h"
32 #include "gen-c_glib/t_test_srv.h"
33 #include "gen-c_glib/t_test_inherited.h"
34 
35 static void
test_structs_doubles_create_and_destroy(void)36 test_structs_doubles_create_and_destroy (void)
37 {
38   GObject *object = NULL;
39 
40   /* A Doubles structure can be created... */
41   object = g_object_new (T_TEST_TYPE_DOUBLES, NULL);
42 
43   g_assert (object != NULL);
44   g_assert (T_TEST_IS_DOUBLES (object));
45 
46   /* ...and destroyed */
47   g_object_unref (object);
48 }
49 
50 static void
test_structs_doubles_initialize(void)51 test_structs_doubles_initialize (void)
52 {
53   TTestDoubles *doubles = NULL;
54   gdouble nan;
55   gdouble inf;
56   gdouble neginf;
57   gdouble repeating;
58   gdouble big;
59   gdouble tiny;
60   gdouble zero;
61   gdouble negzero;
62 
63   /* Note there seems to be no way to get not-a-number ("NAN") values past
64      GObject's range-checking, so that portion of the test has been commented
65      out below. */
66 
67   /* A Doubles structure's members are available as GObject properties
68      that can be initialized at construction... */
69   doubles = g_object_new (T_TEST_TYPE_DOUBLES,
70                           /* "nan",      0 * INFINITY, */
71                           "inf",          INFINITY,
72                           "neginf",      -INFINITY,
73                           "repeating",     1.0 / 3,
74                           "big",       G_MAXDOUBLE,
75                           "tiny",          10E-101,
76                           "zero",          1.0 * 0,
77                           "negzero",      -1.0 * 0,
78                           NULL);
79 
80   g_assert (doubles != NULL);
81 
82   /* ...and later retrieved */
83   g_object_get (doubles,
84                 "nan",       &nan,
85                 "inf",       &inf,
86                 "neginf",    &neginf,
87                 "repeating", &repeating,
88                 "big",       &big,
89                 "tiny",      &tiny,
90                 "zero",      &zero,
91                 "negzero",   &negzero,
92                 NULL);
93 
94   /* g_assert_cmpint (isnan (nan),    !=,  0); */
95   g_assert_cmpint (isinf (inf),    ==,  1);
96   g_assert_cmpint (isinf (neginf), ==, -1);
97 
98   g_assert_cmpfloat (repeating, ==,     1.0 / 3);
99   g_assert_cmpfloat (big,       ==, G_MAXDOUBLE);
100   g_assert_cmpfloat (tiny,      ==,     10E-101);
101   g_assert_cmpfloat (zero,      ==,     1.0 * 0);
102   g_assert_cmpfloat (negzero,   ==,    -1.0 * 0);
103 
104   g_object_unref (doubles);
105 }
106 
107 static void
test_structs_one_of_each_create_and_destroy(void)108 test_structs_one_of_each_create_and_destroy (void)
109 {
110   GObject *object = NULL;
111 
112   /* A OneOfEach structure can be created... */
113   object = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL);
114 
115   g_assert (object != NULL);
116   g_assert (T_TEST_IS_ONE_OF_EACH (object));
117 
118   /* ...and destroyed */
119   g_object_unref (object);
120 }
121 
122 static void
test_structs_one_of_each_initialize_default_values(void)123 test_structs_one_of_each_initialize_default_values (void)
124 {
125   TTestOneOfEach *one_of_each = NULL;
126   gint   a_bite;
127   gint   integer16;
128   gint64 integer64;
129   GArray *byte_list;
130   GArray *i16_list;
131   GArray *i64_list;
132 
133   /* A OneOfEach structure created with no explicit property values
134      will hold the default values specified in the .thrift file */
135   one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL);
136 
137   g_object_get (one_of_each,
138                 "a_bite",    &a_bite,
139                 "integer16", &integer16,
140                 "integer64", &integer64,
141                 "byte_list", &byte_list,
142                 "i16_list",  &i16_list,
143                 "i64_list",  &i64_list,
144                 NULL);
145 
146   g_assert_cmpint (a_bite,    ==, 0x7f);
147   g_assert_cmpint (integer16, ==, 0x7fff);
148   g_assert_cmpint (integer64, ==, G_GINT64_CONSTANT (10000000000));
149 
150   g_assert (byte_list != NULL);
151   g_assert_cmpint (byte_list->len, ==, 3);
152   g_assert_cmpint (g_array_index (byte_list, gint8, 0), ==, 1);
153   g_assert_cmpint (g_array_index (byte_list, gint8, 1), ==, 2);
154   g_assert_cmpint (g_array_index (byte_list, gint8, 2), ==, 3);
155 
156   g_assert (i16_list != NULL);
157   g_assert_cmpint (i16_list->len, ==, 3);
158   g_assert_cmpint (g_array_index (i16_list, gint16, 0), ==, 1);
159   g_assert_cmpint (g_array_index (i16_list, gint16, 1), ==, 2);
160   g_assert_cmpint (g_array_index (i16_list, gint16, 2), ==, 3);
161 
162   g_assert (i64_list != NULL);
163   g_assert_cmpint (i64_list->len, ==, 3);
164   g_assert_cmpint (g_array_index (i64_list, gint64, 0), ==, 1);
165   g_assert_cmpint (g_array_index (i64_list, gint64, 1), ==, 2);
166   g_assert_cmpint (g_array_index (i64_list, gint64, 2), ==, 3);
167 
168   g_array_unref (i64_list);
169   g_array_unref (i16_list);
170   g_array_unref (byte_list);
171   g_object_unref (one_of_each);
172 }
173 
174 static void
test_structs_one_of_each_initialize_specified_values(void)175 test_structs_one_of_each_initialize_specified_values (void)
176 {
177   static const gint8 initial_byte_list[5] = { 13, 21, 34, 55, 89 };
178   static const gint16 initial_i16_list[5] = { 4181, 6765, 10946, 17711, 28657 };
179   static const gint64 initial_i64_list[5] =
180     {
181       G_GINT64_CONSTANT (1100087778366101931),
182       G_GINT64_CONSTANT (1779979416004714189),
183       G_GINT64_CONSTANT (2880067194370816120),
184       G_GINT64_CONSTANT (4660046610375530309),
185       G_GINT64_CONSTANT (7540113804746346429)
186     };
187   static const guint8 initial_base64[8] =
188     {
189       0x56, 0x47, 0x68, 0x79, 0x61, 0x57, 0x5a, 0x30
190     };
191 
192   TTestOneOfEach *one_of_each;
193   gboolean im_true;
194   gboolean im_false;
195   gint a_bite;
196   gint integer16;
197   gint integer32;
198   gint64 integer64;
199   double double_precision;
200   gchar *some_characters;
201   gchar *zomg_unicode;
202   gboolean what_who;
203   GByteArray *base64;
204   GArray *byte_list;
205   GArray *i16_list;
206   GArray *i64_list;
207 
208   base64 = g_byte_array_new ();
209   g_byte_array_append (base64, initial_base64, 8);
210 
211   byte_list = g_array_new (FALSE, FALSE, sizeof (gint8));
212   g_array_append_vals (byte_list, initial_byte_list, 5);
213 
214   i16_list = g_array_new (FALSE, FALSE, sizeof (gint16));
215   g_array_append_vals (i16_list, initial_i16_list, 5);
216 
217   i64_list = g_array_new (FALSE, FALSE, sizeof (gint64));
218   g_array_append_vals (i64_list, initial_i64_list, 5);
219 
220   /* All of OneOfEach's properties can be set at construction... */
221   one_of_each =
222     g_object_new (T_TEST_TYPE_ONE_OF_EACH,
223                   "im_true",          TRUE,
224                   "im_false",         FALSE,
225                   "a_bite",           0x50,
226                   "integer16",        0x7e57,
227                   "integer32",        0xdeadbeef,
228                   "integer64",        G_GINT64_CONSTANT (0xfa15efacade15bad),
229                   "double_precision", M_PI,
230                   "some_characters",  "Debug THIS!",
231                   "zomg_unicode",     "\xd7\n\a\t",
232                   "what_who",         TRUE,
233                   "base64",           base64,
234                   "byte_list",        byte_list,
235                   "i16_list",         i16_list,
236                   "i64_list",         i64_list,
237                   NULL);
238   g_assert (one_of_each != NULL);
239 
240   g_array_unref (i64_list);
241   i64_list = NULL;
242   g_array_unref (i16_list);
243   i16_list = NULL;
244   g_array_unref (byte_list);
245   byte_list = NULL;
246   g_byte_array_unref (base64);
247   base64 = NULL;
248 
249   /* ...and later retrieved */
250   g_object_get (one_of_each,
251                 "im_true",          &im_true,
252                 "im_false",         &im_false,
253                 "a_bite",           &a_bite,
254                 "integer16",        &integer16,
255                 "integer32",        &integer32,
256                 "integer64",        &integer64,
257                 "double_precision", &double_precision,
258                 "some_characters",  &some_characters,
259                 "zomg_unicode",     &zomg_unicode,
260                 "what_who",         &what_who,
261                 "base64",           &base64,
262                 "byte_list",        &byte_list,
263                 "i16_list",         &i16_list,
264                 "i64_list",         &i64_list,
265                 NULL);
266 
267   g_assert (im_true  == TRUE);
268   g_assert (im_false == FALSE);
269 
270   g_assert_cmphex (a_bite,    ==, 0x50);
271   g_assert_cmphex (integer16, ==, 0x7e57);
272   g_assert_cmphex (integer32, ==, (gint32)0xdeadbeef);
273   g_assert_cmphex (integer64, ==, G_GINT64_CONSTANT (0xfa15efacade15bad));
274 
275   g_assert_cmpfloat (double_precision, ==, M_PI);
276 
277   g_assert_cmpstr (some_characters, ==, "Debug THIS!");
278   g_assert_cmpstr (zomg_unicode,    ==, "\xd7\n\a\t");
279 
280   g_assert (what_who == TRUE);
281 
282   g_assert_cmpint (base64->len, ==, 8);
283   g_assert_cmpint (memcmp (base64->data,
284                            initial_base64,
285                            8 * sizeof (guint8)), ==, 0);
286 
287   g_assert_cmpint (byte_list->len, ==, 5);
288   g_assert_cmpint (memcmp (byte_list->data,
289                            initial_byte_list,
290                            5 * sizeof (gint8)),  ==, 0);
291 
292   g_assert_cmpint (i16_list->len, ==, 5);
293   g_assert_cmpint (memcmp (i16_list->data,
294                            initial_i16_list,
295                            5 * sizeof (gint16)), ==, 0);
296 
297   g_assert_cmpint (i64_list->len, ==, 5);
298   g_assert_cmpint (memcmp (i64_list->data,
299                            initial_i64_list,
300                            5 * sizeof (gint64)), ==, 0);
301 
302   g_array_unref (i64_list);
303   g_array_unref (i16_list);
304   g_array_unref (byte_list);
305   g_byte_array_unref (base64);
306 
307   g_object_unref (one_of_each);
308 }
309 
310 static void
test_structs_one_of_each_properties_byte_list(void)311 test_structs_one_of_each_properties_byte_list (void)
312 {
313   TTestOneOfEach *one_of_each;
314   GArray *byte_list = NULL;
315 
316   one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL);
317 
318   /* OneOfEach's "byte_list" member is a list that holds eight-bit-wide integer
319      values */
320   g_object_get (one_of_each, "byte_list", &byte_list, NULL);
321 
322   g_assert (byte_list != NULL);
323   g_assert_cmpint (g_array_get_element_size (byte_list), ==, sizeof (gint8));
324 
325   g_array_unref (byte_list);
326   g_object_unref (one_of_each);
327 }
328 
329 static void
test_structs_one_of_each_properties_i16_list(void)330 test_structs_one_of_each_properties_i16_list (void)
331 {
332   TTestOneOfEach *one_of_each;
333   GArray *i16_list = NULL;
334 
335   one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL);
336 
337   /* OneOfEach's "i16_list" member is a list that holds sixteen-bit-wide integer
338      values */
339   g_object_get (one_of_each, "i16_list", &i16_list, NULL);
340 
341   g_assert (i16_list != NULL);
342   g_assert_cmpint (g_array_get_element_size (i16_list), ==, sizeof (gint16));
343 
344   g_array_unref (i16_list);
345   g_object_unref (one_of_each);
346 }
347 
348 static void
test_structs_one_of_each_properties_i64_list(void)349 test_structs_one_of_each_properties_i64_list (void)
350 {
351   TTestOneOfEach *one_of_each;
352   GArray *i64_list = NULL;
353 
354   one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH, NULL);
355 
356   /* OneOfEach's "i64_list" member is a list that holds sixty-four-bit-wide
357      integer values */
358   g_object_get (one_of_each, "i64_list", &i64_list, NULL);
359 
360   g_assert (i64_list != NULL);
361   g_assert_cmpint (g_array_get_element_size (i64_list), ==, sizeof (gint64));
362 
363   g_array_unref (i64_list);
364   g_object_unref (one_of_each);
365 }
366 
367 static void
test_structs_nesting_create_and_destroy(void)368 test_structs_nesting_create_and_destroy (void)
369 {
370   GObject *object = NULL;
371 
372   /* A Nesting structure can be created... */
373   object = g_object_new (T_TEST_TYPE_NESTING, NULL);
374 
375   g_assert (object != NULL);
376   g_assert (T_TEST_IS_NESTING (object));
377 
378   /* ...and destroyed */
379   g_object_unref (object);
380 }
381 
382 static void
test_structs_nesting_properties_my_bonk(void)383 test_structs_nesting_properties_my_bonk (void)
384 {
385   TTestNesting *nesting;
386   TTestBonk *bonk = NULL;
387   gint type;
388   gchar *message;
389 
390   nesting = g_object_new (T_TEST_TYPE_NESTING, NULL);
391 
392   /* Nesting's "my_bonk" member is initialized with a new, default Bonk object
393      during construction */
394   g_object_get (nesting, "my_bonk", &bonk, NULL);
395 
396   g_assert (bonk != NULL);
397   g_assert (T_TEST_IS_BONK (bonk));
398 
399   g_object_get (bonk,
400                 "type",    &type,
401                 "message", &message,
402                 NULL);
403 
404   g_assert_cmpint (type, ==, 0);
405   g_assert (message == NULL);
406 
407   g_object_unref (bonk);
408   bonk = NULL;
409 
410   /* It can be replaced... */
411   bonk = g_object_new (T_TEST_TYPE_BONK,
412                        "type",    100,
413                        "message", "Replacement Bonk",
414                        NULL);
415   g_object_set (nesting, "my_bonk", bonk, NULL);
416   g_object_unref (bonk);
417   bonk = NULL;
418 
419   g_object_get (nesting, "my_bonk", &bonk, NULL);
420 
421   g_assert (bonk != NULL);
422   g_assert (T_TEST_IS_BONK (bonk));
423 
424   g_object_get (bonk,
425                 "type",    &type,
426                 "message", &message,
427                 NULL);
428 
429   g_assert_cmpint (type, ==, 100);
430   g_assert_cmpstr (message, ==, "Replacement Bonk");
431 
432   g_free (message);
433   g_object_unref (bonk);
434   bonk = NULL;
435 
436   /* ...or set to null */
437   g_object_set (nesting, "my_bonk", NULL, NULL);
438   g_object_get (nesting, "my_bonk", &bonk, NULL);
439 
440   g_assert (bonk == NULL);
441 
442   g_object_unref (nesting);
443 }
444 
445 static void
test_structs_nesting_properties_my_ooe(void)446 test_structs_nesting_properties_my_ooe (void)
447 {
448   TTestNesting *nesting;
449   TTestOneOfEach *one_of_each = NULL;
450   gint a_bite;
451   gint integer16;
452 
453   nesting = g_object_new (T_TEST_TYPE_NESTING, NULL);
454 
455   /* Nesting's "my_ooe" member is initialized with a new, default OneOfEach
456      object during construction */
457   g_object_get (nesting, "my_ooe", &one_of_each, NULL);
458 
459   g_assert (one_of_each != NULL);
460   g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each));
461 
462   g_object_get (one_of_each,
463                 "a_bite",    &a_bite,
464                 "integer16", &integer16,
465                 NULL);
466 
467   g_assert_cmphex (a_bite,    ==, 0x7f);
468   g_assert_cmphex (integer16, ==, 0x7fff);
469 
470   g_object_unref (one_of_each);
471   one_of_each = NULL;
472 
473   /* It can be replaced... */
474   one_of_each = g_object_new (T_TEST_TYPE_ONE_OF_EACH,
475                               "a_bite",    0x50,
476                               "integer16", 0x5050,
477                               NULL);
478   g_object_set (nesting, "my_ooe", one_of_each, NULL);
479   g_object_unref (one_of_each);
480   one_of_each = NULL;
481 
482   g_object_get (nesting, "my_ooe", &one_of_each, NULL);
483 
484   g_assert (one_of_each != NULL);
485   g_assert (T_TEST_IS_ONE_OF_EACH (one_of_each));
486 
487   g_object_get (one_of_each,
488                 "a_bite",    &a_bite,
489                 "integer16", &integer16,
490                 NULL);
491 
492   g_assert_cmphex (a_bite,    ==, 0x50);
493   g_assert_cmphex (integer16, ==, 0x5050);
494 
495   g_object_unref (one_of_each);
496   one_of_each = NULL;
497 
498   /* ...or set to null */
499   g_object_set (nesting, "my_ooe", NULL, NULL);
500   g_object_get (nesting, "my_ooe", &one_of_each, NULL);
501 
502   g_assert (one_of_each == NULL);
503 
504   g_object_unref (nesting);
505 }
506 
507 static void
test_structs_holy_moley_create_and_destroy(void)508 test_structs_holy_moley_create_and_destroy (void)
509 {
510   GObject *object = NULL;
511 
512   /* A HolyMoley structure can be created... */
513   object = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL);
514 
515   g_assert (object != NULL);
516   g_assert (T_TEST_IS_HOLY_MOLEY (object));
517 
518   /* ...and destroyed */
519   g_object_unref (object);
520 }
521 
522 static void
test_structs_holy_moley_properties_big(void)523 test_structs_holy_moley_properties_big (void)
524 {
525   TTestHolyMoley *holy_moley;
526   GPtrArray *big = NULL;
527   gint a_bite = 0;
528   gint integer16 = 0;
529 
530   holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL);
531 
532   /* A HolyMoley's "big" member is is initialized on construction */
533   g_object_get (holy_moley, "big", &big, NULL);
534 
535   g_assert (big != NULL);
536   g_assert_cmpint (big->len, ==, 0);
537 
538   /* It can be modified... */
539   g_ptr_array_add (big,
540                    g_object_new (T_TEST_TYPE_ONE_OF_EACH,
541                                  "a_bite",    0x50,
542                                  "integer16", 0x5050,
543                                  NULL));
544 
545   g_ptr_array_unref (big);
546   big = NULL;
547 
548   g_object_get (holy_moley, "big", &big, NULL);
549 
550   g_assert_cmpint (big->len, ==, 1);
551   g_object_get (g_ptr_array_index (big, 0),
552                 "a_bite",    &a_bite,
553                 "integer16", &integer16,
554                 NULL);
555 
556   g_assert_cmphex (a_bite,    ==, 0x50);
557   g_assert_cmphex (integer16, ==, 0x5050);
558 
559   g_ptr_array_unref (big);
560   big = NULL;
561 
562   /* ...replaced... */
563   big = g_ptr_array_new_with_free_func (g_object_unref);
564   g_ptr_array_add (big,
565                    g_object_new (T_TEST_TYPE_ONE_OF_EACH,
566                                  "a_bite",    0x64,
567                                  "integer16", 0x1541,
568                                  NULL));
569 
570   g_object_set (holy_moley, "big", big, NULL);
571 
572   g_ptr_array_unref (big);
573   big = NULL;
574 
575   g_object_get (holy_moley, "big", &big, NULL);
576 
577   g_assert_cmpint (big->len, ==, 1);
578   g_object_get (g_ptr_array_index (big, 0),
579                 "a_bite",    &a_bite,
580                 "integer16", &integer16,
581                 NULL);
582 
583   g_assert_cmphex (a_bite,    ==, 0x64);
584   g_assert_cmphex (integer16, ==, 0x1541);
585 
586   g_ptr_array_unref (big);
587   big = NULL;
588 
589   /* ...or set to NULL */
590   g_object_set (holy_moley, "big", NULL, NULL);
591   g_object_get (holy_moley, "big", &big, NULL);
592 
593   g_assert (big == NULL);
594 
595   g_object_unref (holy_moley);
596 }
597 
598 static void
test_structs_holy_moley_properties_contain(void)599 test_structs_holy_moley_properties_contain (void)
600 {
601   static gchar *strings[2] = { "Apache", "Thrift" };
602 
603   TTestHolyMoley *holy_moley;
604   GHashTable *contain = NULL;
605   GPtrArray *string_list;
606   GList *key_list;
607 
608   holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL);
609 
610   /* A HolyMoley's "contain" member is initialized on construction */
611   g_object_get (holy_moley, "contain", &contain, NULL);
612 
613   g_assert (contain != NULL);
614   g_assert_cmpint (g_hash_table_size (contain), ==, 0);
615 
616   /* It can be modified... */
617   string_list = g_ptr_array_new ();
618   g_ptr_array_add (string_list, strings[0]);
619   g_ptr_array_add (string_list, strings[1]);
620 
621   g_hash_table_insert (contain, string_list, NULL);
622   string_list = NULL;
623 
624   g_hash_table_unref (contain);
625   contain = NULL;
626 
627   g_object_get (holy_moley, "contain", &contain, NULL);
628 
629   g_assert_cmpint (g_hash_table_size (contain), ==, 1);
630 
631   key_list = g_hash_table_get_keys (contain);
632   string_list = g_list_nth_data (key_list, 0);
633 
634   g_assert_cmpint (string_list->len, ==, 2);
635   g_assert_cmpstr (g_ptr_array_index (string_list, 0), ==, "Apache");
636   g_assert_cmpstr (g_ptr_array_index (string_list, 1), ==, "Thrift");
637 
638   g_list_free (key_list);
639   g_hash_table_unref (contain);
640   contain = NULL;
641 
642   /* ...replaced... */
643   contain = g_hash_table_new_full (g_direct_hash,
644                                    g_direct_equal,
645                                    (GDestroyNotify) g_ptr_array_unref,
646                                    NULL);
647   g_object_set (holy_moley, "contain", contain, NULL);
648   g_hash_table_unref (contain);
649   contain = NULL;
650 
651   g_object_get (holy_moley, "contain", &contain, NULL);
652 
653   g_assert_cmpint (g_hash_table_size (contain), ==, 0);
654 
655   g_hash_table_unref (contain);
656   contain = NULL;
657 
658   /* ...or set to NULL */
659   g_object_set (holy_moley, "contain", NULL, NULL);
660   g_object_get (holy_moley, "contain", &contain, NULL);
661 
662   g_assert (contain == NULL);
663 
664   g_object_unref (holy_moley);
665 }
666 
667 static void
test_structs_holy_moley_properties_bonks(void)668 test_structs_holy_moley_properties_bonks (void)
669 {
670   TTestHolyMoley *holy_moley;
671   GHashTable *bonks = NULL;
672   GPtrArray *bonk_list = NULL;
673   TTestBonk *bonk = NULL;
674   gint type;
675   gchar *message;
676   GList *key_list;
677 
678   holy_moley = g_object_new (T_TEST_TYPE_HOLY_MOLEY, NULL);
679 
680   /* A HolyMoley's "bonks" member is initialized on construction */
681   g_object_get (holy_moley, "bonks", &bonks, NULL);
682 
683   g_assert (bonks != NULL);
684   g_assert_cmpint (g_hash_table_size (bonks), ==, 0);
685 
686   /* It can be modified... */
687   bonk = g_object_new (T_TEST_TYPE_BONK,
688                        "type",    100,
689                        "message", "Sample Bonk",
690                        NULL);
691   bonk_list = g_ptr_array_new_with_free_func (g_object_unref);
692   g_ptr_array_add (bonk_list, bonk);
693   bonk = NULL;
694 
695   g_hash_table_insert (bonks, g_strdup ("Sample Bonks"), bonk_list);
696   bonk_list = NULL;
697 
698   g_hash_table_unref (bonks);
699   bonks = NULL;
700 
701   g_object_get (holy_moley, "bonks", &bonks, NULL);
702 
703   g_assert_cmpint (g_hash_table_size (bonks), ==, 1);
704 
705   key_list = g_hash_table_get_keys (bonks);
706   bonk_list = g_hash_table_lookup (bonks, g_list_nth_data (key_list, 0));
707 
708   g_assert_cmpint (bonk_list->len, ==, 1);
709 
710   bonk = (g_ptr_array_index (bonk_list, 0));
711   g_object_get (bonk,
712                 "type",    &type,
713                 "message", &message,
714                 NULL);
715 
716   g_assert_cmpint (type, ==, 100);
717   g_assert_cmpstr (message, ==, "Sample Bonk");
718 
719   bonk = NULL;
720   g_free (message);
721   g_list_free (key_list);
722   g_hash_table_unref (bonks);
723   bonks = NULL;
724 
725   /* ...replaced... */
726   bonks = g_hash_table_new_full (g_str_hash,
727                                  g_str_equal,
728                                  g_free,
729                                  (GDestroyNotify) g_ptr_array_unref);
730   g_object_set (holy_moley, "bonks", bonks, NULL);
731   g_hash_table_unref (bonks);
732   bonks = NULL;
733 
734   g_object_get (holy_moley, "bonks", &bonks, NULL);
735 
736   g_assert_cmpint (g_hash_table_size (bonks), ==, 0);
737 
738   g_hash_table_unref (bonks);
739   bonks = NULL;
740 
741   /* ...or set to NULL */
742   g_object_set (holy_moley, "bonks", NULL, NULL);
743   g_object_get (holy_moley, "bonks", &bonks, NULL);
744 
745   g_assert (bonks == NULL);
746 
747   g_object_unref (holy_moley);
748 }
749 
750 static void
test_structs_empty(void)751 test_structs_empty (void)
752 {
753   GObject *object = NULL;
754   GParamSpec **properties;
755   guint property_count;
756 
757   /* An Empty structure can be created */
758   object = g_object_new (T_TEST_TYPE_EMPTY, NULL);
759 
760   g_assert (object != NULL);
761   g_assert (T_TEST_IS_EMPTY (object));
762 
763   /* An Empty structure has no members and thus no properties */
764   properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (object),
765                                                &property_count);
766   g_assert_cmpint (property_count, ==, 0);
767   g_free (properties);
768 
769   /* An Empty structure can be destroyed  */
770   g_object_unref (object);
771 }
772 
773 static void
test_structs_wrapper_create_and_destroy(void)774 test_structs_wrapper_create_and_destroy (void)
775 {
776   GObject *object = NULL;
777 
778   /* A Wrapper structure can be created... */
779   object = g_object_new (T_TEST_TYPE_EMPTY, NULL);
780 
781   g_assert (object != NULL);
782   g_assert (T_TEST_IS_EMPTY (object));
783 
784   /* ...and destroyed  */
785   g_object_unref (object);
786 }
787 
788 static void
test_structs_wrapper_properties_foo(void)789 test_structs_wrapper_properties_foo (void) {
790   TTestWrapper *wrapper;
791   TTestEmpty *foo;
792 
793   wrapper = g_object_new (T_TEST_TYPE_WRAPPER, NULL);
794 
795   /* A Wrapper structure has one member, "foo", which is an Empty
796      structure initialized during construction */
797   g_object_get (wrapper, "foo", &foo, NULL);
798 
799   g_assert (foo != NULL);
800   g_assert (T_TEST_IS_EMPTY (foo));
801 
802   g_object_unref (foo);
803   foo = NULL;
804 
805   /* A Wrapper's foo property can be replaced... */
806   foo = g_object_new (T_TEST_TYPE_EMPTY, NULL);
807   g_object_set (wrapper, "foo", foo, NULL);
808 
809   g_object_unref (foo);
810   foo = NULL;
811 
812   g_object_get (wrapper, "foo", &foo, NULL);
813   g_assert (foo != NULL);
814   g_assert (T_TEST_IS_EMPTY (foo));
815 
816   g_object_unref (foo);
817   foo = NULL;
818 
819   /* ...or set to NULL */
820   g_object_set (wrapper, "foo", NULL, NULL);
821   g_object_get (wrapper, "foo", &foo, NULL);
822 
823   g_assert (foo == NULL);
824 
825   g_object_unref (wrapper);
826 }
827 
828 static void
test_services_inherited(void)829 test_services_inherited (void)
830 {
831   ThriftProtocol *protocol;
832   TTestInheritedClient *inherited_client;
833   GObject *input_protocol, *output_protocol;
834 
835   protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, NULL);
836   inherited_client = g_object_new (T_TEST_TYPE_INHERITED_CLIENT,
837                                    NULL);
838 
839   /* TTestInheritedClient inherits from TTestSrvClient */
840   g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
841                        T_TEST_TYPE_SRV_CLIENT));
842 
843   /* TTestInheritedClient implements TTestSrvClient's interface */
844   g_assert (g_type_is_a (T_TEST_TYPE_INHERITED_CLIENT,
845                        T_TEST_TYPE_SRV_IF));
846 
847   /* TTestInheritedClient's inherited properties can be set and retrieved */
848   g_object_set (inherited_client,
849                 "input_protocol", protocol,
850                 "output_protocol", protocol,
851                 NULL);
852 
853   g_object_get (inherited_client,
854                 "input_protocol", &input_protocol,
855                 "output_protocol", &output_protocol,
856                 NULL);
857 
858   g_assert (input_protocol == G_OBJECT(protocol));
859   g_assert (output_protocol == G_OBJECT(protocol));
860 
861   g_object_unref (output_protocol);
862   g_object_unref (input_protocol);
863   g_object_unref (inherited_client);
864   g_object_unref (protocol);
865 }
866 
867 int
main(int argc,char * argv[])868 main(int argc, char *argv[])
869 {
870 #if (!GLIB_CHECK_VERSION (2, 36, 0))
871   g_type_init ();
872 #endif
873 
874   g_test_init (&argc, &argv, NULL);
875 
876   g_test_add_func
877     ("/testdebugproto/DebugProto/Structs/Doubles/CreateAndDestroy",
878      test_structs_doubles_create_and_destroy);
879   g_test_add_func
880     ("/testdebugproto/DebugProto/Structs/Doubles/Initialize",
881      test_structs_doubles_initialize);
882 
883   g_test_add_func
884     ("/testdebugproto/DebugProto/Structs/OneOfEach/CreateAndDestroy",
885      test_structs_one_of_each_create_and_destroy);
886   g_test_add_func
887     ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/DefaultValues",
888      test_structs_one_of_each_initialize_default_values);
889   g_test_add_func
890     ("/testdebugproto/DebugProto/Structs/OneOfEach/Initialize/SpecifiedValues",
891      test_structs_one_of_each_initialize_specified_values);
892   g_test_add_func
893     ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/byte_list",
894      test_structs_one_of_each_properties_byte_list);
895   g_test_add_func
896     ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i16_list",
897      test_structs_one_of_each_properties_i16_list);
898   g_test_add_func
899     ("/testdebugproto/DebugProto/Structs/OneOfEach/Properties/i64_list",
900      test_structs_one_of_each_properties_i64_list);
901 
902   g_test_add_func
903     ("/testdebugproto/DebugProto/Structs/Nesting/CreateAndDestroy",
904      test_structs_nesting_create_and_destroy);
905   g_test_add_func
906     ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_bonk",
907      test_structs_nesting_properties_my_bonk);
908   g_test_add_func
909     ("/testdebugproto/DebugProto/Structs/Nesting/Properties/my_ooe",
910      test_structs_nesting_properties_my_ooe);
911 
912   g_test_add_func
913     ("/testdebugproto/DebugProto/Structs/HolyMoley/CreateAndDestroy",
914      test_structs_holy_moley_create_and_destroy);
915   g_test_add_func
916     ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/big",
917      test_structs_holy_moley_properties_big);
918   g_test_add_func
919     ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/contain",
920      test_structs_holy_moley_properties_contain);
921   g_test_add_func
922     ("/testdebugproto/DebugProto/Structs/HolyMoley/Properties/bonks",
923      test_structs_holy_moley_properties_bonks);
924 
925   g_test_add_func
926     ("/testdebugproto/DebugProto/Structs/Empty",
927      test_structs_empty);
928 
929   g_test_add_func
930     ("/testdebugproto/DebugProto/Structs/Wrapper/CreateAndDestroy",
931      test_structs_wrapper_create_and_destroy);
932   g_test_add_func
933     ("/testdebugproto/DebugProto/Structs/Wrapper/Properties/foo",
934      test_structs_wrapper_properties_foo);
935 
936   g_test_add_func
937     ("/testdebugproto/DebugProto/Services/Inherited",
938      test_services_inherited);
939 
940   return g_test_run ();
941 }
942