Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
15
tests/gobject/.gitignore
vendored
Normal file
15
tests/gobject/.gitignore
vendored
Normal 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
307
tests/gobject/accumulator.c
Normal 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;
|
||||
}
|
||||
199
tests/gobject/defaultiface.c
Normal file
199
tests/gobject/defaultiface.c
Normal 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
59
tests/gobject/deftype.c
Normal 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
175
tests/gobject/dynamictype.c
Normal 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
98
tests/gobject/meson.build
Normal 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
418
tests/gobject/override.c
Normal 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;
|
||||
}
|
||||
375
tests/gobject/performance-threaded.c
Normal file
375
tests/gobject/performance-threaded.c
Normal 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
1060
tests/gobject/performance.c
Normal file
File diff suppressed because it is too large
Load diff
280
tests/gobject/references.c
Normal file
280
tests/gobject/references.c
Normal 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
134
tests/gobject/signals.c
Normal 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
84
tests/gobject/singleton.c
Normal 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
105
tests/gobject/testcommon.h
Normal 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
445
tests/gobject/testgobject.c
Normal 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;
|
||||
}
|
||||
4
tests/gobject/testmarshal.list
Normal file
4
tests/gobject/testmarshal.list
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Marshallers used in tests
|
||||
BOOLEAN:INT
|
||||
STRING:INT
|
||||
VARIANT:POINTER
|
||||
66
tests/gobject/testmodule.c
Normal file
66
tests/gobject/testmodule.c
Normal 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);
|
||||
}
|
||||
55
tests/gobject/testmodule.h
Normal file
55
tests/gobject/testmodule.h
Normal 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__ */
|
||||
228
tests/gobject/timeloop-closure.c
Normal file
228
tests/gobject/timeloop-closure.c
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue