2
Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License as
6
published by the Free Software Foundation; version 2 of the
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
36
#include <glib/gstdio.h> /* for g_unlink */
38
#include "network-socket.h"
40
#if GLIB_CHECK_VERSION(2, 16, 0)
41
#define C(x) x, sizeof(x) - 1
44
#define LOCAL_SOCK "/tmp/mysql-proxy-test.socket"
47
char sockname[sizeof(LOCAL_SOCK) + 10];
50
static local_unix_t *pp = NULL;
51
static local_unix_t local_test_arg;
54
void test_network_socket_new() {
57
sock = network_socket_new();
60
network_socket_free(sock);
63
void test_network_queue_append() {
66
q = network_queue_new();
69
network_queue_append(q, g_string_new("123"));
70
network_queue_append(q, g_string_new("345"));
72
network_queue_free(q);
75
void test_network_queue_peek_string() {
79
q = network_queue_new();
82
network_queue_append(q, g_string_new("123"));
83
g_assert_cmpint(q->len, ==, 3);
84
network_queue_append(q, g_string_new("456"));
85
g_assert_cmpint(q->len, ==, 6);
87
s = network_queue_peek_string(q, 3, NULL);
89
g_assert_cmpint(s->len, ==, 3);
90
g_assert_cmpstr(s->str, ==, "123");
91
g_string_free(s, TRUE);
93
s = network_queue_peek_string(q, 4, NULL);
95
g_assert_cmpint(s->len, ==, 4);
96
g_assert_cmpstr(s->str, ==, "1234");
97
g_string_free(s, TRUE);
99
s = network_queue_peek_string(q, 7, NULL);
102
g_assert_cmpint(q->len, ==, 6);
104
network_queue_free(q);
107
void test_network_queue_pop_string() {
111
q = network_queue_new();
114
network_queue_append(q, g_string_new("123"));
115
g_assert_cmpint(q->len, ==, 3);
116
network_queue_append(q, g_string_new("456"));
117
g_assert_cmpint(q->len, ==, 6);
118
network_queue_append(q, g_string_new("789"));
119
g_assert_cmpint(q->len, ==, 9);
121
s = network_queue_pop_string(q, 3, NULL);
123
g_assert_cmpint(s->len, ==, 3);
124
g_assert_cmpstr(s->str, ==, "123");
125
g_string_free(s, TRUE);
127
g_assert_cmpint(q->len, ==, 6);
129
s = network_queue_pop_string(q, 4, NULL);
131
g_assert_cmpint(s->len, ==, 4);
132
g_assert_cmpstr(s->str, ==, "4567");
133
g_string_free(s, TRUE);
134
g_assert_cmpint(q->len, ==, 2);
136
s = network_queue_pop_string(q, 7, NULL);
139
s = network_queue_peek_string(q, 2, NULL);
141
g_assert_cmpint(s->len, ==, 2);
142
g_assert_cmpstr(s->str, ==, "89");
143
g_string_free(s, TRUE);
144
g_assert_cmpint(q->len, ==, 2);
146
s = network_queue_pop_string(q, 2, NULL);
148
g_assert_cmpint(s->len, ==, 2);
149
g_assert_cmpstr(s->str, ==, "89");
150
g_string_free(s, TRUE);
151
g_assert_cmpint(q->len, ==, 0);
153
network_queue_free(q);
156
#define TEST_ADDR_IP "127.0.0.1:57684"
157
#define TEST_ADDR_CLIENT_UDP "127.0.0.1:0"
159
void t_network_socket_bind(void) {
160
network_socket *sock;
162
g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
164
sock = network_socket_new();
166
/* w/o a address set it should fail */
167
g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_bind(sock)); /* should fail, no address */
169
g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
171
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
173
network_socket_free(sock);
175
/* bind again, to test if REUSEADDR works */
176
sock = network_socket_new();
178
g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
180
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
182
g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_bind(sock)); /* bind a socket that is already bound, should fail */
184
network_socket_free(sock);
188
* @test check if the network_socket_connect() works by
189
* - setting up a listening socket
196
void t_network_socket_connect(void) {
197
network_socket *sock;
198
network_socket *client;
199
network_socket *client_connected;
201
struct timeval timeout;
202
network_socket_retval_t ret;
204
g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
206
sock = network_socket_new();
208
g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
210
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
212
client = network_socket_new();
213
g_assert_cmpint(0, ==, network_address_set_address(client->dst, TEST_ADDR_IP));
215
switch ((ret = network_socket_connect(client))) {
216
case NETWORK_SOCKET_ERROR_RETRY:
217
client_connected = network_socket_accept(sock);
219
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect_finish(client));
222
case NETWORK_SOCKET_SUCCESS:
223
/* looks like solaris makes a successful connect() even if the listen-socket isn't in accept() yet */
224
client_connected = network_socket_accept(sock);
227
client_connected = NULL;
228
g_assert_cmpint(NETWORK_SOCKET_ERROR_RETRY, ==, ret);
232
g_assert(client_connected);
233
g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_connect(client)); /* we are already connected, sure fail */
235
/* we are connected */
237
network_queue_append(client->send_queue, g_string_new_len(C("foo")));
238
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_write(client, -1)); /* send all */
241
FD_SET(client_connected->fd, &read_fds);
243
timeout.tv_usec = 500 * 000; /* wait 500ms */
244
g_assert_cmpint(1, ==, select(client_connected->fd + 1, &read_fds, NULL, NULL, &timeout));
246
/* socket_read() needs ->to_read set */
247
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_to_read(client_connected));
248
g_assert_cmpint(3, ==, client_connected->to_read);
249
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_read(client_connected)); /* read all */
250
g_assert_cmpint(0, ==, client_connected->to_read);
252
network_socket_free(client);
255
/* try to read from closed socket */
256
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_to_read(client_connected));
257
g_assert_cmpint(0, ==, client_connected->to_read);
259
network_socket_free(client_connected);
260
network_socket_free(sock);
264
* @test check if the network_socket_connect() works by
265
* - setting up a listening socket
272
void t_network_socket_connect_udp(void) {
273
network_socket *server;
274
network_socket *client;
276
struct timeval timeout;
277
network_socket_retval_t ret;
279
g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
281
server = network_socket_new();
282
server->socket_type = SOCK_DGRAM;
284
g_assert_cmpint(0, ==, network_address_set_address(server->src, TEST_ADDR_IP)); /* our UDP port */
286
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(server));
287
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_to_read(server));
288
g_assert_cmpint(0, ==, server->to_read);
290
client = network_socket_new();
291
client->socket_type = SOCK_DGRAM;
292
g_assert_cmpint(0, ==, network_address_set_address(client->dst, TEST_ADDR_IP)); /* the server's port */
293
g_assert_cmpint(0, ==, network_address_set_address(client->src, TEST_ADDR_CLIENT_UDP)); /* a random port */
295
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(client));
297
/* we are connected */
299
network_queue_append(client->send_queue, g_string_new_len(C("foo")));
300
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_write(client, -1)); /* send all */
303
FD_SET(server->fd, &read_fds);
305
timeout.tv_usec = 500 * 000; /* wait 500ms */
306
g_assert_cmpint(1, ==, select(server->fd + 1, &read_fds, NULL, NULL, &timeout));
308
/* socket_read() needs ->to_read set */
309
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_to_read(server));
310
g_assert_cmpint(3, ==, server->to_read);
311
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_read(server)); /* read all */
312
g_assert_cmpint(0, ==, server->to_read);
314
network_socket_free(client);
315
network_socket_free(server);
321
* test if _is_local() works on unix-domain sockets
323
* MacOS X 10.4 doesn't report a .sa_family for one of the sides of the connection if it is a unix-socket
325
void t_network_socket_is_local_unix() {
326
network_socket *s_sock; /* the server side socket, listening for requests */
327
network_socket *c_sock; /* the client side socket, that connects */
328
network_socket *a_sock; /* the server side, accepted socket */
331
g_log_set_always_fatal(G_LOG_FATAL_MASK); /* gtest modifies the fatal-mask */
333
s_sock = network_socket_new();
334
network_address_set_address(s_sock->dst, "/tmp/mysql-proxy-test.socket");
336
c_sock = network_socket_new();
337
network_address_set_address(c_sock->dst, "/tmp/mysql-proxy-test.socket");
340
/* hack together a network_socket_accept() which we don't have in this tree yet */
341
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(s_sock));
343
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect(c_sock));
345
a_sock = network_socket_accept(s_sock);
348
g_assert_cmpint(TRUE, ==, network_address_is_local(s_sock->dst, a_sock->dst));
350
network_socket_free(a_sock);
351
network_socket_free(c_sock);
352
network_socket_free(s_sock);
354
g_unlink("/tmp/mysql-proxy-test.socket");
357
void t_network_localsocket_setup(local_unix_t *p, gconstpointer G_GNUC_UNUSED _test_data) {
359
snprintf(p->sockname, sizeof(p->sockname), LOCAL_SOCK ".%d", (int)getpid());
363
void t_network_localsocket_teardown(local_unix_t *p, gconstpointer G_GNUC_UNUSED _test_data) {
365
if (p->sockname[0] != '\0') {
366
(void) g_unlink(p->sockname);
367
p->sockname[0] = '\0';
372
void exitfunc(int sig) {
373
if (pp != NULL && pp->sockname[0] != '\0')
374
(void) g_unlink(pp->sockname);
380
* test if local sockets are removed at shutdown
381
* this is an extension of _is_local_unix(), therefore looks much like it;
382
* just in case, we leave all tests from that function in as well.
384
void t_network_socket_rem_local_unix(local_unix_t *p, gconstpointer G_GNUC_UNUSED _test_data) {
385
network_socket *s_sock; /* the server side socket, listening for requests */
386
network_socket *c_sock; /* the client side socket, that connects */
387
network_socket *a_sock; /* the server side, accepted socket */
390
* if an assertion fails, we receive the ABORT signal. We need to
391
* close the unix socket in that case too. The regular teardown function
392
* is not called in this case, so we install our own handler.
394
signal(SIGABRT, exitfunc);
396
g_log_set_always_fatal(G_LOG_FATAL_MASK); /* gtest modifies the fatal-mask */
398
s_sock = network_socket_new();
399
network_address_set_address(s_sock->dst, p->sockname);
401
c_sock = network_socket_new();
402
network_address_set_address(c_sock->dst, p->sockname);
404
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(s_sock));
406
g_assert_cmpint(g_access(p->sockname, 0), ==, 0);
408
g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect(c_sock));
410
a_sock = network_socket_accept(s_sock);
413
g_assert_cmpint(TRUE, ==, network_address_is_local(s_sock->dst, a_sock->dst));
415
network_socket_free(a_sock);
416
g_assert_cmpint(g_access(p->sockname, 0), ==, 0);
417
network_socket_free(c_sock);
418
g_assert_cmpint(g_access(p->sockname, 0), ==, 0);
419
network_socket_free(s_sock);
420
g_assert_cmpint(g_access(p->sockname, 0), ==, -1);
422
/* re-establish default signal disposition */
423
signal(SIGABRT, SIG_DFL);
428
int main(int argc, char **argv) {
429
g_test_init(&argc, &argv, NULL);
430
g_test_bug_base("http://bugs.mysql.com/");
432
g_test_add_func("/core/network_socket_new", test_network_socket_new);
433
g_test_add_func("/core/network_socket_bind", t_network_socket_bind);
434
g_test_add_func("/core/network_socket_connect", t_network_socket_connect);
435
g_test_add_func("/core/network_queue_append", test_network_queue_append);
436
g_test_add_func("/core/network_queue_peek_string", test_network_queue_peek_string);
437
g_test_add_func("/core/network_queue_pop_string", test_network_queue_pop_string);
439
g_test_add_func("/core/network_socket_is_local_unix",t_network_socket_is_local_unix);
441
g_test_add("/core/network_socket_rem_local_unix", local_unix_t,
443
t_network_localsocket_setup, t_network_socket_rem_local_unix,
444
t_network_localsocket_teardown);
448
* disabled for now until we fixed the _to_read() on HP/UX and AIX (and MacOS X)
450
* ERROR:(t_network_socket.c:287):???: assertion failed (3 == server->to_read): (3 == 19)
452
g_test_add_func("/core/network_socket_udp", t_network_socket_connect_udp);
457
#else /* GLIB_CHECK_VERSION */
461
#endif /* GLIB_CHECK_VERSION */