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 /* Disable string-function optimizations when glibc is used, as these produce
21 compiler warnings about string length when a string function is used inside
22 a call to g_assert () */
23 #if !defined(__APPLE__) && !defined(__FreeBSD__) && \
24 !defined(__OpenBSD__) && !defined(__NetBSD__)
25 #include <features.h>
26 #endif
27
28 #ifdef __GLIBC__
29 #define __NO_STRING_INLINES 1
30 #endif
31
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <netdb.h>
36 #include <string.h>
37 #include <sys/wait.h>
38
39 #include <thrift/c_glib/protocol/thrift_protocol.h>
40 #include <thrift/c_glib/transport/thrift_socket.h>
41 #include <thrift/c_glib/transport/thrift_server_socket.h>
42 #include <thrift/c_glib/transport/thrift_framed_transport.h>
43
44 #define TEST_BOOL TRUE
45 #define TEST_BYTE 123
46 #define TEST_I16 12345
47 #define TEST_I32 1234567890
48 #define TEST_I64 123456789012345
49 #define TEST_NI16 (-12345)
50 #define TEST_NI32 (-1234567890)
51 #define TEST_NI64 (-123456789012345)
52 #define TEST_DOUBLE 1234567890.123
53 #define TEST_STRING "this is a test string 1234567890!@#$%^&*()"
54 #define TEST_PORT 51199
55
56 #define MAX_MESSAGE_SIZE 2
57
58 static int transport_read_count = 0;
59 static int transport_read_error = 0;
60 static int transport_read_error_at = -1;
61 gint32
my_thrift_transport_read_all(ThriftTransport * transport,gpointer buf,guint32 len,GError ** error)62 my_thrift_transport_read_all (ThriftTransport *transport, gpointer buf,
63 guint32 len, GError **error)
64 {
65 if (transport_read_count != transport_read_error_at
66 && transport_read_error == 0)
67 {
68 transport_read_count++;
69 return thrift_transport_read_all (transport, buf, len, error);
70 }
71 return -1;
72 }
73
74 static int transport_write_count = 0;
75 static int transport_write_error = 0;
76 static int transport_write_error_at = -1;
77 gboolean
my_thrift_transport_write(ThriftTransport * transport,const gpointer buf,const guint32 len,GError ** error)78 my_thrift_transport_write (ThriftTransport *transport, const gpointer buf,
79 const guint32 len, GError **error)
80 {
81 if (transport_write_count != transport_write_error_at
82 && transport_write_error == 0)
83 {
84 transport_write_count++;
85 return thrift_transport_write (transport, buf, len, error);
86 }
87 return FALSE;
88 }
89
90 #define thrift_transport_read_all my_thrift_transport_read_all
91 #define thrift_transport_write my_thrift_transport_write
92 #include "../src/thrift/c_glib/protocol/thrift_compact_protocol.c"
93 #undef thrift_transport_read_all
94 #undef thrift_transport_write
95
96 static void thrift_server_complex_types (const int port);
97
98 static void
test_create_and_destroy(void)99 test_create_and_destroy (void)
100 {
101 GObject *object = NULL;
102
103 /* create an object and then destroy it */
104 object = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, NULL);
105 g_assert (object != NULL);
106 g_object_unref (object);
107 }
108
109 static void
test_initialize(void)110 test_initialize (void)
111 {
112 ThriftSocket *tsocket = NULL;
113 ThriftCompactProtocol *protocol = NULL;
114 ThriftSocket *temp = NULL;
115 ThriftConfiguration *tconfiguration = NULL;
116 ThriftConfiguration *tempconf = NULL;
117 glong tempsize = 0;
118
119 /* create a ThriftConfiguration */
120 tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
121 "max_frame_size", MAX_MESSAGE_SIZE, NULL);
122 /* create a ThriftTransport */
123 tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
124 "port", 51188, "configuration", tconfiguration,
125 "remainingmessagesize", MAX_MESSAGE_SIZE, NULL);
126 g_assert (tsocket != NULL);
127 /* fetch the properties */
128 g_object_get (G_OBJECT (tconfiguration), "max_message_size", &tempsize, NULL);
129 g_assert (tempsize == MAX_MESSAGE_SIZE);
130 /* fetch the properties */
131 g_object_get (G_OBJECT (tsocket), "remainingmessagesize", &tempsize, NULL);
132 g_assert (tempsize == MAX_MESSAGE_SIZE);
133 /* fetch the properties */
134 g_object_get (G_OBJECT (tsocket), "configuration", &tempconf, NULL);
135 g_object_unref (tempconf);
136 /* create a ThriftCompactProtocol using the Transport */
137 protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport",
138 tsocket, NULL);
139 g_assert (protocol != NULL);
140 /* fetch the properties */
141 g_object_get (G_OBJECT (protocol), "transport", &temp, NULL);
142 g_object_unref (temp);
143
144 /* clean up memory */
145 g_object_unref (protocol);
146 g_object_unref (tsocket);
147 }
148
149
150 static void
test_read_and_write_complex_types(void)151 test_read_and_write_complex_types (void)
152 {
153 int status;
154 pid_t pid;
155 ThriftSocket *tsocket = NULL;
156 ThriftTransport *transport = NULL;
157 ThriftCompactProtocol *tc = NULL;
158 ThriftProtocol *protocol = NULL;
159 int port = TEST_PORT;
160
161 /* fork a server from the client */
162 pid = fork ();
163 g_assert (pid >= 0);
164
165 if (pid == 0)
166 {
167 /* child listens */
168 thrift_server_complex_types (port);
169 exit (0);
170 } else {
171 /* parent. wait a bit for the socket to be created. */
172 sleep (1);
173
174 /* create a ThriftSocket */
175 tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
176 "port", port, NULL);
177 transport = THRIFT_TRANSPORT (tsocket);
178 thrift_transport_open (transport, NULL);
179 g_assert (thrift_transport_is_open (transport));
180
181 /* create a ThriftCompactTransport */
182 tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport",
183 tsocket, NULL);
184 protocol = THRIFT_PROTOCOL (tc);
185 g_assert (protocol != NULL);
186
187 g_assert (thrift_compact_protocol_write_map_begin (protocol, T_VOID, T_BYTE,
188 1, NULL) > 0);
189 g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0);
190
191 g_assert (thrift_compact_protocol_write_map_begin (protocol, T_VOID, T_BYTE,
192 3, NULL) > 0);
193 g_assert (thrift_compact_protocol_write_map_end (protocol, NULL) == 0);
194
195 g_assert (thrift_compact_protocol_write_list_begin (protocol, T_BYTE,
196 1, NULL) > 0);
197 g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0);
198
199 g_assert (thrift_compact_protocol_write_list_begin (protocol, T_I32,
200 3, NULL) > 0);
201 g_assert (thrift_compact_protocol_write_list_end (protocol, NULL) == 0);
202
203 /* clean up */
204 thrift_transport_close (transport, NULL);
205 g_object_unref (tsocket);
206 g_object_unref (protocol);
207 g_assert (wait (&status) == pid);
208 g_assert (status == 0);
209 }
210 }
211
212
213 static void
thrift_server_complex_types(const int port)214 thrift_server_complex_types (const int port)
215 {
216 ThriftServerTransport *transport = NULL;
217 ThriftTransport *client = NULL;
218 ThriftCompactProtocol *tc = NULL;
219 ThriftProtocol *protocol = NULL;
220 ThriftType element_type, key_type, value_type;
221 guint32 size = 0;
222
223 ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION, "max_message_size", MAX_MESSAGE_SIZE,
224 "max_frame_size", MAX_MESSAGE_SIZE, NULL);
225 ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
226 "port", port, "configuration", tconfiguration, NULL);
227 transport = THRIFT_SERVER_TRANSPORT (tsocket);
228 THRIFT_SERVER_TRANSPORT_GET_CLASS (tsocket)->resetConsumedMessageSize(transport, -1, NULL);
229 thrift_server_transport_listen (transport, NULL);
230 client = thrift_server_transport_accept (transport, NULL);
231 g_assert (client != NULL);
232
233 tc = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, "transport",
234 client, NULL);
235 protocol = THRIFT_PROTOCOL (tc);
236
237 g_assert (thrift_compact_protocol_read_map_begin (protocol, &key_type, &value_type,
238 &size, NULL) > 0);
239 g_assert (thrift_compact_protocol_read_map_end (protocol, NULL) == 0);
240
241 g_assert (thrift_compact_protocol_read_map_begin (protocol, &key_type, &value_type,
242 &size, NULL) == -1);
243 g_assert (thrift_compact_protocol_read_map_end (protocol, NULL) == 0);
244
245 g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type,
246 &size, NULL) > 0);
247 g_assert (thrift_compact_protocol_read_list_end (protocol, NULL) == 0);
248
249 g_assert (thrift_compact_protocol_read_list_begin (protocol, &element_type,
250 &size, NULL) == -1);
251 g_assert (thrift_compact_protocol_read_list_end (protocol, NULL) == 0);
252
253 g_object_unref (client);
254 g_object_unref (tsocket);
255 g_object_unref (tconfiguration);
256 }
257
258
259 int
main(int argc,char * argv[])260 main (int argc, char *argv[])
261 {
262 #if (!GLIB_CHECK_VERSION (2, 36, 0))
263 g_type_init ();
264 #endif
265
266 g_test_init (&argc, &argv, NULL);
267
268 g_test_add_func ("/testthriftcompactreadcheck/CreateAndDestroy",
269 test_create_and_destroy);
270 g_test_add_func ("/testthriftcompactreadcheck/Initialize", test_initialize);
271 g_test_add_func ("/testthriftcompactreadcheck/ReadAndWriteComplexTypes",
272 test_read_and_write_complex_types);
273
274 return g_test_run ();
275 }
276