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 : 16 : pspec = g_object_interface_find_property (klass, "check");
68 : : }
69 : 16 : 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 : 2 : while (g_atomic_int_get (&n_checks) != N_THREADS)
97 : 1 : 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 : : }
|