Import Upstream version 2.72.4

This commit is contained in:
evinadmin 2023-07-04 11:23:22 +02:00
commit 4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions

15
tests/gobject/.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
accumulator
defaultiface
dynamictype
gvalue-test
ifacecheck
ifaceinherit
ifaceinit
ifaceproperties
override
paramspec-test
performance
performance-threaded
references
signals
singleton

307
tests/gobject/accumulator.c Normal file
View file

@ -0,0 +1,307 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2001, 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestAccumulator"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <string.h>
#include <glib-object.h>
#include "testmarshal.h"
#include "testcommon.h"
/* What this test tests is the behavior of signal accumulators
* Two accumulators are tested:
*
* 1: A custom accumulator that appends the returned strings
* 2: The standard g_signal_accumulator_true_handled that stops
* emission on TRUE returns.
*/
/*
* TestObject, a parent class for TestObject
*/
#define TEST_TYPE_OBJECT (test_object_get_type ())
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
struct _TestObject
{
GObject parent_instance;
};
struct _TestObjectClass
{
GObjectClass parent_class;
gchar* (*test_signal1) (TestObject *tobject,
gint param);
gboolean (*test_signal2) (TestObject *tobject,
gint param);
GVariant* (*test_signal3) (TestObject *tobject,
gboolean *weak_ptr);
};
static GType test_object_get_type (void);
static gboolean
test_signal1_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
const gchar *accu_string = g_value_get_string (return_accu);
const gchar *new_string = g_value_get_string (handler_return);
gchar *result_string;
if (accu_string)
result_string = g_strconcat (accu_string, new_string, NULL);
else if (new_string)
result_string = g_strdup (new_string);
else
result_string = NULL;
g_value_set_string_take_ownership (return_accu, result_string);
return TRUE;
}
static gchar *
test_object_signal1_callback_before (TestObject *tobject,
gint param,
gpointer data)
{
return g_strdup ("<before>");
}
static gchar *
test_object_real_signal1 (TestObject *tobject,
gint param)
{
return g_strdup ("<default>");
}
static gchar *
test_object_signal1_callback_after (TestObject *tobject,
gint param,
gpointer data)
{
return g_strdup ("<after>");
}
static gboolean
test_object_signal2_callback_before (TestObject *tobject,
gint param)
{
switch (param)
{
case 1: return TRUE;
case 2: return FALSE;
case 3: return FALSE;
case 4: return FALSE;
}
g_assert_not_reached ();
return FALSE;
}
static gboolean
test_object_real_signal2 (TestObject *tobject,
gint param)
{
switch (param)
{
case 1: g_assert_not_reached (); return FALSE;
case 2: return TRUE;
case 3: return FALSE;
case 4: return FALSE;
}
g_assert_not_reached ();
return FALSE;
}
static gboolean
test_object_signal2_callback_after (TestObject *tobject,
gint param)
{
switch (param)
{
case 1: g_assert_not_reached (); return FALSE;
case 2: g_assert_not_reached (); return FALSE;
case 3: return TRUE;
case 4: return FALSE;
}
g_assert_not_reached ();
return FALSE;
}
static gboolean
test_signal3_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
GVariant *variant;
variant = g_value_get_variant (handler_return);
g_assert (!g_variant_is_floating (variant));
g_value_set_variant (return_accu, variant);
return variant == NULL;
}
/* To be notified when the variant is finalised, we construct
* it from data with a custom GDestroyNotify.
*/
typedef struct {
char *mem;
gsize n;
gboolean *weak_ptr;
} VariantData;
static void
free_data (VariantData *data)
{
*(data->weak_ptr) = TRUE;
g_free (data->mem);
g_slice_free (VariantData, data);
}
static GVariant *
test_object_real_signal3 (TestObject *tobject,
gboolean *weak_ptr)
{
GVariant *variant;
VariantData *data;
variant = g_variant_ref_sink (g_variant_new_uint32 (42));
data = g_slice_new (VariantData);
data->weak_ptr = weak_ptr;
data->n = g_variant_get_size (variant);
data->mem = g_malloc (data->n);
g_variant_store (variant, data->mem);
g_variant_unref (variant);
variant = g_variant_new_from_data (G_VARIANT_TYPE ("u"),
data->mem,
data->n,
TRUE,
(GDestroyNotify) free_data,
data);
return g_variant_ref_sink (variant);
}
static void
test_object_class_init (TestObjectClass *class)
{
class->test_signal1 = test_object_real_signal1;
class->test_signal2 = test_object_real_signal2;
class->test_signal3 = test_object_real_signal3;
g_signal_new ("test-signal1",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestObjectClass, test_signal1),
test_signal1_accumulator, NULL,
test_marshal_STRING__INT,
G_TYPE_STRING, 1, G_TYPE_INT);
g_signal_new ("test-signal2",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestObjectClass, test_signal2),
g_signal_accumulator_true_handled, NULL,
test_marshal_BOOLEAN__INT,
G_TYPE_BOOLEAN, 1, G_TYPE_INT);
g_signal_new ("test-signal3",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestObjectClass, test_signal3),
test_signal3_accumulator, NULL,
test_marshal_VARIANT__POINTER,
G_TYPE_VARIANT, 1, G_TYPE_POINTER);
}
static DEFINE_TYPE(TestObject, test_object,
test_object_class_init, NULL, NULL,
G_TYPE_OBJECT)
int
main (int argc,
char *argv[])
{
TestObject *object;
gchar *string_result;
gboolean bool_result;
gboolean variant_finalised;
GVariant *variant_result;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_signal_connect (object, "test-signal1",
G_CALLBACK (test_object_signal1_callback_before), NULL);
g_signal_connect_after (object, "test-signal1",
G_CALLBACK (test_object_signal1_callback_after), NULL);
g_signal_emit_by_name (object, "test-signal1", 0, &string_result);
g_assert (strcmp (string_result, "<before><default><after>") == 0);
g_free (string_result);
g_signal_connect (object, "test-signal2",
G_CALLBACK (test_object_signal2_callback_before), NULL);
g_signal_connect_after (object, "test-signal2",
G_CALLBACK (test_object_signal2_callback_after), NULL);
bool_result = FALSE;
g_signal_emit_by_name (object, "test-signal2", 1, &bool_result);
g_assert (bool_result == TRUE);
bool_result = FALSE;
g_signal_emit_by_name (object, "test-signal2", 2, &bool_result);
g_assert (bool_result == TRUE);
bool_result = FALSE;
g_signal_emit_by_name (object, "test-signal2", 3, &bool_result);
g_assert (bool_result == TRUE);
bool_result = TRUE;
g_signal_emit_by_name (object, "test-signal2", 4, &bool_result);
g_assert (bool_result == FALSE);
variant_finalised = FALSE;
variant_result = NULL;
g_signal_emit_by_name (object, "test-signal3", &variant_finalised, &variant_result);
g_assert (variant_result != NULL);
g_assert (!g_variant_is_floating (variant_result));
/* Test that variant_result had refcount 1 */
g_assert (!variant_finalised);
g_variant_unref (variant_result);
g_assert (variant_finalised);
g_object_unref (object);
return 0;
}

View file

@ -0,0 +1,199 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2001, 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestDefaultIface"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <glib-object.h>
#include "testcommon.h"
#include "testmodule.h"
/* This test tests getting the default vtable for an interface
* and the initialization and finalization of such default
* interfaces.
*
* We test this both for static and for dynamic interfaces.
*/
/**********************************************************************
* Static interface tests
**********************************************************************/
typedef struct _TestStaticIfaceClass TestStaticIfaceClass;
struct _TestStaticIfaceClass
{
GTypeInterface base_iface;
guint val;
};
GType test_static_iface_get_type (void);
#define TEST_TYPE_STATIC_IFACE (test_static_iface_get_type ())
static void
test_static_iface_default_init (TestStaticIfaceClass *iface)
{
iface->val = 42;
}
DEFINE_IFACE (TestStaticIface, test_static_iface,
NULL, test_static_iface_default_init)
static void
test_static_iface (void)
{
TestStaticIfaceClass *static_iface;
/* Not loaded until we call ref for the first time */
static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
g_assert (static_iface == NULL);
/* Ref loads */
static_iface = g_type_default_interface_ref (TEST_TYPE_STATIC_IFACE);
g_assert (static_iface && static_iface->val == 42);
/* Peek then works */
static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
g_assert (static_iface && static_iface->val == 42);
/* Unref does nothing */
g_type_default_interface_unref (static_iface);
/* And peek still works */
static_iface = g_type_default_interface_peek (TEST_TYPE_STATIC_IFACE);
g_assert (static_iface && static_iface->val == 42);
}
/**********************************************************************
* Dynamic interface tests
**********************************************************************/
typedef struct _TestDynamicIfaceClass TestDynamicIfaceClass;
struct _TestDynamicIfaceClass
{
GTypeInterface base_iface;
guint val;
};
static GType test_dynamic_iface_type;
static gboolean dynamic_iface_init = FALSE;
#define TEST_TYPE_DYNAMIC_IFACE (test_dynamic_iface_type)
static void
test_dynamic_iface_default_init (TestStaticIfaceClass *iface)
{
dynamic_iface_init = TRUE;
iface->val = 42;
}
static void
test_dynamic_iface_default_finalize (TestStaticIfaceClass *iface)
{
dynamic_iface_init = FALSE;
}
static void
test_dynamic_iface_register (GTypeModule *module)
{
const GTypeInfo iface_info =
{
sizeof (TestDynamicIfaceClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) test_dynamic_iface_default_init,
(GClassFinalizeFunc) test_dynamic_iface_default_finalize,
NULL,
0,
0,
NULL,
NULL
};
test_dynamic_iface_type = g_type_module_register_type (module, G_TYPE_INTERFACE,
"TestDynamicIface", &iface_info, 0);
}
static void
module_register (GTypeModule *module)
{
test_dynamic_iface_register (module);
}
static void
test_dynamic_iface (void)
{
TestDynamicIfaceClass *dynamic_iface;
test_module_new (module_register);
/* Not loaded until we call ref for the first time */
dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
g_assert (dynamic_iface == NULL);
/* Ref loads */
dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
g_assert (dynamic_iface_init);
g_assert (dynamic_iface && dynamic_iface->val == 42);
/* Peek then works */
dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
g_assert (dynamic_iface && dynamic_iface->val == 42);
/* Unref causes finalize */
g_type_default_interface_unref (dynamic_iface);
#if 0
g_assert (!dynamic_iface_init);
#endif
/* Peek returns NULL */
dynamic_iface = g_type_default_interface_peek (TEST_TYPE_DYNAMIC_IFACE);
#if 0
g_assert (dynamic_iface == NULL);
#endif
/* Ref reloads */
dynamic_iface = g_type_default_interface_ref (TEST_TYPE_DYNAMIC_IFACE);
g_assert (dynamic_iface_init);
g_assert (dynamic_iface && dynamic_iface->val == 42);
/* And Unref causes finalize once more*/
g_type_default_interface_unref (dynamic_iface);
#if 0
g_assert (!dynamic_iface_init);
#endif
}
int
main (int argc,
char *argv[])
{
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
test_static_iface ();
test_dynamic_iface ();
return 0;
}

59
tests/gobject/deftype.c Normal file
View file

@ -0,0 +1,59 @@
/* deftype.c
* Copyright (C) 2006 Behdad Esfahbod
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <glib-object.h>
/* see http://bugzilla.gnome.org/show_bug.cgi?id=337128 for the purpose of this test */
#define MY_G_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) { \
const GInterfaceInfo g_implement_interface_info = { \
(GInterfaceInitFunc) iface_init, \
NULL, \
NULL \
}; \
g_type_add_interface_static (g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
}
#define MY_DEFINE_TYPE(TN, t_n, T_P) \
G_DEFINE_TYPE_WITH_CODE (TN, t_n, T_P, \
MY_G_IMPLEMENT_INTERFACE (G_TYPE_INTERFACE, NULL))
typedef struct _TypeName {
GObject parent_instance;
const char *name;
} TypeName;
typedef struct _TypeNameClass {
GObjectClass parent_parent;
} TypeNameClass;
GType type_name_get_type (void);
MY_DEFINE_TYPE (TypeName, type_name, G_TYPE_OBJECT)
static void type_name_init (TypeName *self)
{
}
static void type_name_class_init (TypeNameClass *klass)
{
}
int
main (void)
{
return 0;
}

175
tests/gobject/dynamictype.c Normal file
View file

@ -0,0 +1,175 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2001, 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestDynamicType"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <glib-object.h>
#include "testcommon.h"
#include "testmodule.h"
/* This test tests the macros for defining dynamic types.
*/
static gboolean loaded = FALSE;
struct _TestIfaceClass
{
GTypeInterface base_iface;
guint val;
};
static GType test_iface_get_type (void);
#define TEST_TYPE_IFACE (test_iface_get_type ())
#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass))
typedef struct _TestIface TestIface;
typedef struct _TestIfaceClass TestIfaceClass;
static void test_iface_base_init (TestIfaceClass *iface);
static void test_iface_default_init (TestIfaceClass *iface, gpointer class_data);
static DEFINE_IFACE(TestIface, test_iface, test_iface_base_init, test_iface_default_init)
static void
test_iface_default_init (TestIfaceClass *iface,
gpointer class_data)
{
}
static void
test_iface_base_init (TestIfaceClass *iface)
{
}
GType dynamic_object_get_type (void);
#define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ())
typedef GObject DynamicObject;
typedef struct _DynamicObjectClass DynamicObjectClass;
struct _DynamicObjectClass
{
GObjectClass parent_class;
guint val;
};
static void dynamic_object_iface_init (TestIface *iface);
G_DEFINE_DYNAMIC_TYPE_EXTENDED(DynamicObject, dynamic_object, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE_DYNAMIC (TEST_TYPE_IFACE,
dynamic_object_iface_init));
static void
dynamic_object_class_init (DynamicObjectClass *class)
{
class->val = 42;
loaded = TRUE;
}
static void
dynamic_object_class_finalize (DynamicObjectClass *class)
{
loaded = FALSE;
}
static void
dynamic_object_iface_init (TestIface *iface)
{
}
static void
dynamic_object_init (DynamicObject *dynamic_object)
{
}
static void
module_register (GTypeModule *module)
{
dynamic_object_register_type (module);
}
static void
test_dynamic_type (void)
{
DynamicObjectClass *class;
test_module_new (module_register);
/* Not loaded until we call ref for the first time */
class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
g_assert (class == NULL);
g_assert (!loaded);
/* Make sure interfaces work */
g_assert (g_type_is_a (DYNAMIC_OBJECT_TYPE,
TEST_TYPE_IFACE));
/* Ref loads */
class = g_type_class_ref (DYNAMIC_OBJECT_TYPE);
g_assert (class && class->val == 42);
g_assert (loaded);
/* Peek then works */
class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
g_assert (class && class->val == 42);
g_assert (loaded);
/* Make sure interfaces still work */
g_assert (g_type_is_a (DYNAMIC_OBJECT_TYPE,
TEST_TYPE_IFACE));
/* Unref causes finalize */
g_type_class_unref (class);
/* Peek returns NULL */
class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
#if 0
g_assert (!class);
g_assert (!loaded);
#endif
/* Ref reloads */
class = g_type_class_ref (DYNAMIC_OBJECT_TYPE);
g_assert (class && class->val == 42);
g_assert (loaded);
/* And Unref causes finalize once more*/
g_type_class_unref (class);
class = g_type_class_peek (DYNAMIC_OBJECT_TYPE);
#if 0
g_assert (!class);
g_assert (!loaded);
#endif
}
int
main (int argc,
char *argv[])
{
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
test_dynamic_type ();
return 0;
}

98
tests/gobject/meson.build Normal file
View file

@ -0,0 +1,98 @@
# We cannot use gnome.genmarshal() here
testmarshal_h = custom_target('testmarshal_h',
output : 'testmarshal.h',
input : 'testmarshal.list',
command : [
python, glib_genmarshal,
'--prefix=test_marshal',
'--output=@OUTPUT@',
'--quiet',
'--header',
'@INPUT@',
],
)
testmarshal_c = custom_target('testmarshal_c',
output : 'testmarshal.c',
input : 'testmarshal.list',
command : [
python, glib_genmarshal,
'--prefix=test_marshal',
'--include-header=testmarshal.h',
'--output=@OUTPUT@',
'--quiet',
'--body',
'@INPUT@',
],
)
gobject_tests = {
'deftype' : {},
'defaultiface' : {
'extra_sources' : ['testmodule.c'],
},
'dynamictype' : {
'extra_sources' : ['testmodule.c'],
},
'override' : {},
'signals' : {},
'singleton' : {},
'references' : {},
'testgobject' : {},
'accumulator' : {
'extra_sources' : [testmarshal_c, testmarshal_h],
},
}
if host_system != 'windows'
gobject_tests += {
'timeloop-closure' : {},
}
endif
common_c_args = test_cargs + ['-DGLIB_DISABLE_DEPRECATION_WARNINGS']
common_deps = [libm, thread_dep, libglib_dep, libgobject_dep]
foreach test_name, extra_args : gobject_tests
source = extra_args.get('source', test_name + '.c')
extra_sources = extra_args.get('extra_sources', [])
install = installed_tests_enabled and extra_args.get('install', true)
template = extra_args.get('tap', false) ? installed_tests_template_tap : installed_tests_template
if install
test_conf = configuration_data()
test_conf.set('installed_tests_dir', installed_tests_execdir)
test_conf.set('program', test_name)
test_conf.set('env', '')
configure_file(
input: template,
output: test_name + '.test',
install_dir: installed_tests_metadir,
configuration: test_conf
)
endif
# FIXME? $(GLIB_DEBUG_FLAGS)
exe = executable(test_name, [source, extra_sources],
c_args : common_c_args + extra_args.get('c_args', []),
dependencies : common_deps + extra_args.get('dependencies', []),
install_dir: installed_tests_execdir,
install: install,
)
suite = ['gobject'] + extra_args.get('suite', [])
timeout = suite.contains('slow') ? test_timeout_slow : test_timeout
# FIXME? TESTS_ENVIRONMENT = LIBCHARSET_ALIAS_DIR=$(top_builddir)/glib/libcharset
test(test_name, exe, env : test_env, timeout : timeout, suite : suite)
endforeach
# Don't install these ones, and keep them out of 'make check' because they take too long...
executable('performance', 'performance.c',
c_args : common_c_args,
dependencies : common_deps,
install : false)
executable('performance-threaded', 'performance-threaded.c',
c_args : common_c_args,
dependencies : common_deps,
install : false)

418
tests/gobject/override.c Normal file
View file

@ -0,0 +1,418 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* override.c: Closure override test program
* Copyright (C) 2001, James Henstridge
* Copyright (C) 2003, Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestOverride"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#undef VERBOSE
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include "testcommon.h"
static guint foo_signal_id = 0;
static guint bar_signal_id = 0;
static guint baz_signal_id = 0;
static GType test_i_get_type (void);
static GType test_a_get_type (void);
static GType test_b_get_type (void);
static GType test_c_get_type (void);
static void record (const gchar *str);
#define TEST_TYPE_I (test_i_get_type ())
typedef struct _TestI TestI;
typedef struct _TestIClass TestIClass;
struct _TestIClass
{
GTypeInterface base_iface;
};
static void
test_i_foo (TestI *self)
{
record ("TestI::foo");
}
static void
test_i_default_init (gpointer g_class)
{
foo_signal_id = g_signal_newv ("foo",
TEST_TYPE_I,
G_SIGNAL_RUN_LAST,
g_cclosure_new(G_CALLBACK(test_i_foo),
NULL, NULL),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, NULL);
}
static DEFINE_IFACE (TestI, test_i, NULL, test_i_default_init)
#define TEST_TYPE_A (test_a_get_type())
typedef struct _TestA TestA;
typedef struct _TestAClass TestAClass;
struct _TestA {
GObject parent;
};
struct _TestAClass {
GObjectClass parent_class;
void (* bar) (TestA *self);
};
static void
test_a_foo (TestI *self)
{
GValue args[1] = { G_VALUE_INIT };
record ("TestA::foo");
g_value_init (&args[0], TEST_TYPE_A);
g_value_set_object (&args[0], self);
g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
g_signal_chain_from_overridden (args, NULL);
g_value_unset (&args[0]);
}
static void
test_a_bar (TestA *self)
{
record ("TestA::bar");
}
static gchar *
test_a_baz (TestA *self,
GObject *object,
gpointer pointer)
{
record ("TestA::baz");
g_assert (object == G_OBJECT (self));
g_assert (GPOINTER_TO_INT (pointer) == 23);
return g_strdup ("TestA::baz");
}
static void
test_a_class_init (TestAClass *class)
{
class->bar = test_a_bar;
bar_signal_id = g_signal_new ("bar",
TEST_TYPE_A,
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestAClass, bar),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, NULL);
baz_signal_id = g_signal_new_class_handler ("baz",
TEST_TYPE_A,
G_SIGNAL_RUN_LAST,
G_CALLBACK (test_a_baz),
NULL, NULL,
g_cclosure_marshal_STRING__OBJECT_POINTER,
G_TYPE_STRING, 2,
G_TYPE_OBJECT,
G_TYPE_POINTER);
}
static void
test_a_interface_init (TestIClass *iface)
{
g_signal_override_class_closure (foo_signal_id,
TEST_TYPE_A,
g_cclosure_new (G_CALLBACK (test_a_foo),
NULL, NULL));
}
static DEFINE_TYPE_FULL (TestA, test_a,
test_a_class_init, NULL, NULL,
G_TYPE_OBJECT,
INTERFACE (test_a_interface_init, TEST_TYPE_I))
#define TEST_TYPE_B (test_b_get_type())
typedef struct _TestB TestB;
typedef struct _TestBClass TestBClass;
struct _TestB {
TestA parent;
};
struct _TestBClass {
TestAClass parent_class;
};
static void
test_b_foo (TestI *self)
{
GValue args[1] = { G_VALUE_INIT };
record ("TestB::foo");
g_value_init (&args[0], TEST_TYPE_A);
g_value_set_object (&args[0], self);
g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
g_signal_chain_from_overridden (args, NULL);
g_value_unset (&args[0]);
}
static void
test_b_bar (TestA *self)
{
GValue args[1] = { G_VALUE_INIT };
record ("TestB::bar");
g_value_init (&args[0], TEST_TYPE_A);
g_value_set_object (&args[0], self);
g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
g_signal_chain_from_overridden (args, NULL);
g_value_unset (&args[0]);
}
static gchar *
test_b_baz (TestA *self,
GObject *object,
gpointer pointer)
{
gchar *retval = NULL;
record ("TestB::baz");
g_assert (object == G_OBJECT (self));
g_assert (GPOINTER_TO_INT (pointer) == 23);
g_signal_chain_from_overridden_handler (self, object, pointer, &retval);
if (retval)
{
gchar *tmp = g_strconcat (retval , ",TestB::baz", NULL);
g_free (retval);
retval = tmp;
}
return retval;
}
static void
test_b_class_init (TestBClass *class)
{
g_signal_override_class_closure (foo_signal_id,
TEST_TYPE_B,
g_cclosure_new (G_CALLBACK (test_b_foo),
NULL, NULL));
g_signal_override_class_closure (bar_signal_id,
TEST_TYPE_B,
g_cclosure_new (G_CALLBACK (test_b_bar),
NULL, NULL));
g_signal_override_class_handler ("baz",
TEST_TYPE_B,
G_CALLBACK (test_b_baz));
}
static DEFINE_TYPE (TestB, test_b,
test_b_class_init, NULL, NULL,
TEST_TYPE_A)
#define TEST_TYPE_C (test_c_get_type())
typedef struct _TestC TestC;
typedef struct _TestCClass TestCClass;
struct _TestC {
TestB parent;
};
struct _TestCClass {
TestBClass parent_class;
};
static void
test_c_foo (TestI *self)
{
GValue args[1] = { G_VALUE_INIT };
record ("TestC::foo");
g_value_init (&args[0], TEST_TYPE_A);
g_value_set_object (&args[0], self);
g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
g_signal_chain_from_overridden (args, NULL);
g_value_unset (&args[0]);
}
static void
test_c_bar (TestA *self)
{
GValue args[1] = { G_VALUE_INIT };
record ("TestC::bar");
g_value_init (&args[0], TEST_TYPE_A);
g_value_set_object (&args[0], self);
g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
g_signal_chain_from_overridden (args, NULL);
g_value_unset (&args[0]);
}
static gchar *
test_c_baz (TestA *self,
GObject *object,
gpointer pointer)
{
gchar *retval = NULL;
record ("TestC::baz");
g_assert (object == G_OBJECT (self));
g_assert (GPOINTER_TO_INT (pointer) == 23);
g_signal_chain_from_overridden_handler (self, object, pointer, &retval);
if (retval)
{
gchar *tmp = g_strconcat (retval , ",TestC::baz", NULL);
g_free (retval);
retval = tmp;
}
return retval;
}
static void
test_c_class_init (TestBClass *class)
{
g_signal_override_class_closure (foo_signal_id,
TEST_TYPE_C,
g_cclosure_new (G_CALLBACK (test_c_foo),
NULL, NULL));
g_signal_override_class_closure (bar_signal_id,
TEST_TYPE_C,
g_cclosure_new (G_CALLBACK (test_c_bar),
NULL, NULL));
g_signal_override_class_handler ("baz",
TEST_TYPE_C,
G_CALLBACK (test_c_baz));
}
static DEFINE_TYPE (TestC, test_c,
test_c_class_init, NULL, NULL,
TEST_TYPE_B)
static GString *test_string = NULL;
gboolean failed = FALSE;
static void
record (const gchar *str)
{
if (test_string->len)
g_string_append_c (test_string, ',');
g_string_append (test_string, str);
}
static void
test (GType type,
const gchar *signal,
const gchar *expected,
const gchar *expected_retval)
{
GObject *self = g_object_new (type, NULL);
test_string = g_string_new (NULL);
if (strcmp (signal, "baz"))
{
g_signal_emit_by_name (self, signal);
}
else
{
gchar *ret;
g_signal_emit_by_name (self, signal, self, GINT_TO_POINTER (23), &ret);
if (strcmp (ret, expected_retval) != 0)
failed = TRUE;
g_free (ret);
}
#ifndef VERBOSE
if (strcmp (test_string->str, expected) != 0)
#endif
{
g_printerr ("*** emitting %s on a %s instance\n"
" Expecting: %s\n"
" Got: %s\n",
signal, g_type_name (type),
expected,
test_string->str);
if (strcmp (test_string->str, expected) != 0)
failed = TRUE;
}
g_string_free (test_string, TRUE);
g_object_unref (self);
}
int
main (int argc, char **argv)
{
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
test (TEST_TYPE_A, "foo", "TestA::foo,TestI::foo", NULL);
test (TEST_TYPE_A, "bar", "TestA::bar", NULL);
test (TEST_TYPE_A, "baz", "TestA::baz", "TestA::baz");
test (TEST_TYPE_B, "foo", "TestB::foo,TestA::foo,TestI::foo", NULL);
test (TEST_TYPE_B, "bar", "TestB::bar,TestA::bar", NULL);
test (TEST_TYPE_B, "baz", "TestB::baz,TestA::baz", "TestA::baz,TestB::baz");
test (TEST_TYPE_C, "foo", "TestC::foo,TestB::foo,TestA::foo,TestI::foo", NULL);
test (TEST_TYPE_C, "bar", "TestC::bar,TestB::bar,TestA::bar", NULL);
test (TEST_TYPE_C, "baz", "TestC::baz,TestB::baz,TestA::baz", "TestA::baz,TestB::baz,TestC::baz");
return failed ? 1 : 0;
}

View file

@ -0,0 +1,375 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2009 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string.h>
#include <glib-object.h>
#include "testcommon.h"
#define DEFAULT_TEST_TIME 2 /* seconds */
static GType
simple_register_class (const char *name, GType parent, ...)
{
GInterfaceInfo interface_info = { NULL, NULL, NULL };
va_list args;
GType type, interface;
va_start (args, parent);
type = g_type_register_static_simple (parent, name, sizeof (GObjectClass),
NULL, parent == G_TYPE_INTERFACE ? 0 : sizeof (GObject), NULL, 0);
for (;;)
{
interface = va_arg (args, GType);
if (interface == 0)
break;
g_type_add_interface_static (type, interface, &interface_info);
}
va_end (args);
return type;
}
/* test emulating liststore behavior for interface lookups */
static GType liststore;
static GType liststore_interfaces[6];
static gpointer
register_types (void)
{
static gsize inited = 0;
if (g_once_init_enter (&inited))
{
liststore_interfaces[0] = simple_register_class ("GtkBuildable", G_TYPE_INTERFACE, 0);
liststore_interfaces[1] = simple_register_class ("GtkTreeDragDest", G_TYPE_INTERFACE, 0);
liststore_interfaces[2] = simple_register_class ("GtkTreeModel", G_TYPE_INTERFACE, 0);
liststore_interfaces[3] = simple_register_class ("GtkTreeDragSource", G_TYPE_INTERFACE, 0);
liststore_interfaces[4] = simple_register_class ("GtkTreeSortable", G_TYPE_INTERFACE, 0);
liststore_interfaces[5] = simple_register_class ("UnrelatedInterface", G_TYPE_INTERFACE, 0);
liststore = simple_register_class ("GtkListStore", G_TYPE_OBJECT,
liststore_interfaces[0], liststore_interfaces[1], liststore_interfaces[2],
liststore_interfaces[3], liststore_interfaces[4], (GType) 0);
g_once_init_leave (&inited, 1);
}
return NULL;
}
static void
liststore_is_a_run (gpointer data)
{
guint i;
for (i = 0; i < 1000; i++)
{
g_assert (g_type_is_a (liststore, liststore_interfaces[0]));
g_assert (g_type_is_a (liststore, liststore_interfaces[1]));
g_assert (g_type_is_a (liststore, liststore_interfaces[2]));
g_assert (g_type_is_a (liststore, liststore_interfaces[3]));
g_assert (g_type_is_a (liststore, liststore_interfaces[4]));
g_assert (!g_type_is_a (liststore, liststore_interfaces[5]));
}
}
static gpointer
liststore_get_class (void)
{
register_types ();
return g_type_class_ref (liststore);
}
static void
liststore_interface_peek_run (gpointer klass)
{
guint i;
gpointer iface;
for (i = 0; i < 1000; i++)
{
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[1]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[2]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[3]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[4]);
g_assert (iface);
}
}
static void
liststore_interface_peek_same_run (gpointer klass)
{
guint i;
gpointer iface;
for (i = 0; i < 1000; i++)
{
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
iface = g_type_interface_peek (klass, liststore_interfaces[0]);
g_assert (iface);
}
}
#if 0
/* DUMB test doing nothing */
static gpointer
no_setup (void)
{
return NULL;
}
static void
no_run (gpointer data)
{
}
#endif
static void
no_reset (gpointer data)
{
}
static void
no_teardown (gpointer data)
{
}
typedef struct _PerformanceTest PerformanceTest;
struct _PerformanceTest {
const char *name;
gpointer (*setup) (void);
void (*run) (gpointer data);
void (*reset) (gpointer data);
void (*teardown) (gpointer data);
};
static const PerformanceTest tests[] = {
{ "liststore-is-a",
register_types,
liststore_is_a_run,
no_reset,
no_teardown },
{ "liststore-interface-peek",
liststore_get_class,
liststore_interface_peek_run,
no_reset,
g_type_class_unref },
{ "liststore-interface-peek-same",
liststore_get_class,
liststore_interface_peek_same_run,
no_reset,
g_type_class_unref },
#if 0
{ "nothing",
no_setup,
no_run,
no_reset,
no_teardown }
#endif
};
static gboolean verbose = FALSE;
static guint n_threads = 0;
static gboolean list = FALSE;
static int test_length = DEFAULT_TEST_TIME;
static GOptionEntry cmd_entries[] = {
{"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
"Print extra information", NULL},
{"threads", 't', 0, G_OPTION_ARG_INT, &n_threads,
"number of threads to run in parallel", NULL},
{"seconds", 's', 0, G_OPTION_ARG_INT, &test_length,
"Time to run each test in seconds", NULL},
{"list", 'l', 0, G_OPTION_ARG_NONE, &list,
"List all available tests and exit", NULL},
G_OPTION_ENTRY_NULL
};
static gpointer
run_test_thread (gpointer user_data)
{
const PerformanceTest *test = user_data;
gpointer data;
double elapsed;
GTimer *timer, *total;
GArray *results;
total = g_timer_new ();
g_timer_start (total);
/* Set up test */
timer = g_timer_new ();
data = test->setup ();
results = g_array_new (FALSE, FALSE, sizeof (double));
/* Run the test */
while (g_timer_elapsed (total, NULL) < test_length)
{
g_timer_reset (timer);
g_timer_start (timer);
test->run (data);
g_timer_stop (timer);
elapsed = g_timer_elapsed (timer, NULL);
g_array_append_val (results, elapsed);
test->reset (data);
}
/* Tear down */
test->teardown (data);
g_timer_destroy (timer);
g_timer_destroy (total);
return results;
}
static int
compare_doubles (gconstpointer a, gconstpointer b)
{
double d = *(double *) a - *(double *) b;
if (d < 0)
return -1;
if (d > 0)
return 1;
return 0;
}
static void
print_results (GArray *array)
{
double min, max, avg;
guint i;
g_array_sort (array, compare_doubles);
/* FIXME: discard outliers */
min = g_array_index (array, double, 0) * 1000;
max = g_array_index (array, double, array->len - 1) * 1000;
avg = 0;
for (i = 0; i < array->len; i++)
{
avg += g_array_index (array, double, i);
}
avg = avg / array->len * 1000;
g_print (" %u runs, min/avg/max = %.3f/%.3f/%.3f ms\n", array->len, min, avg, max);
}
static void
run_test (const PerformanceTest *test)
{
GArray *results;
g_print ("Running test \"%s\"\n", test->name);
if (n_threads == 0) {
results = run_test_thread ((gpointer) test);
} else {
guint i;
GThread **threads;
GArray *thread_results;
threads = g_new (GThread *, n_threads);
for (i = 0; i < n_threads; i++) {
threads[i] = g_thread_create (run_test_thread, (gpointer) test, TRUE, NULL);
g_assert (threads[i] != NULL);
}
results = g_array_new (FALSE, FALSE, sizeof (double));
for (i = 0; i < n_threads; i++) {
thread_results = g_thread_join (threads[i]);
g_array_append_vals (results, thread_results->data, thread_results->len);
g_array_free (thread_results, TRUE);
}
g_free (threads);
}
print_results (results);
g_array_free (results, TRUE);
}
static const PerformanceTest *
find_test (const char *name)
{
gsize i;
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
if (strcmp (tests[i].name, name) == 0)
return &tests[i];
}
return NULL;
}
int
main (int argc,
char *argv[])
{
const PerformanceTest *test;
GOptionContext *context;
GError *error = NULL;
gsize i;
context = g_option_context_new ("GObject performance tests");
g_option_context_add_main_entries (context, cmd_entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error))
{
g_printerr ("%s: %s\n", argv[0], error->message);
return 1;
}
if (list)
{
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
g_print ("%s\n", tests[i].name);
}
return 0;
}
if (argc > 1)
{
int k;
for (k = 1; k < argc; k++)
{
test = find_test (argv[k]);
if (test)
run_test (test);
}
}
else
{
for (i = 0; i < G_N_ELEMENTS (tests); i++)
run_test (&tests[i]);
}
return 0;
}

1060
tests/gobject/performance.c Normal file

File diff suppressed because it is too large Load diff

280
tests/gobject/references.c Normal file
View file

@ -0,0 +1,280 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2005 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestReferences"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <glib-object.h>
/* This test tests weak and toggle references
*/
static GObject *global_object;
static gboolean object_destroyed;
static gboolean weak_ref1_notified;
static gboolean weak_ref2_notified;
static gboolean toggle_ref1_weakened;
static gboolean toggle_ref1_strengthened;
static gboolean toggle_ref2_weakened;
static gboolean toggle_ref2_strengthened;
static gboolean toggle_ref3_weakened;
static gboolean toggle_ref3_strengthened;
/*
* TestObject, a parent class for TestObject
*/
static GType test_object_get_type (void);
#define TEST_TYPE_OBJECT (test_object_get_type ())
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
struct _TestObject
{
GObject parent_instance;
};
struct _TestObjectClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
static void
test_object_finalize (GObject *object)
{
object_destroyed = TRUE;
G_OBJECT_CLASS (test_object_parent_class)->finalize (object);
}
static void
test_object_class_init (TestObjectClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = test_object_finalize;
}
static void
test_object_init (TestObject *test_object)
{
}
static void
clear_flags (void)
{
object_destroyed = FALSE;
weak_ref1_notified = FALSE;
weak_ref2_notified = FALSE;
toggle_ref1_weakened = FALSE;
toggle_ref1_strengthened = FALSE;
toggle_ref2_weakened = FALSE;
toggle_ref2_strengthened = FALSE;
toggle_ref3_weakened = FALSE;
toggle_ref3_strengthened = FALSE;
}
static void
weak_ref1 (gpointer data,
GObject *object)
{
g_assert (object == global_object);
g_assert (data == GUINT_TO_POINTER (42));
weak_ref1_notified = TRUE;
}
static void
weak_ref2 (gpointer data,
GObject *object)
{
g_assert (object == global_object);
g_assert (data == GUINT_TO_POINTER (24));
weak_ref2_notified = TRUE;
}
static void
toggle_ref1 (gpointer data,
GObject *object,
gboolean is_last_ref)
{
g_assert (object == global_object);
g_assert (data == GUINT_TO_POINTER (42));
if (is_last_ref)
toggle_ref1_weakened = TRUE;
else
toggle_ref1_strengthened = TRUE;
}
static void
toggle_ref2 (gpointer data,
GObject *object,
gboolean is_last_ref)
{
g_assert (object == global_object);
g_assert (data == GUINT_TO_POINTER (24));
if (is_last_ref)
toggle_ref2_weakened = TRUE;
else
toggle_ref2_strengthened = TRUE;
}
static void
toggle_ref3 (gpointer data,
GObject *object,
gboolean is_last_ref)
{
g_assert (object == global_object);
g_assert (data == GUINT_TO_POINTER (34));
if (is_last_ref)
{
toggle_ref3_weakened = TRUE;
g_object_remove_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
}
else
toggle_ref3_strengthened = TRUE;
}
int
main (int argc,
char *argv[])
{
GObject *object;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
/* Test basic weak reference operation
*/
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
clear_flags ();
g_object_unref (object);
g_assert (weak_ref1_notified == TRUE);
g_assert (object_destroyed == TRUE);
/* Test two weak references at once
*/
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
clear_flags ();
g_object_unref (object);
g_assert (weak_ref1_notified == TRUE);
g_assert (weak_ref2_notified == TRUE);
g_assert (object_destroyed == TRUE);
/* Test remove weak references
*/
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_object_weak_ref (object, weak_ref1, GUINT_TO_POINTER (42));
g_object_weak_ref (object, weak_ref2, GUINT_TO_POINTER (24));
g_object_weak_unref (object, weak_ref1, GUINT_TO_POINTER (42));
clear_flags ();
g_object_unref (object);
g_assert (weak_ref1_notified == FALSE);
g_assert (weak_ref2_notified == TRUE);
g_assert (object_destroyed == TRUE);
/* Test basic toggle reference operation
*/
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
clear_flags ();
g_object_unref (object);
g_assert (toggle_ref1_weakened == TRUE);
g_assert (toggle_ref1_strengthened == FALSE);
g_assert (object_destroyed == FALSE);
clear_flags ();
g_object_ref (object);
g_assert (toggle_ref1_weakened == FALSE);
g_assert (toggle_ref1_strengthened == TRUE);
g_assert (object_destroyed == FALSE);
g_object_unref (object);
clear_flags ();
g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
g_assert (toggle_ref1_weakened == FALSE);
g_assert (toggle_ref1_strengthened == FALSE);
g_assert (object_destroyed == TRUE);
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
/* Test two toggle references at once
*/
g_object_add_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
g_object_add_toggle_ref (object, toggle_ref2, GUINT_TO_POINTER (24));
clear_flags ();
g_object_unref (object);
g_assert (toggle_ref1_weakened == FALSE);
g_assert (toggle_ref1_strengthened == FALSE);
g_assert (toggle_ref2_weakened == FALSE);
g_assert (toggle_ref2_strengthened == FALSE);
g_assert (object_destroyed == FALSE);
clear_flags ();
g_object_remove_toggle_ref (object, toggle_ref1, GUINT_TO_POINTER (42));
g_assert (toggle_ref1_weakened == FALSE);
g_assert (toggle_ref1_strengthened == FALSE);
g_assert (toggle_ref2_weakened == TRUE);
g_assert (toggle_ref2_strengthened == FALSE);
g_assert (object_destroyed == FALSE);
clear_flags ();
/* Check that removing a toggle ref with %NULL data works fine. */
g_object_remove_toggle_ref (object, toggle_ref2, NULL);
g_assert (toggle_ref1_weakened == FALSE);
g_assert (toggle_ref1_strengthened == FALSE);
g_assert (toggle_ref2_weakened == FALSE);
g_assert (toggle_ref2_strengthened == FALSE);
g_assert (object_destroyed == TRUE);
/* Test a toggle reference that removes itself
*/
global_object = object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_object_add_toggle_ref (object, toggle_ref3, GUINT_TO_POINTER (34));
clear_flags ();
g_object_unref (object);
g_assert (toggle_ref3_weakened == TRUE);
g_assert (toggle_ref3_strengthened == FALSE);
g_assert (object_destroyed == TRUE);
return 0;
}

134
tests/gobject/signals.c Normal file
View file

@ -0,0 +1,134 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2013 Red Hat, Inc.
* Copy and pasted from accumulator.c and modified.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestSignals"
#undef G_DISABLE_ASSERT
#undef G_DISABLE_CHECKS
#undef G_DISABLE_CAST_CHECKS
#include <glib-object.h>
#include "testcommon.h"
/* What this test tests is the behavior of signal disconnection
* from within a signal handler for the signal being disconnected.
*
* The test demonstrates that signal handlers disconnected from a signal
* from an earlier handler in the same emission will not be run.
*
* It also demonstrates that signal handlers connected from a signal
* from an earlier handler in the same emission will not be run.
*/
/*
* TestObject, a parent class for TestObject
*/
#define TEST_TYPE_OBJECT (test_object_get_type ())
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
static gboolean callback1_ran = FALSE, callback2_ran = FALSE, callback3_ran = FALSE, default_handler_ran = FALSE;
struct _TestObject
{
GObject parent_instance;
};
struct _TestObjectClass
{
GObjectClass parent_class;
void (*test_signal) (TestObject *object);
};
static GType test_object_get_type (void);
static void
test_object_real_signal (TestObject *object)
{
default_handler_ran = TRUE;
}
static void
test_object_signal_callback3 (TestObject *object,
gpointer data)
{
callback3_ran = TRUE;
}
static void
test_object_signal_callback2 (TestObject *object,
gpointer data)
{
callback2_ran = TRUE;
}
static void
test_object_signal_callback1 (TestObject *object,
gpointer data)
{
callback1_ran = TRUE;
g_signal_handlers_disconnect_by_func (G_OBJECT (object),
test_object_signal_callback2,
data);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback3), NULL);
}
static void
test_object_class_init (TestObjectClass *class)
{
class->test_signal = test_object_real_signal;
g_signal_new ("test-signal",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (TestObjectClass, test_signal),
NULL, NULL, NULL, G_TYPE_NONE, 0);
}
static DEFINE_TYPE(TestObject, test_object,
test_object_class_init, NULL, NULL,
G_TYPE_OBJECT)
int
main (int argc,
char *argv[])
{
TestObject *object;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
object = g_object_new (TEST_TYPE_OBJECT, NULL);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback1), NULL);
g_signal_connect (object, "test-signal",
G_CALLBACK (test_object_signal_callback2), NULL);
g_signal_emit_by_name (object, "test-signal");
g_assert (callback1_ran);
g_assert (!callback2_ran);
g_assert (!callback3_ran);
g_assert (default_handler_ran);
g_object_unref (object);
return 0;
}

84
tests/gobject/singleton.c Normal file
View file

@ -0,0 +1,84 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2006 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestSingleton"
#include <glib-object.h>
#include <string.h>
/* --- MySingleton class --- */
typedef struct {
GObject parent_instance;
} MySingleton;
typedef struct {
GObjectClass parent_class;
} MySingletonClass;
static GType my_singleton_get_type (void);
#define MY_TYPE_SINGLETON (my_singleton_get_type ())
#define MY_SINGLETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MY_TYPE_SINGLETON, MySingleton))
#define MY_IS_SINGLETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MY_TYPE_SINGLETON))
#define MY_SINGLETON_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), MY_TYPE_SINGLETON, MySingletonClass))
#define MY_IS_SINGLETON_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), MY_TYPE_SINGLETON))
#define MY_SINGLETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MY_TYPE_SINGLETON, MySingletonClass))
G_DEFINE_TYPE (MySingleton, my_singleton, G_TYPE_OBJECT)
static MySingleton *the_one_and_only = NULL;
/* --- methods --- */
static GObject*
my_singleton_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
if (the_one_and_only)
return g_object_ref (G_OBJECT (the_one_and_only));
else
return G_OBJECT_CLASS (my_singleton_parent_class)->constructor (type, n_construct_properties, construct_properties);
}
static void
my_singleton_init (MySingleton *self)
{
g_assert (the_one_and_only == NULL);
the_one_and_only = self;
}
static void
my_singleton_class_init (MySingletonClass *klass)
{
G_OBJECT_CLASS (klass)->constructor = my_singleton_constructor;
}
/* --- test program --- */
int
main (int argc,
char *argv[])
{
MySingleton *singleton, *obj;
/* create the singleton */
singleton = g_object_new (MY_TYPE_SINGLETON, NULL);
g_assert (singleton != NULL);
/* assert _singleton_ creation */
obj = g_object_new (MY_TYPE_SINGLETON, NULL);
g_assert (singleton == obj);
g_object_unref (obj);
/* shutdown */
g_object_unref (singleton);
return 0;
}

105
tests/gobject/testcommon.h Normal file
View file

@ -0,0 +1,105 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TEST_COMMON_H__
#define __TEST_COMMON_H__
G_BEGIN_DECLS
#define DEFINE_TYPE_FULL(name, prefix, \
class_init, base_init, instance_init, \
parent_type, interface_decl) \
GType \
prefix ## _get_type (void) \
{ \
static GType object_type = 0; \
\
if (!object_type) \
{ \
const GTypeInfo object_info = \
{ \
sizeof (name ## Class), \
(GBaseInitFunc) base_init, \
(GBaseFinalizeFunc) NULL, \
(GClassInitFunc) class_init, \
(GClassFinalizeFunc) NULL, \
NULL, /* class_data */ \
sizeof (name), \
0, /* n_prelocs */ \
(GInstanceInitFunc) instance_init, \
(const GTypeValueTable *) NULL, \
}; \
\
object_type = g_type_register_static (parent_type, \
# name, \
&object_info, 0); \
interface_decl \
} \
\
return object_type; \
}
#define DEFINE_TYPE(name, prefix, \
class_init, base_init, instance_init, \
parent_type) \
DEFINE_TYPE_FULL(name, prefix, class_init, base_init, \
instance_init, parent_type, {})
#define DEFINE_IFACE(name, prefix, base_init, dflt_init) \
GType \
prefix ## _get_type (void) \
{ \
static GType iface_type = 0; \
\
if (!iface_type) \
{ \
const GTypeInfo iface_info = \
{ \
sizeof (name ## Class), \
(GBaseInitFunc) base_init, \
(GBaseFinalizeFunc) NULL, \
(GClassInitFunc) dflt_init, \
(GClassFinalizeFunc) NULL, \
(gconstpointer) NULL, \
(guint16) 0, \
(guint16) 0, \
(GInstanceInitFunc) NULL, \
(const GTypeValueTable*) NULL, \
}; \
\
iface_type = g_type_register_static (G_TYPE_INTERFACE, \
# name, \
&iface_info, 0); \
} \
return iface_type; \
}
#define INTERFACE_FULL(type, init_func, iface_type) \
{ \
GInterfaceInfo const iface = \
{ \
(GInterfaceInitFunc) init_func, NULL, NULL \
}; \
\
g_type_add_interface_static (type, iface_type, &iface); \
}
#define INTERFACE(init_func, iface_type) \
INTERFACE_FULL(object_type, init_func, iface_type)
G_END_DECLS
#endif /* __TEST_COMMON_H__ */

445
tests/gobject/testgobject.c Normal file
View file

@ -0,0 +1,445 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* Copyright (C) 2001 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "TestObject"
#include <glib-object.h>
/* --- TestIface --- */
#define TEST_TYPE_IFACE (test_iface_get_type ())
#define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface))
#define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE))
#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass))
typedef struct _TestIface TestIface;
typedef struct _TestIfaceClass TestIfaceClass;
struct _TestIfaceClass
{
GTypeInterface base_iface;
void (*print_string) (TestIface *tiobj,
const gchar *string);
};
static void iface_base_init (TestIfaceClass *iface);
static void iface_base_finalize (TestIfaceClass *iface);
static void print_foo (TestIface *tiobj,
const gchar *string);
static GType
test_iface_get_type (void)
{
static GType test_iface_type = 0;
if (!test_iface_type)
{
const GTypeInfo test_iface_info =
{
sizeof (TestIfaceClass),
(GBaseInitFunc) iface_base_init, /* base_init */
(GBaseFinalizeFunc) iface_base_finalize, /* base_finalize */
NULL,
NULL,
NULL,
0,
0,
NULL,
NULL
};
test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0);
g_type_interface_add_prerequisite (test_iface_type, G_TYPE_OBJECT);
}
return test_iface_type;
}
static guint iface_base_init_count = 0;
static void
iface_base_init (TestIfaceClass *iface)
{
iface_base_init_count++;
if (iface_base_init_count == 1)
{
/* add signals here */
}
}
static void
iface_base_finalize (TestIfaceClass *iface)
{
iface_base_init_count--;
if (iface_base_init_count == 0)
{
/* destroy signals here */
}
}
static void
print_foo (TestIface *tiobj,
const gchar *string)
{
if (!string)
string = "<NULL>";
g_print ("Iface-FOO: \"%s\" from %p\n", string, tiobj);
}
static void
test_object_test_iface_init (gpointer giface,
gpointer iface_data)
{
TestIfaceClass *iface = giface;
g_assert (iface_data == GUINT_TO_POINTER (42));
g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE);
/* assert iface_base_init() was already called */
g_assert (iface_base_init_count > 0);
/* initialize stuff */
iface->print_string = print_foo;
}
static void
iface_print_string (TestIface *tiobj,
const gchar *string)
{
TestIfaceClass *iface;
g_return_if_fail (TEST_IS_IFACE (tiobj));
g_return_if_fail (G_IS_OBJECT (tiobj)); /* ensured through prerequisite */
iface = TEST_IFACE_GET_CLASS (tiobj);
g_object_ref (tiobj);
iface->print_string (tiobj, string);
g_object_unref (tiobj);
}
/* --- TestObject --- */
#define TEST_TYPE_OBJECT (test_object_get_type ())
#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject))
#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass))
#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT))
#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT))
#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass))
#define TEST_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TEST_TYPE_OBJECT, TestObjectPrivate))
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
typedef struct _TestObjectPrivate TestObjectPrivate;
struct _TestObject
{
GObject parent_instance;
};
struct _TestObjectClass
{
GObjectClass parent_class;
gchar* (*test_signal) (TestObject *tobject,
TestIface *iface_object,
gpointer tdata);
};
struct _TestObjectPrivate
{
int dummy1;
gdouble dummy2;
};
static void test_object_class_init (TestObjectClass *class);
static void test_object_init (TestObject *tobject);
static gboolean test_signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data);
static gchar* test_object_test_signal (TestObject *tobject,
TestIface *iface_object,
gpointer tdata);
static gint TestObject_private_offset;
static inline gpointer
test_object_get_instance_private (TestObject *self)
{
return (G_STRUCT_MEMBER_P (self, TestObject_private_offset));
}
static GType
test_object_get_type (void)
{
static GType test_object_type = 0;
if (!test_object_type)
{
const GTypeInfo test_object_info =
{
sizeof (TestObjectClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) test_object_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (TestObject),
5, /* n_preallocs */
(GInstanceInitFunc) test_object_init,
NULL
};
GInterfaceInfo iface_info = { test_object_test_iface_init, NULL, GUINT_TO_POINTER (42) };
test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0);
g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info);
TestObject_private_offset =
g_type_add_instance_private (test_object_type, sizeof (TestObjectPrivate));
}
return test_object_type;
}
static void
test_object_class_init (TestObjectClass *class)
{
/* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */
g_type_class_adjust_private_offset (class, &TestObject_private_offset);
class->test_signal = test_object_test_signal;
g_signal_new ("test-signal",
G_OBJECT_CLASS_TYPE (class),
G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
G_STRUCT_OFFSET (TestObjectClass, test_signal),
test_signal_accumulator, NULL,
g_cclosure_marshal_STRING__OBJECT_POINTER,
G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER);
}
static void
test_object_init (TestObject *tobject)
{
TestObjectPrivate *priv = test_object_get_instance_private (tobject);
g_assert (priv);
priv->dummy1 = 54321;
}
/* Check to see if private data initialization in the
* instance init function works.
*/
static void
test_object_check_private_init (TestObject *tobject)
{
TestObjectPrivate *priv = test_object_get_instance_private (tobject);
g_print ("private data during initialization: %u == %u\n", priv->dummy1, 54321);
g_assert (priv->dummy1 == 54321);
}
static gboolean
test_signal_accumulator (GSignalInvocationHint *ihint,
GValue *return_accu,
const GValue *handler_return,
gpointer data)
{
const gchar *accu_string = g_value_get_string (return_accu);
const gchar *new_string = g_value_get_string (handler_return);
gchar *result_string;
if (accu_string)
result_string = g_strconcat (accu_string, new_string, NULL);
else if (new_string)
result_string = g_strdup (new_string);
else
result_string = NULL;
g_value_take_string (return_accu, result_string);
return TRUE;
}
static gchar*
test_object_test_signal (TestObject *tobject,
TestIface *iface_object,
gpointer tdata)
{
g_message ("::test_signal default_handler called");
g_return_val_if_fail (TEST_IS_IFACE (iface_object), NULL);
return g_strdup ("<default_handler>");
}
/* --- TestIface for DerivedObject --- */
static void
print_bar (TestIface *tiobj,
const gchar *string)
{
TestIfaceClass *parent_iface;
g_return_if_fail (TEST_IS_IFACE (tiobj));
if (!string)
string = "<NULL>";
g_print ("Iface-BAR: \"%s\" from %p\n", string, tiobj);
g_print ("chaining: ");
parent_iface = g_type_interface_peek_parent (TEST_IFACE_GET_CLASS (tiobj));
parent_iface->print_string (tiobj, string);
g_assert (g_type_interface_peek_parent (parent_iface) == NULL);
}
static void
derived_object_test_iface_init (gpointer giface,
gpointer iface_data)
{
TestIfaceClass *iface = giface;
g_assert (iface_data == GUINT_TO_POINTER (87));
g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE);
/* assert test_object_test_iface_init() was already called */
g_assert (iface->print_string == print_foo);
/* override stuff */
iface->print_string = print_bar;
}
/* --- DerivedObject --- */
#define DERIVED_TYPE_OBJECT (derived_object_get_type ())
#define DERIVED_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DERIVED_TYPE_OBJECT, DerivedObject))
#define DERIVED_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DERIVED_TYPE_OBJECT, DerivedObjectClass))
#define DERIVED_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DERIVED_TYPE_OBJECT))
#define DERIVED_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DERIVED_TYPE_OBJECT))
#define DERIVED_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DERIVED_TYPE_OBJECT, DerivedObjectClass))
#define DERIVED_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DERIVED_TYPE_OBJECT, DerivedObjectPrivate))
typedef struct _DerivedObject DerivedObject;
typedef struct _TestObjectClass DerivedObjectClass;
typedef struct _DerivedObjectPrivate DerivedObjectPrivate;
struct _DerivedObject
{
TestObject parent_instance;
int dummy1;
int dummy2;
};
struct _DerivedObjectPrivate
{
char dummy;
};
static void derived_object_class_init (DerivedObjectClass *class);
static void derived_object_init (DerivedObject *dobject);
static gint DerivedObject_private_offset;
static inline gpointer
derived_object_get_instance_private (DerivedObject *self)
{
return (G_STRUCT_MEMBER_P (self, DerivedObject_private_offset));
}
static GType
derived_object_get_type (void)
{
static GType derived_object_type = 0;
if (!derived_object_type)
{
const GTypeInfo derived_object_info =
{
sizeof (DerivedObjectClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) derived_object_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (DerivedObject),
5, /* n_preallocs */
(GInstanceInitFunc) derived_object_init,
NULL
};
GInterfaceInfo iface_info = { derived_object_test_iface_init, NULL, GUINT_TO_POINTER (87) };
derived_object_type = g_type_register_static (TEST_TYPE_OBJECT, "DerivedObject", &derived_object_info, 0);
g_type_add_interface_static (derived_object_type, TEST_TYPE_IFACE, &iface_info);
DerivedObject_private_offset =
g_type_add_instance_private (derived_object_type, sizeof (DerivedObjectPrivate));
}
return derived_object_type;
}
static void
derived_object_class_init (DerivedObjectClass *class)
{
g_type_class_adjust_private_offset (class, &DerivedObject_private_offset);
}
static void
derived_object_init (DerivedObject *dobject)
{
TestObjectPrivate *test_priv;
DerivedObjectPrivate *derived_priv;
derived_priv = derived_object_get_instance_private (dobject);
g_assert (derived_priv);
test_priv = test_object_get_instance_private (TEST_OBJECT (dobject));
g_assert (test_priv);
}
/* --- main --- */
int
main (int argc,
char *argv[])
{
GTypeInfo info = { 0, };
GTypeFundamentalInfo finfo = { 0, };
GType type;
TestObject *sigarg;
DerivedObject *dobject;
TestObjectPrivate *priv;
gchar *string = NULL;
g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) |
G_LOG_LEVEL_WARNING |
G_LOG_LEVEL_CRITICAL);
/* test new fundamentals */
g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST) == g_type_fundamental_next ());
type = g_type_register_fundamental (g_type_fundamental_next (), "FooShadow1", &info, &finfo, 0);
g_assert (type == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1) == g_type_fundamental_next ());
type = g_type_register_fundamental (g_type_fundamental_next (), "FooShadow2", &info, &finfo, 0);
g_assert (type == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1));
g_assert (G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 2) == g_type_fundamental_next ());
g_assert (g_type_from_name ("FooShadow1") == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST));
g_assert (g_type_from_name ("FooShadow2") == G_TYPE_MAKE_FUNDAMENTAL (G_TYPE_RESERVED_USER_FIRST + 1));
/* to test past class initialization interface setups, create the class here */
g_type_class_ref (TEST_TYPE_OBJECT);
dobject = g_object_new (DERIVED_TYPE_OBJECT, NULL);
test_object_check_private_init (TEST_OBJECT (dobject));
sigarg = g_object_new (TEST_TYPE_OBJECT, NULL);
g_print ("MAIN: emit test-signal:\n");
g_signal_emit_by_name (dobject, "test-signal", sigarg, NULL, &string);
g_message ("signal return: \"%s\"", string);
g_assert_cmpstr (string, ==, "<default_handler><default_handler><default_handler>");
g_free (string);
g_print ("MAIN: call iface print-string on test and derived object:\n");
iface_print_string (TEST_IFACE (sigarg), "iface-string-from-test-type");
iface_print_string (TEST_IFACE (dobject), "iface-string-from-derived-type");
priv = test_object_get_instance_private (TEST_OBJECT (dobject));
g_print ("private data after initialization: %u == %u\n", priv->dummy1, 54321);
g_assert (priv->dummy1 == 54321);
g_object_unref (sigarg);
g_object_unref (dobject);
g_message ("%s done", argv[0]);
return 0;
}

View file

@ -0,0 +1,4 @@
# Marshallers used in tests
BOOLEAN:INT
STRING:INT
VARIANT:POINTER

View file

@ -0,0 +1,66 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* testmodule.c: Dummy dynamic type module
* Copyright (C) 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "testmodule.h"
#include "testcommon.h"
static gboolean test_module_load (GTypeModule *module);
static void test_module_unload (GTypeModule *module);
static void
test_module_class_init (TestModuleClass *class)
{
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
module_class->load = test_module_load;
module_class->unload = test_module_unload;
}
DEFINE_TYPE (TestModule, test_module,
test_module_class_init, NULL, NULL,
G_TYPE_TYPE_MODULE)
static gboolean
test_module_load (GTypeModule *module)
{
TestModule *test_module = TEST_MODULE (module);
test_module->register_func (module);
return TRUE;
}
static void
test_module_unload (GTypeModule *module)
{
}
GTypeModule *
test_module_new (TestModuleRegisterFunc register_func)
{
TestModule *test_module = g_object_new (TEST_TYPE_MODULE, NULL);
GTypeModule *module = G_TYPE_MODULE (test_module);
test_module->register_func = register_func;
/* Register the types initially */
g_type_module_use (module);
g_type_module_unuse (module);
return G_TYPE_MODULE (module);
}

View file

@ -0,0 +1,55 @@
/* GObject - GLib Type, Object, Parameter and Signal Library
* testmodule.h: Dummy dynamic type module
* Copyright (C) 2003 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TEST_MODULE_H__
#define __TEST_MODULE_H__
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct _TestModule TestModule;
typedef struct _TestModuleClass TestModuleClass;
#define TEST_TYPE_MODULE (test_module_get_type ())
#define TEST_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TEST_TYPE_MODULE, TestModule))
#define TEST_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), TEST_TYPE_MODULE, TestModuleClass))
#define TEST_IS_MODULE(module) (G_TYPE_CHECK_INSTANCE_TYPE ((module), TEST_TYPE_MODULE))
#define TEST_IS_MODULE_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), TEST_TYPE_MODULE))
#define TEST_MODULE_GET_CLASS(module) (G_TYPE_INSTANCE_GET_CLASS ((module), TEST_TYPE_MODULE, TestModuleClass))
typedef void (*TestModuleRegisterFunc) (GTypeModule *module);
struct _TestModule
{
GTypeModule parent_instance;
TestModuleRegisterFunc register_func;
};
struct _TestModuleClass
{
GTypeModuleClass parent_class;
};
GType test_module_get_type (void);
GTypeModule *test_module_new (TestModuleRegisterFunc register_func);
G_END_DECLS
#endif /* __TEST_MODULE_H__ */

View file

@ -0,0 +1,228 @@
#undef G_DISABLE_ASSERT
#undef G_LOG_DOMAIN
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <glib.h>
#include <glib-object.h>
static int n_children = 3;
static int n_active_children;
static int n_iters = 10000;
static GMainLoop *loop;
static void
io_pipe (GIOChannel **channels)
{
int fds[2];
if (pipe(fds) < 0)
{
int errsv = errno;
fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errsv));
exit (1);
}
channels[0] = g_io_channel_unix_new (fds[0]);
channels[1] = g_io_channel_unix_new (fds[1]);
}
static gboolean
read_all (GIOChannel *channel, char *buf, gsize len)
{
gsize bytes_read = 0;
gsize count;
GIOError err;
while (bytes_read < len)
{
err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
if (err)
{
if (err != G_IO_ERROR_AGAIN)
return FALSE;
}
else if (count == 0)
return FALSE;
bytes_read += count;
}
return TRUE;
}
static gboolean
write_all (GIOChannel *channel, char *buf, gsize len)
{
gsize bytes_written = 0;
gsize count;
GIOError err;
while (bytes_written < len)
{
err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
if (err && err != G_IO_ERROR_AGAIN)
return FALSE;
bytes_written += count;
}
return TRUE;
}
static void
run_child (GIOChannel *in_channel, GIOChannel *out_channel)
{
int i;
int val = 1;
GTimer *timer = g_timer_new();
for (i = 0; i < n_iters; i++)
{
write_all (out_channel, (char *)&val, sizeof (val));
read_all (in_channel, (char *)&val, sizeof (val));
}
val = 0;
write_all (out_channel, (char *)&val, sizeof (val));
val = g_timer_elapsed (timer, NULL) * 1000;
write_all (out_channel, (char *)&val, sizeof (val));
g_timer_destroy (timer);
exit (0);
}
static gboolean
input_callback (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
int val;
GIOChannel *dest = (GIOChannel *)data;
if (!read_all (source, (char *)&val, sizeof(val)))
{
fprintf (stderr, "Unexpected EOF\n");
exit (1);
}
if (val)
{
write_all (dest, (char *)&val, sizeof(val));
return TRUE;
}
else
{
g_io_channel_close (source);
g_io_channel_close (dest);
n_active_children--;
if (n_active_children == 0)
g_main_loop_quit (loop);
return FALSE;
}
}
static void
create_child (void)
{
int pid, errsv;
GIOChannel *in_channels[2];
GIOChannel *out_channels[2];
GSource *source;
io_pipe (in_channels);
io_pipe (out_channels);
pid = fork ();
errsv = errno;
if (pid > 0) /* Parent */
{
g_io_channel_close (in_channels[0]);
g_io_channel_close (out_channels[1]);
source = g_io_create_watch (out_channels[0], G_IO_IN | G_IO_HUP);
g_source_set_closure (source,
g_cclosure_new (G_CALLBACK (input_callback), in_channels[1],
(GClosureNotify)g_io_channel_unref));
g_source_attach (source, NULL);
g_source_unref (source);
g_io_channel_unref (in_channels[0]);
g_io_channel_unref (out_channels[0]);
g_io_channel_unref (out_channels[1]);
}
else if (pid == 0) /* Child */
{
g_io_channel_close (in_channels[1]);
g_io_channel_close (out_channels[0]);
setsid ();
run_child (in_channels[0], out_channels[1]);
}
else /* Error */
{
fprintf (stderr, "Cannot fork: %s\n", g_strerror (errsv));
exit (1);
}
}
static double
difftimeval (struct timeval *old, struct timeval *new)
{
return
(new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
}
int
main (int argc, char **argv)
{
int i;
struct rusage old_usage;
struct rusage new_usage;
if (argc > 1)
n_children = atoi(argv[1]);
if (argc > 2)
n_iters = atoi(argv[2]);
printf ("Children: %d Iters: %d\n", n_children, n_iters);
n_active_children = n_children;
for (i = 0; i < n_children; i++)
create_child ();
getrusage (RUSAGE_SELF, &old_usage);
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
getrusage (RUSAGE_SELF, &new_usage);
printf ("Elapsed user: %g\n",
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
printf ("Elapsed system: %g\n",
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
printf ("Elapsed total: %g\n",
difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
printf ("total / iteration: %g\n",
(difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
(n_iters * n_children));
g_main_loop_unref (loop);
return 0;
}