Branch data Line data Source code
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 [ + + + - : 11 : G_DEFINE_INTERFACE (MyTestable, my_testable, G_TYPE_OBJECT) + + ] 22 : : 23 : : static void 24 : 2 : my_testable_default_init (MyTestableInterface *iface) 25 : : { 26 : 2 : g_object_interface_install_property (iface, 27 : : g_param_spec_int ("check", NULL, NULL, -1, 10, 0, G_PARAM_READWRITE)); 28 : 2 : } 29 : : 30 : : static void 31 : 2 : properties_introspection (void) 32 : : { 33 : 2 : g_test_summary ("Verify that introspecting properties on an interface initializes the GParamSpecPool."); 34 : : 35 [ + + ]: 2 : if (g_test_subprocess ()) 36 : : { 37 : 1 : gpointer klass = g_type_default_interface_ref (my_testable_get_type ()); 38 : 1 : g_assert_nonnull (klass); 39 : : 40 : 1 : GParamSpec *pspec = g_object_interface_find_property (klass, "check"); 41 : 1 : g_assert_nonnull (pspec); 42 : : 43 : 1 : g_type_default_interface_unref (klass); 44 : 1 : return; 45 : : } 46 : : 47 : 1 : g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT); 48 : 1 : g_test_trap_assert_passed (); 49 : 1 : g_test_trap_assert_stderr (""); 50 : : } 51 : : 52 : : static gpointer 53 : 10 : inspect_func (gpointer data) 54 : : { 55 : 10 : unsigned int *n_checks = data; /* (atomic) */ 56 : : 57 : 10 : gpointer klass = NULL; 58 : : do 59 : : { 60 : 10 : klass = g_type_default_interface_ref (my_testable_get_type ()); 61 : : } 62 [ - + ]: 10 : while (klass == NULL); 63 : : 64 : 10 : GParamSpec *pspec = NULL; 65 : : do 66 : : { 67 : 10 : pspec = g_object_interface_find_property (klass, "check"); 68 : : } 69 [ - + ]: 10 : while (pspec == NULL); 70 : : 71 : 10 : g_type_default_interface_unref (klass); 72 : : 73 : 10 : g_atomic_int_inc (n_checks); 74 : : 75 : 10 : return NULL; 76 : : } 77 : : 78 : : #define N_THREADS 10 79 : : 80 : : static void 81 : 1 : properties_collision (void) 82 : : { 83 : : GThread *threads[N_THREADS]; 84 : 1 : unsigned int n_checks = 0; /* (atomic) */ 85 : : 86 : 1 : g_test_summary ("Verify that multiple threads create a single GParamSpecPool."); 87 : : 88 [ + + ]: 11 : for (unsigned int i = 0; i < N_THREADS; i++) 89 : : { 90 : 10 : char *t_name = g_strdup_printf ("inspect [%d]", i); 91 : 10 : threads[i] = g_thread_new (t_name, inspect_func, &n_checks); 92 : 10 : g_assert_nonnull (threads[i]); 93 : 10 : g_free (t_name); 94 : : } 95 : : 96 [ + + ]: 114 : while (g_atomic_int_get (&n_checks) != N_THREADS) 97 : 113 : g_usleep (50); 98 : : 99 [ + + ]: 11 : for (unsigned int i = 0; i < N_THREADS; i++) 100 : 10 : g_thread_join (threads[i]); 101 : 1 : } 102 : : 103 : : #undef N_THREADS 104 : : 105 : : int 106 : 2 : main (int argc, char *argv[]) 107 : : { 108 : 2 : g_test_init (&argc, &argv, NULL); 109 : : 110 : 2 : g_test_add_func ("/properties/introspection", properties_introspection); 111 : 2 : g_test_add_func ("/properties/collision", properties_collision); 112 : : 113 : 2 : return g_test_run (); 114 : : }