39722ef0b92848cf35f48f66efb1a38ac1e6932a
[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 GLib
30 from gi.repository import GIMarshallingTests
31 from gi.repository import GIRepository as IntrospectedRepository
32
33 try:
34     import cairo
35     cairo
36     has_cairo = True
37 except ImportError:
38     has_cairo = False
39
40
41 def find_child_info(info, getter_name, name):
42     getter = getattr(info, getter_name)
43     for child in getter():
44         if child.get_name() == name:
45             return child
46     else:
47         raise ValueError('child info %s not found' % name)
48
49
50 class Test(unittest.TestCase):
51     def setUp(self):
52         repo.require('GObject')
53         repo.require('GIMarshallingTests')
54
55     def test_arg_info(self):
56         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
57         args = func_info.get_arguments()
58         self.assertTrue(len(args), 1)
59
60         arg = args[0]
61         self.assertEqual(arg.get_container(), func_info)
62         self.assertEqual(arg.get_direction(), GIRepository.Direction.OUT)
63         self.assertEqual(arg.get_name(), 'structs')
64         self.assertEqual(arg.get_namespace(), 'GIMarshallingTests')
65         self.assertFalse(arg.is_caller_allocates())
66         self.assertFalse(arg.is_optional())
67         self.assertFalse(arg.is_return_value())
68         self.assertFalse(arg.may_be_null())
69         self.assertEqual(arg.get_destroy(), -1)
70         self.assertEqual(arg.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
71         self.assertEqual(arg.get_scope(), GIRepository.ScopeType.INVALID)
72         self.assertEqual(arg.get_type().get_tag(), GIRepository.TypeTag.ARRAY)
73
74     def test_base_info(self):
75         info = repo.find_by_name('GIMarshallingTests', 'Object')
76         self.assertEqual(info.__name__, 'Object')
77         self.assertEqual(info.get_name(), 'Object')
78         self.assertEqual(info.__module__, 'gi.repository.GIMarshallingTests')
79         self.assertEqual(info.get_name_unescaped(), 'Object')
80         self.assertEqual(info.get_namespace(), 'GIMarshallingTests')
81         self.assertEqual(info.get_container(), None)
82         info2 = repo.find_by_name('GIMarshallingTests', 'Object')
83         self.assertFalse(info is info2)
84         self.assertEqual(info, info2)
85         self.assertTrue(info.equal(info2))
86
87     def test_object_info(self):
88         info = repo.find_by_name('GIMarshallingTests', 'Object')
89         self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
90         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
91         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
92         self.assertTrue(isinstance(info.get_interfaces(), collections.Iterable))
93         self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
94         self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
95         self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
96         self.assertFalse(info.get_abstract())
97         self.assertEqual(info.get_class_struct(), repo.find_by_name('GIMarshallingTests', 'ObjectClass'))
98         self.assertEqual(info.get_type_name(), 'GIMarshallingTestsObject')
99         self.assertEqual(info.get_type_init(), 'gi_marshalling_tests_object_get_type')
100         self.assertFalse(info.get_fundamental())
101         self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
102
103     def test_registered_type_info(self):
104         info = repo.find_by_name('GIMarshallingTests', 'Object')
105         # Call these from the class because GIObjectInfo overrides them
106         self.assertEqual(GIRepository.RegisteredTypeInfo.get_g_type(info),
107                          GObject.type_from_name('GIMarshallingTestsObject'))
108         self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_name(info),
109                          'GIMarshallingTestsObject')
110         self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_init(info),
111                          'gi_marshalling_tests_object_get_type')
112
113     @unittest.skipUnless(has_cairo, 'Regress needs cairo')
114     def test_fundamental_object_info(self):
115         repo.require('Regress')
116         info = repo.find_by_name('Regress', 'TestFundamentalObject')
117         self.assertTrue(info.get_abstract())
118         self.assertTrue(info.get_fundamental())
119         self.assertEqual(info.get_ref_function(), 'regress_test_fundamental_object_ref')
120         self.assertEqual(info.get_unref_function(), 'regress_test_fundamental_object_unref')
121         self.assertEqual(info.get_get_value_function(), 'regress_test_value_get_fundamental_object')
122         self.assertEqual(info.get_set_value_function(), 'regress_test_value_set_fundamental_object')
123
124     def test_interface_info(self):
125         info = repo.find_by_name('GIMarshallingTests', 'Interface')
126         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
127         self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
128         self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
129         self.assertTrue(isinstance(info.get_prerequisites(), collections.Iterable))
130         self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
131         self.assertTrue(isinstance(info.get_signals(), collections.Iterable))
132
133         method = info.find_method('test_int8_in')
134         vfunc = info.find_vfunc('test_int8_in')
135         self.assertEqual(method.get_name(), 'test_int8_in')
136         self.assertEqual(vfunc.get_invoker(), method)
137         self.assertEqual(method.get_vfunc(), vfunc)
138
139         iface = info.get_iface_struct()
140         self.assertEqual(iface, repo.find_by_name('GIMarshallingTests', 'InterfaceIface'))
141
142     def test_struct_info(self):
143         info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
144         self.assertTrue(isinstance(info, GIRepository.StructInfo))
145         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
146         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
147         self.assertTrue(isinstance(info.get_size(), int))
148         self.assertTrue(isinstance(info.get_alignment(), int))
149         self.assertTrue(info.is_gtype_struct())
150         self.assertFalse(info.is_foreign())
151
152     def test_enum_info(self):
153         info = repo.find_by_name('GIMarshallingTests', 'Enum')
154         self.assertTrue(isinstance(info, GIRepository.EnumInfo))
155         self.assertTrue(isinstance(info.get_values(), collections.Iterable))
156         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
157         self.assertFalse(info.is_flags())
158         self.assertTrue(info.get_storage_type() > 0)  # might be platform dependent
159
160     def test_union_info(self):
161         info = repo.find_by_name('GIMarshallingTests', 'Union')
162         self.assertTrue(isinstance(info, GIRepository.UnionInfo))
163         self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
164         self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
165
166     def test_type_info(self):
167         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
168         arg_info, = func_info.get_arguments()
169         type_info = arg_info.get_type()
170
171         self.assertTrue(type_info.is_pointer())
172         self.assertEqual(type_info.get_tag(), GIRepository.TypeTag.ARRAY)
173         self.assertEqual(type_info.get_tag_as_string(), 'array')
174         self.assertEqual(type_info.get_param_type(0).get_tag(),
175                          GIRepository.TypeTag.INTERFACE)
176         self.assertEqual(type_info.get_param_type(0).get_interface(),
177                          repo.find_by_name('GIMarshallingTests', 'SimpleStruct'))
178         self.assertEqual(type_info.get_interface(), None)
179         self.assertEqual(type_info.get_array_length(), -1)
180         self.assertEqual(type_info.get_array_fixed_size(), 2)
181         self.assertFalse(type_info.is_zero_terminated())
182         self.assertEqual(type_info.get_array_type(), GIRepository.ArrayType.C)
183
184     def test_field_info(self):
185         info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
186         field = find_child_info(info, 'get_fields', 'test_int8_in')
187         self.assertEqual(field.get_name(), 'test_int8_in')
188         self.assertTrue(field.get_flags() & GIRepository.FieldInfoFlags.IS_READABLE)
189         self.assertFalse(field.get_flags() & GIRepository.FieldInfoFlags.IS_WRITABLE)
190         self.assertEqual(field.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
191
192         # don't test actual values because that might fail with architecture differences
193         self.assertTrue(isinstance(field.get_size(), int))
194         self.assertTrue(isinstance(field.get_offset(), int))
195
196     def test_property_info(self):
197         info = repo.find_by_name('GIMarshallingTests', 'PropertiesObject')
198         prop = find_child_info(info, 'get_properties', 'some-object')
199
200         flags = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT
201         self.assertEqual(prop.get_flags(), flags)
202         self.assertEqual(prop.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
203         self.assertEqual(prop.get_type().get_interface(),
204                          repo.find_by_name('GObject', 'Object'))
205         self.assertEqual(prop.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
206
207     def test_callable_info(self):
208         func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
209         self.assertTrue(hasattr(func_info, 'invoke'))
210         self.assertTrue(isinstance(func_info.get_arguments(), collections.Iterable))
211         self.assertEqual(func_info.get_caller_owns(), GIRepository.Transfer.NOTHING)
212         self.assertFalse(func_info.may_return_null())
213         self.assertEqual(func_info.get_return_type().get_tag(), GIRepository.TypeTag.VOID)
214         self.assertRaises(AttributeError, func_info.get_return_attribute, '_not_an_attr')
215
216     @unittest.skip('https://bugzilla.gnome.org/show_bug.cgi?id=709462')
217     @unittest.skipUnless(has_cairo, 'Regress needs cairo')
218     def test_signal_info(self):
219         repo.require('Regress')
220         info = repo.find_by_name('Regress', 'TestObj')
221         sig_info = find_child_info(info, 'get_signals', 'test')
222
223         sig_flags = GObject.SignalFlags.RUN_LAST | \
224             GObject.SignalFlags.NO_RECURSE | GObject.SignalFlags.NO_HOOKS
225
226         self.assertTrue(sig_info is not None)
227         self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
228         self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
229         self.assertEqual(sig_info.get_name(), 'test')
230         self.assertEqual(sig_info.get_class_closure(), None)
231         self.assertFalse(sig_info.true_stops_emit())
232         self.assertEqual(sig_info.get_flags(), sig_flags)
233
234     @unittest.skip('https://bugzilla.gnome.org/show_bug.cgi?id=709462')
235     @unittest.skipUnless(has_cairo, 'Regress needs cairo')
236     def test_notify_signal_info_with_obj(self):
237         repo.require('Regress')
238         info = repo.find_by_name('Regress', 'TestObj')
239         sig_info = find_child_info(info, 'get_signals', 'sig-with-array-prop')
240
241         sig_flags = GObject.SignalFlags.RUN_LAST
242
243         self.assertTrue(sig_info is not None)
244         self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
245         self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
246         self.assertEqual(sig_info.get_name(), 'sig-with-array-prop')
247         self.assertEqual(sig_info.get_class_closure(), None)
248         self.assertFalse(sig_info.true_stops_emit())
249         self.assertEqual(sig_info.get_flags(), sig_flags)
250
251     def test_object_constructor(self):
252         info = repo.find_by_name('GIMarshallingTests', 'Object')
253         method = find_child_info(info, 'get_methods', 'new')
254
255         self.assertTrue(isinstance(method, GIRepository.CallableInfo))
256         self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
257         self.assertTrue(method in info.get_methods())
258         self.assertEqual(method.get_name(), 'new')
259         self.assertFalse(method.is_method())
260         self.assertTrue(method.is_constructor())
261         self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_new')
262
263         flags = method.get_flags()
264         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
265         self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
266         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
267         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
268         self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
269         self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
270
271     def test_method_info(self):
272         info = repo.find_by_name('GIMarshallingTests', 'Object')
273         method = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
274
275         self.assertTrue(isinstance(method, GIRepository.CallableInfo))
276         self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
277         self.assertTrue(method in info.get_methods())
278         self.assertEqual(method.get_name(), 'vfunc_return_value_only')
279         self.assertFalse(method.is_constructor())
280         self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_vfunc_return_value_only')
281         self.assertTrue(method.is_method())
282
283         flags = method.get_flags()
284         self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
285         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
286         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
287         self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
288         self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
289         self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
290
291     def test_vfunc_info(self):
292         info = repo.find_by_name('GIMarshallingTests', 'Object')
293         invoker = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
294         vfunc = find_child_info(info, 'get_vfuncs', 'vfunc_return_value_only')
295
296         self.assertTrue(isinstance(vfunc, GIRepository.CallableInfo))
297         self.assertTrue(isinstance(vfunc, GIRepository.VFuncInfo))
298         self.assertEqual(vfunc.get_name(), 'vfunc_return_value_only')
299         self.assertEqual(vfunc.get_invoker(), invoker)
300         self.assertEqual(invoker, info.find_method('vfunc_return_value_only'))
301         self.assertEqual(vfunc.get_flags(), 0)
302         self.assertEqual(vfunc.get_offset(), 0xFFFF)  # unknown offset
303         self.assertEqual(vfunc.get_signal(), None)
304
305     def test_flags_double_registration_error(self):
306         # a warning is printed for double registration and pygobject will
307         # also raise a RuntimeError.
308         GIMarshallingTests.NoTypeFlags  # cause flags registration
309         info = repo.find_by_name('GIMarshallingTests', 'NoTypeFlags')
310         old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
311         try:
312             self.assertRaises(RuntimeError,
313                               GIRepository.flags_register_new_gtype_and_add,
314                               info)
315         finally:
316             GLib.log_set_always_fatal(old_mask)
317
318     def test_enum_double_registration_error(self):
319         # a warning is printed for double registration and pygobject will
320         # also raise a RuntimeError.
321         GIMarshallingTests.Enum  # cause enum registration
322         info = repo.find_by_name('GIMarshallingTests', 'Enum')
323         old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
324         try:
325             self.assertRaises(RuntimeError,
326                               GIRepository.enum_register_new_gtype_and_add,
327                               info)
328         finally:
329             GLib.log_set_always_fatal(old_mask)
330
331     def test_enums(self):
332         self.assertTrue(hasattr(GIRepository, 'Direction'))
333         self.assertTrue(hasattr(GIRepository, 'Transfer'))
334         self.assertTrue(hasattr(GIRepository, 'ArrayType'))
335         self.assertTrue(hasattr(GIRepository, 'ScopeType'))
336         self.assertTrue(hasattr(GIRepository, 'VFuncInfoFlags'))
337         self.assertTrue(hasattr(GIRepository, 'FieldInfoFlags'))
338         self.assertTrue(hasattr(GIRepository, 'FunctionInfoFlags'))
339         self.assertTrue(hasattr(GIRepository, 'TypeTag'))
340         self.assertTrue(hasattr(GIRepository, 'InfoType'))
341
342     def test_introspected_argument_info(self):
343         self.assertTrue(isinstance(IntrospectedRepository.Argument.__info__,
344                                    GIRepository.UnionInfo))
345
346         arg = IntrospectedRepository.Argument()
347         self.assertTrue(isinstance(arg.__info__, GIRepository.UnionInfo))
348
349         old_info = IntrospectedRepository.Argument.__info__
350         IntrospectedRepository.Argument.__info__ = 'not an info'
351         self.assertRaises(TypeError, IntrospectedRepository.Argument)
352         IntrospectedRepository.Argument.__info__ = old_info
353
354
355 if __name__ == '__main__':
356     unittest.main()