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 <netdb.h>
21 #include <sys/wait.h>
22 
23 #include <thrift/c_glib/transport/thrift_transport.h>
24 #include <thrift/c_glib/transport/thrift_socket.h>
25 #include <thrift/c_glib/transport/thrift_server_transport.h>
26 #include <thrift/c_glib/transport/thrift_server_socket.h>
27 
28 #define TEST_DATA { 'a', 'b' }
29 #define MAX_MESSAGE_SIZE 2
30 
31 #include "../src/thrift/c_glib/transport/thrift_framed_transport.c"
32 
33 static void thrift_server (const int port);
34 static void thrift_socket_server_open (const int port, int times);
35 
36 static void
test_open_and_close(void)37 test_open_and_close(void)
38 {
39   ThriftSocket *tsocket = NULL;
40   ThriftTransport *transport = NULL;
41   GError *err = NULL;
42   pid_t pid;
43   int port = 51199;
44   int status;
45 
46   pid = fork ();
47   g_assert ( pid >= 0 );
48 
49   if ( pid == 0 )
50   {
51     /* child listens */
52     thrift_socket_server_open (port,1);
53     exit (0);
54   } else {
55     /* parent connects, wait a bit for the socket to be created */
56     sleep (1);
57     /* create a ThriftSocket */
58     tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
59                             "port", port, NULL);
60 
61     /* create a BufferedTransport wrapper of the Socket */
62     transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
63                               "transport", THRIFT_TRANSPORT (tsocket), NULL);
64 
65     /* this shouldn't work */
66     g_assert (thrift_framed_transport_open (transport, NULL) == TRUE);
67     g_assert (thrift_framed_transport_is_open (transport) == TRUE);
68     g_assert (thrift_framed_transport_close (transport, NULL) == TRUE);
69     g_object_unref (transport);
70     g_object_unref (tsocket);
71 
72     /* try and underlying socket failure */
73     tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost.broken",
74                             NULL);
75 
76     /* create a BufferedTransport wrapper of the Socket */
77     transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
78                               "transport", THRIFT_TRANSPORT (tsocket), NULL);
79 
80     g_assert (thrift_framed_transport_open (transport, &err) == FALSE);
81     g_object_unref (transport);
82     g_object_unref (tsocket);
83     g_error_free (err);
84     err = NULL;
85 
86     g_assert ( wait (&status) == pid );
87     g_assert ( status == 0 );
88   }
89 }
90 
91 static void
test_read_and_write(void)92 test_read_and_write(void)
93 {
94   int status;
95   pid_t pid;
96   ThriftSocket *tsocket = NULL;
97   ThriftTransport *transport = NULL;
98   int port = 51199;
99   guchar buf[10] = TEST_DATA; /* a buffer */
100 
101   pid = fork ();
102   g_assert ( pid >= 0 );
103 
104   if ( pid == 0 )
105   {
106     /* child listens */
107     thrift_server (port);
108     exit (0);
109   } else {
110     /* parent connects, wait a bit for the socket to be created */
111     sleep (1);
112 
113     tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
114                             "port", port, NULL);
115     transport = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT,
116                               "transport", THRIFT_TRANSPORT (tsocket),
117                               "w_buf_size", 4, NULL);
118 
119     g_assert (thrift_framed_transport_open (transport, NULL) == TRUE);
120     g_assert (thrift_framed_transport_is_open (transport));
121 
122     /* write 2 bytes */
123     thrift_framed_transport_write (transport, buf, 2, NULL);
124     thrift_framed_transport_flush (transport, NULL);
125 
126     thrift_framed_transport_write (transport, buf, 3, NULL);
127     thrift_framed_transport_flush (transport, NULL);
128 
129     thrift_framed_transport_write_end (transport, NULL);
130     thrift_framed_transport_flush (transport, NULL);
131     thrift_framed_transport_close (transport, NULL);
132 
133     g_object_unref (transport);
134     g_object_unref (tsocket);
135 
136     g_assert ( wait (&status) == pid );
137     g_assert ( status == 0 );
138   }
139 }
140 
141 static void
thrift_socket_server_open(const int port,int times)142 thrift_socket_server_open (const int port, int times)
143 {
144   ThriftServerTransport *transport = NULL;
145   ThriftTransport *client = NULL;
146   int i;
147 
148   ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
149                                                       "max_message_size", MAX_MESSAGE_SIZE,
150                                                       "max_frame_size", MAX_MESSAGE_SIZE, NULL);
151 
152   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
153                                               "port", port, "configuration", tconfiguration, NULL);
154 
155   transport = THRIFT_SERVER_TRANSPORT (tsocket);
156   thrift_server_transport_listen (transport, NULL);
157   for(i=0;i<times;i++){
158       client = thrift_server_transport_accept (transport, NULL);
159       g_assert (client != NULL);
160       thrift_socket_close (client, NULL);
161       g_object_unref (client);
162   }
163   g_object_unref (tsocket);
164   g_object_unref (tconfiguration);
165 }
166 
167 static void
thrift_server(const int port)168 thrift_server (const int port)
169 {
170   int bytes = 0;
171   ThriftServerTransport *transport = NULL;
172   ThriftTransport *client = NULL;
173   guchar buf[12]; /* a buffer */
174   guchar match[10] = TEST_DATA;
175 
176   ThriftConfiguration *tconfiguration = g_object_new (THRIFT_TYPE_CONFIGURATION,
177                                                       "max_message_size", MAX_MESSAGE_SIZE,
178                                                       "max_frame_size", MAX_MESSAGE_SIZE,
179                                                       NULL);
180 
181   ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
182                                               "port", port, NULL);
183 
184   transport = THRIFT_SERVER_TRANSPORT (tsocket);
185   thrift_server_transport_listen (transport, NULL);
186 
187   /* wrap the client in a BufferedTransport */
188   client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport",
189                          thrift_server_transport_accept (transport, NULL),
190                          "r_buf_size", 5, "configuration", tconfiguration,
191                          "remainingmessagesize", MAX_MESSAGE_SIZE, NULL);
192   g_assert (client != NULL);
193 
194   /* read 2 bytes */
195   bytes = thrift_framed_transport_read (client, buf, 2, NULL);
196   g_assert (bytes == 2); /* make sure we've read 2 bytes */
197   g_assert ( memcmp (buf, match, 1) == 0 ); /* make sure what we got matches */
198 
199   bytes = thrift_framed_transport_read (client, buf, 3, NULL);
200   g_assert (bytes == -1);
201 
202   thrift_framed_transport_read_end (client, NULL);
203   thrift_framed_transport_close (client, NULL);
204   g_object_unref (client);
205   g_object_unref (tsocket);
206   g_object_unref (tconfiguration);
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 ("/testframedtransport/OpenAndClose", test_open_and_close);
219   g_test_add_func ("/testframedtransport/ReadAndWrite", test_read_and_write);
220 
221   return g_test_run ();
222 }
223