(root)/
glib-2.79.0/
gobject/
tests/
properties-introspection.c
       1  /* properties-introspection.c: Test the properties introspection API
       2   *
       3   * SPDX-FileCopyrightText: 2023 Emmanuele Bassi
       4   * SPDX-License-Identifier: LGPL-2.1-or-later
       5   */
       6  
       7  /* This test is isolated so we can control the initialization of
       8   * GObjectClass, and the global GParamSpecPool
       9   */
      10  
      11  #include <stdlib.h>
      12  #include <glib-object.h>
      13  
      14  G_DECLARE_INTERFACE (MyTestable, my_testable, MY, TESTABLE, GObject)
      15  
      16  struct _MyTestableInterface
      17  {
      18    GTypeInterface g_iface;
      19  };
      20  
      21  G_DEFINE_INTERFACE (MyTestable, my_testable, G_TYPE_OBJECT)
      22  
      23  static void
      24  my_testable_default_init (MyTestableInterface *iface)
      25  {
      26    g_object_interface_install_property (iface,
      27      g_param_spec_int ("check", NULL, NULL, -1, 10, 0, G_PARAM_READWRITE));
      28  }
      29  
      30  static void
      31  properties_introspection (void)
      32  {
      33    g_test_summary ("Verify that introspecting properties on an interface initializes the GParamSpecPool.");
      34  
      35    if (g_test_subprocess ())
      36      {
      37        gpointer klass = g_type_default_interface_ref (my_testable_get_type ());
      38        g_assert_nonnull (klass);
      39  
      40        GParamSpec *pspec = g_object_interface_find_property (klass, "check");
      41        g_assert_nonnull (pspec);
      42  
      43        g_type_default_interface_unref (klass);
      44        return;
      45      }
      46  
      47    g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
      48    g_test_trap_assert_passed ();
      49    g_test_trap_assert_stderr ("");
      50  }
      51  
      52  static gpointer
      53  inspect_func (gpointer data)
      54  {
      55    unsigned int *n_checks = data; /* (atomic) */
      56  
      57    gpointer klass = NULL;
      58    do
      59      {
      60        klass = g_type_default_interface_ref (my_testable_get_type ());
      61      }
      62    while (klass == NULL);
      63  
      64    GParamSpec *pspec = NULL;
      65    do
      66      {
      67        pspec = g_object_interface_find_property (klass, "check");
      68      }
      69    while (pspec == NULL);
      70  
      71    g_type_default_interface_unref (klass);
      72  
      73    g_atomic_int_inc (n_checks);
      74  
      75    return NULL;
      76  }
      77  
      78  #define N_THREADS 10
      79  
      80  static void
      81  properties_collision (void)
      82  {
      83    GThread *threads[N_THREADS];
      84    unsigned int n_checks = 0; /* (atomic) */
      85  
      86    g_test_summary ("Verify that multiple threads create a single GParamSpecPool.");
      87  
      88    for (unsigned int i = 0; i < N_THREADS; i++)
      89      {
      90        char *t_name = g_strdup_printf ("inspect [%d]", i);
      91        threads[i] = g_thread_new (t_name, inspect_func, &n_checks);
      92        g_assert_nonnull (threads[i]);
      93        g_free (t_name);
      94      }
      95  
      96    while (g_atomic_int_get (&n_checks) != N_THREADS)
      97      g_usleep (50);
      98  
      99    for (unsigned int i = 0; i < N_THREADS; i++)
     100      g_thread_join (threads[i]);
     101  }
     102  
     103  #undef N_THREADS
     104  
     105  int
     106  main (int argc, char *argv[])
     107  {
     108    g_test_init (&argc, &argv, NULL);
     109  
     110    g_test_add_func ("/properties/introspection", properties_introspection);
     111    g_test_add_func ("/properties/collision", properties_collision);
     112  
     113    return g_test_run ();
     114  }