1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/glib/tsrc/BC/tests/gio-test.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,551 @@
1.4 +/* GLIB - Library of useful routines for C programming
1.5 + * Copyright (C) 2000 Tor Lillqvist
1.6 + * Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
1.7 + * This library is free software; you can redistribute it and/or
1.8 + * modify it under the terms of the GNU Lesser General Public
1.9 + * License as published by the Free Software Foundation; either
1.10 + * version 2 of the License, or (at your option) any later version.
1.11 + *
1.12 + * This library is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.15 + * Lesser General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU Lesser General Public
1.18 + * License along with this library; if not, write to the
1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.20 + * Boston, MA 02111-1307, USA.
1.21 + */
1.22 +
1.23 +/* A test program for the main loop and IO channel code.
1.24 + * Just run it. Optional parameter is number of sub-processes.
1.25 + */
1.26 +
1.27 +
1.28 +#undef G_DISABLE_ASSERT
1.29 +#undef G_LOG_DOMAIN
1.30 +
1.31 +#include "config.h"
1.32 +
1.33 +#include <glib.h>
1.34 +#include <unistd.h>
1.35 +#include <stdio.h>
1.36 +#include <stdlib.h>
1.37 +#include <math.h>
1.38 +#include <time.h>
1.39 +
1.40 +#ifdef SYMBIAN
1.41 + //#define VERBOSE
1.42 + #include <pthread.h>
1.43 + #include "mrt2_glib2_test.h"
1.44 + void *child_function(void*);
1.45 + gboolean child_terminated = FALSE;
1.46 + int from_descriptor, to_descriptor;
1.47 +#endif /*SYMBIAN*/
1.48 +
1.49 +#ifdef G_OS_WIN32
1.50 + #include <io.h>
1.51 + #include <fcntl.h>
1.52 + #include <process.h>
1.53 + #define STRICT
1.54 + #include <windows.h>
1.55 +#else
1.56 + #ifdef HAVE_UNISTD_H
1.57 + #include <unistd.h>
1.58 + #endif
1.59 +#endif
1.60 +
1.61 +
1.62 +static int nrunning;
1.63 +static GMainLoop *main_loop;
1.64 +
1.65 +#ifdef SYMBIAN
1.66 +#define BUFSIZE 1000
1.67 +#else
1.68 +#define BUFSIZE 5000 /* Larger than the circular buffer in giowin32.c on purpose.*/
1.69 +#endif
1.70 +
1.71 +static int nkiddies;
1.72 +
1.73 +static struct {
1.74 + int fd;
1.75 + int seq;
1.76 +} *seqtab;
1.77 +
1.78 +
1.79 +
1.80 +static GIOError
1.81 +read_all (int fd,
1.82 + GIOChannel *channel,
1.83 + char *buffer,
1.84 + guint nbytes,
1.85 + guint *bytes_read)
1.86 +{
1.87 + guint left = nbytes;
1.88 + gsize nb;
1.89 + GIOError error = G_IO_ERROR_NONE;
1.90 + char *bufp = buffer;
1.91 +
1.92 + /* g_io_channel_read() doesn't necessarily return all the
1.93 + * data we want at once.
1.94 + */
1.95 + *bytes_read = 0;
1.96 + while (left)
1.97 + {
1.98 + error = g_io_channel_read (channel, bufp, left, &nb);
1.99 +
1.100 + if (error != G_IO_ERROR_NONE)
1.101 + {
1.102 + g_print ("gio-test: ...from %d: G_IO_ERROR_%s\n", fd,
1.103 + (error == G_IO_ERROR_AGAIN ? "AGAIN" :
1.104 + (error == G_IO_ERROR_INVAL ? "INVAL" :
1.105 + (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???"))));
1.106 + if (error == G_IO_ERROR_AGAIN)
1.107 + continue;
1.108 + break;
1.109 + }
1.110 + if (nb == 0)
1.111 + return error;
1.112 + left -= nb;
1.113 + bufp += nb;
1.114 + *bytes_read += nb;
1.115 + }
1.116 + return error;
1.117 +}
1.118 +
1.119 +static void
1.120 +shutdown_source (gpointer data)
1.121 +{
1.122 + if (g_source_remove (*(guint *) data))
1.123 + {
1.124 + nrunning--;
1.125 + if (nrunning == 0)
1.126 + g_main_loop_quit (main_loop);
1.127 + }
1.128 +}
1.129 +
1.130 +static gboolean
1.131 +recv_message (GIOChannel *channel,
1.132 + GIOCondition cond,
1.133 + gpointer data)
1.134 +{
1.135 + gint fd = g_io_channel_unix_get_fd (channel);
1.136 + gboolean retval = TRUE;
1.137 +
1.138 +#ifdef VERBOSE
1.139 + g_print ("gio-test: ...from %d:%s%s%s%s\n", fd,
1.140 + (cond & G_IO_ERR) ? " ERR" : "",
1.141 + (cond & G_IO_HUP) ? " HUP" : "",
1.142 + (cond & G_IO_IN) ? " IN" : "",
1.143 + (cond & G_IO_PRI) ? " PRI" : "");
1.144 +#endif
1.145 +
1.146 + if ((cond & (G_IO_ERR | G_IO_HUP)))
1.147 + {
1.148 + shutdown_source (data);
1.149 + retval = FALSE;
1.150 + }
1.151 +
1.152 + if (cond & G_IO_IN)
1.153 + {
1.154 + char buf[BUFSIZE];
1.155 + guint nbytes;
1.156 + guint nb;
1.157 + int i, j, seq;
1.158 + GIOError error;
1.159 +
1.160 + error = read_all (fd, channel, (gchar *) &seq, sizeof (seq), &nb);
1.161 + if (error == G_IO_ERROR_NONE)
1.162 + {
1.163 + if (nb == 0)
1.164 + {
1.165 +#ifdef VERBOSE
1.166 + g_print ("gio-test: ...from %d: EOF\n", fd);
1.167 +#endif
1.168 + shutdown_source (data);
1.169 + return FALSE;
1.170 + }
1.171 +
1.172 + g_assert (nb == sizeof (nbytes));
1.173 +
1.174 + for (i = 0; i < nkiddies; i++)
1.175 + if (seqtab[i].fd == fd)
1.176 + {
1.177 + if (seq != seqtab[i].seq)
1.178 + {
1.179 + g_print ("gio-test: ...from %d: invalid sequence number %d, expected %d\n",
1.180 + fd, seq, seqtab[i].seq);
1.181 + g_assert_not_reached ();
1.182 +
1.183 + g_assert(FALSE && "gio-test failed");
1.184 + }
1.185 + seqtab[i].seq++;
1.186 + break;
1.187 + }
1.188 +
1.189 +
1.190 + error = read_all (fd, channel, (gchar *) &nbytes, sizeof (nbytes), &nb);
1.191 + }
1.192 +
1.193 + if (error != G_IO_ERROR_NONE)
1.194 + return FALSE;
1.195 +
1.196 + if (nb == 0)
1.197 + {
1.198 +#ifdef VERBOSE
1.199 + g_print ("gio-test: ...from %d: EOF\n", fd);
1.200 +#endif
1.201 + shutdown_source (data);
1.202 + return FALSE;
1.203 + }
1.204 +
1.205 + g_assert (nb == sizeof (nbytes));
1.206 +
1.207 + if (nbytes >= BUFSIZE)
1.208 + {
1.209 + g_print ("gio-test: ...from %d: nbytes = %d (%#x)!\n", fd, nbytes, nbytes);
1.210 + g_assert_not_reached ();
1.211 + g_assert(FALSE && "gio-test failed");
1.212 + }
1.213 + g_assert (nbytes >= 0 && nbytes < BUFSIZE);
1.214 +#ifdef VERBOSE
1.215 + g_print ("gio-test: ...from %d: %d bytes\n", fd, nbytes);
1.216 +#endif
1.217 + if (nbytes > 0)
1.218 + {
1.219 + error = read_all (fd, channel, buf, nbytes, &nb);
1.220 + if(child_terminated)
1.221 + shutdown_source (data);
1.222 +
1.223 +
1.224 + if (error != G_IO_ERROR_NONE)
1.225 + return FALSE;
1.226 +
1.227 + if (nb == 0)
1.228 + {
1.229 +#ifdef VERBOSE
1.230 + g_print ("gio-test: ...from %d: EOF\n", fd);
1.231 +#endif
1.232 + shutdown_source (data);
1.233 + return FALSE;
1.234 + }
1.235 +
1.236 + for (j = 0; j < nbytes; j++)
1.237 + if (buf[j] != ' ' + ((nbytes + j) % 95))
1.238 + {
1.239 + g_print ("gio-test: ...from %d: buf[%d] == '%c', should be '%c'\n",
1.240 + fd, j, buf[j], 'a' + ((nbytes + j) % 32));
1.241 + g_assert_not_reached ();
1.242 + g_assert(FALSE && "gio-test failed");
1.243 + }
1.244 +#ifdef VERBOSE
1.245 + g_print ("gio-test: ...from %d: OK\n", fd);
1.246 +#endif
1.247 + }
1.248 + }
1.249 + return retval;
1.250 +}
1.251 +
1.252 +#ifdef G_OS_WIN32
1.253 +
1.254 +static gboolean
1.255 +recv_windows_message (GIOChannel *channel,
1.256 + GIOCondition cond,
1.257 + gpointer data)
1.258 +{
1.259 + GIOError error;
1.260 + MSG msg;
1.261 + guint nb;
1.262 +
1.263 + while (1)
1.264 + {
1.265 + error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb);
1.266 +
1.267 + if (error != G_IO_ERROR_NONE)
1.268 + {
1.269 + g_print ("gio-test: ...reading Windows message: G_IO_ERROR_%s\n",
1.270 + (error == G_IO_ERROR_AGAIN ? "AGAIN" :
1.271 + (error == G_IO_ERROR_INVAL ? "INVAL" :
1.272 + (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???"))));
1.273 + if (error == G_IO_ERROR_AGAIN)
1.274 + continue;
1.275 + }
1.276 + break;
1.277 + }
1.278 +
1.279 + g_print ("gio-test: ...Windows message for %#x: %d,%d,%d\n",
1.280 + msg.hwnd, msg.message, msg.wParam, msg.lParam);
1.281 +
1.282 + return TRUE;
1.283 +}
1.284 +
1.285 +LRESULT CALLBACK
1.286 +window_procedure (HWND hwnd,
1.287 + UINT message,
1.288 + WPARAM wparam,
1.289 + LPARAM lparam)
1.290 +{
1.291 + g_print ("gio-test: window_procedure for %#x: %d,%d,%d\n",
1.292 + hwnd, message, wparam, lparam);
1.293 + return DefWindowProc (hwnd, message, wparam, lparam);
1.294 +}
1.295 +
1.296 +#endif
1.297 +
1.298 +int
1.299 +main (int argc,
1.300 + char **argv)
1.301 +{
1.302 +
1.303 + #ifdef SYMBIAN
1.304 + /*GLIB_INIT();*/
1.305 + pthread_t thread_child;
1.306 + int rc,t;
1.307 + g_log_set_handler (NULL, G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL);
1.308 + g_set_print_handler(mrtPrintHandler);
1.309 + #endif /*SYMBIAN*/
1.310 +
1.311 +
1.312 + if (argc < 3)
1.313 + {
1.314 + /* Parent */
1.315 +
1.316 + GIOChannel *my_read_channel;
1.317 + gchar *cmdline;
1.318 + guint *id;
1.319 + int i;
1.320 +#ifdef G_OS_WIN32
1.321 + GTimeVal start, end;
1.322 + GPollFD pollfd;
1.323 + int pollresult;
1.324 + ATOM klass;
1.325 + static WNDCLASS wcl;
1.326 + HWND hwnd;
1.327 + GIOChannel *windows_messages_channel;
1.328 +#endif
1.329 +
1.330 + nkiddies = (argc == 1 ? 1 : atoi(argv[1]));
1.331 + seqtab = g_malloc (nkiddies * 2 * sizeof (int));
1.332 +
1.333 +#ifdef G_OS_WIN32
1.334 + wcl.style = 0;
1.335 + wcl.lpfnWndProc = window_procedure;
1.336 + wcl.cbClsExtra = 0;
1.337 + wcl.cbWndExtra = 0;
1.338 + wcl.hInstance = GetModuleHandle (NULL);
1.339 + wcl.hIcon = NULL;
1.340 + wcl.hCursor = NULL;
1.341 + wcl.hbrBackground = NULL;
1.342 + wcl.lpszMenuName = NULL;
1.343 + wcl.lpszClassName = "gio-test";
1.344 +
1.345 + klass = RegisterClass (&wcl);
1.346 +
1.347 + if (!klass)
1.348 + {
1.349 + g_print ("gio-test: RegisterClass failed\n");
1.350 + exit (1);
1.351 + }
1.352 +
1.353 + hwnd = CreateWindow (MAKEINTATOM(klass), "gio-test", 0, 0, 0, 10, 10,
1.354 + NULL, NULL, wcl.hInstance, NULL);
1.355 + if (!hwnd)
1.356 + {
1.357 + g_print ("gio-test: CreateWindow failed\n");
1.358 + exit (1);
1.359 + }
1.360 +
1.361 + windows_messages_channel = g_io_channel_win32_new_messages ((guint)hwnd);
1.362 + g_io_add_watch (windows_messages_channel, G_IO_IN, recv_windows_message, 0);
1.363 +#endif
1.364 +
1.365 + for (i = 0; i < nkiddies; i++)
1.366 + {
1.367 + int pipe_to_sub[2], pipe_from_sub[2];
1.368 +
1.369 + if (pipe (pipe_to_sub) == -1 ||
1.370 + pipe (pipe_from_sub) == -1)
1.371 + perror ("pipe"), exit (1);
1.372 +
1.373 + seqtab[i].fd = pipe_from_sub[0];
1.374 + seqtab[i].seq = 0;
1.375 +
1.376 + my_read_channel = g_io_channel_unix_new (pipe_from_sub[0]);
1.377 +
1.378 + id = g_new (guint, 1);
1.379 + *id =
1.380 + g_io_add_watch (my_read_channel,
1.381 + G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
1.382 + recv_message,
1.383 + id);
1.384 +
1.385 + nrunning++;
1.386 +
1.387 +#ifdef G_OS_WIN32
1.388 + cmdline = g_strdup_g_print ("%d:%d:%d",
1.389 + pipe_to_sub[0],
1.390 + pipe_from_sub[1],
1.391 + hwnd);
1.392 + _spawnl (_P_NOWAIT, argv[0], argv[0], "--child", cmdline, NULL);
1.393 +#else
1.394 + cmdline = g_strdup_printf ("%s --child %d:%d &", argv[0],
1.395 + pipe_to_sub[0], pipe_from_sub[1]);
1.396 +
1.397 +
1.398 +#ifndef SYMBIAN
1.399 + system (cmdline);
1.400 +#else
1.401 + from_descriptor = pipe_to_sub[0];
1.402 + to_descriptor = pipe_from_sub[1];
1.403 + rc = pthread_create(&thread_child,NULL,child_function,NULL);
1.404 +
1.405 +
1.406 + if(rc)
1.407 + {
1.408 + g_print("Failed to create thread.\n");
1.409 + exit(1);
1.410 + }
1.411 +#endif /*SYMBIAN*/
1.412 +
1.413 +#endif
1.414 +
1.415 +#ifndef SYMBIAN
1.416 + close (pipe_to_sub[0]);
1.417 + close (pipe_from_sub [1]);
1.418 +#endif
1.419 +
1.420 +#ifdef G_OS_WIN32
1.421 + g_get_current_time (&start);
1.422 + g_io_channel_win32_make_pollfd (my_read_channel, G_IO_IN, &pollfd);
1.423 + pollresult = g_io_channel_win32_poll (&pollfd, 1, 100);
1.424 + g_get_current_time (&end);
1.425 + if (end.tv_usec < start.tv_usec)
1.426 + end.tv_sec--, end.tv_usec += 1000000;
1.427 + g_print ("gio-test: had to wait %ld.%03ld s, result:%d\n",
1.428 + end.tv_sec - start.tv_sec,
1.429 + (end.tv_usec - start.tv_usec) / 1000,
1.430 + pollresult);
1.431 +#endif
1.432 + }
1.433 +
1.434 + main_loop = g_main_loop_new (NULL, FALSE);
1.435 + g_main_loop_run (main_loop);
1.436 +
1.437 + }
1.438 + else if (argc == 3)
1.439 + {
1.440 + /* Child */
1.441 +
1.442 + int readfd, writefd;
1.443 +#ifdef G_OS_WIN32
1.444 + HWND hwnd;
1.445 +#endif
1.446 + int i, j;
1.447 + char buf[BUFSIZE];
1.448 + int buflen;
1.449 + GTimeVal tv;
1.450 + int n;
1.451 +
1.452 + g_get_current_time (&tv);
1.453 +
1.454 + sscanf (argv[2], "%d:%d%n", &readfd, &writefd, &n);
1.455 +
1.456 +#ifdef G_OS_WIN32
1.457 + sscanf (argv[2] + n, ":%d", &hwnd);
1.458 +#endif
1.459 +
1.460 + srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
1.461 +
1.462 + for (i = 0; i < 20 + rand() % 20; i++)
1.463 + {
1.464 + g_usleep (100 + (rand() % 10) * 5000);
1.465 + buflen = rand() % BUFSIZE;
1.466 + for (j = 0; j < buflen; j++)
1.467 + buf[j] = ' ' + ((buflen + j) % 95);
1.468 +#ifdef VERBOSE
1.469 + g_print ("gio-test: child writing %d+%d bytes to %d\n",
1.470 + (int)(sizeof(i) + sizeof(buflen)), buflen, writefd);
1.471 +#endif
1.472 + write (writefd, &i, sizeof (i));
1.473 + write (writefd, &buflen, sizeof (buflen));
1.474 + write (writefd, buf, buflen);
1.475 +
1.476 +#ifdef G_OS_WIN32
1.477 + if (rand() % 100 < 5)
1.478 + {
1.479 + int msg = WM_USER + (rand() % 100);
1.480 + WPARAM wparam = rand ();
1.481 + LPARAM lparam = rand ();
1.482 + g_print ("gio-test: child posting message %d,%d,%d to %#x\n",
1.483 + msg, wparam, lparam, hwnd);
1.484 + PostMessage (hwnd, msg, wparam, lparam);
1.485 + }
1.486 +#endif
1.487 + }
1.488 +#ifdef VERBOSE
1.489 + g_print ("gio-test: child exiting, closing %d\n", writefd);
1.490 +#endif
1.491 + close (writefd);
1.492 + }
1.493 + else
1.494 + g_print ("Huh?\n");
1.495 +
1.496 +
1.497 +#ifdef SYMBIAN
1.498 + close(from_descriptor);
1.499 + close(to_descriptor);
1.500 +#endif
1.501 +
1.502 +#ifdef VERBOSE
1.503 +printf("Completed tests\n");
1.504 +#endif
1.505 +
1.506 + #if SYMBIAN
1.507 + testResultXml("gio-test");
1.508 + #endif /* EMULATOR */
1.509 +
1.510 + return 0;
1.511 +}
1.512 +
1.513 +#ifdef SYMBIAN
1.514 +void *child_function(void* t)
1.515 +{
1.516 + int readfd, writefd;
1.517 +
1.518 + int i, j;
1.519 + char buf[BUFSIZE];
1.520 + int buflen;
1.521 + GTimeVal tv;
1.522 + int n;
1.523 +
1.524 + g_get_current_time (&tv);
1.525 +
1.526 +
1.527 + readfd=from_descriptor;
1.528 + writefd=to_descriptor;
1.529 +
1.530 + srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
1.531 +
1.532 + for (i = 0; i < 5; i++)
1.533 + {
1.534 + if(i==4)
1.535 + child_terminated = TRUE;
1.536 + g_usleep (100 + (rand() % 10) * 5000);
1.537 + buflen = rand() % BUFSIZE;
1.538 + for (j = 0; j < buflen; j++)
1.539 + buf[j] = ' ' + ((buflen + j) % 95);
1.540 +#ifdef VERBOSE
1.541 + g_print ("gio-test: child writing %d+%d bytes to %d\n",
1.542 + (int)(sizeof(i) + sizeof(buflen)), buflen, writefd);
1.543 +#endif
1.544 + write (writefd, &i, sizeof (i));
1.545 + write (writefd, &buflen, sizeof (buflen));
1.546 + write (writefd, buf, buflen);
1.547 + }
1.548 +#ifdef VERBOSE
1.549 + g_print ("gio-test: child exiting, closing %d\n", writefd);
1.550 +#endif
1.551 + close (writefd);
1.552 +
1.553 +}
1.554 +#endif