1
0
mirror of https://gitlab.gnome.org/GNOME/glib.git synced 2025-07-31 06:13:29 +02:00
Files
.gitlab-ci
.reuse
LICENSES
docs
fuzzing
gio
girepository
glib
gmodule
gobject
tests
performance
accumulator.c
autoptr.c
basic-signals.c
basics-gobject.c
binding.c
bindinggroup.c
boxed.c
closure-refcount.c
closure.c
custom-dispatch.c
cxx.cpp
defaultiface.c
deftype.c
deprecated-properties.c
dynamictests.c
dynamictype.c
enums.c
flags.c
genmarshal.py
gobject-query.py
ifaceproperties.c
marshalers.list
max-version.c
meson.build
mkenums.py
notify-init.c
notify-init2.c
object.c
objects-refcount1.c
objects-refcount2.c
override.c
param.c
private.c
properties-introspection.c
properties-refcount1.c
properties-refcount2.c
properties-refcount3.c
properties-refcount4.c
properties.c
qdata.c
reference.c
references.c
signal-handler.c
signalgroup.c
signals-refcount.c
signals.c
singleton.c
taptestrunner.py
testcommon.h
testing.c
testmodule.c
testmodule.h
threadtests.c
type-flags.c
type.c
value.c
gatomicarray.c
gatomicarray.h
gbinding.c
gbinding.h
gbindinggroup.c
gbindinggroup.h
gboxed.c
gboxed.h
gclosure.c
gclosure.h
genums.c
genums.h
glib-enumtypes.c.template
glib-enumtypes.h.template
glib-genmarshal.in
glib-mkenums.in
glib-types.h
gmarshal.c
gmarshal.h
gobject-autocleanups.h
gobject-query.c
gobject.c
gobject.h
gobject.rc.in
gobject.stp.in
gobject_gdb.py
gobject_probes.d
gobject_trace.h
gobjectnotifyqueue.c
gparam.c
gparam.h
gparamspecs.c
gparamspecs.h
gsignal.c
gsignal.h
gsignalgroup.c
gsignalgroup.h
gsourceclosure.c
gsourceclosure.h
gtype-private.h
gtype.c
gtype.h
gtypemodule.c
gtypemodule.h
gtypeplugin.c
gtypeplugin.h
gvalue.c
gvalue.h
gvaluearray.c
gvaluearray.h
gvaluecollector.h
gvaluetransform.c
gvaluetypes.c
gvaluetypes.h
libgobject-gdb.py.in
meson.build
gthread
m4macros
po
subprojects
tests
tools
.clang-format
.dir-locals.el
.editorconfig
.gitignore
.gitlab-ci.yml
.gitmodules
.lcovrc
CODE_OF_CONDUCT.md
CONTRIBUTING.md
INSTALL.md
NEWS
README.md
SECURITY.md
glib.doap
meson.build
meson.options
glib/gobject/tests/properties-introspection.c
Emmanuele Bassi 4a270c947c tests: Check thread safety of GParamSpecPool
Aside from checking that we're accessing the global GParamSpecPool
without necessarily initializing GObjectClass, we should also verify
that we're doing so safely without the class init lock.
2023-12-19 22:48:03 +00:00

115 lines
2.6 KiB
C

/* properties-introspection.c: Test the properties introspection API
*
* SPDX-FileCopyrightText: 2023 Emmanuele Bassi
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/* This test is isolated so we can control the initialization of
* GObjectClass, and the global GParamSpecPool
*/
#include <stdlib.h>
#include <glib-object.h>
G_DECLARE_INTERFACE (MyTestable, my_testable, MY, TESTABLE, GObject)
struct _MyTestableInterface
{
GTypeInterface g_iface;
};
G_DEFINE_INTERFACE (MyTestable, my_testable, G_TYPE_OBJECT)
static void
my_testable_default_init (MyTestableInterface *iface)
{
g_object_interface_install_property (iface,
g_param_spec_int ("check", NULL, NULL, -1, 10, 0, G_PARAM_READWRITE));
}
static void
properties_introspection (void)
{
g_test_summary ("Verify that introspecting properties on an interface initializes the GParamSpecPool.");
if (g_test_subprocess ())
{
gpointer klass = g_type_default_interface_ref (my_testable_get_type ());
g_assert_nonnull (klass);
GParamSpec *pspec = g_object_interface_find_property (klass, "check");
g_assert_nonnull (pspec);
g_type_default_interface_unref (klass);
return;
}
g_test_trap_subprocess (NULL, 0, G_TEST_SUBPROCESS_DEFAULT);
g_test_trap_assert_passed ();
g_test_trap_assert_stderr ("");
}
static gpointer
inspect_func (gpointer data)
{
unsigned int *n_checks = data; /* (atomic) */
gpointer klass = NULL;
do
{
klass = g_type_default_interface_ref (my_testable_get_type ());
}
while (klass == NULL);
GParamSpec *pspec = NULL;
do
{
pspec = g_object_interface_find_property (klass, "check");
}
while (pspec == NULL);
g_type_default_interface_unref (klass);
g_atomic_int_inc (n_checks);
return NULL;
}
#define N_THREADS 10
static void
properties_collision (void)
{
GThread *threads[N_THREADS];
unsigned int n_checks = 0; /* (atomic) */
g_test_summary ("Verify that multiple threads create a single GParamSpecPool.");
for (unsigned int i = 0; i < N_THREADS; i++)
{
char *t_name = g_strdup_printf ("inspect [%d]", i);
threads[i] = g_thread_new (t_name, inspect_func, &n_checks);
g_assert_nonnull (threads[i]);
g_free (t_name);
}
while (g_atomic_int_get (&n_checks) != N_THREADS)
g_usleep (50);
for (unsigned int i = 0; i < N_THREADS; i++)
g_thread_join (threads[i]);
}
#undef N_THREADS
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
g_test_add_func ("/properties/introspection", properties_introspection);
g_test_add_func ("/properties/collision", properties_collision);
return g_test_run ();
}