1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/glib/tsrc/BC/tests/mainloop-test.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,500 @@
1.4 +/* Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.*/
1.5 +#undef G_DISABLE_ASSERT
1.6 +#undef G_LOG_DOMAIN
1.7 +
1.8 +
1.9 +#include <errno.h>
1.10 +#include <glib.h>
1.11 +
1.12 +#ifdef G_OS_UNIX
1.13 +#include <unistd.h>
1.14 +#endif
1.15 +#include <stdio.h>
1.16 +#include <stdlib.h>
1.17 +
1.18 +#ifdef G_OS_WIN32
1.19 +#include <fcntl.h> /* For _O_BINARY used by pipe() macro */
1.20 +#include <io.h> /* for _pipe() */
1.21 +#endif
1.22 +
1.23 +
1.24 +
1.25 +#ifdef SYMBIAN
1.26 +#include <glib_global.h>
1.27 +#include "mrt2_glib2_test.h"
1.28 +#endif /*SYMBIAN*/
1.29 +
1.30 +
1.31 +#define ITERS 10
1.32 +#define INCREMENT 10
1.33 +#define NTHREADS 4
1.34 +#define NCRAWLERS 4
1.35 +#define CRAWLER_TIMEOUT_RANGE 40
1.36 +#define RECURSER_TIMEOUT 50
1.37 +
1.38 +/* The partial ordering between the context array mutex and
1.39 + * crawler array mutex is that the crawler array mutex cannot
1.40 + * be locked while the context array mutex is locked
1.41 + */
1.42 +GPtrArray *context_array;
1.43 +GMutex *context_array_mutex;
1.44 +GCond *context_array_cond;
1.45 +
1.46 +GMainLoop *main_loop;
1.47 +
1.48 +G_LOCK_DEFINE_STATIC (crawler_array_lock);
1.49 +GPtrArray *crawler_array;
1.50 +
1.51 +typedef struct _AddrData AddrData;
1.52 +typedef struct _TestData TestData;
1.53 +
1.54 +struct _AddrData
1.55 +{
1.56 + GMainLoop *loop;
1.57 + GIOChannel *dest;
1.58 + gint count;
1.59 +};
1.60 +
1.61 +struct _TestData
1.62 +{
1.63 + gint current_val;
1.64 + gint iters;
1.65 + GIOChannel *in;
1.66 +};
1.67 +
1.68 +static void cleanup_crawlers (GMainContext *context);
1.69 +
1.70 +gboolean
1.71 +read_all (GIOChannel *channel, char *buf, gsize len)
1.72 +{
1.73 + gsize bytes_read = 0;
1.74 + gsize count;
1.75 + GIOError err;
1.76 +
1.77 + while (bytes_read < len)
1.78 + {
1.79 + err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
1.80 + if (err)
1.81 + {
1.82 + if (err != G_IO_ERROR_AGAIN)
1.83 + g_assert(FALSE && "mainloop-test failed");
1.84 + return FALSE;
1.85 + }
1.86 + else if (count == 0)
1.87 + return FALSE;
1.88 +
1.89 + bytes_read += count;
1.90 + }
1.91 +
1.92 + return TRUE;
1.93 +}
1.94 +
1.95 +gboolean
1.96 +write_all (GIOChannel *channel, char *buf, gsize len)
1.97 +{
1.98 + gsize bytes_written = 0;
1.99 + gsize count;
1.100 + GIOError err;
1.101 +
1.102 + while (bytes_written < len)
1.103 + {
1.104 + err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
1.105 + if (err && err != G_IO_ERROR_AGAIN)
1.106 + return FALSE;
1.107 +
1.108 + bytes_written += count;
1.109 + }
1.110 +
1.111 + return TRUE;
1.112 +}
1.113 +
1.114 +gboolean
1.115 +adder_callback (GIOChannel *source,
1.116 + GIOCondition condition,
1.117 + gpointer data)
1.118 +{
1.119 + char buf1[32];
1.120 + char buf2[32];
1.121 +
1.122 + char result[32];
1.123 +
1.124 + AddrData *addr_data = data;
1.125 +
1.126 + if (!read_all (source, buf1, 32) ||
1.127 + !read_all (source, buf2, 32))
1.128 + {
1.129 + g_main_loop_quit (addr_data->loop);
1.130 + return FALSE;
1.131 + }
1.132 +
1.133 + sprintf (result, "%d", atoi(buf1) + atoi(buf2));
1.134 + write_all (addr_data->dest, result, 32);
1.135 +
1.136 + return TRUE;
1.137 +}
1.138 +
1.139 +gboolean
1.140 +timeout_callback (gpointer data)
1.141 +{
1.142 + AddrData *addr_data = data;
1.143 +
1.144 + addr_data->count++;
1.145 +
1.146 + return TRUE;
1.147 +}
1.148 +
1.149 +gpointer
1.150 +adder_thread (gpointer data)
1.151 +{
1.152 + GMainContext *context;
1.153 + GSource *adder_source;
1.154 + GSource *timeout_source;
1.155 +
1.156 + GIOChannel **channels = data;
1.157 + AddrData addr_data;
1.158 +
1.159 + context = g_main_context_new ();
1.160 +
1.161 + g_assert(context != NULL);
1.162 +
1.163 + g_mutex_lock (context_array_mutex);
1.164 +
1.165 + g_ptr_array_add (context_array, context);
1.166 +
1.167 + if (context_array->len == NTHREADS)
1.168 + g_cond_broadcast (context_array_cond);
1.169 +
1.170 + g_mutex_unlock (context_array_mutex);
1.171 +
1.172 + addr_data.dest = channels[1];
1.173 + addr_data.loop = g_main_loop_new (context, FALSE);
1.174 + addr_data.count = 0;
1.175 +
1.176 + adder_source = g_io_create_watch (channels[0], G_IO_IN | G_IO_HUP);
1.177 +
1.178 + g_assert(adder_source != NULL);
1.179 +
1.180 + g_source_set_callback (adder_source, (GSourceFunc)adder_callback, &addr_data, NULL);
1.181 + g_source_attach (adder_source, context);
1.182 + g_source_unref (adder_source);
1.183 +
1.184 + timeout_source = g_timeout_source_new (10);
1.185 +
1.186 + g_assert(timeout_source != NULL);
1.187 +
1.188 + g_source_set_callback (timeout_source, (GSourceFunc)timeout_callback, &addr_data, NULL);
1.189 + g_source_set_priority (timeout_source, G_PRIORITY_HIGH);
1.190 + g_source_attach (timeout_source, context);
1.191 + g_source_unref (timeout_source);
1.192 +
1.193 + g_main_loop_run (addr_data.loop);
1.194 +
1.195 + g_io_channel_unref (channels[0]);
1.196 + g_io_channel_unref (channels[1]);
1.197 +
1.198 + g_free (channels);
1.199 +
1.200 + g_main_loop_unref (addr_data.loop);
1.201 +
1.202 +#ifdef VERBOSE
1.203 + g_print ("Timeout run %d times\n", addr_data.count);
1.204 +#endif
1.205 +
1.206 + g_mutex_lock (context_array_mutex);
1.207 + g_ptr_array_remove (context_array, context);
1.208 + if (context_array->len == 0)
1.209 + g_main_loop_quit (main_loop);
1.210 + g_mutex_unlock (context_array_mutex);
1.211 +
1.212 + cleanup_crawlers (context);
1.213 +
1.214 + return NULL;
1.215 +}
1.216 +
1.217 +
1.218 +void
1.219 +io_pipe (GIOChannel **channels)
1.220 +{
1.221 + gint fds[2];
1.222 +
1.223 + if (pipe(fds) < 0)
1.224 + {
1.225 + g_warning ("Cannot create pipe %s\n", g_strerror (errno));
1.226 +
1.227 + g_assert(FALSE && "mainloop-test failed");
1.228 +
1.229 + exit (1);
1.230 + }
1.231 +
1.232 + channels[0] = g_io_channel_unix_new (fds[0]);
1.233 + channels[1] = g_io_channel_unix_new (fds[1]);
1.234 +
1.235 + g_io_channel_set_close_on_unref (channels[0], TRUE);
1.236 + g_io_channel_set_close_on_unref (channels[1], TRUE);
1.237 +}
1.238 +
1.239 +void
1.240 +do_add (GIOChannel *in, gint a, gint b)
1.241 +{
1.242 + char buf1[32];
1.243 + char buf2[32];
1.244 +
1.245 + sprintf (buf1, "%d", a);
1.246 + sprintf (buf2, "%d", b);
1.247 +
1.248 + write_all (in, buf1, 32);
1.249 + write_all (in, buf2, 32);
1.250 +}
1.251 +
1.252 +gboolean
1.253 +adder_response (GIOChannel *source,
1.254 + GIOCondition condition,
1.255 + gpointer data)
1.256 +{
1.257 + char result[32];
1.258 + TestData *test_data = data;
1.259 +
1.260 + if (!read_all (source, result, 32))
1.261 + return FALSE;
1.262 +
1.263 + test_data->current_val = atoi (result);
1.264 + test_data->iters--;
1.265 +
1.266 + if (test_data->iters == 0)
1.267 + {
1.268 + if (test_data->current_val != ITERS * INCREMENT)
1.269 + {
1.270 + g_print ("Addition failed: %d != %d\n",
1.271 + test_data->current_val, ITERS * INCREMENT);
1.272 +
1.273 + g_assert(FALSE && "mainloop-test failed");
1.274 +
1.275 + exit (1);
1.276 + }
1.277 +
1.278 + g_io_channel_unref (source);
1.279 + g_io_channel_unref (test_data->in);
1.280 +
1.281 + g_free (test_data);
1.282 +
1.283 + return FALSE;
1.284 + }
1.285 +
1.286 + do_add (test_data->in, test_data->current_val, INCREMENT);
1.287 +
1.288 + return TRUE;
1.289 +}
1.290 +
1.291 +void
1.292 +create_adder_thread (void)
1.293 +{
1.294 + GError *err = NULL;
1.295 + TestData *test_data;
1.296 + GThread *thread;
1.297 +
1.298 + GIOChannel *in_channels[2];
1.299 + GIOChannel *out_channels[2];
1.300 +
1.301 + GIOChannel **sub_channels;
1.302 +
1.303 + sub_channels = g_new (GIOChannel *, 2);
1.304 +
1.305 + io_pipe (in_channels);
1.306 + io_pipe (out_channels);
1.307 +
1.308 + sub_channels[0] = in_channels[0];
1.309 + sub_channels[1] = out_channels[1];
1.310 +
1.311 + g_thread_create (adder_thread, sub_channels, FALSE, &err);
1.312 +
1.313 + if (err)
1.314 + {
1.315 + g_warning ("Cannot create thread: %s", err->message);
1.316 +
1.317 + g_assert(FALSE && "mainloop-test failed");
1.318 +
1.319 + exit (1);
1.320 + }
1.321 +
1.322 + test_data = g_new (TestData, 1);
1.323 + test_data->in = in_channels[1];
1.324 + test_data->current_val = 0;
1.325 + test_data->iters = ITERS;
1.326 +
1.327 + g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
1.328 + adder_response, test_data);
1.329 +
1.330 + do_add (test_data->in, test_data->current_val, INCREMENT);
1.331 +}
1.332 +
1.333 +static void create_crawler (void);
1.334 +
1.335 +static void
1.336 +remove_crawler (void)
1.337 +{
1.338 + GSource *other_source;
1.339 +
1.340 + if (crawler_array->len > 0)
1.341 + {
1.342 + other_source = crawler_array->pdata[g_random_int_range (0, crawler_array->len)];
1.343 + g_source_destroy (other_source);
1.344 + g_assert (g_ptr_array_remove_fast (crawler_array, other_source));
1.345 + }
1.346 +}
1.347 +
1.348 +static gint
1.349 +crawler_callback (gpointer data)
1.350 +{
1.351 + GSource *source = data;
1.352 +
1.353 + G_LOCK (crawler_array_lock);
1.354 +
1.355 + if (!g_ptr_array_remove_fast (crawler_array, source))
1.356 + remove_crawler();
1.357 +
1.358 + remove_crawler();
1.359 + G_UNLOCK (crawler_array_lock);
1.360 +
1.361 + create_crawler();
1.362 + //create_crawler();
1.363 +
1.364 + return FALSE;
1.365 +}
1.366 +
1.367 +static void
1.368 +create_crawler (void)
1.369 +{
1.370 + GSource *source = g_timeout_source_new (g_random_int_range (0, CRAWLER_TIMEOUT_RANGE));
1.371 +
1.372 + g_assert(source != NULL);
1.373 +
1.374 + g_source_set_callback (source, (GSourceFunc)crawler_callback, source, NULL);
1.375 +
1.376 + G_LOCK (crawler_array_lock);
1.377 + g_ptr_array_add (crawler_array, source);
1.378 +
1.379 + g_mutex_lock (context_array_mutex);
1.380 + if(context_array->len == 0)
1.381 + g_source_attach (source, context_array->pdata[0]);
1.382 + else
1.383 + g_source_attach (source, context_array->pdata[g_random_int_range (0, context_array->len)]);
1.384 + g_source_unref (source);
1.385 + g_mutex_unlock (context_array_mutex);
1.386 +
1.387 + G_UNLOCK (crawler_array_lock);
1.388 +}
1.389 +
1.390 +static void
1.391 +cleanup_crawlers (GMainContext *context)
1.392 +{
1.393 + gint i;
1.394 +
1.395 + G_LOCK (crawler_array_lock);
1.396 + for (i=0; i < crawler_array->len; i++)
1.397 + {
1.398 + if (g_source_get_context (crawler_array->pdata[i]) == context)
1.399 + {
1.400 + g_source_destroy (g_ptr_array_remove_index (crawler_array, i));
1.401 + i--;
1.402 + }
1.403 + }
1.404 + G_UNLOCK (crawler_array_lock);
1.405 +}
1.406 +
1.407 +static gboolean
1.408 +recurser_idle (gpointer data)
1.409 +{
1.410 + GMainContext *context = data;
1.411 + gint i;
1.412 +
1.413 + for (i = 0; i < 10; i++)
1.414 + g_main_context_iteration (context, FALSE);
1.415 +
1.416 + return FALSE;
1.417 +}
1.418 +
1.419 +static gboolean
1.420 +recurser_start (gpointer data)
1.421 +{
1.422 + GMainContext *context;
1.423 + GSource *source;
1.424 +
1.425 + g_mutex_lock (context_array_mutex);
1.426 +
1.427 + if(context_array->len == 0)
1.428 + context = context_array->pdata[0];
1.429 + else
1.430 + context = context_array->pdata[g_random_int_range (0, context_array->len)];
1.431 + source = g_idle_source_new ();
1.432 + g_source_set_callback (source, recurser_idle, context, NULL);
1.433 + g_source_attach (source, context);
1.434 + g_source_unref (source);
1.435 + g_mutex_unlock (context_array_mutex);
1.436 +
1.437 + return TRUE;
1.438 +}
1.439 +
1.440 +int
1.441 +main (int argc,
1.442 + char *argv[])
1.443 +{
1.444 + /* Only run the test, if threads are enabled and a default thread
1.445 + implementation is available */
1.446 +#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
1.447 + gint i;
1.448 +
1.449 + #ifdef SYMBIAN
1.450 + 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.451 + g_set_print_handler(mrtPrintHandler);
1.452 + #endif /*SYMBIAN*/
1.453 +#if 0
1.454 + g_thread_init (NULL);
1.455 +
1.456 + context_array = g_ptr_array_new ();
1.457 +
1.458 + g_assert(context_array != NULL);
1.459 +
1.460 + context_array_mutex = g_mutex_new ();
1.461 +
1.462 + g_assert(context_array_mutex != NULL);
1.463 +
1.464 + context_array_cond = g_cond_new ();
1.465 +
1.466 + g_assert(context_array_cond != NULL);
1.467 +
1.468 + crawler_array = g_ptr_array_new ();
1.469 +
1.470 + g_assert(crawler_array != NULL);
1.471 +
1.472 + main_loop = g_main_loop_new (NULL, FALSE);
1.473 +
1.474 + g_assert(main_loop != NULL);
1.475 +
1.476 + for (i = 0; i < NTHREADS; i++)
1.477 + create_adder_thread ();
1.478 +
1.479 + /* Wait for all threads to start
1.480 + */
1.481 + g_mutex_lock (context_array_mutex);
1.482 +
1.483 + if (context_array->len < NTHREADS)
1.484 + g_cond_wait (context_array_cond, context_array_mutex);
1.485 +
1.486 + g_mutex_unlock (context_array_mutex);
1.487 +
1.488 + for (i = 0; i < NCRAWLERS; i++)
1.489 + create_crawler ();
1.490 +
1.491 + g_timeout_add (RECURSER_TIMEOUT, recurser_start, NULL);
1.492 +
1.493 + g_main_loop_run (main_loop);
1.494 + g_main_loop_unref (main_loop);
1.495 +#endif
1.496 +#endif
1.497 +
1.498 + #ifdef SYMBIAN
1.499 + testResultXml("mainloop-test");
1.500 + #endif /* EMULATOR */
1.501 +
1.502 + return 0;
1.503 +}