diff --git a/girepository/gibaseinfo-private.h b/girepository/gibaseinfo-private.h index 96c77155a..453a18ddc 100644 --- a/girepository/gibaseinfo-private.h +++ b/girepository/gibaseinfo-private.h @@ -31,9 +31,6 @@ G_BEGIN_DECLS -#define GI_IS_BASE_INFO_TYPE(info,type) \ - (G_TYPE_INSTANCE_GET_CLASS ((info), GI_TYPE_BASE_INFO, GIBaseInfoClass)->info_type == (type)) - struct _GIBaseInfoClass { GTypeClass parent_class; diff --git a/girepository/gibaseinfo.c b/girepository/gibaseinfo.c index d24cd4aa8..ccc5aed37 100644 --- a/girepository/gibaseinfo.c +++ b/girepository/gibaseinfo.c @@ -443,7 +443,9 @@ gi_info_init (GIRealInfo *info, * Clears memory allocated internally by a stack-allocated * [type@GIRepository.BaseInfo]. * - * This does not deallocate the [type@GIRepository.BaseInfo] struct itself. + * This does not deallocate the [type@GIRepository.BaseInfo] struct itself. It + * does clear the struct to zero so that calling this function subsequent times + * on the same struct is a no-op. * * This must only be called on stack-allocated [type@GIRepository.BaseInfo]s. * Use [method@GIRepository.BaseInfo.unref] for heap-allocated ones. @@ -455,6 +457,11 @@ gi_base_info_clear (void *info) { GIBaseInfo *rinfo = (GIBaseInfo *) info; + /* If @info is zero-filled, do nothing. This allows gi_base_info_clear() to be + * used with g_auto(). */ + if (rinfo->ref_count == 0) + return; + g_return_if_fail (GI_IS_BASE_INFO (rinfo)); g_assert (rinfo->ref_count == INVALID_REFCOUNT); @@ -462,6 +469,8 @@ gi_base_info_clear (void *info) GI_BASE_INFO_GET_CLASS (info)->finalize (rinfo); g_type_class_unref (rinfo->parent_instance.g_class); + + memset (rinfo, 0, sizeof (*rinfo)); } GIBaseInfo * diff --git a/girepository/girepository-autocleanups.h b/girepository/girepository-autocleanups.h new file mode 100644 index 000000000..d48e7b2c5 --- /dev/null +++ b/girepository/girepository-autocleanups.h @@ -0,0 +1,56 @@ +/* + * Copyright 2024 GNOME Foundation, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * 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 . + * + * Author: Philip Withnall + */ + +#if !defined (__GIREPOSITORY_H_INSIDE__) && !defined (GI_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __GI_SCANNER__ + +/* GIRepository already has its cleanups defined by G_DECLARE_FINAL_TYPE */ +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GITypelib, gi_typelib_unref) + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIBaseInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIArgInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GICallableInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GICallbackInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIConstantInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIEnumInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIFieldInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIFlagsInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIFunctionInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIInterfaceInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIObjectInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIPropertyInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIRegisteredTypeInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GISignalInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIStructInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GITypeInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIUnionInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIUnresolvedInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIValueInfo, gi_base_info_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GIVFuncInfo, gi_base_info_unref) + +/* These types can additionally be stack allocated and cleared */ +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (GIArgInfo, gi_base_info_clear) +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (GITypeInfo, gi_base_info_clear) + +#endif /* __GI_SCANNER__ */ diff --git a/girepository/girepository-private.h b/girepository/girepository-private.h index 0433bac30..8ff312365 100644 --- a/girepository/girepository-private.h +++ b/girepository/girepository-private.h @@ -31,6 +31,8 @@ #include #include +#include "gitypelib-internal.h" + /* FIXME: For now, GIRealInfo is a compatibility define. This will eventually * be removed. */ typedef struct _GIBaseInfo GIRealInfo; @@ -133,6 +135,8 @@ typedef enum /* keep GI_INFO_TYPE_N_TYPES in sync with this */ } GIInfoType; +GIInfoType gi_typelib_blob_type_to_info_type (GITypelibBlobType blob_type); + /** * GI_INFO_TYPE_N_TYPES: * diff --git a/girepository/girepository.c b/girepository/girepository.c index 4da671bcf..24d83ca25 100644 --- a/girepository/girepository.c +++ b/girepository/girepository.c @@ -2097,3 +2097,21 @@ gi_info_type_to_string (GIInfoType type) return "unknown"; } } + +GIInfoType +gi_typelib_blob_type_to_info_type (GITypelibBlobType blob_type) +{ + switch (blob_type) + { + case BLOB_TYPE_BOXED: + /* `BLOB_TYPE_BOXED` now always refers to a `StructBlob`, and + * `GIRegisteredTypeInfo` (the parent type of `GIStructInfo`) has a method + * for distinguishing whether the struct is a boxed type. So presenting + * `BLOB_TYPE_BOXED` as its own `GIBaseInfo` subclass is not helpful. + * See commit e28078c70cbf4a57c7dbd39626f43f9bd2674145 and + * https://gitlab.gnome.org/GNOME/glib/-/issues/3245. */ + return GI_INFO_TYPE_STRUCT; + default: + return (GIInfoType) blob_type; + } +} diff --git a/girepository/girepository.h b/girepository/girepository.h index fa0b93e30..13d94cdf0 100644 --- a/girepository/girepository.h +++ b/girepository/girepository.h @@ -62,6 +62,7 @@ G_DECLARE_FINAL_TYPE (GIRepository, gi_repository, GI, REPOSITORY, GObject) /** * GIRepositoryLoadFlags: + * @GI_REPOSITORY_LOAD_FLAG_NONE: No flags set. * @GI_REPOSITORY_LOAD_FLAG_LAZY: Lazily load the typelib. * * Flags that control how a typelib is loaded. @@ -70,6 +71,7 @@ G_DECLARE_FINAL_TYPE (GIRepository, gi_repository, GI, REPOSITORY, GObject) */ typedef enum { + GI_REPOSITORY_LOAD_FLAG_NONE = 0, GI_REPOSITORY_LOAD_FLAG_LAZY = 1 << 0 } GIRepositoryLoadFlags; @@ -240,4 +242,6 @@ void gi_cclosure_marshal_generic (GClosure *closure, void *invocation_hint, void *marshal_data); +#include + G_END_DECLS diff --git a/girepository/girffi.h b/girepository/girffi.h index 85197d87d..5d792c92d 100644 --- a/girepository/girffi.h +++ b/girepository/girffi.h @@ -110,6 +110,7 @@ gboolean gi_function_invoker_new_for_address (void *addr, GI_AVAILABLE_IN_ALL void gi_function_invoker_clear (GIFunctionInvoker *invoker); +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC (GIFunctionInvoker, gi_function_invoker_clear) GI_AVAILABLE_IN_ALL ffi_closure * gi_callable_info_create_closure (GICallableInfo *callable_info, diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 8df65fb5b..f7b928fe3 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -27,7 +27,6 @@ #include #include "girepository.h" -#include "girepository-private.h" G_BEGIN_DECLS @@ -195,8 +194,6 @@ typedef enum { BLOB_TYPE_UNION } GITypelibBlobType; -GIInfoType gi_typelib_blob_type_to_info_type (GITypelibBlobType blob_type); - #if defined (G_CAN_INLINE) && defined (G_ALWAYS_INLINE) diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c index fecfbb18d..3c88a79e6 100644 --- a/girepository/gitypelib.c +++ b/girepository/gitypelib.c @@ -43,24 +43,6 @@ G_DEFINE_BOXED_TYPE (GITypelib, gi_typelib, gi_typelib_ref, gi_typelib_unref) -GIInfoType -gi_typelib_blob_type_to_info_type (GITypelibBlobType blob_type) -{ - switch (blob_type) - { - case BLOB_TYPE_BOXED: - /* `BLOB_TYPE_BOXED` now always refers to a `StructBlob`, and - * `GIRegisteredTypeInfo` (the parent type of `GIStructInfo`) has a method - * for distinguishing whether the struct is a boxed type. So presenting - * `BLOB_TYPE_BOXED` as its own `GIBaseInfo` subclass is not helpful. - * See commit e28078c70cbf4a57c7dbd39626f43f9bd2674145 and - * https://gitlab.gnome.org/GNOME/glib/-/issues/3245. */ - return GI_INFO_TYPE_STRUCT; - default: - return (GIInfoType) blob_type; - } -} - typedef struct { GITypelib *typelib; GSList *context_stack; diff --git a/girepository/meson.build b/girepository/meson.build index d64a64aca..a779d90cb 100644 --- a/girepository/meson.build +++ b/girepository/meson.build @@ -56,6 +56,7 @@ girepo_headers = files( 'gipropertyinfo.h', 'giregisteredtypeinfo.h', 'girepository.h', + 'girepository-autocleanups.h', 'gisignalinfo.h', 'gistructinfo.h', 'gitypeinfo.h', diff --git a/girepository/tests/autoptr.c b/girepository/tests/autoptr.c new file mode 100644 index 000000000..8f3a3fc93 --- /dev/null +++ b/girepository/tests/autoptr.c @@ -0,0 +1,354 @@ +/* + * Copyright 2024 GNOME Foundation, Inc. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * 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 . + * + * Author: Philip Withnall + */ + +#include "girepository.h" +#include "girffi.h" +#include "glib.h" +#include "test-common.h" + +static void +test_autoptr_repository (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIRepository) repository = gi_repository_new (); + g_assert_nonnull (repository); +} + +static void +test_autoptr_typelib (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GITypelib) typelib = NULL; + GError *local_error = NULL; + + typelib = gi_repository_require (fx->repository, "Gio", "2.0", + GI_REPOSITORY_LOAD_FLAG_NONE, &local_error); + g_assert_no_error (local_error); + g_assert_nonnull (typelib); + + /* gi_repository_require() doesn’t return a reference so let’s add one */ + gi_typelib_ref (typelib); +} + +static void +test_autoptr_base_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIBaseInfo) base_info = gi_repository_find_by_name (fx->repository, "Gio", "Resolver"); + g_assert_nonnull (base_info); +} + +static void +test_autoptr_arg_info (RepositoryFixture *fx, + const void *unused) +{ + GIObjectInfo *object_info = NULL; + GIFunctionInfo *method_info = NULL; + g_autoptr(GIArgInfo) arg_info = NULL; + + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "GObject", "Object")); + g_assert_nonnull (object_info); + method_info = gi_object_info_find_method (object_info, "get_property"); + g_assert_nonnull (method_info); + arg_info = gi_callable_info_get_arg (GI_CALLABLE_INFO (method_info), 0); + g_assert_nonnull (arg_info); + + g_clear_pointer (&method_info, gi_base_info_unref); + g_clear_pointer (&object_info, gi_base_info_unref); +} + +static void +test_autoptr_callable_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GICallableInfo) callable_info = GI_CALLABLE_INFO (gi_repository_find_by_name (fx->repository, "Gio", "tls_server_connection_new")); + g_assert_nonnull (callable_info); +} + +static void +test_autoptr_callback_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GICallbackInfo) callback_info = GI_CALLBACK_INFO (gi_repository_find_by_name (fx->repository, "Gio", "AsyncReadyCallback")); + g_assert_nonnull (callback_info); +} + +static void +test_autoptr_constant_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIConstantInfo) constant_info = GI_CONSTANT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "DBUS_METHOD_INVOCATION_HANDLED")); + g_assert_nonnull (constant_info); +} + +static void +test_autoptr_enum_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIEnumInfo) enum_info = GI_ENUM_INFO (gi_repository_find_by_name (fx->repository, "Gio", "DBusError")); + g_assert_nonnull (enum_info); +} + +static void +test_autoptr_field_info (RepositoryFixture *fx, + const void *unused) +{ + GIStructInfo *struct_info = NULL; + g_autoptr(GIFieldInfo) field_info = NULL; + + struct_info = GI_STRUCT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "ActionEntry")); + g_assert_nonnull (struct_info); + field_info = gi_struct_info_find_field (struct_info, "name"); + g_assert_nonnull (field_info); + + g_clear_pointer (&struct_info, gi_base_info_unref); +} + +static void +test_autoptr_flags_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIFlagsInfo) flags_info = GI_FLAGS_INFO (gi_repository_find_by_name (fx->repository, "Gio", "AppInfoCreateFlags")); + g_assert_nonnull (flags_info); +} + +static void +test_autoptr_function_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIFunctionInfo) function_info = GI_FUNCTION_INFO (gi_repository_find_by_name (fx->repository, "Gio", "tls_server_connection_new")); + g_assert_nonnull (function_info); +} + +static void +test_autoptr_interface_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIInterfaceInfo) interface_info = GI_INTERFACE_INFO (gi_repository_find_by_name (fx->repository, "Gio", "AsyncInitable")); + g_assert_nonnull (interface_info); +} + +static void +test_autoptr_object_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIObjectInfo) object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "BufferedInputStream")); + g_assert_nonnull (object_info); +} + +static void +test_autoptr_property_info (RepositoryFixture *fx, + const void *unused) +{ + GIObjectInfo *object_info = NULL; + g_autoptr(GIPropertyInfo) property_info = NULL; + + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "BufferedInputStream")); + g_assert_nonnull (object_info); + property_info = gi_object_info_get_property (object_info, 0); + g_assert_nonnull (property_info); + + g_clear_pointer (&object_info, gi_base_info_unref); +} + +static void +test_autoptr_registered_type_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIRegisteredTypeInfo) registered_type_info = + GI_REGISTERED_TYPE_INFO (gi_repository_find_by_name (fx->repository, "Gio", "SrvTarget")); + g_assert_nonnull (registered_type_info); +} + +static void +test_autoptr_signal_info (RepositoryFixture *fx, + const void *unused) +{ + GIObjectInfo *object_info = NULL; + g_autoptr(GISignalInfo) signal_info = NULL; + + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "Cancellable")); + g_assert_nonnull (object_info); + signal_info = gi_object_info_find_signal (object_info, "cancelled"); + g_assert_nonnull (signal_info); + + g_clear_pointer (&object_info, gi_base_info_unref); +} + +static void +test_autoptr_struct_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIStructInfo) struct_info = GI_STRUCT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "DBusAnnotationInfo")); + g_assert_nonnull (struct_info); +} + +static void +test_autoptr_type_info (RepositoryFixture *fx, + const void *unused) +{ + GIStructInfo *struct_info = NULL; + GIFieldInfo *field_info = NULL; + g_autoptr(GITypeInfo) type_info = NULL; + + struct_info = GI_STRUCT_INFO (gi_repository_find_by_name (fx->repository, "Gio", "ActionEntry")); + g_assert_nonnull (struct_info); + field_info = gi_struct_info_find_field (struct_info, "name"); + g_assert_nonnull (field_info); + type_info = gi_field_info_get_type_info (field_info); + g_assert_nonnull (type_info); + + g_clear_pointer (&field_info, gi_base_info_unref); + g_clear_pointer (&struct_info, gi_base_info_unref); +} + +static void +test_autoptr_union_info (RepositoryFixture *fx, + const void *unused) +{ + g_autoptr(GIUnionInfo) union_info = GI_UNION_INFO (gi_repository_find_by_name (fx->repository, "GLib", "DoubleIEEE754")); + g_assert_nonnull (union_info); +} + +static void +test_autoptr_value_info (RepositoryFixture *fx, + const void *unused) +{ + GIEnumInfo *enum_info = NULL; + g_autoptr(GIValueInfo) value_info = NULL; + + enum_info = GI_ENUM_INFO (gi_repository_find_by_name (fx->repository, "Gio", "ZlibCompressorFormat")); + g_assert_nonnull (enum_info); + value_info = gi_enum_info_get_value (enum_info, 0); + g_assert_nonnull (value_info); + + g_clear_pointer (&enum_info, gi_base_info_unref); +} + +static void +test_autoptr_vfunc_info (RepositoryFixture *fx, + const void *unused) +{ + GIInterfaceInfo *interface_info = NULL; + g_autoptr(GIVFuncInfo) vfunc_info = NULL; + + interface_info = GI_INTERFACE_INFO (gi_repository_find_by_name (fx->repository, "Gio", "Action")); + g_assert_nonnull (interface_info); + vfunc_info = gi_interface_info_find_vfunc (interface_info, "activate"); + g_assert_nonnull (vfunc_info); + + g_clear_pointer (&interface_info, gi_base_info_unref); +} + +static void +test_auto_arg_info (RepositoryFixture *fx, + const void *unused) +{ + GIObjectInfo *object_info = NULL; + GIFunctionInfo *method_info = NULL; + g_auto(GIArgInfo) arg_info = { 0, }; + + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "GObject", "Object")); + g_assert_nonnull (object_info); + method_info = gi_object_info_find_method (object_info, "get_property"); + g_assert_nonnull (method_info); + gi_callable_info_load_arg (GI_CALLABLE_INFO (method_info), 0, &arg_info); + g_assert_true (GI_IS_ARG_INFO (&arg_info)); + + g_clear_pointer (&method_info, gi_base_info_unref); + g_clear_pointer (&object_info, gi_base_info_unref); +} + +static void +test_auto_type_info (RepositoryFixture *fx, + const void *unused) +{ + GIObjectInfo *object_info = NULL; + GIFunctionInfo *method_info = NULL; + GIArgInfo *arg_info = NULL; + g_auto(GITypeInfo) type_info = { 0, }; + + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "GObject", "Object")); + g_assert_nonnull (object_info); + method_info = gi_object_info_find_method (object_info, "get_property"); + g_assert_nonnull (method_info); + arg_info = gi_callable_info_get_arg (GI_CALLABLE_INFO (method_info), 0); + g_assert_nonnull (arg_info); + gi_arg_info_load_type_info (arg_info, &type_info); + g_assert_true (GI_IS_TYPE_INFO (&type_info)); + + g_clear_pointer (&arg_info, gi_base_info_unref); + g_clear_pointer (&method_info, gi_base_info_unref); + g_clear_pointer (&object_info, gi_base_info_unref); +} + +static void +test_auto_function_invoker (RepositoryFixture *fx, + const void *unused) +{ + GIFunctionInfo *function_info = NULL; + g_auto(GIFunctionInvoker) invoker = { 0, }; + GError *local_error = NULL; + + function_info = GI_FUNCTION_INFO (gi_repository_find_by_name (fx->repository, "Gio", "tls_server_connection_new")); + g_assert_nonnull (function_info); + gi_function_info_prep_invoker (function_info, &invoker, &local_error); + g_assert_no_error (local_error); + + g_clear_pointer (&function_info, gi_base_info_unref); +} + +int +main (int argc, + char *argv[]) +{ + repository_init (&argc, &argv); + + ADD_REPOSITORY_TEST ("/autoptr/repository", test_autoptr_repository, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/typelib", test_autoptr_typelib, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/base-info", test_autoptr_base_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/arg-info", test_autoptr_arg_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/callable-info", test_autoptr_callable_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/callback-info", test_autoptr_callback_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/constant-info", test_autoptr_constant_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/enum-info", test_autoptr_enum_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/field-info", test_autoptr_field_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/flags-info", test_autoptr_flags_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/function-info", test_autoptr_function_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/interface-info", test_autoptr_interface_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/object-info", test_autoptr_object_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/property-info", test_autoptr_property_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/registered-type-info", test_autoptr_registered_type_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/signal-info", test_autoptr_signal_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/struct-info", test_autoptr_struct_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/type-info", test_autoptr_type_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/union-info", test_autoptr_union_info, &typelib_load_spec_glib); + /* no easy way to test GIUnresolvedInfo */ + ADD_REPOSITORY_TEST ("/autoptr/value-info", test_autoptr_value_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/autoptr/vfunc-info", test_autoptr_vfunc_info, &typelib_load_spec_gio); + + ADD_REPOSITORY_TEST ("/auto/arg-info", test_auto_arg_info, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/auto/type-info", test_auto_type_info, &typelib_load_spec_gio); + + ADD_REPOSITORY_TEST ("/auto/function-invoker", test_auto_function_invoker, &typelib_load_spec_gio); + + return g_test_run (); +} diff --git a/girepository/tests/meson.build b/girepository/tests/meson.build index 7814ca0c5..7f5b70964 100644 --- a/girepository/tests/meson.build +++ b/girepository/tests/meson.build @@ -40,6 +40,15 @@ if enable_gir 'depends': [glib_gir], }, } + + if cc.get_id() != 'msvc' + girepository_tests += { + 'autoptr-girepository' : { + 'source' : 'autoptr.c', + 'depends': [glib_gir, gio_gir], + }, + } + endif endif test_env = environment() diff --git a/girepository/tests/repository.c b/girepository/tests/repository.c index 506726375..565023147 100644 --- a/girepository/tests/repository.c +++ b/girepository/tests/repository.c @@ -156,6 +156,42 @@ test_repository_dependencies (RepositoryFixture *fx, g_clear_pointer (&dependencies, g_strfreev); } +static void +test_repository_base_info_clear (RepositoryFixture *fx, + const void *unused) +{ + GITypeInfo zeroed_type_info = { 0, }; + GITypeInfo idempotent_type_info; + GIObjectInfo *object_info = NULL; + GIFunctionInfo *method_info = NULL; + GIArgInfo *arg_info = NULL; + + g_test_summary ("Test calling gi_base_info_clear() on a zero-filled struct"); + + /* Load a valid #GITypeInfo onto the stack and clear it multiple times to + * check gi_base_info_clear() is idempotent after the first call. */ + object_info = GI_OBJECT_INFO (gi_repository_find_by_name (fx->repository, "GObject", "Object")); + g_assert_nonnull (object_info); + method_info = gi_object_info_find_method (object_info, "get_property"); + g_assert_nonnull (method_info); + arg_info = gi_callable_info_get_arg (GI_CALLABLE_INFO (method_info), 0); + g_assert_nonnull (arg_info); + gi_arg_info_load_type_info (arg_info, &idempotent_type_info); + + gi_base_info_clear (&idempotent_type_info); + gi_base_info_clear (&idempotent_type_info); + gi_base_info_clear (&idempotent_type_info); + + g_clear_pointer (&arg_info, gi_base_info_unref); + g_clear_pointer (&method_info, gi_base_info_unref); + g_clear_pointer (&object_info, gi_base_info_unref); + + /* Try clearing a #GITypeInfo which has always been zero-filled on the stack. */ + gi_base_info_clear (&zeroed_type_info); + gi_base_info_clear (&zeroed_type_info); + gi_base_info_clear (&zeroed_type_info); +} + static void test_repository_arg_info (RepositoryFixture *fx, const void *unused) @@ -750,6 +786,7 @@ main (int argc, ADD_REPOSITORY_TEST ("/repository/basic", test_repository_basic, &typelib_load_spec_glib); ADD_REPOSITORY_TEST ("/repository/info", test_repository_info, &typelib_load_spec_gobject); ADD_REPOSITORY_TEST ("/repository/dependencies", test_repository_dependencies, &typelib_load_spec_gobject); + ADD_REPOSITORY_TEST ("/repository/base-info/clear", test_repository_base_info_clear, &typelib_load_spec_gobject); ADD_REPOSITORY_TEST ("/repository/arg-info", test_repository_arg_info, &typelib_load_spec_gobject); ADD_REPOSITORY_TEST ("/repository/callable-info", test_repository_callable_info, &typelib_load_spec_gobject); ADD_REPOSITORY_TEST ("/repository/callback-info", test_repository_callback_info, &typelib_load_spec_gobject);