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 <glib.h>
21 
22 #include <thrift/c_glib/thrift_struct.h>
23 #include <thrift/c_glib/protocol/thrift_protocol.h>
24 #include <thrift/c_glib/protocol/thrift_binary_protocol.h>
25 #include <thrift/c_glib/transport/thrift_memory_buffer.h>
26 #include "gen-c_glib/t_test_optional_required_test_types.h"
27 
28 #include "gen-c_glib/t_test_optional_required_test_types.c"
29 
30 static void
write_to_read(ThriftStruct * w,ThriftStruct * r,GError ** write_error,GError ** read_error)31 write_to_read (ThriftStruct *w, ThriftStruct *r, GError **write_error,
32                GError **read_error)
33 {
34   ThriftMemoryBuffer *tbuffer = NULL;
35   ThriftProtocol *protocol = NULL;
36 
37   tbuffer = g_object_new (THRIFT_TYPE_MEMORY_BUFFER, NULL);
38   protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, "transport",
39                            tbuffer, NULL);
40 
41   thrift_struct_write (w, protocol, write_error);
42   thrift_struct_read (r, protocol, read_error);
43 
44   g_object_unref (protocol);
45   g_object_unref (tbuffer);
46 }
47 
48 static void
test_old_school1(void)49 test_old_school1 (void)
50 {
51   TTestOldSchool *o = NULL;
52 
53   o = g_object_new (T_TEST_TYPE_OLD_SCHOOL, NULL);
54   o->im_int = 10;
55   o->im_str = g_strdup ("test");
56   o->im_big = g_ptr_array_new ();
57   g_ptr_array_free (o->im_big, TRUE);
58   o->im_big = NULL;
59   g_free (o->im_str);
60   o->im_str = NULL;
61   g_object_unref (o);
62 }
63 
64 /**
65  * Write to read with optional fields
66  */
67 static void
test_simple(void)68 test_simple (void)
69 {
70   TTestSimple *s1 = NULL, *s2 = NULL, *s3 = NULL;
71 
72   s1 = g_object_new (T_TEST_TYPE_SIMPLE, NULL);
73   s2 = g_object_new (T_TEST_TYPE_SIMPLE, NULL);
74   s3 = g_object_new (T_TEST_TYPE_SIMPLE, NULL);
75 
76   /* write-to-read with optional fields */
77   s1->im_optional = 10;
78   g_assert (s1->__isset_im_default == FALSE);
79   g_assert (s1->__isset_im_optional == FALSE);
80   write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s2), NULL, NULL);
81   g_assert (s2->__isset_im_default == TRUE);
82   g_assert (s2->__isset_im_optional == FALSE);
83   g_assert (s2->im_optional == 0);
84 
85   s1->__isset_im_optional = TRUE;
86   write_to_read (THRIFT_STRUCT (s1), THRIFT_STRUCT (s3), NULL, NULL);
87   g_assert (s3->__isset_im_default == TRUE);
88   g_assert (s3->__isset_im_optional == TRUE);
89   g_assert (s3->im_optional == 10);
90 
91   g_object_unref (s1);
92   g_object_unref (s2);
93 }
94 
95 /**
96  * Writing between optional and default
97  */
98 static void
test_tricky1(void)99 test_tricky1 (void)
100 {
101   TTestTricky1 *t1 = NULL;
102   TTestTricky2 *t2 = NULL;
103 
104   t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL);
105   t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL);
106 
107   t2->im_optional = 10;
108   write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t1), NULL, NULL);
109   write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t2), NULL, NULL);
110 
111   g_assert (t1->__isset_im_default == FALSE);
112   g_assert (t2->__isset_im_optional == TRUE);
113   g_assert (t1->im_default == t2->im_optional);
114   g_assert (t1->im_default == 0);
115 
116   g_object_unref (t1);
117   g_object_unref (t2);
118 }
119 
120 /**
121  * Writing between default and required.
122  */
123 static void
test_tricky2(void)124 test_tricky2 (void)
125 {
126   TTestTricky1 *t1 = NULL;
127   TTestTricky3 *t3 = NULL;
128 
129   t1 = g_object_new (T_TEST_TYPE_TRICKY1, NULL);
130   t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL);
131 
132   write_to_read (THRIFT_STRUCT (t1), THRIFT_STRUCT (t3), NULL, NULL);
133   write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t1), NULL, NULL);
134 
135   g_assert (t1->__isset_im_default == TRUE);
136 
137   g_object_unref (t1);
138   g_object_unref (t3);
139 }
140 
141 /**
142  * Writing between optional and required.
143  */
144 static void
test_tricky3(void)145 test_tricky3 (void)
146 {
147   TTestTricky2 *t2 = NULL;
148   TTestTricky3 *t3 = NULL;
149 
150   t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL);
151   t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL);
152 
153   t2->__isset_im_optional = TRUE;
154 
155   write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, NULL);
156   write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL);
157 
158   g_object_unref (t2);
159   g_object_unref (t3);
160 }
161 
162 /**
163  * Catch an optional not set exception.  To quote the
164  * C++ test, "Mu-hu-ha-ha-ha!"
165  */
166 static void
test_tricky4(void)167 test_tricky4 (void)
168 {
169   TTestTricky2 *t2 = NULL;
170   TTestTricky3 *t3 = NULL;
171   GError *read_error = NULL;
172 
173   t2 = g_object_new (T_TEST_TYPE_TRICKY2, NULL);
174   t3 = g_object_new (T_TEST_TYPE_TRICKY3, NULL);
175 
176   /* throws protocol exception */
177   write_to_read (THRIFT_STRUCT (t2), THRIFT_STRUCT (t3), NULL, &read_error);
178   g_assert (read_error != NULL);
179   g_error_free (read_error);
180 
181   write_to_read (THRIFT_STRUCT (t3), THRIFT_STRUCT (t2), NULL, NULL);
182 
183   g_assert (t2->__isset_im_optional);
184 
185   g_object_unref (t2);
186   g_object_unref (t3);
187 }
188 
189 static void
test_non_set_binary(void)190 test_non_set_binary (void)
191 {
192   TTestBinaries *b1 = NULL;
193   TTestBinaries *b2 = NULL;
194   GError *error = NULL;
195 
196   b1 = g_object_new (T_TEST_TYPE_BINARIES, NULL);
197   b2 = g_object_new (T_TEST_TYPE_BINARIES, NULL);
198 
199   write_to_read (THRIFT_STRUCT (b1), THRIFT_STRUCT (b2), NULL, &error);
200   g_assert(!error);
201   write_to_read (THRIFT_STRUCT (b2), THRIFT_STRUCT (b1), NULL, &error);
202   g_assert(!error);
203   /* OK. No segfault */
204 
205   g_object_unref (b1);
206   g_object_unref (b2);
207 }
208 
209 int
main(int argc,char * argv[])210 main(int argc, char *argv[])
211 {
212 #if (!GLIB_CHECK_VERSION (2, 36, 0))
213   g_type_init();
214 #endif
215 
216   g_test_init (&argc, &argv, NULL);
217 
218   g_test_add_func ("/testoptionalrequired/OldSchool", test_old_school1);
219   g_test_add_func ("/testoptionalrequired/Simple", test_simple);
220   g_test_add_func ("/testoptionalrequired/Tricky1", test_tricky1);
221   g_test_add_func ("/testoptionalrequired/Tricky2", test_tricky2);
222   g_test_add_func ("/testoptionalrequired/Tricky3", test_tricky3);
223   g_test_add_func ("/testoptionalrequired/Tricky4", test_tricky4);
224   g_test_add_func ("/testoptionalrequired/Binary", test_non_set_binary);
225 
226   return g_test_run ();
227 }
228