mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-31 06:13:29 +02:00
.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
COPYING
INSTALL.md
NEWS
README.md
SECURITY.md
glib.doap
meson.build
meson.options
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.
115 lines
2.6 KiB
C
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 ();
|
|
}
|