d7b6d2e1bc7b2d3e8e679a5a1f28cb8b4b37787d
[platform/upstream/pygobject2.git] / tests / test_repository.py
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
3 #
4 # Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
5 #
6 #   test_repository.py: Test for the GIRepository module
7 #
8 # This library is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU Lesser General Public
10 # License as published by the Free Software Foundation; either
11 # version 2.1 of the License, or (at your option) any later version.
12 #
13 # This library is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 # Lesser General Public License for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public
19 # License along with this library; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
21 # USA
22
23 import unittest
24 import collections
25
26 import gi._gi as GIRepository
27 from gi.module import repository as repo
28 from gi.repository import GObject
29 from gi.repository import GIMarshallingTests
30 from gi.repository import GIRepository as IntrospectedRepository
31
32 from helper import capture_glib_warnings
33
34
35 def find_child_info(info, getter_name, name):
36     getter = getattr(info, getter_name)
37     for child in getter():
38         if child.get_name() == name:
39             return child
40     else:
41         raise ValueError('child info %s not found' % name)
42
43
44 class Test(unittest.TestCase):
45     def setUp(self):
46         repo.require('GLib')
47         repo.require('GObject')
48         repo.require('GIMarshallingTests')
49
50     def test_repo_get_dependencies(self):
51         self.assertRaises(TypeError, repo.get_dependencies)
52         self.assertEqual(repo.get_dependencies("GLib"), [])
53         self.assertEqual(repo.get_dependencies("GObject"), ["GLib-2.0"])
54
55     def test_repo_is_registered(self):
56         self.assertRaises(TypeError, repo.is_registered)
57         self.assertRaises(TypeError, repo.is_registered, None)
58         self.assertTrue(repo.is_registered("GIRepository"))
59         self.assertTrue(repo.is_registered("GIRepository", None))
60         self.assertTrue(isinstance(repo.is_registered("GIRepository"), bool))
61         self.assertTrue(repo.is_registered("GIRepository", "2.0"))
62         self.assertFalse(repo.is_registered("GIRepository", ""))
63         self.assertFalse(repo.is_registered("GIRepository", "99.0"))
64         self.assertFalse(repo.is_registered("GIRepository", "1.0"))
65
66     def test_repo_get_immediate_dependencies(self):
67         self.assertRaises(TypeError, repo.get_immediate_dependencies)
68         self.assertEqual(repo.get_immediate_dependencies("GLib"), [])
69         self.assertEqual(
70             repo.get_immediate_dependencies("GObject"), ["GLib-2.0"])
71         self.assertEqual(
72             repo.get_immediate_dependencies(namespace="GObject"), ["GLib-2.0"])
73         self.assertEqual(
74             repo.get_immediate_dependencies("GIMarshallingTests"), ["Gio-2.0"])
75
76     def test_arg_info(self):
77         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
78         args = func_info.get_arguments()
79         self.assertTrue(len(args), 1)
80
81         arg = args[0]
82         self.assertEqual(arg.get_container(), func_info)
83         self.assertEqual(arg.get_direction(), GIRepository.Direction.OUT)
84         self.assertEqual(arg.get_name(), 'structs')
85         self.assertEqual(arg.get_namespace(), 'GIMarshallingTests')
86         self.assertFalse(arg.is_caller_allocates())
87         self.assertFalse(arg.is_optional())
88         self.assertFalse(arg.is_return_value())
89         self.assertFalse(arg.may_be_null())
90         self.assertEqual(arg.get_destroy(), -1)
91         self.assertEqual(arg.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
92         self.assertEqual(arg.get_scope(), GIRepository.ScopeType.INVALID)
93         self.assertEqual(arg.get_type().get_tag(), GIRepository.TypeTag.ARRAY)
94
95     def test_base_info(self):
96         info = repo.find_by_name('GIMarshallingTests', 'Object')
97         self.assertEqual(info.__name__, 'Object')
98         self.assertEqual(info.get_name(), 'Object')
99         self.assertEqual(info.__module__, 'gi.repository.GIMarshallingTests')
100         self.assertEqual(info.get_name_unescaped(), 'Object')
101         self.assertEqual(info.get_namespace(), 'GIMarshallingTests')
102         self.assertEqual(info.get_container(), None)
103         info2 = repo.find_by_name('GIMarshallingTests', 'Object')
104         self.assertFalse(info is info2)
105         self.assertEqual(info, info2)
106         self.assertTrue(info.equal(info2))
107
108     def test_object_info(self):
109         info = repo.find_by_name('GIMarshallingTests', 'Object')
110         self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
111         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
112         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
113         self.assertTrue(isinstance(info.get_interfaces(), collections.Iterable))
114         self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
115         self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
116         self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
117         self.assertFalse(info.get_abstract())
118         self.assertEqual(info.get_class_struct(), repo.find_by_name('GIMarshallingTests', 'ObjectClass'))
119         self.assertEqual(info.get_type_name(), 'GIMarshallingTestsObject')
120         self.assertEqual(info.get_type_init(), 'gi_marshalling_tests_object_get_type')
121         self.assertFalse(info.get_fundamental())
122         self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
123
124     def test_callable_inheritance(self):
125         self.assertTrue(issubclass(GIRepository.CallableInfo, GIRepository.BaseInfo))
126         self.assertTrue(issubclass(GIRepository.CallbackInfo, GIRepository.CallableInfo))
127         self.assertTrue(issubclass(GIRepository.FunctionInfo, GIRepository.CallableInfo))
128         self.assertTrue(issubclass(GIRepository.VFuncInfo, GIRepository.CallableInfo))
129         self.assertTrue(issubclass(GIRepository.SignalInfo, GIRepository.CallableInfo))
130
131     def test_registered_type_info(self):
132         info = repo.find_by_name('GIMarshallingTests', 'Object')
133         # Call these from the class because GIObjectInfo overrides them
134         self.assertEqual(GIRepository.RegisteredTypeInfo.get_g_type(info),
135                          GObject.type_from_name('GIMarshallingTestsObject'))
136         self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_name(info),
137                          'GIMarshallingTestsObject')
138         self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_init(info),
139                          'gi_marshalling_tests_object_get_type')
140
141     def test_fundamental_object_info(self):
142         repo.require('Regress')
143         info = repo.find_by_name('Regress', 'TestFundamentalObject')
144         self.assertTrue(info.get_abstract())
145         self.assertTrue(info.get_fundamental())
146         self.assertEqual(info.get_ref_function(), 'regress_test_fundamental_object_ref')
147         self.assertEqual(info.get_unref_function(), 'regress_test_fundamental_object_unref')
148         self.assertEqual(info.get_get_value_function(), 'regress_test_value_get_fundamental_object')
149         self.assertEqual(info.get_set_value_function(), 'regress_test_value_set_fundamental_object')
150
151     def test_interface_info(self):
152         info = repo.find_by_name('GIMarshallingTests', 'Interface')
153         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
154         self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
155         self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
156         self.assertTrue(isinstance(info.get_prerequisites(), collections.Iterable))
157         self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
158         self.assertTrue(isinstance(info.get_signals(), collections.Iterable))
159
160         method = info.find_method('test_int8_in')
161         vfunc = info.find_vfunc('test_int8_in')
162         self.assertEqual(method.get_name(), 'test_int8_in')
163         self.assertEqual(vfunc.get_invoker(), method)
164         self.assertEqual(method.get_vfunc(), vfunc)
165
166         iface = info.get_iface_struct()
167         self.assertEqual(iface, repo.find_by_name('GIMarshallingTests', 'InterfaceIface'))
168
169     def test_struct_info(self):
170         info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
171         self.assertTrue(isinstance(info, GIRepository.StructInfo))
172         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
173         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
174         self.assertTrue(isinstance(info.get_size(), int))
175         self.assertTrue(isinstance(info.get_alignment(), int))
176         self.assertTrue(info.is_gtype_struct())
177         self.assertFalse(info.is_foreign())
178
179     def test_enum_info(self):
180         info = repo.find_by_name('GIMarshallingTests', 'Enum')
181         self.assertTrue(isinstance(info, GIRepository.EnumInfo))
182         self.assertTrue(isinstance(info.get_values(), collections.Iterable))
183         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
184         self.assertFalse(info.is_flags())
185         self.assertTrue(info.get_storage_type() > 0)  # might be platform dependent
186
187     def test_union_info(self):
188         info = repo.find_by_name('GIMarshallingTests', 'Union')
189         self.assertTrue(isinstance(info, GIRepository.UnionInfo))
190         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
191         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
192         self.assertTrue(isinstance(info.get_size(), int))
193
194     def test_type_info(self):
195         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
196         arg_info, = func_info.get_arguments()
197         type_info = arg_info.get_type()
198
199         self.assertTrue(type_info.is_pointer())
200         self.assertEqual(type_info.get_tag(), GIRepository.TypeTag.ARRAY)
201         self.assertEqual(type_info.get_tag_as_string(), 'array')
202         self.assertEqual(type_info.get_param_type(0).get_tag(),
203                          GIRepository.TypeTag.INTERFACE)
204         self.assertEqual(type_info.get_param_type(0).get_interface(),
205                          repo.find_by_name('GIMarshallingTests', 'SimpleStruct'))
206         self.assertEqual(type_info.get_interface(), None)
207         self.assertEqual(type_info.get_array_length(), -1)
208         self.assertEqual(type_info.get_array_fixed_size(), 2)
209         self.assertFalse(type_info.is_zero_terminated())
210         self.assertEqual(type_info.get_array_type(), GIRepository.ArrayType.C)
211
212     def test_field_info(self):
213         info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
214         field = find_child_info(info, 'get_fields', 'test_int8_in')
215         self.assertEqual(field.get_name(), 'test_int8_in')
216         self.assertTrue(field.get_flags() & GIRepository.FieldInfoFlags.IS_READABLE)
217         self.assertFalse(field.get_flags() & GIRepository.FieldInfoFlags.IS_WRITABLE)
218         self.assertEqual(field.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
219
220         # don't test actual values because that might fail with architecture differences
221         self.assertTrue(isinstance(field.get_size(), int))
222         self.assertTrue(isinstance(field.get_offset(), int))
223
224     def test_property_info(self):
225         info = repo.find_by_name('GIMarshallingTests', 'PropertiesObject')
226         prop = find_child_info(info, 'get_properties', 'some-object')
227
228         flags = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT
229         self.assertEqual(prop.get_flags(), flags)
230         self.assertEqual(prop.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
231         self.assertEqual(prop.get_type().get_interface(),
232                          repo.find_by_name('GObject', 'Object'))
233         self.assertEqual(prop.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
234
235     def test_callable_info(self):
236         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
237         self.assertTrue(hasattr(func_info, 'invoke'))
238         self.assertTrue(isinstance(func_info.get_arguments(), collections.Iterable))
239         self.assertEqual(func_info.get_caller_owns(), GIRepository.Transfer.NOTHING)
240         self.assertFalse(func_info.may_return_null())
241         self.assertEqual(func_info.get_return_type().get_tag(), GIRepository.TypeTag.VOID)
242         self.assertRaises(AttributeError, func_info.get_return_attribute, '_not_an_attr')
243
244     def test_signal_info(self):
245         repo.require('Regress')
246         info = repo.find_by_name('Regress', 'TestObj')
247         sig_info = find_child_info(info, 'get_signals', 'test')
248
249         sig_flags = GObject.SignalFlags.RUN_LAST | \
250             GObject.SignalFlags.NO_RECURSE | GObject.SignalFlags.NO_HOOKS
251
252         self.assertTrue(sig_info is not None)
253         self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
254         self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
255         self.assertEqual(sig_info.get_name(), 'test')
256         self.assertEqual(sig_info.get_class_closure(), None)
257         self.assertFalse(sig_info.true_stops_emit())
258         self.assertEqual(sig_info.get_flags(), sig_flags)
259
260     def test_notify_signal_info_with_obj(self):
261         repo.require('Regress')
262         info = repo.find_by_name('Regress', 'TestObj')
263         sig_info = find_child_info(info, 'get_signals', 'sig-with-array-prop')
264
265         sig_flags = GObject.SignalFlags.RUN_LAST
266
267         self.assertTrue(sig_info is not None)
268         self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
269         self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
270         self.assertEqual(sig_info.get_name(), 'sig-with-array-prop')
271         self.assertEqual(sig_info.get_class_closure(), None)
272         self.assertFalse(sig_info.true_stops_emit())
273         self.assertEqual(sig_info.get_flags(), sig_flags)
274
275     def test_object_constructor(self):
276         info = repo.find_by_name('GIMarshallingTests', 'Object')
277         method = find_child_info(info, 'get_methods', 'new')
278
279         self.assertTrue(isinstance(method, GIRepository.CallableInfo))
280         self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
281         self.assertTrue(method in info.get_methods())
282         self.assertEqual(method.get_name(), 'new')
283         self.assertFalse(method.is_method())
284         self.assertTrue(method.is_constructor())
285         self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_new')
286
287         flags = method.get_flags()
288         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
289         self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
290         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
291         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
292         self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
293         self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
294
295     def test_method_info(self):
296         info = repo.find_by_name('GIMarshallingTests', 'Object')
297         method = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
298
299         self.assertTrue(isinstance(method, GIRepository.CallableInfo))
300         self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
301         self.assertTrue(method in info.get_methods())
302         self.assertEqual(method.get_name(), 'vfunc_return_value_only')
303         self.assertFalse(method.is_constructor())
304         self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_vfunc_return_value_only')
305         self.assertTrue(method.is_method())
306
307         flags = method.get_flags()
308         self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
309         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
310         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
311         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
312         self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
313         self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
314
315     def test_vfunc_info(self):
316         info = repo.find_by_name('GIMarshallingTests', 'Object')
317         invoker = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
318         vfunc = find_child_info(info, 'get_vfuncs', 'vfunc_return_value_only')
319
320         self.assertTrue(isinstance(vfunc, GIRepository.CallableInfo))
321         self.assertTrue(isinstance(vfunc, GIRepository.VFuncInfo))
322         self.assertEqual(vfunc.get_name(), 'vfunc_return_value_only')
323         self.assertEqual(vfunc.get_invoker(), invoker)
324         self.assertEqual(invoker, info.find_method('vfunc_return_value_only'))
325         self.assertEqual(vfunc.get_flags(), 0)
326         self.assertEqual(vfunc.get_offset(), 0xFFFF)  # unknown offset
327         self.assertEqual(vfunc.get_signal(), None)
328
329     def test_callable_can_throw_gerror(self):
330         info = repo.find_by_name('GIMarshallingTests', 'Object')
331         invoker = find_child_info(info, 'get_methods', 'vfunc_meth_with_error')
332         vfunc = find_child_info(info, 'get_vfuncs', 'vfunc_meth_with_err')
333
334         self.assertTrue(invoker.can_throw_gerror())
335         self.assertTrue(vfunc.can_throw_gerror())
336
337         # Test that args do not include the GError**
338         self.assertEqual(len(invoker.get_arguments()), 1)
339         self.assertEqual(len(vfunc.get_arguments()), 1)
340
341         # Sanity check method that does not throw.
342         invoker_no_throws = find_child_info(info, 'get_methods', 'method_int8_in')
343         self.assertFalse(invoker_no_throws.can_throw_gerror())
344
345     def test_flags_double_registration_error(self):
346         # a warning is printed for double registration and pygobject will
347         # also raise a RuntimeError.
348         GIMarshallingTests.NoTypeFlags  # cause flags registration
349         info = repo.find_by_name('GIMarshallingTests', 'NoTypeFlags')
350         with capture_glib_warnings(allow_warnings=True):
351             self.assertRaises(RuntimeError,
352                               GIRepository.flags_register_new_gtype_and_add,
353                               info)
354
355     def test_enum_double_registration_error(self):
356         # a warning is printed for double registration and pygobject will
357         # also raise a RuntimeError.
358         GIMarshallingTests.Enum  # cause enum registration
359         info = repo.find_by_name('GIMarshallingTests', 'Enum')
360         with capture_glib_warnings(allow_warnings=True):
361             self.assertRaises(RuntimeError,
362                               GIRepository.enum_register_new_gtype_and_add,
363                               info)
364
365     def test_enums(self):
366         self.assertTrue(hasattr(GIRepository, 'Direction'))
367         self.assertTrue(hasattr(GIRepository, 'Transfer'))
368         self.assertTrue(hasattr(GIRepository, 'ArrayType'))
369         self.assertTrue(hasattr(GIRepository, 'ScopeType'))
370         self.assertTrue(hasattr(GIRepository, 'VFuncInfoFlags'))
371         self.assertTrue(hasattr(GIRepository, 'FieldInfoFlags'))
372         self.assertTrue(hasattr(GIRepository, 'FunctionInfoFlags'))
373         self.assertTrue(hasattr(GIRepository, 'TypeTag'))
374         self.assertTrue(hasattr(GIRepository, 'InfoType'))
375
376     def test_introspected_argument_info(self):
377         self.assertTrue(isinstance(IntrospectedRepository.Argument.__info__,
378                                    GIRepository.UnionInfo))
379
380         arg = IntrospectedRepository.Argument()
381         self.assertTrue(isinstance(arg.__info__, GIRepository.UnionInfo))
382
383         old_info = IntrospectedRepository.Argument.__info__
384         IntrospectedRepository.Argument.__info__ = 'not an info'
385         self.assertRaises(TypeError, IntrospectedRepository.Argument)
386         IntrospectedRepository.Argument.__info__ = old_info
387
388
389 if __name__ == '__main__':
390     unittest.main()