os/ossrv/glib/tsrc/BC/tests/gio-test.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* GLIB - Library of useful routines for C programming
     2  * Copyright (C) 2000  Tor Lillqvist
     3  * Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
     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