apicompatanamdw/bcdrivers/os/ossrv/glib/tests/gio-test.c
changeset 2 0cb2248d0edc
equal deleted inserted replaced
1:61e9400fe245 2:0cb2248d0edc
       
     1 /* GLIB - Library of useful routines for C programming
       
     2  * Copyright (C) 2000  Tor Lillqvist
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Lesser General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library 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 GNU
       
    12  * Lesser General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Lesser General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /* A test program for the main loop and IO channel code.
       
    21  * Just run it. Optional parameter is number of sub-processes.
       
    22  */
       
    23 
       
    24 
       
    25 #undef G_DISABLE_ASSERT
       
    26 #undef G_LOG_DOMAIN
       
    27 
       
    28 #include "config.h"
       
    29 
       
    30 #include <glib.h>
       
    31 #include <unistd.h>
       
    32 #include <stdio.h>
       
    33 #include <stdlib.h>
       
    34 #include <math.h>
       
    35 #include <time.h>
       
    36 
       
    37 #ifdef SYMBIAN
       
    38   //#define VERBOSE
       
    39   #include <pthread.h>
       
    40   #include "mrt2_glib2_test.h"
       
    41   void *child_function(void*);
       
    42   gboolean child_terminated = FALSE;
       
    43   int from_descriptor, to_descriptor;
       
    44 #endif /*SYMBIAN*/
       
    45 
       
    46 #ifdef G_OS_WIN32
       
    47   #include <io.h>
       
    48   #include <fcntl.h>
       
    49   #include <process.h>
       
    50   #define STRICT
       
    51   #include <windows.h>
       
    52 #else
       
    53   #ifdef HAVE_UNISTD_H
       
    54     #include <unistd.h>
       
    55   #endif
       
    56 #endif
       
    57 
       
    58 
       
    59 static int nrunning;
       
    60 static GMainLoop *main_loop;
       
    61 
       
    62 #ifdef SYMBIAN
       
    63 #define BUFSIZE 1000
       
    64 #else
       
    65 #define BUFSIZE 5000		/* Larger than the circular buffer in giowin32.c on purpose.*/
       
    66 #endif
       
    67 
       
    68 static int nkiddies;
       
    69 
       
    70 static struct {
       
    71   int fd;
       
    72   int seq;
       
    73 } *seqtab;
       
    74 
       
    75 
       
    76 
       
    77 static GIOError
       
    78 read_all (int         fd,
       
    79 	  GIOChannel *channel,
       
    80 	  char       *buffer,
       
    81 	  guint       nbytes,
       
    82 	  guint      *bytes_read)
       
    83 {
       
    84   guint left = nbytes;
       
    85   gsize nb;
       
    86   GIOError error = G_IO_ERROR_NONE;
       
    87   char *bufp = buffer;
       
    88 
       
    89   /* g_io_channel_read() doesn't necessarily return all the
       
    90    * data we want at once.
       
    91    */
       
    92   *bytes_read = 0;
       
    93   while (left)
       
    94     {
       
    95       error = g_io_channel_read (channel, bufp, left, &nb);
       
    96       
       
    97       if (error != G_IO_ERROR_NONE)
       
    98 	{	  
       
    99 	  g_print ("gio-test: ...from %d: G_IO_ERROR_%s\n", fd,
       
   100 		   (error == G_IO_ERROR_AGAIN ? "AGAIN" :
       
   101 		    (error == G_IO_ERROR_INVAL ? "INVAL" :
       
   102 		     (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???"))));
       
   103 	  if (error == G_IO_ERROR_AGAIN)
       
   104 	    continue;
       
   105 	  break;
       
   106 	}
       
   107       if (nb == 0)
       
   108 	return error;
       
   109       left -= nb;
       
   110       bufp += nb;
       
   111       *bytes_read += nb;
       
   112     }
       
   113   return error;
       
   114 }
       
   115 
       
   116 static void
       
   117 shutdown_source (gpointer data)
       
   118 {
       
   119   if (g_source_remove (*(guint *) data))
       
   120     {
       
   121       nrunning--;
       
   122       if (nrunning == 0)
       
   123 	g_main_loop_quit (main_loop);
       
   124     }
       
   125 }
       
   126 
       
   127 static gboolean
       
   128 recv_message (GIOChannel  *channel,
       
   129 	      GIOCondition cond,
       
   130 	      gpointer    data)
       
   131 {
       
   132   gint fd = g_io_channel_unix_get_fd (channel);
       
   133   gboolean retval = TRUE;
       
   134 
       
   135 #ifdef VERBOSE
       
   136   g_print ("gio-test: ...from %d:%s%s%s%s\n", fd,
       
   137 	   (cond & G_IO_ERR) ? " ERR" : "",
       
   138 	   (cond & G_IO_HUP) ? " HUP" : "",
       
   139 	   (cond & G_IO_IN)  ? " IN"  : "",
       
   140 	   (cond & G_IO_PRI) ? " PRI" : "");
       
   141 #endif
       
   142 
       
   143   if ((cond & (G_IO_ERR | G_IO_HUP)))
       
   144     {
       
   145       shutdown_source (data);
       
   146       retval = FALSE;
       
   147     }
       
   148 
       
   149   if (cond & G_IO_IN)
       
   150     {
       
   151       char buf[BUFSIZE];
       
   152       guint nbytes;
       
   153       guint nb;
       
   154       int i, j, seq;
       
   155       GIOError error;
       
   156       
       
   157       error = read_all (fd, channel, (gchar *) &seq, sizeof (seq), &nb);
       
   158       if (error == G_IO_ERROR_NONE)
       
   159 	{
       
   160 	  if (nb == 0)
       
   161 	    {
       
   162 #ifdef VERBOSE
       
   163 	      g_print ("gio-test: ...from %d: EOF\n", fd);
       
   164 #endif
       
   165 	      shutdown_source (data);
       
   166 	      return FALSE;
       
   167 	    }
       
   168 	  
       
   169 	  g_assert (nb == sizeof (nbytes));
       
   170 
       
   171 	  for (i = 0; i < nkiddies; i++)
       
   172 	    if (seqtab[i].fd == fd)
       
   173 	      {
       
   174 		if (seq != seqtab[i].seq)
       
   175 		  {
       
   176 		    g_print ("gio-test: ...from %d: invalid sequence number %d, expected %d\n",
       
   177 			     fd, seq, seqtab[i].seq);
       
   178 		    g_assert_not_reached ();
       
   179 		    
       
   180 		    g_assert(FALSE && "gio-test failed");
       
   181 		  }
       
   182 		seqtab[i].seq++;
       
   183 		break;
       
   184 	      }
       
   185 
       
   186 
       
   187 	  error = read_all (fd, channel, (gchar *) &nbytes, sizeof (nbytes), &nb);
       
   188 	}
       
   189 
       
   190       if (error != G_IO_ERROR_NONE)
       
   191 	return FALSE;
       
   192       
       
   193       if (nb == 0)
       
   194 	{
       
   195 #ifdef VERBOSE
       
   196 	  g_print ("gio-test: ...from %d: EOF\n", fd);
       
   197 #endif
       
   198 	  shutdown_source (data);
       
   199 	  return FALSE;
       
   200 	}
       
   201       
       
   202       g_assert (nb == sizeof (nbytes));
       
   203 
       
   204       if (nbytes >= BUFSIZE)
       
   205 	{
       
   206 	  g_print ("gio-test: ...from %d: nbytes = %d (%#x)!\n", fd, nbytes, nbytes);
       
   207 	  g_assert_not_reached ();
       
   208 	  g_assert(FALSE && "gio-test failed");
       
   209 	}
       
   210       g_assert (nbytes >= 0 && nbytes < BUFSIZE);
       
   211 #ifdef VERBOSE      
       
   212       g_print ("gio-test: ...from %d: %d bytes\n", fd, nbytes);
       
   213 #endif      
       
   214       if (nbytes > 0)
       
   215 	{
       
   216 	  error = read_all (fd, channel, buf, nbytes, &nb);
       
   217 	  if(child_terminated)
       
   218 	  	shutdown_source (data);
       
   219 	  	
       
   220 
       
   221 	  if (error != G_IO_ERROR_NONE)
       
   222 	    return FALSE;
       
   223 
       
   224 	  if (nb == 0)
       
   225 	    {
       
   226 #ifdef VERBOSE
       
   227 	      g_print ("gio-test: ...from %d: EOF\n", fd);
       
   228 #endif
       
   229 	      shutdown_source (data);
       
   230 	      return FALSE;
       
   231 	    }
       
   232       
       
   233 	  for (j = 0; j < nbytes; j++)
       
   234 	    if (buf[j] != ' ' + ((nbytes + j) % 95))
       
   235 	      {
       
   236 		g_print ("gio-test: ...from %d: buf[%d] == '%c', should be '%c'\n",
       
   237 			 fd, j, buf[j], 'a' + ((nbytes + j) % 32));
       
   238 		g_assert_not_reached ();
       
   239 		g_assert(FALSE && "gio-test failed");
       
   240 	      }
       
   241 #ifdef VERBOSE
       
   242 	  g_print ("gio-test: ...from %d: OK\n", fd);
       
   243 #endif
       
   244 	}
       
   245     }
       
   246   return retval;
       
   247 }
       
   248 
       
   249 #ifdef G_OS_WIN32
       
   250 
       
   251 static gboolean
       
   252 recv_windows_message (GIOChannel  *channel,
       
   253 		      GIOCondition cond,
       
   254 		      gpointer    data)
       
   255 {
       
   256   GIOError error;
       
   257   MSG msg;
       
   258   guint nb;
       
   259   
       
   260   while (1)
       
   261     {
       
   262       error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb);
       
   263       
       
   264       if (error != G_IO_ERROR_NONE)
       
   265 	{
       
   266 	  g_print ("gio-test: ...reading Windows message: G_IO_ERROR_%s\n",
       
   267 		   (error == G_IO_ERROR_AGAIN ? "AGAIN" :
       
   268 		    (error == G_IO_ERROR_INVAL ? "INVAL" :
       
   269 		     (error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???"))));
       
   270 	  if (error == G_IO_ERROR_AGAIN)
       
   271 	    continue;
       
   272 	}
       
   273       break;
       
   274     }
       
   275 
       
   276   g_print ("gio-test: ...Windows message for %#x: %d,%d,%d\n",
       
   277 	   msg.hwnd, msg.message, msg.wParam, msg.lParam);
       
   278 
       
   279   return TRUE;
       
   280 }
       
   281 
       
   282 LRESULT CALLBACK 
       
   283 window_procedure (HWND hwnd,
       
   284 		  UINT message,
       
   285 		  WPARAM wparam,
       
   286 		  LPARAM lparam)
       
   287 {
       
   288   g_print ("gio-test: window_procedure for %#x: %d,%d,%d\n",
       
   289 	   hwnd, message, wparam, lparam);
       
   290   return DefWindowProc (hwnd, message, wparam, lparam);
       
   291 }
       
   292 
       
   293 #endif
       
   294 
       
   295 int
       
   296 main (int    argc,
       
   297       char **argv)
       
   298 {
       
   299    
       
   300   #ifdef SYMBIAN
       
   301   /*GLIB_INIT();*/
       
   302   pthread_t thread_child;
       
   303   int rc,t;
       
   304   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);
       
   305   g_set_print_handler(mrtPrintHandler);
       
   306   #endif /*SYMBIAN*/
       
   307  
       
   308 
       
   309   if (argc < 3)
       
   310     {
       
   311       /* Parent */
       
   312       
       
   313       GIOChannel *my_read_channel;
       
   314       gchar *cmdline;
       
   315       guint *id;
       
   316       int i;
       
   317 #ifdef G_OS_WIN32
       
   318       GTimeVal start, end;
       
   319       GPollFD pollfd;
       
   320       int pollresult;
       
   321       ATOM klass;
       
   322       static WNDCLASS wcl;
       
   323       HWND hwnd;
       
   324       GIOChannel *windows_messages_channel;
       
   325 #endif
       
   326 
       
   327       nkiddies = (argc == 1 ? 1 : atoi(argv[1]));
       
   328       seqtab = g_malloc (nkiddies * 2 * sizeof (int));
       
   329 
       
   330 #ifdef G_OS_WIN32
       
   331       wcl.style = 0;
       
   332       wcl.lpfnWndProc = window_procedure;
       
   333       wcl.cbClsExtra = 0;
       
   334       wcl.cbWndExtra = 0;
       
   335       wcl.hInstance = GetModuleHandle (NULL);
       
   336       wcl.hIcon = NULL;
       
   337       wcl.hCursor = NULL;
       
   338       wcl.hbrBackground = NULL;
       
   339       wcl.lpszMenuName = NULL;
       
   340       wcl.lpszClassName = "gio-test";
       
   341 
       
   342       klass = RegisterClass (&wcl);
       
   343 
       
   344       if (!klass)
       
   345 	{
       
   346 	  g_print ("gio-test: RegisterClass failed\n");
       
   347 	  exit (1);
       
   348 	}
       
   349 
       
   350       hwnd = CreateWindow (MAKEINTATOM(klass), "gio-test", 0, 0, 0, 10, 10,
       
   351 			   NULL, NULL, wcl.hInstance, NULL);
       
   352       if (!hwnd)
       
   353 	{
       
   354 	  g_print ("gio-test: CreateWindow failed\n");
       
   355 	  exit (1);
       
   356 	}
       
   357 
       
   358       windows_messages_channel = g_io_channel_win32_new_messages ((guint)hwnd);
       
   359       g_io_add_watch (windows_messages_channel, G_IO_IN, recv_windows_message, 0);
       
   360 #endif
       
   361 
       
   362       for (i = 0; i < nkiddies; i++)
       
   363 	{
       
   364 	  int pipe_to_sub[2], pipe_from_sub[2];
       
   365 	  
       
   366 	  if (pipe (pipe_to_sub) == -1 ||
       
   367 	      pipe (pipe_from_sub) == -1)
       
   368 	    perror ("pipe"), exit (1);
       
   369 	  
       
   370 	  seqtab[i].fd = pipe_from_sub[0];
       
   371 	  seqtab[i].seq = 0;
       
   372 
       
   373 	  my_read_channel = g_io_channel_unix_new (pipe_from_sub[0]);
       
   374 	  
       
   375 	  id = g_new (guint, 1);
       
   376 	  *id =
       
   377 	    g_io_add_watch (my_read_channel,
       
   378 			    G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
       
   379 			    recv_message,
       
   380 			    id);
       
   381 	  
       
   382 	  nrunning++;
       
   383 	  
       
   384 #ifdef G_OS_WIN32
       
   385 	  cmdline = g_strdup_g_print ("%d:%d:%d",
       
   386 				     pipe_to_sub[0],
       
   387 				     pipe_from_sub[1],
       
   388 				     hwnd);
       
   389 	  _spawnl (_P_NOWAIT, argv[0], argv[0], "--child", cmdline, NULL);
       
   390 #else
       
   391 	  cmdline = g_strdup_printf ("%s --child %d:%d &", argv[0],
       
   392 				     pipe_to_sub[0], pipe_from_sub[1]);
       
   393 				     
       
   394 	  
       
   395 #ifndef SYMBIAN
       
   396 	  system (cmdline);
       
   397 #else
       
   398 	 from_descriptor = pipe_to_sub[0];
       
   399      to_descriptor = pipe_from_sub[1]; 
       
   400 	  rc = pthread_create(&thread_child,NULL,child_function,NULL);
       
   401      
       
   402 
       
   403 	  if(rc)
       
   404 	  {
       
   405 	  	g_print("Failed to create thread.\n");
       
   406 	  	exit(1);
       
   407 	  }
       
   408 #endif /*SYMBIAN*/	  
       
   409 	  
       
   410 #endif
       
   411 
       
   412 #ifndef SYMBIAN
       
   413 	  close (pipe_to_sub[0]);
       
   414 	  close (pipe_from_sub [1]);
       
   415 #endif	  
       
   416 
       
   417 #ifdef G_OS_WIN32
       
   418 	  g_get_current_time (&start);
       
   419 	  g_io_channel_win32_make_pollfd (my_read_channel, G_IO_IN, &pollfd);
       
   420 	  pollresult = g_io_channel_win32_poll (&pollfd, 1, 100);
       
   421 	  g_get_current_time (&end);
       
   422 	  if (end.tv_usec < start.tv_usec)
       
   423 	    end.tv_sec--, end.tv_usec += 1000000;
       
   424 	  g_print ("gio-test: had to wait %ld.%03ld s, result:%d\n",
       
   425 		   end.tv_sec - start.tv_sec,
       
   426 		   (end.tv_usec - start.tv_usec) / 1000,
       
   427 		   pollresult);
       
   428 #endif
       
   429 	}
       
   430       
       
   431       main_loop = g_main_loop_new (NULL, FALSE);
       
   432       g_main_loop_run (main_loop);
       
   433 
       
   434     }
       
   435   else if (argc == 3)
       
   436     {
       
   437       /* Child */
       
   438       
       
   439       int readfd, writefd;
       
   440 #ifdef G_OS_WIN32
       
   441       HWND hwnd;
       
   442 #endif
       
   443       int i, j;
       
   444       char buf[BUFSIZE];
       
   445       int buflen;
       
   446       GTimeVal tv;
       
   447       int n;
       
   448   
       
   449       g_get_current_time (&tv);
       
   450       
       
   451       sscanf (argv[2], "%d:%d%n", &readfd, &writefd, &n);
       
   452 
       
   453 #ifdef G_OS_WIN32
       
   454       sscanf (argv[2] + n, ":%d", &hwnd);
       
   455 #endif
       
   456       
       
   457       srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
       
   458   
       
   459       for (i = 0; i < 20 + rand() % 20; i++)
       
   460 	{
       
   461 	  g_usleep (100 + (rand() % 10) * 5000);
       
   462 	  buflen = rand() % BUFSIZE;
       
   463 	  for (j = 0; j < buflen; j++)
       
   464 	    buf[j] = ' ' + ((buflen + j) % 95);
       
   465 #ifdef VERBOSE
       
   466 	  g_print ("gio-test: child writing %d+%d bytes to %d\n",
       
   467 		   (int)(sizeof(i) + sizeof(buflen)), buflen, writefd);
       
   468 #endif
       
   469 	  write (writefd, &i, sizeof (i));
       
   470 	  write (writefd, &buflen, sizeof (buflen));
       
   471 	  write (writefd, buf, buflen);
       
   472 
       
   473 #ifdef G_OS_WIN32
       
   474 	  if (rand() % 100 < 5)
       
   475 	    {
       
   476 	      int msg = WM_USER + (rand() % 100);
       
   477 	      WPARAM wparam = rand ();
       
   478 	      LPARAM lparam = rand ();
       
   479 	      g_print ("gio-test: child posting message %d,%d,%d to %#x\n",
       
   480 		       msg, wparam, lparam, hwnd);
       
   481 	      PostMessage (hwnd, msg, wparam, lparam);
       
   482 	    }
       
   483 #endif
       
   484 	}
       
   485 #ifdef VERBOSE
       
   486       g_print ("gio-test: child exiting, closing %d\n", writefd);
       
   487 #endif
       
   488       close (writefd);
       
   489     }
       
   490   else
       
   491     g_print ("Huh?\n");
       
   492   
       
   493 
       
   494 #ifdef SYMBIAN
       
   495   close(from_descriptor);
       
   496   close(to_descriptor);
       
   497 #endif
       
   498 
       
   499 #ifdef VERBOSE
       
   500 printf("Completed tests\n");
       
   501 #endif
       
   502   
       
   503   #if SYMBIAN
       
   504   testResultXml("gio-test");
       
   505   #endif /* EMULATOR */
       
   506   
       
   507   return 0;
       
   508 }
       
   509 
       
   510 #ifdef SYMBIAN
       
   511 void *child_function(void* t)
       
   512 {
       
   513       int readfd, writefd;
       
   514 
       
   515       int i, j;
       
   516       char buf[BUFSIZE];
       
   517       int buflen;
       
   518       GTimeVal tv;
       
   519       int n;
       
   520   
       
   521       g_get_current_time (&tv);
       
   522 
       
   523 
       
   524       readfd=from_descriptor;
       
   525       writefd=to_descriptor;
       
   526 
       
   527       srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
       
   528   
       
   529       for (i = 0; i < 5; i++)
       
   530 	  {
       
   531 	    if(i==4)
       
   532 	    	child_terminated = TRUE;
       
   533 	    g_usleep (100 + (rand() % 10) * 5000);
       
   534 	    buflen = rand() % BUFSIZE;
       
   535 	    for (j = 0; j < buflen; j++)
       
   536 	      buf[j] = ' ' + ((buflen + j) % 95);
       
   537 #ifdef VERBOSE
       
   538 	    g_print ("gio-test: child writing %d+%d bytes to %d\n",
       
   539 		   (int)(sizeof(i) + sizeof(buflen)), buflen, writefd);
       
   540 #endif
       
   541 	    write (writefd, &i, sizeof (i));
       
   542 	    write (writefd, &buflen, sizeof (buflen));
       
   543 	    write (writefd, buf, buflen);
       
   544 	  }
       
   545 #ifdef VERBOSE
       
   546       g_print ("gio-test: child exiting, closing %d\n", writefd);
       
   547 #endif
       
   548       close (writefd);
       
   549       
       
   550 }
       
   551 #endif