source: trunk/third/ORBit2/linc2/test/test-linc.c @ 21310

Revision 21310, 11.9 KB checked in by ghudson, 19 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21309, which included commits to RCS files with non-trunk default branches.
Line 
1#include "config.h"
2#ifdef HAVE_SYS_WAIT_H
3#  include <sys/wait.h>
4#endif
5#include <linc/linc.h>
6#include "linc-private.h"
7#include "linc-compat.h"
8
9#define SYS_SOCKET_BUFFER_MAX (512 * 1024)
10#define BUFFER_MAX 1024
11
12static void
13test_protos (void)
14{
15        LinkProtocolInfo *info;
16
17        info = link_protocol_all ();
18
19        fprintf (stderr, "Available protocols: {\n");
20
21        while (info && info->name) {
22                fprintf (stderr, "\t'%8s': %2d, %3d, %2d, 0x%.4x [%c%c%c%c%c]\n",
23                         info->name, info->family, info->addr_len,
24                         info->stream_proto_num, info->flags,
25                         info->setup ?        's' : '-',
26                         info->destroy ?      'd' : '-',
27                         info->get_sockaddr ? 'a' : '-',
28                         info->get_sockinfo ? 'i' : '-',
29                         info->is_local ?     'l' : '-');
30                info++;
31        }
32       
33        fprintf (stderr, " }\n");
34}
35
36static void
37init_tmp (void)
38{
39        char *dir;
40        const char *user = g_get_user_name ();
41
42        dir = g_build_filename (g_get_tmp_dir (),
43                                g_strconcat ("orbit-", user, NULL),
44                                NULL);
45         
46
47        link_set_tmpdir (dir);
48
49        g_free (dir);
50}
51
52GType    test_server_cnx_type = 0;
53GType    test_client_cnx_type = 0;
54gboolean connected = FALSE;
55
56static LinkConnection *
57test_server_create_connection (LinkServer *cnx)
58{
59        GType t;
60
61        t = test_server_cnx_type ? test_server_cnx_type : link_connection_get_type ();
62
63        connected = TRUE;
64
65        return g_object_new (t, NULL);
66}
67
68static void
69create_server (LinkServer **server)
70{
71        LinkServerClass *klass;
72
73        klass = g_type_class_ref (link_server_get_type ());
74        klass->create_connection = test_server_create_connection;
75
76        *server = g_object_new (link_server_get_type (), NULL);
77       
78#ifdef G_OS_WIN32
79        g_assert (link_server_setup (*server, "IPv4", NULL, "1234",
80                                     LINK_CONNECTION_NONBLOCKING));
81#else   
82        g_assert (link_server_setup (*server, "UNIX", NULL, NULL,
83                                     LINK_CONNECTION_NONBLOCKING));
84#endif
85        g_object_add_weak_pointer (G_OBJECT (*server),
86                                   (gpointer *) server);
87}
88
89static void
90create_client (LinkServer *server, LinkConnection **client)
91{
92        *client = link_connection_initiate
93                (test_client_cnx_type ? test_client_cnx_type :
94                 link_connection_get_type (),
95#ifdef G_OS_WIN32
96                 "IPv4",
97#else
98                 "UNIX",
99#endif
100                 server->local_host_info,
101                 server->local_serv_info,
102                 LINK_CONNECTION_NONBLOCKING,
103                 NULL);
104        g_assert (*client != NULL);
105
106        g_object_add_weak_pointer (G_OBJECT (*client),
107                                   (gpointer *) client);
108}
109
110#ifdef HAVE_SYS_WAIT_H
111
112static gboolean
113test_broken_cnx_handle_input (LinkConnection *cnx)
114{
115        glong  ret;
116        guchar buffer;
117
118        ret = link_connection_read (cnx, &buffer, 1, FALSE);
119
120        g_assert (ret == LINK_IO_FATAL_ERROR);
121
122        link_connection_state_changed (cnx, LINK_DISCONNECTED);
123
124        return TRUE;
125}
126
127static void
128test_broken_cnx_class_init (LinkConnectionClass *klass)
129{
130        klass->handle_input = test_broken_cnx_handle_input;
131}
132
133static GType
134test_get_broken_cnx_type (void)
135{
136        static GType object_type = 0;
137
138        if (!object_type) {
139                static const GTypeInfo object_info = {
140                        sizeof (LinkConnectionClass),
141                        (GBaseInitFunc) NULL,
142                        (GBaseFinalizeFunc) NULL,
143                        (GClassInitFunc) test_broken_cnx_class_init,
144                        NULL,           /* class_finalize */
145                        NULL,           /* class_data */
146                        sizeof (LinkConnection),
147                        0,              /* n_preallocs */
148                        (GInstanceInitFunc) NULL,
149                };
150     
151                object_type = g_type_register_static (
152                        LINK_TYPE_CONNECTION, "TestConnection",
153                        &object_info, 0);
154        }
155
156        return object_type;
157}
158
159static void
160broken_cb (LinkConnection *cnx, gpointer user_data)
161{
162        g_assert (user_data == NULL);
163
164        exit (13);
165}
166
167static void
168test_broken (void)
169{
170        LinkServer     *server;
171        LinkConnection *client;
172        pid_t           child;
173        int             status;
174
175        fprintf (stderr, "Testing 'broken' ...\n");
176
177        create_server (&server);
178
179        if ((child = fork ()) == 0) { /* child */
180                test_client_cnx_type = test_get_broken_cnx_type ();
181                create_client (server, &client);
182                test_client_cnx_type = 0;
183
184                g_signal_connect (G_OBJECT (client), "broken",
185                                  G_CALLBACK (broken_cb), NULL);
186
187                g_object_unref (G_OBJECT (server));
188                g_assert (server == NULL);
189
190                link_main_loop_run ();
191
192                g_assert_not_reached ();
193        }
194
195        while (!connected)
196                link_main_iteration (FALSE);
197        connected = FALSE;
198
199        g_object_unref (G_OBJECT (server));
200        g_assert (server == NULL);
201
202        waitpid (child, &status, 0);
203        g_assert (WIFEXITED (status) && WEXITSTATUS (status) == 13);
204}
205
206#endif
207
208#ifndef G_OS_WIN32
209
210static GIOCondition
211knobble_watch (LinkWatch *watch, GIOCondition new_cond)
212{
213        GIOCondition   old_cond;
214
215        g_assert (watch != NULL);
216
217        old_cond = ((LinkUnixWatch *) watch->link_source)->condition;
218
219        g_assert (old_cond == ((LinkUnixWatch *) watch->main_source)->condition);
220       
221        link_watch_set_condition (watch, new_cond);
222
223        return old_cond;
224}
225
226typedef struct {
227        int             status;
228        GIOCondition    old_cond;
229        LinkConnection *s_cnx;
230} BlockingData;
231
232static void
233blocking_cb (LinkConnection *cnx,
234             gulong          buffer_size,
235             gpointer        user_data)
236{
237        BlockingData *bd = user_data;
238
239        fprintf (stderr, "blocking_cb\n");
240
241        if (bd->status < 3)
242                fprintf (stderr, " buffer %ld\n", buffer_size);
243
244        bd->status++;
245
246        if (buffer_size == BUFFER_MAX) {
247                knobble_watch (bd->s_cnx->priv->tag, bd->old_cond);
248
249                /* flush the queue to other side */
250                while (cnx->priv->write_queue != NULL &&
251                       cnx->status == LINK_CONNECTED)
252                        link_main_iteration (FALSE);
253
254                g_assert (cnx->status == LINK_CONNECTED);
255        }
256}
257
258static gboolean
259test_blocking_cnx_handle_input (LinkConnection *cnx)
260{
261        static  gulong idx = 0;
262        glong   size, i;
263        guint32 buffer[1024];
264
265        size = link_connection_read (cnx, (guchar *) buffer, 512, TRUE);
266        g_assert (size != -1);
267        g_assert ((size & 0x3) == 0);
268        g_assert (size <= 512);
269
270        for (i = 0; i < (size >> 2); i++)
271                g_assert (buffer [i] == idx++);
272
273        return TRUE;
274}
275
276static void
277test_blocking_cnx_class_init (LinkConnectionClass *klass)
278{
279        klass->handle_input = test_blocking_cnx_handle_input;
280}
281
282static GType
283test_get_blocking_cnx_type (void)
284{
285        static GType object_type = 0;
286
287        if (!object_type) {
288                static const GTypeInfo object_info = {
289                        sizeof (LinkConnectionClass),
290                        (GBaseInitFunc) NULL,
291                        (GBaseFinalizeFunc) NULL,
292                        (GClassInitFunc) test_blocking_cnx_class_init,
293                        NULL,           /* class_finalize */
294                        NULL,           /* class_data */
295                        sizeof (LinkConnection),
296                        0,              /* n_preallocs */
297                        (GInstanceInitFunc) NULL,
298                };
299     
300                object_type = g_type_register_static (
301                        LINK_TYPE_CONNECTION, "TestConnection",
302                        &object_info, 0);
303        }
304
305        return object_type;
306}
307
308static void
309test_blocking (void)
310{
311        BlockingData    bd;
312        LinkServer     *server;
313        LinkConnection *client;
314        LinkWriteOpts  *options;
315        guint32         buffer[1024] = { 0 };
316        glong           l;
317        int             i;
318
319        fprintf (stderr, "Testing blocking code ...\n");
320
321        /* Create our own LinkConnection to verify input */
322        test_server_cnx_type = test_get_blocking_cnx_type ();
323
324        create_server (&server);
325        create_client (server, &client);
326        link_main_iteration (FALSE); /* connect */
327
328        g_assert (server->priv->connections != NULL);
329        bd.s_cnx = server->priv->connections->data;
330        g_assert (bd.s_cnx != NULL);
331        g_assert (bd.s_cnx->priv->tag != NULL);
332        bd.old_cond = knobble_watch (bd.s_cnx->priv->tag, 0); /* stop it listening */
333
334        options = link_write_options_new (FALSE);
335        link_connection_set_max_buffer (client, BUFFER_MAX);
336        g_signal_connect (G_OBJECT (client), "blocking",
337                          G_CALLBACK (blocking_cb), &bd);
338        client->options |= LINK_CONNECTION_BLOCK_SIGNAL;
339
340        l = 0;
341        bd.status = 0;
342        for (i = 0; i < SYS_SOCKET_BUFFER_MAX; i+= 128) {
343                int j;
344
345                for (j = 0; j < 128/4; j++)
346                        buffer [j] = l++;
347
348                link_connection_write (
349                        client, (guchar *) buffer, 128, options);
350                if (client->status != LINK_CONNECTED)
351                        break;
352        }
353
354        g_assert (client->status == LINK_CONNECTED);
355        g_assert (bd.status >= 3);
356
357        link_connection_unref (client);
358        g_assert (client == NULL);
359
360        link_main_iteration (FALSE);
361
362        g_object_unref (server);
363        g_assert (server == NULL);
364
365        test_server_cnx_type = 0;
366
367        link_write_options_free (options);
368}
369
370#endif
371
372static void
373test_local_ipv4 (void)
374{
375        LinkSockLen saddr_len;
376        LinkProtocolInfo *proto;
377        struct sockaddr *saddr;
378        struct sockaddr_in ipv4_addr = { 0 };
379
380        fprintf (stderr, " IPv4\n");
381        proto = link_protocol_find ("IPv4");
382        g_assert (proto != NULL);
383
384        ipv4_addr.sin_family = AF_INET;
385        ipv4_addr.sin_port = 1234;
386        memset (&ipv4_addr.sin_addr.s_addr, 0xaa, 4);
387        g_assert (!link_protocol_is_local (
388                proto, (struct sockaddr *)&ipv4_addr,
389                sizeof (ipv4_addr)));
390
391        saddr = link_protocol_get_sockaddr (
392                proto, link_get_local_hostname (), NULL, &saddr_len);
393
394        g_assert (link_protocol_is_local (proto, saddr, saddr_len));
395        g_free (saddr);
396}
397
398static void
399test_local_ipv6 (void)
400{
401#ifdef AF_INET6
402        LinkProtocolInfo *proto;
403        struct sockaddr_in6 ipv6_addr = { 0 };
404
405        fprintf (stderr, " IPv6\n");
406        proto = link_protocol_find ("IPv6");
407        g_assert (proto != NULL);
408
409        g_assert (proto != NULL);
410
411        ipv6_addr.sin6_family = AF_INET6;
412        ipv6_addr.sin6_port = 1234;
413        memset (&ipv6_addr.sin6_addr.s6_addr, 0xaa, 16);
414        g_assert (!link_protocol_is_local (
415                proto, (struct sockaddr *)&ipv6_addr,
416                sizeof (ipv6_addr)));
417#else
418        g_assert (link_protocol_find ("IPv6") == NULL);
419#endif
420}
421
422static void
423test_local (void)
424{
425        LinkProtocolInfo *proto;
426
427        fprintf (stderr, "Testing is_local checking ...\n");
428
429        g_assert (!link_protocol_is_local (NULL, NULL, -1));
430
431#ifndef G_OS_WIN32
432        fprintf (stderr, " UNIX\n");
433        proto = link_protocol_find ("UNIX");
434        g_assert (proto != NULL);
435        g_assert (link_protocol_is_local (proto, NULL, -1));
436#endif
437        test_local_ipv4 ();
438        test_local_ipv6 ();
439}
440
441static void
442verify_addr_is_loopback (guint8 *addr, int length)
443{
444        int i;
445
446        if (length == 4)
447                i = 0;
448
449        else if (length == 16) {
450
451                for (i = 0; i < 10; i++)
452                        if (addr [i] != 0)
453                                return;
454
455                if (addr [i++] != 0xff || addr [i++] != 0xff)
456                        return;
457        } else {
458                i = 0;
459                g_assert_not_reached ();
460        }
461
462        if (addr [i + 0] == 127 &&
463            addr [i + 1] == 0 &&
464            addr [i + 2] == 0 &&
465            addr [i + 3] == 1) {
466                g_warning (" --- The reverse lookup of your hostname "
467                           "is 127.0.0.1 you will not be able to "
468                           "do inter-machine comms. ---");
469                exit (0);
470        }
471}
472
473static void
474test_hosts_lookup (void)
475{
476        int i;
477        struct hostent *hent;
478        LinkProtocolInfo *proto;
479        LinkSockLen saddr_len;
480        struct sockaddr_in *addr;
481               
482        hent = gethostbyname (link_get_local_hostname ());
483        g_assert (hent != NULL);
484
485        fprintf (stderr, " official name '%s' aliases: ",
486                 hent->h_name);
487
488        for (i = 0; hent->h_aliases [i]; i++)
489                fprintf (stderr, " '%s'", hent->h_aliases [i]);
490        fprintf (stderr, "\n");
491
492        verify_addr_is_loopback (hent->h_addr_list [0], hent->h_length);
493
494        proto = link_protocol_find ("IPv4");
495        addr = (struct sockaddr_in *)link_protocol_get_sockaddr (
496                proto, "127.0.0.1", "1047", &saddr_len);
497        g_assert (addr != NULL);
498        g_assert (saddr_len == sizeof (struct sockaddr_in));
499       
500        verify_addr_is_loopback ((guint8 *) &addr->sin_addr.s_addr, saddr_len);
501}
502
503static void
504test_host (void)
505{
506        char *portnum;
507        char *hostname;
508        LinkSockLen saddr_len;
509        struct sockaddr *saddr;
510        LinkProtocolInfo *proto;
511
512        proto = link_protocol_find ("IPv4");
513        g_assert (proto != NULL);
514        g_assert (proto->get_sockinfo != NULL);
515
516        saddr = link_protocol_get_sockaddr (
517                proto, link_get_local_hostname (),
518                NULL, &saddr_len);
519        g_assert (saddr != NULL);
520
521        g_assert (link_protocol_get_sockinfo (
522                proto, saddr, &hostname, &portnum));
523
524        g_free (saddr);
525
526        fprintf (stderr, " '%s': '%s' \n",
527                 link_get_local_hostname (),
528                 hostname);
529
530        g_free (hostname);
531        g_free (portnum);
532
533        test_hosts_lookup ();
534}
535
536static void
537test_connected (void)
538{
539        LinkServer *server = NULL;
540        LinkConnection *client = NULL;
541
542        create_server (&server);
543        g_assert (server != NULL);
544        create_client (server, &client);
545        g_assert (client != NULL);
546
547        /* FIXME: this is horribly difficult to regression test properly: we fail */
548        g_assert (link_connection_wait_connected (client) == LINK_CONNECTED);
549
550        g_object_unref (server);
551        link_connection_unref (client);
552}
553
554int
555main (int argc, char **argv)
556{       
557        link_init (TRUE);
558        init_tmp ();
559
560        test_protos ();
561        test_connected ();
562#ifdef HAVE_SYS_WAIT_H
563        test_broken ();
564#endif
565#ifndef G_OS_WIN32
566        test_blocking ();
567#endif
568        test_local ();
569        test_host ();
570
571        fprintf (stderr, "All tests passed successfully\n");
572       
573        return 0;
574}
Note: See TracBrowser for help on using the repository browser.