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