source: trunk/ORBit2-2.14.0/linc2/test/test-linc.c

Last change on this file was 92, checked in by cinc, 19 years ago

Orbit2 modified for use with NOM

File size: 11.8 KB
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
52static GType test_server_cnx_type = 0;
53static GType test_client_cnx_type = 0;
54static gboolean 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
208static GIOCondition
209knobble_watch (LinkWatch *watch, GIOCondition new_cond)
210{
211 GIOCondition old_cond;
212
213 g_assert (watch != NULL);
214
215 old_cond = ((LinkUnixWatch *) watch->link_source)->condition;
216
217 g_assert (old_cond == ((LinkUnixWatch *) watch->main_source)->condition);
218
219 link_watch_set_condition (watch, new_cond);
220
221 return old_cond;
222}
223
224typedef struct {
225 int status;
226 GIOCondition old_cond;
227 LinkConnection *s_cnx;
228} BlockingData;
229
230static void
231blocking_cb (LinkConnection *cnx,
232 gulong buffer_size,
233 gpointer user_data)
234{
235 BlockingData *bd = user_data;
236
237 if (bd->status < 3)
238 fprintf (stderr, " buffer %ld\n", buffer_size);
239
240 bd->status++;
241
242 if (buffer_size == BUFFER_MAX) {
243 knobble_watch (bd->s_cnx->priv->tag, bd->old_cond);
244
245 /* flush the queue to other side */
246 while (cnx->priv->write_queue != NULL &&
247 cnx->status == LINK_CONNECTED)
248 link_main_iteration (FALSE);
249
250 g_assert (cnx->status == LINK_CONNECTED);
251 }
252}
253
254static gboolean
255test_blocking_cnx_handle_input (LinkConnection *cnx)
256{
257 static gulong idx = 0;
258 glong size, i;
259 guint32 buffer[1024];
260
261 size = link_connection_read (cnx, (guchar *) buffer, 512, TRUE);
262 g_assert (size != -1);
263 g_assert ((size & 0x3) == 0);
264 g_assert (size <= 512);
265
266 for (i = 0; i < (size >> 2); i++)
267 g_assert (buffer [i] == idx++);
268
269 return TRUE;
270}
271
272static void
273test_blocking_cnx_class_init (LinkConnectionClass *klass)
274{
275 klass->handle_input = test_blocking_cnx_handle_input;
276}
277
278static GType
279test_get_blocking_cnx_type (void)
280{
281 static GType object_type = 0;
282
283 if (!object_type) {
284 static const GTypeInfo object_info = {
285 sizeof (LinkConnectionClass),
286 (GBaseInitFunc) NULL,
287 (GBaseFinalizeFunc) NULL,
288 (GClassInitFunc) test_blocking_cnx_class_init,
289 NULL, /* class_finalize */
290 NULL, /* class_data */
291 sizeof (LinkConnection),
292 0, /* n_preallocs */
293 (GInstanceInitFunc) NULL,
294 };
295
296 object_type = g_type_register_static (
297 LINK_TYPE_CONNECTION, "TestConnection",
298 &object_info, 0);
299 }
300
301 return object_type;
302}
303
304static void
305test_blocking (void)
306{
307 BlockingData bd;
308 LinkServer *server;
309 LinkConnection *client;
310 LinkWriteOpts *options;
311 guint32 buffer[1024] = { 0 };
312 glong l;
313 int i;
314
315 fprintf (stderr, "Testing blocking code ...\n");
316
317 /* Create our own LinkConnection to verify input */
318 test_server_cnx_type = test_get_blocking_cnx_type ();
319
320 create_server (&server);
321 create_client (server, &client);
322 link_main_iteration (FALSE); /* connect */
323
324 g_assert (server->priv->connections != NULL);
325 bd.s_cnx = server->priv->connections->data;
326 g_assert (bd.s_cnx != NULL);
327 g_assert (bd.s_cnx->priv->tag != NULL);
328 bd.old_cond = knobble_watch (bd.s_cnx->priv->tag, 0); /* stop it listening */
329
330 options = link_write_options_new (FALSE);
331 link_connection_set_max_buffer (client, BUFFER_MAX);
332 g_signal_connect (G_OBJECT (client), "blocking",
333 G_CALLBACK (blocking_cb), &bd);
334 client->options |= LINK_CONNECTION_BLOCK_SIGNAL;
335
336 l = 0;
337 bd.status = 0;
338 for (i = 0; i < SYS_SOCKET_BUFFER_MAX; i+= 128) {
339 int j;
340
341 for (j = 0; j < 128/4; j++)
342 buffer [j] = l++;
343
344 link_connection_write (
345 client, (guchar *) buffer, 128, options);
346 if (client->status != LINK_CONNECTED)
347 break;
348 }
349
350 g_assert (client->status == LINK_CONNECTED);
351 g_assert (bd.status >= 3);
352
353 link_connection_unref (client);
354 g_assert (client == NULL);
355
356 link_main_iteration (FALSE);
357
358 g_object_unref (server);
359 g_assert (server == NULL);
360
361 test_server_cnx_type = 0;
362
363 link_write_options_free (options);
364}
365
366static void
367test_local_ipv4 (void)
368{
369 LinkSockLen saddr_len;
370 LinkProtocolInfo *proto;
371 struct sockaddr *saddr;
372 struct sockaddr_in ipv4_addr = { 0 };
373
374 fprintf (stderr, " IPv4\n");
375 proto = link_protocol_find ("IPv4");
376 g_assert (proto != NULL);
377
378 ipv4_addr.sin_family = AF_INET;
379 ipv4_addr.sin_port = 1234;
380 memset (&ipv4_addr.sin_addr.s_addr, 0xaa, 4);
381 g_assert (!link_protocol_is_local (
382 proto, (struct sockaddr *)&ipv4_addr,
383 sizeof (ipv4_addr)));
384
385 saddr = link_protocol_get_sockaddr (
386 proto, link_get_local_hostname (), NULL, &saddr_len);
387
388 g_assert (link_protocol_is_local (proto, saddr, saddr_len));
389 g_free (saddr);
390}
391
392static void
393test_local_ipv6 (void)
394{
395#ifdef AF_INET6
396 LinkProtocolInfo *proto;
397 struct sockaddr_in6 ipv6_addr = { 0 };
398
399 fprintf (stderr, " IPv6\n");
400 proto = link_protocol_find ("IPv6");
401 g_assert (proto != NULL);
402
403 g_assert (proto != NULL);
404
405 ipv6_addr.sin6_family = AF_INET6;
406 ipv6_addr.sin6_port = 1234;
407 memset (&ipv6_addr.sin6_addr.s6_addr, 0xaa, 16);
408 g_assert (!link_protocol_is_local (
409 proto, (struct sockaddr *)&ipv6_addr,
410 sizeof (ipv6_addr)));
411#else
412 g_assert (link_protocol_find ("IPv6") == NULL);
413#endif
414}
415
416static void
417test_local (void)
418{
419#ifndef G_OS_WIN32
420 LinkProtocolInfo *proto;
421#endif
422
423 fprintf (stderr, "Testing is_local checking ...\n");
424
425 g_assert (!link_protocol_is_local (NULL, NULL, -1));
426
427#ifndef G_OS_WIN32
428 fprintf (stderr, " UNIX\n");
429 proto = link_protocol_find ("UNIX");
430 g_assert (proto != NULL);
431 g_assert (link_protocol_is_local (proto, NULL, -1));
432#endif
433 test_local_ipv4 ();
434 test_local_ipv6 ();
435}
436
437static void
438verify_addr_is_loopback (guint8 *addr, int length)
439{
440 int i;
441
442 if (length == 4)
443 i = 0;
444
445 else if (length == 16) {
446
447 for (i = 0; i < 10; i++)
448 if (addr [i] != 0)
449 return;
450
451 if (addr [i++] != 0xff || addr [i++] != 0xff)
452 return;
453 } else {
454 i = 0;
455 g_assert_not_reached ();
456 }
457
458 if (addr [i + 0] == 127 &&
459 addr [i + 1] == 0 &&
460 addr [i + 2] == 0 &&
461 addr [i + 3] == 1) {
462 g_warning (" --- The reverse lookup of your hostname "
463 "is 127.0.0.1 you will not be able to "
464 "do inter-machine comms. ---");
465 exit (0);
466 }
467}
468
469static void
470test_hosts_lookup (void)
471{
472 int i;
473 struct hostent *hent;
474 LinkProtocolInfo *proto;
475 LinkSockLen saddr_len;
476 struct sockaddr_in *addr;
477
478 hent = gethostbyname (link_get_local_hostname ());
479 g_assert (hent != NULL);
480
481 fprintf (stderr, " official name '%s' aliases: ",
482 hent->h_name);
483
484 for (i = 0; hent->h_aliases [i]; i++)
485 fprintf (stderr, " '%s'", hent->h_aliases [i]);
486 fprintf (stderr, "\n");
487
488 verify_addr_is_loopback (hent->h_addr_list [0], hent->h_length);
489
490 proto = link_protocol_find ("IPv4");
491 addr = (struct sockaddr_in *)link_protocol_get_sockaddr (
492 proto, "127.0.0.1", "1047", &saddr_len);
493 g_assert (addr != NULL);
494 g_assert (saddr_len == sizeof (struct sockaddr_in));
495
496 verify_addr_is_loopback ((guint8 *) &addr->sin_addr.s_addr, saddr_len);
497}
498
499static void
500test_host (void)
501{
502 char *portnum;
503 char *hostname;
504 LinkSockLen saddr_len;
505 struct sockaddr *saddr;
506 LinkProtocolInfo *proto;
507
508 proto = link_protocol_find ("IPv4");
509 g_assert (proto != NULL);
510 g_assert (proto->get_sockinfo != NULL);
511
512 saddr = link_protocol_get_sockaddr (
513 proto, link_get_local_hostname (),
514 NULL, &saddr_len);
515 g_assert (saddr != NULL);
516
517 g_assert (link_protocol_get_sockinfo (
518 proto, saddr, &hostname, &portnum));
519
520 g_free (saddr);
521
522 fprintf (stderr, " '%s': '%s' \n",
523 link_get_local_hostname (),
524 hostname);
525
526 g_free (hostname);
527 g_free (portnum);
528
529 test_hosts_lookup ();
530}
531
532static void
533test_connected (void)
534{
535 LinkServer *server = NULL;
536 LinkConnection *client = NULL;
537
538 create_server (&server);
539 g_assert (server != NULL);
540 create_client (server, &client);
541 g_assert (client != NULL);
542
543 /* FIXME: this is horribly difficult to regression test properly: we fail */
544 g_assert (link_connection_wait_connected (client) == LINK_CONNECTED);
545
546 g_object_unref (server);
547 link_connection_unref (client);
548}
549
550int
551main (int argc, char **argv)
552{
553 link_init (TRUE);
554 init_tmp ();
555
556 test_protos ();
557 test_connected ();
558#ifdef HAVE_SYS_WAIT_H
559 test_broken ();
560#endif
561 test_blocking ();
562 test_local ();
563 test_host ();
564
565 fprintf (stderr, "All tests passed successfully\n");
566
567 return 0;
568}
Note: See TracBrowser for help on using the repository browser.