~vinchen13/mysql-proxy/fix_some_bugs

« back to all changes in this revision

Viewing changes to tests/unit/t_network_socket.c

  • Committer: vin
  • Date: 2012-02-15 02:47:30 UTC
  • Revision ID: vinchen13@gmail.com-20120215024730-6xtv6nhn83ina0sc
origin source code from mysql-proxy-0.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $%BEGINLICENSE%$
 
2
 Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
 
3
 
 
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
 
7
 License.
 
8
 
 
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.
 
13
 
 
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
 
17
 02110-1301  USA
 
18
 
 
19
 $%ENDLICENSE%$ */
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#include <errno.h>
 
25
#ifndef _WIN32
 
26
#include <signal.h>
 
27
#endif
 
28
 
 
29
#ifndef WIN32
 
30
#include <unistd.h>
 
31
#include <stdlib.h>
 
32
#include <fcntl.h>
 
33
#endif /* WIN32 */
 
34
 
 
35
#include <glib.h>
 
36
#include <glib/gstdio.h> /* for g_unlink */
 
37
 
 
38
#include "network-socket.h"
 
39
 
 
40
#if GLIB_CHECK_VERSION(2, 16, 0)
 
41
#define C(x) x, sizeof(x) - 1
 
42
 
 
43
#ifndef WIN32
 
44
#define LOCAL_SOCK "/tmp/mysql-proxy-test.socket"
 
45
 
 
46
typedef struct {
 
47
        char    sockname[sizeof(LOCAL_SOCK) + 10];
 
48
} local_unix_t;
 
49
 
 
50
static local_unix_t     *pp = NULL;
 
51
static local_unix_t local_test_arg;
 
52
#endif /* WIN32 */
 
53
 
 
54
void test_network_socket_new() {
 
55
        network_socket *sock;
 
56
 
 
57
        sock = network_socket_new();
 
58
        g_assert(sock);
 
59
 
 
60
        network_socket_free(sock);
 
61
}
 
62
 
 
63
void test_network_queue_append() {
 
64
        network_queue *q;
 
65
 
 
66
        q = network_queue_new();
 
67
        g_assert(q);
 
68
 
 
69
        network_queue_append(q, g_string_new("123"));
 
70
        network_queue_append(q, g_string_new("345"));
 
71
 
 
72
        network_queue_free(q);
 
73
}
 
74
 
 
75
void test_network_queue_peek_string() {
 
76
        network_queue *q;
 
77
        GString *s;
 
78
 
 
79
        q = network_queue_new();
 
80
        g_assert(q);
 
81
 
 
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);
 
86
 
 
87
        s = network_queue_peek_string(q, 3, NULL);
 
88
        g_assert(s);
 
89
        g_assert_cmpint(s->len, ==, 3);
 
90
        g_assert_cmpstr(s->str, ==, "123");
 
91
        g_string_free(s, TRUE);
 
92
 
 
93
        s = network_queue_peek_string(q, 4, NULL);
 
94
        g_assert(s);
 
95
        g_assert_cmpint(s->len, ==, 4);
 
96
        g_assert_cmpstr(s->str, ==, "1234");
 
97
        g_string_free(s, TRUE);
 
98
 
 
99
        s = network_queue_peek_string(q, 7, NULL);
 
100
        g_assert(s == NULL);
 
101
        
 
102
        g_assert_cmpint(q->len, ==, 6);
 
103
 
 
104
        network_queue_free(q);
 
105
}
 
106
 
 
107
void test_network_queue_pop_string() {
 
108
        network_queue *q;
 
109
        GString *s;
 
110
 
 
111
        q = network_queue_new();
 
112
        g_assert(q);
 
113
 
 
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);
 
120
 
 
121
        s = network_queue_pop_string(q, 3, NULL);
 
122
        g_assert(s);
 
123
        g_assert_cmpint(s->len, ==, 3);
 
124
        g_assert_cmpstr(s->str, ==, "123");
 
125
        g_string_free(s, TRUE);
 
126
        
 
127
        g_assert_cmpint(q->len, ==, 6);
 
128
 
 
129
        s = network_queue_pop_string(q, 4, NULL);
 
130
        g_assert(s);
 
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);
 
135
 
 
136
        s = network_queue_pop_string(q, 7, NULL);
 
137
        g_assert(s == NULL);
 
138
 
 
139
        s = network_queue_peek_string(q, 2, NULL);
 
140
        g_assert(s);
 
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);
 
145
 
 
146
        s = network_queue_pop_string(q, 2, NULL);
 
147
        g_assert(s);
 
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);
 
152
 
 
153
        network_queue_free(q);
 
154
}
 
155
 
 
156
#define TEST_ADDR_IP "127.0.0.1:57684"
 
157
#define TEST_ADDR_CLIENT_UDP "127.0.0.1:0"
 
158
 
 
159
void t_network_socket_bind(void) {
 
160
        network_socket *sock;
 
161
        
 
162
        g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
 
163
 
 
164
        sock = network_socket_new();
 
165
 
 
166
        /* w/o a address set it should fail */
 
167
        g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_bind(sock)); /* should fail, no address */
 
168
 
 
169
        g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
 
170
        
 
171
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
 
172
 
 
173
        network_socket_free(sock);
 
174
 
 
175
        /* bind again, to test if REUSEADDR works */
 
176
        sock = network_socket_new();
 
177
        
 
178
        g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
 
179
        
 
180
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
 
181
 
 
182
        g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_bind(sock)); /* bind a socket that is already bound, should fail */
 
183
 
 
184
        network_socket_free(sock);
 
185
}
 
186
 
 
187
/**
 
188
 * @test  check if the network_socket_connect() works by 
 
189
 *   - setting up a listening socket
 
190
 *   - connection to it
 
191
 *   - write data to it
 
192
 *   - read it back
 
193
 *   - closing it
 
194
 *   
 
195
 */
 
196
void t_network_socket_connect(void) {
 
197
        network_socket *sock;
 
198
        network_socket *client;
 
199
        network_socket *client_connected;
 
200
        fd_set read_fds;
 
201
        struct timeval timeout;
 
202
        network_socket_retval_t ret;
 
203
        
 
204
        g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
 
205
 
 
206
        sock = network_socket_new();
 
207
 
 
208
        g_assert_cmpint(0, ==, network_address_set_address(sock->dst, TEST_ADDR_IP));
 
209
        
 
210
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(sock));
 
211
        
 
212
        client = network_socket_new();
 
213
        g_assert_cmpint(0, ==, network_address_set_address(client->dst, TEST_ADDR_IP));
 
214
 
 
215
        switch ((ret = network_socket_connect(client))) {
 
216
        case NETWORK_SOCKET_ERROR_RETRY:
 
217
                client_connected = network_socket_accept(sock);
 
218
        
 
219
                g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect_finish(client));
 
220
        
 
221
                break;
 
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);
 
225
                break;
 
226
        default:
 
227
                client_connected = NULL;
 
228
                g_assert_cmpint(NETWORK_SOCKET_ERROR_RETRY,  ==, ret);
 
229
                break;
 
230
        }
 
231
        
 
232
        g_assert(client_connected);
 
233
        g_assert_cmpint(NETWORK_SOCKET_ERROR, ==, network_socket_connect(client)); /* we are already connected, sure fail */
 
234
 
 
235
        /* we are connected */
 
236
 
 
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 */
 
239
 
 
240
        FD_ZERO(&read_fds);
 
241
        FD_SET(client_connected->fd, &read_fds);
 
242
        timeout.tv_sec = 1;
 
243
        timeout.tv_usec = 500 * 000; /* wait 500ms */
 
244
        g_assert_cmpint(1, ==, select(client_connected->fd + 1, &read_fds, NULL, NULL, &timeout));
 
245
        
 
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);
 
251
        
 
252
        network_socket_free(client);
 
253
        client = NULL;
 
254
 
 
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);
 
258
 
 
259
        network_socket_free(client_connected);
 
260
        network_socket_free(sock);
 
261
}
 
262
 
 
263
/**
 
264
 * @test  check if the network_socket_connect() works by 
 
265
 *   - setting up a listening socket
 
266
 *   - connection to it
 
267
 *   - write data to it
 
268
 *   - read it back
 
269
 *   - closing it
 
270
 *   
 
271
 */
 
272
void t_network_socket_connect_udp(void) {
 
273
        network_socket *server;
 
274
        network_socket *client;
 
275
        fd_set read_fds;
 
276
        struct timeval timeout;
 
277
        network_socket_retval_t ret;
 
278
        
 
279
        g_log_set_always_fatal(G_LOG_FATAL_MASK); /* we log g_critical() which is fatal for the test-suite */
 
280
 
 
281
        server = network_socket_new();
 
282
        server->socket_type = SOCK_DGRAM;
 
283
 
 
284
        g_assert_cmpint(0, ==, network_address_set_address(server->src, TEST_ADDR_IP)); /* our UDP port */
 
285
        
 
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);
 
289
        
 
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 */
 
294
 
 
295
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(client));
 
296
 
 
297
        /* we are connected */
 
298
 
 
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 */
 
301
 
 
302
        FD_ZERO(&read_fds);
 
303
        FD_SET(server->fd, &read_fds);
 
304
        timeout.tv_sec = 1;
 
305
        timeout.tv_usec = 500 * 000; /* wait 500ms */
 
306
        g_assert_cmpint(1, ==, select(server->fd + 1, &read_fds, NULL, NULL, &timeout));
 
307
        
 
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);
 
313
        
 
314
        network_socket_free(client);
 
315
        network_socket_free(server);
 
316
}
 
317
 
 
318
#ifndef WIN32
 
319
 
 
320
/**
 
321
 * test if _is_local() works on unix-domain sockets
 
322
 *
 
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 
 
324
 */
 
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 */
 
329
 
 
330
        g_test_bug("42220");
 
331
        g_log_set_always_fatal(G_LOG_FATAL_MASK); /* gtest modifies the fatal-mask */
 
332
 
 
333
        s_sock = network_socket_new();
 
334
        network_address_set_address(s_sock->dst, "/tmp/mysql-proxy-test.socket");
 
335
 
 
336
        c_sock = network_socket_new();
 
337
        network_address_set_address(c_sock->dst, "/tmp/mysql-proxy-test.socket");
 
338
 
 
339
 
 
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));
 
342
 
 
343
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect(c_sock));
 
344
 
 
345
        a_sock = network_socket_accept(s_sock);
 
346
        g_assert(a_sock);
 
347
 
 
348
        g_assert_cmpint(TRUE, ==, network_address_is_local(s_sock->dst, a_sock->dst));
 
349
 
 
350
        network_socket_free(a_sock);
 
351
        network_socket_free(c_sock);
 
352
        network_socket_free(s_sock);
 
353
 
 
354
        g_unlink("/tmp/mysql-proxy-test.socket");
 
355
}
 
356
 
 
357
void t_network_localsocket_setup(local_unix_t *p, gconstpointer G_GNUC_UNUSED _test_data) {
 
358
        g_assert(p != NULL);
 
359
        snprintf(p->sockname, sizeof(p->sockname), LOCAL_SOCK ".%d", (int)getpid());
 
360
        pp = p;
 
361
}
 
362
 
 
363
void t_network_localsocket_teardown(local_unix_t *p, gconstpointer G_GNUC_UNUSED _test_data) {
 
364
        g_assert(p != NULL);
 
365
        if (p->sockname[0] != '\0') {
 
366
                (void) g_unlink(p->sockname);
 
367
                p->sockname[0] = '\0';
 
368
        }
 
369
        pp = NULL;
 
370
}
 
371
 
 
372
void exitfunc(int sig) {
 
373
        if (pp != NULL && pp->sockname[0] != '\0')
 
374
                (void) g_unlink(pp->sockname);
 
375
 
 
376
        abort();
 
377
}
 
378
 
 
379
/**
 
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.
 
383
 */
 
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 */
 
388
 
 
389
        /*
 
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.
 
393
         */
 
394
        signal(SIGABRT, exitfunc);
 
395
        g_test_bug("42220");
 
396
        g_log_set_always_fatal(G_LOG_FATAL_MASK); /* gtest modifies the fatal-mask */
 
397
 
 
398
        s_sock = network_socket_new();
 
399
        network_address_set_address(s_sock->dst, p->sockname);
 
400
 
 
401
        c_sock = network_socket_new();
 
402
        network_address_set_address(c_sock->dst, p->sockname);
 
403
 
 
404
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(s_sock));
 
405
 
 
406
        g_assert_cmpint(g_access(p->sockname, 0), ==, 0);
 
407
 
 
408
        g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect(c_sock));
 
409
 
 
410
        a_sock = network_socket_accept(s_sock);
 
411
        g_assert(a_sock);
 
412
 
 
413
        g_assert_cmpint(TRUE, ==, network_address_is_local(s_sock->dst, a_sock->dst));
 
414
 
 
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);
 
421
 
 
422
        /* re-establish default signal disposition */
 
423
        signal(SIGABRT, SIG_DFL);
 
424
}
 
425
 
 
426
#endif /* WIN32 */
 
427
 
 
428
int main(int argc, char **argv) {
 
429
        g_test_init(&argc, &argv, NULL);
 
430
        g_test_bug_base("http://bugs.mysql.com/");
 
431
 
 
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);
 
438
#ifndef WIN32
 
439
        g_test_add_func("/core/network_socket_is_local_unix",t_network_socket_is_local_unix);
 
440
 
 
441
        g_test_add("/core/network_socket_rem_local_unix", local_unix_t,
 
442
                        &local_test_arg,
 
443
                        t_network_localsocket_setup, t_network_socket_rem_local_unix, 
 
444
                        t_network_localsocket_teardown);
 
445
#endif /* WIN32 */
 
446
#if 0
 
447
        /**
 
448
         * disabled for now until we fixed the _to_read() on HP/UX and AIX (and MacOS X)
 
449
         *
 
450
         * ERROR:(t_network_socket.c:287):???: assertion failed (3 == server->to_read): (3 == 19)
 
451
         */
 
452
        g_test_add_func("/core/network_socket_udp", t_network_socket_connect_udp);
 
453
#endif
 
454
 
 
455
        return g_test_run();
 
456
}
 
457
#else /* GLIB_CHECK_VERSION */
 
458
int main() {
 
459
        return 77;
 
460
}
 
461
#endif /* GLIB_CHECK_VERSION */