Home | History | Annotate | Download | only in tests
      1 #undef G_DISABLE_ASSERT
      2 #undef G_LOG_DOMAIN
      3 
      4 #include <glib.h>
      5 
      6 /* GMutex */
      7 
      8 static GMutex* test_g_mutex_mutex = NULL;
      9 static guint test_g_mutex_int = 0;
     10 static gboolean test_g_mutex_thread_ready;
     11 G_LOCK_DEFINE_STATIC (test_g_mutex);
     12 
     13 static gpointer
     14 test_g_mutex_thread (gpointer data)
     15 {
     16   g_assert (GPOINTER_TO_INT (data) == 42);
     17   g_assert (g_mutex_trylock (test_g_mutex_mutex) == FALSE);
     18   g_assert (G_TRYLOCK (test_g_mutex) == FALSE);
     19   test_g_mutex_thread_ready = TRUE;
     20   g_mutex_lock (test_g_mutex_mutex);
     21   g_assert (test_g_mutex_int == 42);
     22   g_mutex_unlock (test_g_mutex_mutex);
     23 
     24   return GINT_TO_POINTER (41);
     25 }
     26 
     27 static void
     28 test_g_mutex (void)
     29 {
     30   GThread *thread;
     31   test_g_mutex_mutex = g_mutex_new ();
     32 
     33   g_assert (g_mutex_trylock (test_g_mutex_mutex));
     34   g_assert (G_TRYLOCK (test_g_mutex));
     35   test_g_mutex_thread_ready = FALSE;
     36   thread = g_thread_create (test_g_mutex_thread, GINT_TO_POINTER (42),
     37 			    TRUE, NULL);
     38   /* This busy wait is only for testing purposes and not an example of
     39    * good code!*/
     40   while (!test_g_mutex_thread_ready)
     41     g_usleep (G_USEC_PER_SEC / 5);
     42   test_g_mutex_int = 42;
     43   G_UNLOCK (test_g_mutex);
     44   g_mutex_unlock (test_g_mutex_mutex);
     45   g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 41);
     46   g_mutex_free (test_g_mutex_mutex);
     47 }
     48 
     49 /* GStaticRecMutex */
     50 
     51 static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT;
     52 static guint test_g_static_rec_mutex_int = 0;
     53 static gboolean test_g_static_rec_mutex_thread_ready;
     54 
     55 static gpointer
     56 test_g_static_rec_mutex_thread (gpointer data)
     57 {
     58   g_assert (GPOINTER_TO_INT (data) == 42);
     59   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)
     60 	    == FALSE);
     61   test_g_static_rec_mutex_thread_ready = TRUE;
     62   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
     63   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
     64   g_assert (test_g_static_rec_mutex_int == 42);
     65   test_g_static_rec_mutex_thread_ready = FALSE;
     66   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
     67   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
     68 
     69   g_thread_exit (GINT_TO_POINTER (43));
     70 
     71   g_assert_not_reached ();
     72   return NULL;
     73 }
     74 
     75 static void
     76 test_g_static_rec_mutex (void)
     77 {
     78   GThread *thread;
     79 
     80   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
     81   test_g_static_rec_mutex_thread_ready = FALSE;
     82   thread = g_thread_create (test_g_static_rec_mutex_thread,
     83 			    GINT_TO_POINTER (42), TRUE, NULL);
     84   /* This busy wait is only for testing purposes and not an example of
     85    * good code!*/
     86   while (!test_g_static_rec_mutex_thread_ready)
     87     g_usleep (G_USEC_PER_SEC / 5);
     88 
     89   g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex));
     90   test_g_static_rec_mutex_int = 41;
     91   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
     92   test_g_static_rec_mutex_int = 42;
     93   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
     94 
     95   /* This busy wait is only for testing purposes and not an example of
     96    * good code!*/
     97   while (test_g_static_rec_mutex_thread_ready)
     98     g_usleep (G_USEC_PER_SEC / 5);
     99 
    100   g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex);
    101   test_g_static_rec_mutex_int = 0;
    102   g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex);
    103 
    104   g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 43);
    105 }
    106 
    107 /* GStaticPrivate */
    108 
    109 #define THREADS 10
    110 
    111 static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT;
    112 static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT;
    113 static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT;
    114 static guint test_g_static_private_counter = 0;
    115 static guint test_g_static_private_ready = 0;
    116 
    117 static gpointer
    118 test_g_static_private_constructor (void)
    119 {
    120   g_static_mutex_lock (&test_g_static_private_mutex);
    121   test_g_static_private_counter++;
    122   g_static_mutex_unlock (&test_g_static_private_mutex);
    123   return g_new (guint,1);
    124 }
    125 
    126 static void
    127 test_g_static_private_destructor (gpointer data)
    128 {
    129   g_static_mutex_lock (&test_g_static_private_mutex);
    130   test_g_static_private_counter--;
    131   g_static_mutex_unlock (&test_g_static_private_mutex);
    132   g_free (data);
    133 }
    134 
    135 
    136 static gpointer
    137 test_g_static_private_thread (gpointer data)
    138 {
    139   guint number = GPOINTER_TO_INT (data);
    140   guint i;
    141   guint *private1, *private2;
    142   for (i = 0; i < 10; i++)
    143     {
    144       number = number * 11 + 1; /* A very simple and bad RNG ;-) */
    145       private1 = g_static_private_get (&test_g_static_private_private1);
    146       if (!private1 || number % 7 > 3)
    147 	{
    148 	  private1 = test_g_static_private_constructor ();
    149 	  g_static_private_set (&test_g_static_private_private1, private1,
    150 				test_g_static_private_destructor);
    151 	}
    152       *private1 = number;
    153       private2 = g_static_private_get (&test_g_static_private_private2);
    154       if (!private2 || number % 13 > 5)
    155 	{
    156 	  private2 = test_g_static_private_constructor ();
    157 	  g_static_private_set (&test_g_static_private_private2, private2,
    158 				test_g_static_private_destructor);
    159 	}
    160       *private2 = number * 2;
    161       g_usleep (G_USEC_PER_SEC / 5);
    162       g_assert (number == *private1);
    163       g_assert (number * 2 == *private2);
    164     }
    165   g_static_mutex_lock (&test_g_static_private_mutex);
    166   test_g_static_private_ready++;
    167   g_static_mutex_unlock (&test_g_static_private_mutex);
    168 
    169   /* Busy wait is not nice but that's just a test */
    170   while (test_g_static_private_ready != 0)
    171     g_usleep (G_USEC_PER_SEC / 5);
    172 
    173   for (i = 0; i < 10; i++)
    174     {
    175       private2 = g_static_private_get (&test_g_static_private_private2);
    176       number = number * 11 + 1; /* A very simple and bad RNG ;-) */
    177       if (!private2 || number % 13 > 5)
    178 	{
    179 	  private2 = test_g_static_private_constructor ();
    180 	  g_static_private_set (&test_g_static_private_private2, private2,
    181 				test_g_static_private_destructor);
    182 	}
    183       *private2 = number * 2;
    184       g_usleep (G_USEC_PER_SEC / 5);
    185       g_assert (number * 2 == *private2);
    186     }
    187 
    188   return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3);
    189 }
    190 
    191 static void
    192 test_g_static_private (void)
    193 {
    194   GThread *threads[THREADS];
    195   guint i;
    196 
    197   test_g_static_private_ready = 0;
    198 
    199   for (i = 0; i < THREADS; i++)
    200     {
    201       threads[i] = g_thread_create (test_g_static_private_thread,
    202 				    GINT_TO_POINTER (i), TRUE, NULL);
    203     }
    204 
    205   /* Busy wait is not nice but that's just a test */
    206   while (test_g_static_private_ready != THREADS)
    207     g_usleep (G_USEC_PER_SEC / 5);
    208 
    209   /* Reuse the static private */
    210   g_static_private_free (&test_g_static_private_private2);
    211   g_static_private_init (&test_g_static_private_private2);
    212 
    213   test_g_static_private_ready = 0;
    214 
    215   for (i = 0; i < THREADS; i++)
    216     g_assert (GPOINTER_TO_INT (g_thread_join (threads[i])) == i * 3);
    217 
    218   g_assert (test_g_static_private_counter == 0);
    219 }
    220 
    221 /* GStaticRWLock */
    222 
    223 /* -1 = writing; >0 = # of readers */
    224 static gint test_g_static_rw_lock_state = 0;
    225 G_LOCK_DEFINE (test_g_static_rw_lock_state);
    226 
    227 static gboolean test_g_static_rw_lock_run = TRUE;
    228 static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT;
    229 
    230 static gpointer
    231 test_g_static_rw_lock_thread (gpointer data)
    232 {
    233   while (test_g_static_rw_lock_run)
    234     {
    235       if (g_random_double() > .2) /* I'm a reader */
    236 	{
    237 
    238 	  if (g_random_double() > .2) /* I'll block */
    239 	    g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock);
    240 	  else /* I'll only try */
    241 	    if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock))
    242 	      continue;
    243 	  G_LOCK (test_g_static_rw_lock_state);
    244 	  g_assert (test_g_static_rw_lock_state >= 0);
    245 	  test_g_static_rw_lock_state++;
    246 	  G_UNLOCK (test_g_static_rw_lock_state);
    247 
    248 	  g_usleep (g_random_int_range (20,1000));
    249 
    250 	  G_LOCK (test_g_static_rw_lock_state);
    251 	  test_g_static_rw_lock_state--;
    252 	  G_UNLOCK (test_g_static_rw_lock_state);
    253 
    254 	  g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock);
    255 	}
    256       else /* I'm a writer */
    257 	{
    258 
    259 	  if (g_random_double() > .2) /* I'll block */
    260 	    g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock);
    261 	  else /* I'll only try */
    262 	    if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock))
    263 	      continue;
    264 	  G_LOCK (test_g_static_rw_lock_state);
    265 	  g_assert (test_g_static_rw_lock_state == 0);
    266 	  test_g_static_rw_lock_state = -1;
    267 	  G_UNLOCK (test_g_static_rw_lock_state);
    268 
    269 	  g_usleep (g_random_int_range (20,1000));
    270 
    271 	  G_LOCK (test_g_static_rw_lock_state);
    272 	  test_g_static_rw_lock_state = 0;
    273 	  G_UNLOCK (test_g_static_rw_lock_state);
    274 
    275 	  g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock);
    276 	}
    277     }
    278   return NULL;
    279 }
    280 
    281 static void
    282 test_g_static_rw_lock ()
    283 {
    284   GThread *threads[THREADS];
    285   guint i;
    286   for (i = 0; i < THREADS; i++)
    287     {
    288       threads[i] = g_thread_create (test_g_static_rw_lock_thread,
    289 				    NULL, TRUE, NULL);
    290     }
    291   g_usleep (G_USEC_PER_SEC * 5);
    292   test_g_static_rw_lock_run = FALSE;
    293   for (i = 0; i < THREADS; i++)
    294     {
    295       g_thread_join (threads[i]);
    296     }
    297   g_assert (test_g_static_rw_lock_state == 0);
    298 }
    299 
    300 #define G_ONCE_SIZE 100
    301 #define G_ONCE_THREADS 10
    302 
    303 G_LOCK_DEFINE (test_g_once);
    304 static guint test_g_once_guint_array[G_ONCE_SIZE];
    305 static GOnce test_g_once_array[G_ONCE_SIZE];
    306 
    307 static gpointer
    308 test_g_once_init_func(gpointer arg)
    309 {
    310   guint *count = arg;
    311   g_usleep (g_random_int_range (20,1000));
    312   (*count)++;
    313   g_usleep (g_random_int_range (20,1000));
    314   return arg;
    315 }
    316 
    317 static gpointer
    318 test_g_once_thread (gpointer ignore)
    319 {
    320   guint i;
    321   G_LOCK (test_g_once);
    322   /* Don't start before all threads are created */
    323   G_UNLOCK (test_g_once);
    324   for (i = 0; i < 1000; i++)
    325     {
    326       guint pos = g_random_int_range (0, G_ONCE_SIZE);
    327       gpointer ret = g_once (test_g_once_array + pos, test_g_once_init_func,
    328 			     test_g_once_guint_array + pos);
    329       g_assert (ret == test_g_once_guint_array + pos);
    330     }
    331 
    332   /* Make sure, that all counters are touched at least once */
    333   for (i = 0; i < G_ONCE_SIZE; i++)
    334     {
    335       gpointer ret = g_once (test_g_once_array + i, test_g_once_init_func,
    336 			     test_g_once_guint_array + i);
    337       g_assert (ret == test_g_once_guint_array + i);
    338     }
    339 
    340   return NULL;
    341 }
    342 
    343 static void
    344 test_g_thread_once (void)
    345 {
    346   static GOnce once_init = G_ONCE_INIT;
    347   GThread *threads[G_ONCE_THREADS];
    348   guint i;
    349   for (i = 0; i < G_ONCE_SIZE; i++)
    350     {
    351       test_g_once_array[i] = once_init;
    352       test_g_once_guint_array[i] = i;
    353     }
    354   G_LOCK (test_g_once);
    355   for (i = 0; i < G_ONCE_THREADS; i++)
    356     {
    357       threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER(i%2),
    358 				    TRUE, NULL);
    359     }
    360   G_UNLOCK (test_g_once);
    361   for (i = 0; i < G_ONCE_THREADS; i++)
    362     {
    363       g_thread_join (threads[i]);
    364     }
    365 
    366   for (i = 0; i < G_ONCE_SIZE; i++)
    367     {
    368       g_assert (test_g_once_guint_array[i] == i + 1);
    369     }
    370 }
    371 
    372 /* run all the tests */
    373 void
    374 run_all_tests()
    375 {
    376   test_g_mutex ();
    377   test_g_static_rec_mutex ();
    378   test_g_static_private ();
    379   test_g_static_rw_lock ();
    380   test_g_thread_once ();
    381 }
    382 
    383 int
    384 main (int   argc,
    385       char *argv[])
    386 {
    387   /* Only run the test, if threads are enabled and a default thread
    388      implementation is available */
    389 #if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
    390   g_thread_init (NULL);
    391   run_all_tests ();
    392 
    393   /* Now we rerun all tests, but this time we fool the system into
    394    * thinking, that the available thread system is not native, but
    395    * userprovided. */
    396 
    397   g_thread_use_default_impl = FALSE;
    398   run_all_tests ();
    399 
    400 #endif
    401   return 0;
    402 }
    403