Imported Upstream version 3.19.91
[platform/upstream/python-gobject.git] / tests / test_gobject.py
1 # -*- Mode: Python -*-
2
3 import sys
4 import gc
5 import unittest
6 import warnings
7
8 from gi.repository import GObject, GLib
9 from gi import PyGIDeprecationWarning
10 from gi.module import get_introspection_module
11
12 import gi
13 _gobject = gi._gi._gobject
14
15 import testhelper
16
17
18 class TestGObjectAPI(unittest.TestCase):
19     def test_gobject_inheritance(self):
20         # GObject.Object is a class hierarchy as follows:
21         # overrides.Object -> introspection.Object -> static.GObject
22         GIObjectModule = get_introspection_module('GObject')
23         self.assertTrue(issubclass(GObject.Object, GIObjectModule.Object))
24         self.assertTrue(issubclass(GIObjectModule.Object, _gobject.GObject))
25
26         self.assertEqual(_gobject.GObject.__gtype__, GObject.TYPE_OBJECT)
27         self.assertEqual(GIObjectModule.Object.__gtype__, GObject.TYPE_OBJECT)
28         self.assertEqual(GObject.Object.__gtype__, GObject.TYPE_OBJECT)
29
30         # The pytype wrapper should hold the outer most Object class from overrides.
31         self.assertEqual(GObject.TYPE_OBJECT.pytype, GObject.Object)
32
33     def test_gobject_unsupported_overrides(self):
34         obj = GObject.Object()
35
36         with self.assertRaisesRegex(RuntimeError, 'Data access methods are unsupported.*'):
37             obj.get_data()
38
39         with self.assertRaisesRegex(RuntimeError, 'This method is currently unsupported.*'):
40             obj.force_floating()
41
42     def test_compat_api(self):
43         with warnings.catch_warnings(record=True) as w:
44             warnings.simplefilter('always')
45             # GObject formerly exposed a lot of GLib's functions
46             self.assertEqual(GObject.markup_escape_text('foo'), 'foo')
47
48             ml = GObject.MainLoop()
49             self.assertFalse(ml.is_running())
50
51             context = GObject.main_context_default()
52             self.assertTrue(context.pending() in [False, True])
53
54             context = GObject.MainContext()
55             self.assertFalse(context.pending())
56
57             self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
58             self.assertTrue('GLib.markup_escape_text' in str(w[0]), str(w[0]))
59
60             self.assertLess(GObject.PRIORITY_HIGH, GObject.PRIORITY_DEFAULT)
61
62     def test_min_max_int(self):
63         with warnings.catch_warnings():
64             warnings.simplefilter('ignore', PyGIDeprecationWarning)
65
66             self.assertEqual(GObject.G_MAXINT16, 2 ** 15 - 1)
67             self.assertEqual(GObject.G_MININT16, -2 ** 15)
68             self.assertEqual(GObject.G_MAXUINT16, 2 ** 16 - 1)
69
70             self.assertEqual(GObject.G_MAXINT32, 2 ** 31 - 1)
71             self.assertEqual(GObject.G_MININT32, -2 ** 31)
72             self.assertEqual(GObject.G_MAXUINT32, 2 ** 32 - 1)
73
74             self.assertEqual(GObject.G_MAXINT64, 2 ** 63 - 1)
75             self.assertEqual(GObject.G_MININT64, -2 ** 63)
76             self.assertEqual(GObject.G_MAXUINT64, 2 ** 64 - 1)
77
78
79 class TestReferenceCounting(unittest.TestCase):
80     def test_regular_object(self):
81         obj = GObject.GObject()
82         self.assertEqual(obj.__grefcount__, 1)
83
84         obj = GObject.new(GObject.GObject)
85         self.assertEqual(obj.__grefcount__, 1)
86
87     def test_floating(self):
88         obj = testhelper.Floating()
89         self.assertEqual(obj.__grefcount__, 1)
90
91         obj = GObject.new(testhelper.Floating)
92         self.assertEqual(obj.__grefcount__, 1)
93
94     def test_owned_by_library(self):
95         # Upon creation, the refcount of the object should be 2:
96         # - someone already has a reference on the new object.
97         # - the python wrapper should hold its own reference.
98         obj = testhelper.OwnedByLibrary()
99         self.assertEqual(obj.__grefcount__, 2)
100
101         # We ask the library to release its reference, so the only
102         # remaining ref should be our wrapper's. Once the wrapper
103         # will run out of scope, the object will get finalized.
104         obj.release()
105         self.assertEqual(obj.__grefcount__, 1)
106
107     def test_owned_by_library_out_of_scope(self):
108         obj = testhelper.OwnedByLibrary()
109         self.assertEqual(obj.__grefcount__, 2)
110
111         # We are manually taking the object out of scope. This means
112         # that our wrapper has been freed, and its reference dropped. We
113         # cannot check it but the refcount should now be 1 (the ref held
114         # by the library is still there, we didn't call release()
115         obj = None
116
117         # When we get the object back from the lib, the wrapper is
118         # re-created, so our refcount will be 2 once again.
119         obj = testhelper.owned_by_library_get_instance_list()[0]
120         self.assertEqual(obj.__grefcount__, 2)
121
122         obj.release()
123         self.assertEqual(obj.__grefcount__, 1)
124
125     def test_owned_by_library_using_gobject_new(self):
126         # Upon creation, the refcount of the object should be 2:
127         # - someone already has a reference on the new object.
128         # - the python wrapper should hold its own reference.
129         obj = GObject.new(testhelper.OwnedByLibrary)
130         self.assertEqual(obj.__grefcount__, 2)
131
132         # We ask the library to release its reference, so the only
133         # remaining ref should be our wrapper's. Once the wrapper
134         # will run out of scope, the object will get finalized.
135         obj.release()
136         self.assertEqual(obj.__grefcount__, 1)
137
138     def test_owned_by_library_out_of_scope_using_gobject_new(self):
139         obj = GObject.new(testhelper.OwnedByLibrary)
140         self.assertEqual(obj.__grefcount__, 2)
141
142         # We are manually taking the object out of scope. This means
143         # that our wrapper has been freed, and its reference dropped. We
144         # cannot check it but the refcount should now be 1 (the ref held
145         # by the library is still there, we didn't call release()
146         obj = None
147
148         # When we get the object back from the lib, the wrapper is
149         # re-created, so our refcount will be 2 once again.
150         obj = testhelper.owned_by_library_get_instance_list()[0]
151         self.assertEqual(obj.__grefcount__, 2)
152
153         obj.release()
154         self.assertEqual(obj.__grefcount__, 1)
155
156     def test_floating_and_sunk(self):
157         # Upon creation, the refcount of the object should be 2:
158         # - someone already has a reference on the new object.
159         # - the python wrapper should hold its own reference.
160         obj = testhelper.FloatingAndSunk()
161         self.assertEqual(obj.__grefcount__, 2)
162
163         # We ask the library to release its reference, so the only
164         # remaining ref should be our wrapper's. Once the wrapper
165         # will run out of scope, the object will get finalized.
166         obj.release()
167         self.assertEqual(obj.__grefcount__, 1)
168
169     def test_floating_and_sunk_out_of_scope(self):
170         obj = testhelper.FloatingAndSunk()
171         self.assertEqual(obj.__grefcount__, 2)
172
173         # We are manually taking the object out of scope. This means
174         # that our wrapper has been freed, and its reference dropped. We
175         # cannot check it but the refcount should now be 1 (the ref held
176         # by the library is still there, we didn't call release()
177         obj = None
178
179         # When we get the object back from the lib, the wrapper is
180         # re-created, so our refcount will be 2 once again.
181         obj = testhelper.floating_and_sunk_get_instance_list()[0]
182         self.assertEqual(obj.__grefcount__, 2)
183
184         obj.release()
185         self.assertEqual(obj.__grefcount__, 1)
186
187     def test_floating_and_sunk_using_gobject_new(self):
188         # Upon creation, the refcount of the object should be 2:
189         # - someone already has a reference on the new object.
190         # - the python wrapper should hold its own reference.
191         obj = GObject.new(testhelper.FloatingAndSunk)
192         self.assertEqual(obj.__grefcount__, 2)
193
194         # We ask the library to release its reference, so the only
195         # remaining ref should be our wrapper's. Once the wrapper
196         # will run out of scope, the object will get finalized.
197         obj.release()
198         self.assertEqual(obj.__grefcount__, 1)
199
200     def test_floating_and_sunk_out_of_scope_using_gobject_new(self):
201         obj = GObject.new(testhelper.FloatingAndSunk)
202         self.assertEqual(obj.__grefcount__, 2)
203
204         # We are manually taking the object out of scope. This means
205         # that our wrapper has been freed, and its reference dropped. We
206         # cannot check it but the refcount should now be 1 (the ref held
207         # by the library is still there, we didn't call release()
208         obj = None
209
210         # When we get the object back from the lib, the wrapper is
211         # re-created, so our refcount will be 2 once again.
212         obj = testhelper.floating_and_sunk_get_instance_list()[0]
213         self.assertEqual(obj.__grefcount__, 2)
214
215         obj.release()
216         self.assertEqual(obj.__grefcount__, 1)
217
218     def test_uninitialized_object(self):
219         class Obj(GObject.GObject):
220             def __init__(self):
221                 x = self.__grefcount__
222                 super(Obj, self).__init__()
223                 assert x >= 0  # quiesce pyflakes
224
225         # Accessing __grefcount__ before the object is initialized is wrong.
226         # Ensure we get a proper exception instead of a crash.
227         self.assertRaises(TypeError, Obj)
228
229
230 class A(GObject.GObject):
231     def __init__(self):
232         super(A, self).__init__()
233
234
235 class TestPythonReferenceCounting(unittest.TestCase):
236     # Newly created instances should alwayshave two references: one for
237     # the GC, and one for the bound variable in the local scope.
238
239     def test_new_instance_has_two_refs(self):
240         obj = GObject.GObject()
241         self.assertEqual(sys.getrefcount(obj), 2)
242
243     def test_new_instance_has_two_refs_using_gobject_new(self):
244         obj = GObject.new(GObject.GObject)
245         self.assertEqual(sys.getrefcount(obj), 2)
246
247     def test_new_subclass_instance_has_two_refs(self):
248         obj = A()
249         self.assertEqual(sys.getrefcount(obj), 2)
250
251     def test_new_subclass_instance_has_two_refs_using_gobject_new(self):
252         obj = GObject.new(A)
253         self.assertEqual(sys.getrefcount(obj), 2)
254
255
256 class TestContextManagers(unittest.TestCase):
257     class ContextTestObject(GObject.GObject):
258         prop = GObject.Property(default=0, type=int)
259
260     def on_prop_set(self, obj, prop):
261         # Handler which tracks property changed notifications.
262         self.tracking.append(obj.get_property(prop.name))
263
264     def setUp(self):
265         self.tracking = []
266         self.obj = self.ContextTestObject()
267         self.handler = self.obj.connect('notify::prop', self.on_prop_set)
268
269     def test_freeze_notify_context(self):
270         # Verify prop tracking list
271         self.assertEqual(self.tracking, [])
272         self.obj.props.prop = 1
273         self.assertEqual(self.tracking, [1])
274         self.obj.props.prop = 2
275         self.assertEqual(self.tracking, [1, 2])
276         self.assertEqual(self.obj.__grefcount__, 1)
277
278         pyref_count = sys.getrefcount(self.obj)
279
280         # Using the context manager the tracking list should not be affected.
281         # The GObject reference count should stay the same and the python
282         # object ref-count should go up.
283         with self.obj.freeze_notify():
284             self.assertEqual(self.obj.__grefcount__, 1)
285             self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
286             self.obj.props.prop = 3
287             self.assertEqual(self.obj.props.prop, 3)
288             self.assertEqual(self.tracking, [1, 2])
289
290         # After the context manager, the prop should have been modified,
291         # the tracking list will be modified, and the python object ref
292         # count goes back down.
293         gc.collect()
294         self.assertEqual(self.obj.props.prop, 3)
295         self.assertEqual(self.tracking, [1, 2, 3])
296         self.assertEqual(self.obj.__grefcount__, 1)
297         self.assertEqual(sys.getrefcount(self.obj), pyref_count)
298
299     def test_handler_block_context(self):
300         # Verify prop tracking list
301         self.assertEqual(self.tracking, [])
302         self.obj.props.prop = 1
303         self.assertEqual(self.tracking, [1])
304         self.obj.props.prop = 2
305         self.assertEqual(self.tracking, [1, 2])
306         self.assertEqual(self.obj.__grefcount__, 1)
307
308         pyref_count = sys.getrefcount(self.obj)
309
310         # Using the context manager the tracking list should not be affected.
311         # The GObject reference count should stay the same and the python
312         # object ref-count should go up.
313         with self.obj.handler_block(self.handler):
314             self.assertEqual(self.obj.__grefcount__, 1)
315             self.assertEqual(sys.getrefcount(self.obj), pyref_count + 1)
316             self.obj.props.prop = 3
317             self.assertEqual(self.obj.props.prop, 3)
318             self.assertEqual(self.tracking, [1, 2])
319
320         # After the context manager, the prop should have been modified
321         # the tracking list should have stayed the same and the GObject ref
322         # count goes back down.
323         gc.collect()
324         self.assertEqual(self.obj.props.prop, 3)
325         self.assertEqual(self.tracking, [1, 2])
326         self.assertEqual(self.obj.__grefcount__, 1)
327         self.assertEqual(sys.getrefcount(self.obj), pyref_count)
328
329     def test_freeze_notify_context_nested(self):
330         self.assertEqual(self.tracking, [])
331         with self.obj.freeze_notify():
332             self.obj.props.prop = 1
333             self.assertEqual(self.tracking, [])
334
335             with self.obj.freeze_notify():
336                 self.obj.props.prop = 2
337                 self.assertEqual(self.tracking, [])
338
339                 with self.obj.freeze_notify():
340                     self.obj.props.prop = 3
341                     self.assertEqual(self.tracking, [])
342                 self.assertEqual(self.tracking, [])
343             self.assertEqual(self.tracking, [])
344
345         # Finally after last context, the notifications should have collapsed
346         # and the last one sent.
347         self.assertEqual(self.tracking, [3])
348
349     def test_handler_block_context_nested(self):
350         self.assertEqual(self.tracking, [])
351         with self.obj.handler_block(self.handler):
352             self.obj.props.prop = 1
353             self.assertEqual(self.tracking, [])
354
355             with self.obj.handler_block(self.handler):
356                 self.obj.props.prop = 2
357                 self.assertEqual(self.tracking, [])
358
359                 with self.obj.handler_block(self.handler):
360                     self.obj.props.prop = 3
361                     self.assertEqual(self.tracking, [])
362                 self.assertEqual(self.tracking, [])
363             self.assertEqual(self.tracking, [])
364
365         # Finally after last context, the notifications should have collapsed
366         # and the last one sent.
367         self.assertEqual(self.obj.props.prop, 3)
368         self.assertEqual(self.tracking, [])
369
370     def test_freeze_notify_normal_usage_ref_counts(self):
371         # Ensure ref counts without using methods as context managers
372         # maintain the same count.
373         self.assertEqual(self.obj.__grefcount__, 1)
374         self.obj.freeze_notify()
375         self.assertEqual(self.obj.__grefcount__, 1)
376         self.obj.thaw_notify()
377         self.assertEqual(self.obj.__grefcount__, 1)
378
379     def test_handler_block_normal_usage_ref_counts(self):
380         self.assertEqual(self.obj.__grefcount__, 1)
381         self.obj.handler_block(self.handler)
382         self.assertEqual(self.obj.__grefcount__, 1)
383         self.obj.handler_unblock(self.handler)
384         self.assertEqual(self.obj.__grefcount__, 1)
385
386     def test_freeze_notify_context_error(self):
387         # Test an exception occurring within a freeze context exits the context
388         try:
389             with self.obj.freeze_notify():
390                 self.obj.props.prop = 1
391                 self.assertEqual(self.tracking, [])
392                 raise ValueError('Simulation')
393         except ValueError:
394             pass
395
396         # Verify the property set within the context called notify.
397         self.assertEqual(self.obj.props.prop, 1)
398         self.assertEqual(self.tracking, [1])
399
400         # Verify we are still not in a frozen context.
401         self.obj.props.prop = 2
402         self.assertEqual(self.tracking, [1, 2])
403
404     def test_handler_block_context_error(self):
405         # Test an exception occurring within a handler block exits the context
406         try:
407             with self.obj.handler_block(self.handler):
408                 self.obj.props.prop = 1
409                 self.assertEqual(self.tracking, [])
410                 raise ValueError('Simulation')
411         except ValueError:
412             pass
413
414         # Verify the property set within the context didn't call notify.
415         self.assertEqual(self.obj.props.prop, 1)
416         self.assertEqual(self.tracking, [])
417
418         # Verify we are still not in a handler block context.
419         self.obj.props.prop = 2
420         self.assertEqual(self.tracking, [2])
421
422
423 @unittest.skipUnless(hasattr(GObject.Binding, 'unbind'),
424                      'Requires newer GLib which has g_binding_unbind')
425 class TestPropertyBindings(unittest.TestCase):
426     class TestObject(GObject.GObject):
427         int_prop = GObject.Property(default=0, type=int)
428
429     def setUp(self):
430         self.source = self.TestObject()
431         self.target = self.TestObject()
432
433     def test_default_binding(self):
434         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
435                                             GObject.BindingFlags.DEFAULT)
436         binding = binding  # PyFlakes
437
438         # Test setting value on source gets pushed to target
439         self.source.int_prop = 1
440         self.assertEqual(self.source.int_prop, 1)
441         self.assertEqual(self.target.int_prop, 1)
442
443         # Test setting value on target does not change source
444         self.target.props.int_prop = 2
445         self.assertEqual(self.source.int_prop, 1)
446         self.assertEqual(self.target.int_prop, 2)
447
448     def test_bidirectional_binding(self):
449         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
450                                             GObject.BindingFlags.BIDIRECTIONAL)
451         binding = binding  # PyFlakes
452
453         # Test setting value on source gets pushed to target
454         self.source.int_prop = 1
455         self.assertEqual(self.source.int_prop, 1)
456         self.assertEqual(self.target.int_prop, 1)
457
458         # Test setting value on target also changes source
459         self.target.props.int_prop = 2
460         self.assertEqual(self.source.int_prop, 2)
461         self.assertEqual(self.target.int_prop, 2)
462
463     def test_transform_to_only(self):
464         def transform_to(binding, value, user_data=None):
465             self.assertEqual(user_data, 'test-data')
466             return value * 2
467
468         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
469                                             GObject.BindingFlags.DEFAULT,
470                                             transform_to, None, 'test-data')
471         binding = binding  # PyFlakes
472
473         self.source.int_prop = 1
474         self.assertEqual(self.source.int_prop, 1)
475         self.assertEqual(self.target.int_prop, 2)
476
477         self.target.props.int_prop = 1
478         self.assertEqual(self.source.int_prop, 1)
479         self.assertEqual(self.target.int_prop, 1)
480
481     def test_transform_from_only(self):
482         def transform_from(binding, value, user_data=None):
483             self.assertEqual(user_data, None)
484             return value * 2
485
486         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
487                                             GObject.BindingFlags.BIDIRECTIONAL,
488                                             None, transform_from)
489         binding = binding  # PyFlakes
490
491         self.source.int_prop = 1
492         self.assertEqual(self.source.int_prop, 1)
493         self.assertEqual(self.target.int_prop, 1)
494
495         self.target.props.int_prop = 1
496         self.assertEqual(self.source.int_prop, 2)
497         self.assertEqual(self.target.int_prop, 1)
498
499     def test_transform_bidirectional(self):
500         test_data = object()
501
502         def transform_to(binding, value, user_data=None):
503             self.assertEqual(user_data, test_data)
504             return value * 2
505
506         def transform_from(binding, value, user_data=None):
507             self.assertEqual(user_data, test_data)
508             return value // 2
509
510         test_data_ref_count = sys.getrefcount(test_data)
511         transform_to_ref_count = sys.getrefcount(transform_to)
512         transform_from_ref_count = sys.getrefcount(transform_from)
513
514         # bidirectional bindings
515         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
516                                             GObject.BindingFlags.BIDIRECTIONAL,
517                                             transform_to, transform_from, test_data)
518         binding = binding  # PyFlakes
519         binding_ref_count = sys.getrefcount(binding)
520         binding_gref_count = binding.__grefcount__
521
522         self.source.int_prop = 1
523         self.assertEqual(self.source.int_prop, 1)
524         self.assertEqual(self.target.int_prop, 2)
525
526         self.target.props.int_prop = 4
527         self.assertEqual(self.source.int_prop, 2)
528         self.assertEqual(self.target.int_prop, 4)
529
530         self.assertEqual(sys.getrefcount(binding), binding_ref_count)
531         self.assertEqual(binding.__grefcount__, binding_gref_count)
532
533         # test_data ref count increases by 2, once for each callback.
534         self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2)
535         self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1)
536         self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1)
537
538         # Unbind should clear out the binding and its transforms
539         binding.unbind()
540
541         # Setting source or target should not change the other.
542         self.target.int_prop = 3
543         self.source.int_prop = 5
544         self.assertEqual(self.target.int_prop, 3)
545         self.assertEqual(self.source.int_prop, 5)
546
547         self.assertEqual(sys.getrefcount(test_data), test_data_ref_count)
548         self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count)
549         self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count)
550
551     def test_explicit_unbind_clears_connection(self):
552         self.assertEqual(self.source.int_prop, 0)
553         self.assertEqual(self.target.int_prop, 0)
554
555         # Test deleting binding reference removes binding.
556         binding = self.source.bind_property('int_prop', self.target, 'int_prop')
557         self.source.int_prop = 1
558         self.assertEqual(self.source.int_prop, 1)
559         self.assertEqual(self.target.int_prop, 1)
560
561         # unbind should clear out the bindings self reference
562         binding.unbind()
563         self.assertEqual(binding.__grefcount__, 1)
564
565         self.source.int_prop = 10
566         self.assertEqual(self.source.int_prop, 10)
567         self.assertEqual(self.target.int_prop, 1)
568
569         # An already unbound BindingWeakRef will raise if unbind is attempted a second time.
570         self.assertRaises(ValueError, binding.unbind)
571
572     def test_reference_counts(self):
573         self.assertEqual(self.source.__grefcount__, 1)
574         self.assertEqual(self.target.__grefcount__, 1)
575
576         # Binding ref count will be 2 do to the initial ref implicitly held by
577         # the act of binding and the ref incurred by using __call__ to generate
578         # a wrapper from the weak binding ref within python.
579         binding = self.source.bind_property('int_prop', self.target, 'int_prop')
580         self.assertEqual(binding.__grefcount__, 2)
581
582         # Creating a binding does not inc refs on source and target (they are weak
583         # on the binding object itself)
584         self.assertEqual(self.source.__grefcount__, 1)
585         self.assertEqual(self.target.__grefcount__, 1)
586
587         # Use GObject.get_property because the "props" accessor leaks.
588         # Note property names are canonicalized.
589         self.assertEqual(binding.get_property('source'), self.source)
590         self.assertEqual(binding.get_property('source_property'), 'int-prop')
591         self.assertEqual(binding.get_property('target'), self.target)
592         self.assertEqual(binding.get_property('target_property'), 'int-prop')
593         self.assertEqual(binding.get_property('flags'), GObject.BindingFlags.DEFAULT)
594
595         # Delete reference to source or target and the binding will remove its own
596         # "self reference".
597         ref = self.source.weak_ref()
598         del self.source
599         gc.collect()
600         self.assertEqual(ref(), None)
601         self.assertEqual(binding.__grefcount__, 1)
602
603         # Finally clear out the last ref held by the python wrapper
604         ref = binding.weak_ref()
605         del binding
606         gc.collect()
607         self.assertEqual(ref(), None)
608
609
610 class TestGValue(unittest.TestCase):
611     def test_type_constant(self):
612         self.assertEqual(GObject.TYPE_VALUE, GObject.Value.__gtype__)
613         self.assertEqual(GObject.type_name(GObject.TYPE_VALUE), 'GValue')
614
615     def test_no_type(self):
616         value = GObject.Value()
617         self.assertEqual(value.g_type, GObject.TYPE_INVALID)
618         self.assertRaises(TypeError, value.set_value, 23)
619         self.assertEqual(value.get_value(), None)
620
621     def test_int(self):
622         value = GObject.Value(GObject.TYPE_UINT)
623         self.assertEqual(value.g_type, GObject.TYPE_UINT)
624         value.set_value(23)
625         self.assertEqual(value.get_value(), 23)
626         value.set_value(42.0)
627         self.assertEqual(value.get_value(), 42)
628
629     def test_string(self):
630         value = GObject.Value(str, 'foo_bar')
631         self.assertEqual(value.g_type, GObject.TYPE_STRING)
632         self.assertEqual(value.get_value(), 'foo_bar')
633
634     def test_float(self):
635         # python float is G_TYPE_DOUBLE
636         value = GObject.Value(float, 23.4)
637         self.assertEqual(value.g_type, GObject.TYPE_DOUBLE)
638         value.set_value(1e50)
639         self.assertAlmostEqual(value.get_value(), 1e50)
640
641         value = GObject.Value(GObject.TYPE_FLOAT, 23.4)
642         self.assertEqual(value.g_type, GObject.TYPE_FLOAT)
643         self.assertRaises(TypeError, value.set_value, 'string')
644         self.assertRaises(OverflowError, value.set_value, 1e50)
645
646     def test_float_inf_nan(self):
647         nan = float('nan')
648         for type_ in [GObject.TYPE_FLOAT, GObject.TYPE_DOUBLE]:
649             for x in [float('inf'), float('-inf'), nan]:
650                 value = GObject.Value(type_, x)
651                 # assertEqual() is False for (nan, nan)
652                 if x is nan:
653                     self.assertEqual(str(value.get_value()), 'nan')
654                 else:
655                     self.assertEqual(value.get_value(), x)
656
657     def test_enum(self):
658         value = GObject.Value(GLib.FileError, GLib.FileError.FAILED)
659         self.assertEqual(value.get_value(), GLib.FileError.FAILED)
660
661     def test_flags(self):
662         value = GObject.Value(GLib.IOFlags, GLib.IOFlags.IS_READABLE)
663         self.assertEqual(value.get_value(), GLib.IOFlags.IS_READABLE)
664
665     def test_object(self):
666         class TestObject(GObject.Object):
667             pass
668         obj = TestObject()
669         value = GObject.Value(GObject.TYPE_OBJECT, obj)
670         self.assertEqual(value.get_value(), obj)
671
672     def test_value_array(self):
673         value = GObject.Value(GObject.ValueArray)
674         self.assertEqual(value.g_type, GObject.type_from_name('GValueArray'))
675         value.set_value([32, 'foo_bar', 0.3])
676         self.assertEqual(value.get_value(), [32, 'foo_bar', 0.3])
677
678     def test_gerror_boxing(self):
679         error = GLib.Error('test message', domain='mydomain', code=42)
680         value = GObject.Value(GLib.Error, error)
681         self.assertEqual(value.g_type, GObject.type_from_name('GError'))
682
683         unboxed = value.get_value()
684         self.assertEqual(unboxed.message, error.message)
685         self.assertEqual(unboxed.domain, error.domain)
686         self.assertEqual(unboxed.code, error.code)
687
688     def test_gerror_novalue(self):
689         error = GLib.Error('test message', domain='mydomain', code=42)
690         value = GObject.Value(GLib.Error)
691         self.assertEqual(value.g_type, GObject.type_from_name('GError'))
692         self.assertEqual(value.get_value(), None)
693
694
695 if __name__ == '__main__':
696     unittest.main()