test_everything.py 29.9 KB
Newer Older
Tomeu Vizoso's avatar
Tomeu Vizoso committed
1
# -*- Mode: Python; py-indent-offset: 4 -*-
2
# coding=utf-8
Tomeu Vizoso's avatar
Tomeu Vizoso committed
3
4
5
# vim: tabstop=4 shiftwidth=4 expandtab

import unittest
6
import traceback
7
8
9
import warnings
import gc
gc
Tomeu Vizoso's avatar
Tomeu Vizoso committed
10
11

import sys
12
from sys import getrefcount
Tomeu Vizoso's avatar
Tomeu Vizoso committed
13

14
import copy
15
16
17
try:
    import cairo
    has_cairo = True
18
    from gi.repository import Regress as Everything
19
20
except ImportError:
    has_cairo = False
Tomeu Vizoso's avatar
Tomeu Vizoso committed
21

22
#import gi
23
from gi.repository import GObject
24
from gi.repository import GLib
25
from gi.repository import Gio
Tomeu Vizoso's avatar
Tomeu Vizoso committed
26

27
28
29
30
31
32
try:
    from gi.repository import Gtk
    Gtk  # pyflakes
except:
    Gtk = None

33
34
35
36
37
38
39
if sys.version_info < (3, 0):
    UNICHAR = "\xe2\x99\xa5"
    PY2_UNICODE_UNICHAR = unicode(UNICHAR, 'UTF-8')
else:
    UNICHAR = "鈾"


40
@unittest.skipUnless(has_cairo, 'built without cairo support')
Tomeu Vizoso's avatar
Tomeu Vizoso committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class TestEverything(unittest.TestCase):

    def test_cairo_context(self):
        context = Everything.test_cairo_context_full_return()
        self.assertTrue(isinstance(context, cairo.Context))

        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
        context = cairo.Context(surface)
        Everything.test_cairo_context_none_in(context)

    def test_cairo_surface(self):
        surface = Everything.test_cairo_surface_none_return()
        self.assertTrue(isinstance(surface, cairo.ImageSurface))
        self.assertTrue(isinstance(surface, cairo.Surface))
55
56
57
        self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32)
        self.assertEqual(surface.get_width(), 10)
        self.assertEqual(surface.get_height(), 10)
Tomeu Vizoso's avatar
Tomeu Vizoso committed
58
59
60
61

        surface = Everything.test_cairo_surface_full_return()
        self.assertTrue(isinstance(surface, cairo.ImageSurface))
        self.assertTrue(isinstance(surface, cairo.Surface))
62
63
64
        self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32)
        self.assertEqual(surface.get_width(), 10)
        self.assertEqual(surface.get_height(), 10)
Tomeu Vizoso's avatar
Tomeu Vizoso committed
65
66
67
68
69
70
71

        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10)
        Everything.test_cairo_surface_none_in(surface)

        surface = Everything.test_cairo_surface_full_out()
        self.assertTrue(isinstance(surface, cairo.ImageSurface))
        self.assertTrue(isinstance(surface, cairo.Surface))
72
73
74
        self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32)
        self.assertEqual(surface.get_width(), 10)
        self.assertEqual(surface.get_height(), 10)
Tomeu Vizoso's avatar
Tomeu Vizoso committed
75

Paolo Borelli's avatar
Paolo Borelli committed
76
    def test_unichar(self):
77
        self.assertEqual("c", Everything.test_unichar("c"))
78
79

        if sys.version_info < (3, 0):
80
81
            self.assertEqual(UNICHAR, Everything.test_unichar(PY2_UNICODE_UNICHAR))
        self.assertEqual(UNICHAR, Everything.test_unichar(UNICHAR))
82
83
        self.assertRaises(TypeError, Everything.test_unichar, "")
        self.assertRaises(TypeError, Everything.test_unichar, "morethanonechar")
84

85
    def test_floating(self):
86
        e = Everything.TestFloating()
87
        self.assertEqual(e.__grefcount__, 1)
88
89

        e = GObject.new(Everything.TestFloating)
90
        self.assertEqual(e.__grefcount__, 1)
91
92

        e = Everything.TestFloating.new()
93
        self.assertEqual(e.__grefcount__, 1)
94

95
96
97
98
99
100
101
102
103
    def test_caller_allocates(self):
        struct_a = Everything.TestStructA()
        struct_a.some_int = 10
        struct_a.some_int8 = 21
        struct_a.some_double = 3.14
        struct_a.some_enum = Everything.TestEnum.VALUE3

        struct_a_clone = struct_a.clone()
        self.assertTrue(struct_a != struct_a_clone)
104
105
106
107
        self.assertEqual(struct_a.some_int, struct_a_clone.some_int)
        self.assertEqual(struct_a.some_int8, struct_a_clone.some_int8)
        self.assertEqual(struct_a.some_double, struct_a_clone.some_double)
        self.assertEqual(struct_a.some_enum, struct_a_clone.some_enum)
108
109
110
111
112
113
114
115
116
117

        struct_b = Everything.TestStructB()
        struct_b.some_int8 = 8
        struct_b.nested_a.some_int = 20
        struct_b.nested_a.some_int8 = 12
        struct_b.nested_a.some_double = 333.3333
        struct_b.nested_a.some_enum = Everything.TestEnum.VALUE2

        struct_b_clone = struct_b.clone()
        self.assertTrue(struct_b != struct_b_clone)
118
119
120
121
122
        self.assertEqual(struct_b.some_int8, struct_b_clone.some_int8)
        self.assertEqual(struct_b.nested_a.some_int, struct_b_clone.nested_a.some_int)
        self.assertEqual(struct_b.nested_a.some_int8, struct_b_clone.nested_a.some_int8)
        self.assertEqual(struct_b.nested_a.some_double, struct_b_clone.nested_a.some_double)
        self.assertEqual(struct_b.nested_a.some_enum, struct_b_clone.nested_a.some_enum)
123

124
125
126
    def test_wrong_type_of_arguments(self):
        try:
            Everything.test_int8()
127
128
        except TypeError:
            (e_type, e) = sys.exc_info()[:2]
129
            self.assertEqual(e.args, ("test_int8() takes exactly 1 argument (0 given)",))
130

131
132
133
    def test_gtypes(self):
        gchararray_gtype = GObject.type_from_name('gchararray')
        gtype = Everything.test_gtype(str)
134
        self.assertEqual(gchararray_gtype, gtype)
135
        gtype = Everything.test_gtype('gchararray')
136
        self.assertEqual(gchararray_gtype, gtype)
137
138
        gobject_gtype = GObject.GObject.__gtype__
        gtype = Everything.test_gtype(GObject.GObject)
139
        self.assertEqual(gobject_gtype, gtype)
140
        gtype = Everything.test_gtype('GObject')
141
        self.assertEqual(gobject_gtype, gtype)
142
143
144
145
146
147
148
149
150
151
152
        self.assertRaises(TypeError, Everything.test_gtype, 'invalidgtype')

        class NotARegisteredClass(object):
            pass

        self.assertRaises(TypeError, Everything.test_gtype, NotARegisteredClass)

        class ARegisteredClass(GObject.GObject):
            __gtype_name__ = 'EverythingTestsARegisteredClass'

        gtype = Everything.test_gtype('EverythingTestsARegisteredClass')
153
        self.assertEqual(ARegisteredClass.__gtype__, gtype)
154
        gtype = Everything.test_gtype(ARegisteredClass)
155
        self.assertEqual(ARegisteredClass.__gtype__, gtype)
156
        self.assertRaises(TypeError, Everything.test_gtype, 'ARegisteredClass')
157

158
159
    def test_dir(self):
        attr_list = dir(Everything)
160

161
162
        # test that typelib attributes are listed
        self.assertTrue('TestStructA' in attr_list)
163

164
165
166
167
        # test that class attributes and methods are listed
        self.assertTrue('__class__' in attr_list)
        self.assertTrue('__dir__' in attr_list)
        self.assertTrue('__repr__' in attr_list)
168

169
170
        # test that instance members are listed
        self.assertTrue('_namespace' in attr_list)
171
        self.assertTrue('_version' in attr_list)
172

173
174
        # test that there are no duplicates returned
        self.assertEqual(len(attr_list), len(set(attr_list)))
175

Xavier Claessens's avatar
Xavier Claessens committed
176
    def test_ptrarray(self):
177
178
        # transfer container
        result = Everything.test_garray_container_return()
179
        self.assertEqual(result, ['regress'])
180
181
182
183
        result = None

        # transfer full
        result = Everything.test_garray_full_return()
184
        self.assertEqual(result, ['regress'])
185
        result = None
Xavier Claessens's avatar
Xavier Claessens committed
186

187
188
    def test_hash_return(self):
        result = Everything.test_ghash_gvalue_return()
189
190
191
        self.assertEqual(result['integer'], 12)
        self.assertEqual(result['boolean'], True)
        self.assertEqual(result['string'], 'some text')
192
        self.assertEqual(result['strings'], ['first', 'second', 'third'])
193
194
        self.assertEqual(result['flags'], Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3)
        self.assertEqual(result['enum'], Everything.TestEnum.VALUE2)
195
196
        result = None

197
    def test_hash_in(self):
198
199
200
        # specifying a simple string array for "strings" does not work due to
        # https://bugzilla.gnome.org/show_bug.cgi?id=666636
        # workaround by explicitly building a GStrv object
201
        class GStrv(list):
Martin Pitt's avatar
Martin Pitt committed
202
            __gtype__ = GObject.TYPE_STRV
203

204
205
206
207
208
209
210
        data = {'integer': 12,
                'boolean': True,
                'string': 'some text',
                'strings': GStrv(['first', 'second', 'third']),
                'flags': Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3,
                'enum': Everything.TestEnum.VALUE2,
               }
211
212
        Everything.test_ghash_gvalue_in(data)
        data = None
213

214
215
216
217
218
219
220
221
222
223
    def test_struct_gpointer(self):
        l1 = GLib.List()
        self.assertEqual(l1.data, None)
        init_refcount = getrefcount(l1)

        l1.data = 'foo'
        self.assertEqual(l1.data, 'foo')

        l2 = l1
        self.assertEqual(l1.data, l2.data)
224
        self.assertEqual(getrefcount(l1), init_refcount + 1)
225
226
227
228
229
230

        l3 = copy.copy(l1)
        l3.data = 'bar'
        self.assertEqual(l1.data, 'foo')
        self.assertEqual(l2.data, 'foo')
        self.assertEqual(l3.data, 'bar')
231
232
        self.assertEqual(getrefcount(l1), init_refcount + 1)
        self.assertEqual(getrefcount(l3), init_refcount)
233

234
235
236
237
238
    def test_struct_opaque(self):
        # we should get a sensible error message
        try:
            Everything.TestBoxedPrivate()
            self.fail('allocating disguised struct without default constructor unexpectedly succeeded')
239
240
241
242
243
244
245
        except TypeError:
            (e_type, e_value, e_tb) = sys.exc_info()
            self.assertEqual(e_type, TypeError)
            self.assertTrue('TestBoxedPrivate' in str(e_value), str(e_value))
            self.assertTrue('override' in str(e_value), str(e_value))
            self.assertTrue('constructor' in str(e_value), str(e_value))
            tb = ''.join(traceback.format_exception(e_type, e_value, e_tb))
246
247
            self.assertTrue('tests/test_everything.py", line' in tb, tb)

248

249
@unittest.skipUnless(has_cairo, 'built without cairo support')
250
251
252
253
254
255
256
class TestNullableArgs(unittest.TestCase):
    def test_in_nullable_hash(self):
        Everything.test_ghash_null_in(None)

    def test_in_nullable_list(self):
        Everything.test_gslist_null_in(None)
        Everything.test_glist_null_in(None)
257
258
        Everything.test_gslist_null_in([])
        Everything.test_glist_null_in([])
259
260

    def test_in_nullable_array(self):
261
        Everything.test_array_int_null_in(None)
262
        Everything.test_array_int_null_in([])
263
264
265
266

    def test_in_nullable_string(self):
        Everything.test_utf8_null_in(None)

267
    def test_in_nullable_object(self):
268
        Everything.func_obj_null_in(None)
269

270
271
272
273
    def test_out_nullable_hash(self):
        self.assertEqual(None, Everything.test_ghash_null_out())

    def test_out_nullable_list(self):
274
275
        self.assertEqual([], Everything.test_gslist_null_out())
        self.assertEqual([], Everything.test_glist_null_out())
276
277

    def test_out_nullable_array(self):
278
        self.assertEqual([], Everything.test_array_int_null_out())
279
280
281
282

    def test_out_nullable_string(self):
        self.assertEqual(None, Everything.test_utf8_null_out())

283
    def test_out_nullable_object(self):
284
        self.assertEqual(None, Everything.TestObj.null_out())
285

286

287
@unittest.skipUnless(has_cairo, 'built without cairo support')
288
289
class TestCallbacks(unittest.TestCase):
    called = False
290
    main_loop = GLib.MainLoop()
Tomeu Vizoso's avatar
Tomeu Vizoso committed
291

292
    def test_callback(self):
293
        TestCallbacks.called = False
294

295
296
        def callback():
            TestCallbacks.called = True
297

298
299
300
        Everything.test_simple_callback(callback)
        self.assertTrue(TestCallbacks.called)

301
    def test_callback_exception(self):
302
303
304
305
306
307
        """
        This test ensures that we get errors from callbacks correctly
        and in particular that we do not segv when callbacks fail
        """
        def callback():
            x = 1 / 0
308
            self.fail('unexpected surviving zero divsion:' + str(x))
309

310
311
312
313
        # note that we do NOT expect the ZeroDivisionError to be propagated
        # through from the callback, as it crosses the Python<->C boundary
        # twice. (See GNOME #616279)
        Everything.test_simple_callback(callback)
314

315
    def test_double_callback_exception(self):
316
317
318
319
320
321
        """
        This test ensures that we get errors from callbacks correctly
        and in particular that we do not segv when callbacks fail
        """
        def badcallback():
            x = 1 / 0
322
            self.fail('unexpected surviving zero divsion:' + str(x))
323
324
325
326
327
328

        def callback():
            Everything.test_boolean(True)
            Everything.test_boolean(False)
            Everything.test_simple_callback(badcallback())

329
330
331
332
        # note that we do NOT expect the ZeroDivisionError to be propagated
        # through from the callback, as it crosses the Python<->C boundary
        # twice. (See GNOME #616279)
        Everything.test_simple_callback(callback)
333

334
    def test_return_value_callback(self):
335
        TestCallbacks.called = False
336

337
338
339
340
        def callback():
            TestCallbacks.called = True
            return 44

341
        self.assertEqual(Everything.test_callback(callback), 44)
342
        self.assertTrue(TestCallbacks.called)
343

344
    def test_callback_scope_async(self):
345
        TestCallbacks.called = False
346
        ud = 'Test Value 44'
347

348
349
        def callback(user_data):
            self.assertEqual(user_data, ud)
350
            TestCallbacks.called = True
351
352
353
354
            return 44

        ud_refcount = sys.getrefcount(ud)
        callback_refcount = sys.getrefcount(callback)
355

356
357
358
359
360
361
362
363
364
        self.assertEqual(Everything.test_callback_async(callback, ud), None)
        # Callback should not have run and the ref count is increased by 1
        self.assertEqual(TestCallbacks.called, False)
        self.assertEqual(sys.getrefcount(callback), callback_refcount + 1)
        self.assertEqual(sys.getrefcount(ud), ud_refcount + 1)

        # test_callback_thaw_async will run the callback previously supplied.
        # references should be auto decremented after this call.
        self.assertEqual(Everything.test_callback_thaw_async(), 44)
365
        self.assertTrue(TestCallbacks.called)
366

367
368
369
370
371
372
373
        # Make sure refcounts are returned to normal
        self.assertEqual(sys.getrefcount(callback), callback_refcount)
        self.assertEqual(sys.getrefcount(ud), ud_refcount)

    def test_callback_scope_call_multi(self):
        # This tests a callback that gets called multiple times from a
        # single scope call in python.
374
        TestCallbacks.called = 0
375

376
377
378
379
        def callback():
            TestCallbacks.called += 1
            return 0

380
        refcount = sys.getrefcount(callback)
381
        Everything.test_multi_callback(callback)
382
        self.assertEqual(TestCallbacks.called, 2)
383
        self.assertEqual(sys.getrefcount(callback), refcount)
384

385
    def test_callback_userdata(self):
386
        TestCallbacks.called = 0
387

388
        def callback(userdata):
389
            self.assertEqual(userdata, "Test%d" % TestCallbacks.called)
390
391
            TestCallbacks.called += 1
            return TestCallbacks.called
392

393
394
        for i in range(100):
            val = Everything.test_callback_user_data(callback, "Test%d" % i)
395
            self.assertEqual(val, i + 1)
396

397
        self.assertEqual(TestCallbacks.called, 100)
Tomeu Vizoso's avatar
Tomeu Vizoso committed
398

399
    def test_async_ready_callback(self):
Tomeu Vizoso's avatar
Tomeu Vizoso committed
400
        TestCallbacks.called = False
401
        TestCallbacks.main_loop = GLib.MainLoop()
Tomeu Vizoso's avatar
Tomeu Vizoso committed
402
403
404
405
406
407
408
409
410
411

        def callback(obj, result, user_data):
            TestCallbacks.main_loop.quit()
            TestCallbacks.called = True

        Everything.test_async_ready_callback(callback)

        TestCallbacks.main_loop.run()

        self.assertTrue(TestCallbacks.called)
Tomeu Vizoso's avatar
Tomeu Vizoso committed
412

413
414
415
416
    def test_callback_scope_notified_with_destroy(self):
        TestCallbacks.called = 0
        ud = 'Test scope notified data 33'

Tomeu Vizoso's avatar
Tomeu Vizoso committed
417
        def callback(user_data):
418
419
420
            self.assertEqual(user_data, ud)
            TestCallbacks.called += 1
            return 33
Tomeu Vizoso's avatar
Tomeu Vizoso committed
421

422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
        value_refcount = sys.getrefcount(ud)
        callback_refcount = sys.getrefcount(callback)

        # Callback is immediately called.
        for i in range(100):
            res = Everything.test_callback_destroy_notify(callback, ud)
            self.assertEqual(res, 33)

        self.assertEqual(TestCallbacks.called, 100)
        self.assertEqual(sys.getrefcount(callback), callback_refcount + 100)
        self.assertEqual(sys.getrefcount(ud), value_refcount + 100)

        # thaw will call the callback again, this time resources should be freed
        self.assertEqual(Everything.test_callback_thaw_notifications(), 33 * 100)
        self.assertEqual(TestCallbacks.called, 200)
        self.assertEqual(sys.getrefcount(callback), callback_refcount)
        self.assertEqual(sys.getrefcount(ud), value_refcount)

    def test_callback_scope_notified_with_destroy_no_user_data(self):
        TestCallbacks.called = 0

        def callback(user_data):
            self.assertEqual(user_data, None)
            TestCallbacks.called += 1
            return 34

        callback_refcount = sys.getrefcount(callback)

        # Run with warning as exception
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("error")
            self.assertRaises(RuntimeWarning,
                              Everything.test_callback_destroy_notify_no_user_data,
                              callback)

        self.assertEqual(TestCallbacks.called, 0)
        self.assertEqual(sys.getrefcount(callback), callback_refcount)

        # Run with warning as warning
        with warnings.catch_warnings(record=True) as w:
            # Cause all warnings to always be triggered.
            warnings.simplefilter("default")
            # Trigger a warning.
            res = Everything.test_callback_destroy_notify_no_user_data(callback)
            # Verify some things
            self.assertEqual(len(w), 1)
            self.assertTrue(issubclass(w[-1].category, RuntimeWarning))
            self.assertTrue('Callables passed to' in str(w[-1].message))

        self.assertEqual(res, 34)
        self.assertEqual(TestCallbacks.called, 1)
        self.assertEqual(sys.getrefcount(callback), callback_refcount + 1)

        # thaw will call the callback again,
        # refcount will not go down without user_data parameter
        self.assertEqual(Everything.test_callback_thaw_notifications(), 34)
        self.assertEqual(TestCallbacks.called, 2)
        self.assertEqual(sys.getrefcount(callback), callback_refcount + 1)
480

481
    def test_callback_in_methods(self):
482
483
484
485
        object_ = Everything.TestObj()

        def callback():
            TestCallbacks.called = True
486
            return 42
487
488
489
490
491
492
493
494
495
496

        TestCallbacks.called = False
        object_.instance_method_callback(callback)
        self.assertTrue(TestCallbacks.called)

        TestCallbacks.called = False
        Everything.TestObj.static_method_callback(callback)
        self.assertTrue(TestCallbacks.called)

        def callbackWithUserData(user_data):
497
            TestCallbacks.called += 1
498
            return 42
499

500
        TestCallbacks.called = 0
501
        Everything.TestObj.new_callback(callbackWithUserData, None)
502
503
504
505
506
507
        self.assertEqual(TestCallbacks.called, 1)
        # Note: using "new_callback" adds the notification to the same global
        # list as Everything.test_callback_destroy_notify, so thaw the list
        # so we don't get confusion between tests.
        self.assertEqual(Everything.test_callback_thaw_notifications(), 42)
        self.assertEqual(TestCallbacks.called, 2)
508

509
    def test_callback_none(self):
510
        # make sure this doesn't assert or crash
511
        Everything.test_simple_callback(None)
512

513
    def test_callback_gerror(self):
514
515
516
517
518
519
520
521
522
523
        def callback(error):
            self.assertEqual(error.message, 'regression test error')
            self.assertTrue('g-io' in error.domain)
            self.assertEqual(error.code, Gio.IOErrorEnum.NOT_SUPPORTED)
            TestCallbacks.called = True

        TestCallbacks.called = False
        Everything.test_gerror_callback(callback)
        self.assertTrue(TestCallbacks.called)

524
525
526
527
528
529
530
531
532
    def test_callback_null_gerror(self):
        def callback(error):
            self.assertEqual(error, None)
            TestCallbacks.called = True

        TestCallbacks.called = False
        Everything.test_null_gerror_callback(callback)
        self.assertTrue(TestCallbacks.called)

533
    def test_callback_owned_gerror(self):
534
535
536
537
538
539
540
541
542
543
        def callback(error):
            self.assertEqual(error.message, 'regression test owned error')
            self.assertTrue('g-io' in error.domain)
            self.assertEqual(error.code, Gio.IOErrorEnum.PERMISSION_DENIED)
            TestCallbacks.called = True

        TestCallbacks.called = False
        Everything.test_owned_gerror_callback(callback)
        self.assertTrue(TestCallbacks.called)

544
    def test_callback_hashtable(self):
545
546
547
548
549
        def callback(data):
            self.assertEqual(data, mydict)
            mydict['new'] = 42
            TestCallbacks.called = True

550
        mydict = {'foo': 1, 'bar': 2}
551
552
553
        TestCallbacks.called = False
        Everything.test_hash_table_callback(mydict, callback)
        self.assertTrue(TestCallbacks.called)
554
555
        self.assertEqual(mydict, {'foo': 1, 'bar': 2, 'new': 42})

556

557
@unittest.skipUnless(has_cairo, 'built without cairo support')
Martin Pitt's avatar
Martin Pitt committed
558
559
560
561
class TestClosures(unittest.TestCase):
    def test_int_arg(self):
        def callback(num):
            self.called = True
562
            return num + 1
Martin Pitt's avatar
Martin Pitt committed
563
564
565
566
567
568
569
570
571

        self.called = False
        result = Everything.test_closure_one_arg(callback, 42)
        self.assertTrue(self.called)
        self.assertEqual(result, 43)

    def test_variant(self):
        def callback(variant):
            self.called = True
572
573
574
            if variant is None:
                return None
            self.assertEqual(variant.get_type_string(), 'i')
Martin Pitt's avatar
Martin Pitt committed
575
576
577
578
579
580
581
            return GLib.Variant('i', variant.get_int32() + 1)

        self.called = False
        result = Everything.test_closure_variant(callback, GLib.Variant('i', 42))
        self.assertTrue(self.called)
        self.assertEqual(result.get_type_string(), 'i')
        self.assertEqual(result.get_int32(), 43)
582

583
584
585
586
587
588
589
590
591
        self.called = False
        result = Everything.test_closure_variant(callback, None)
        self.assertTrue(self.called)
        self.assertEqual(result, None)

        self.called = False
        self.assertRaises(TypeError, Everything.test_closure_variant, callback, 'foo')
        self.assertFalse(self.called)

592

593
@unittest.skipUnless(has_cairo, 'built without cairo support')
594
595
class TestProperties(unittest.TestCase):

596
597
598
    def test_basic(self):
        object_ = Everything.TestObj()

599
        self.assertEqual(object_.props.int, 0)
600
601
        object_.props.int = 42
        self.assertTrue(isinstance(object_.props.int, int))
602
        self.assertEqual(object_.props.int, 42)
603

604
        self.assertEqual(object_.props.float, 0.0)
605
606
        object_.props.float = 42.42
        self.assertTrue(isinstance(object_.props.float, float))
Martin Pitt's avatar
Martin Pitt committed
607
        self.assertAlmostEqual(object_.props.float, 42.42, places=5)
608

609
        self.assertEqual(object_.props.double, 0.0)
610
611
        object_.props.double = 42.42
        self.assertTrue(isinstance(object_.props.double, float))
Martin Pitt's avatar
Martin Pitt committed
612
        self.assertAlmostEqual(object_.props.double, 42.42, places=5)
613

614
        self.assertEqual(object_.props.string, None)
615
616
        object_.props.string = 'mec'
        self.assertTrue(isinstance(object_.props.string, str))
617
        self.assertEqual(object_.props.string, 'mec')
618

619
        self.assertEqual(object_.props.gtype, GObject.TYPE_INVALID)
620
        object_.props.gtype = int
621
        self.assertEqual(object_.props.gtype, GObject.TYPE_INT)
622

623
624
    def test_hash_table(self):
        object_ = Everything.TestObj()
625
        self.assertEqual(object_.props.hash_table, None)
626
627
628

        object_.props.hash_table = {'mec': 56}
        self.assertTrue(isinstance(object_.props.hash_table, dict))
629
        self.assertEqual(list(object_.props.hash_table.items())[0], ('mec', 56))
630
631
632

    def test_list(self):
        object_ = Everything.TestObj()
633
        self.assertEqual(object_.props.list, [])
634
635
636

        object_.props.list = ['1', '2', '3']
        self.assertTrue(isinstance(object_.props.list, list))
637
        self.assertEqual(object_.props.list, ['1', '2', '3'])
638
639
640

    def test_boxed(self):
        object_ = Everything.TestObj()
641
        self.assertEqual(object_.props.boxed, None)
642
643
644
645
646
647

        boxed = Everything.TestBoxed()
        boxed.some_int8 = 42
        object_.props.boxed = boxed

        self.assertTrue(isinstance(object_.props.boxed, Everything.TestBoxed))
648
        self.assertEqual(object_.props.boxed.some_int8, 42)
649

Jasper St. Pierre's avatar
Jasper St. Pierre committed
650
651
652
653
654
655
656
657
    def test_boxed_equality(self):
        boxed = Everything.TestBoxedC()
        # TestBoxedC uses refcounting, so we know that
        # the pointer is the same when copied
        copy = boxed.copy()
        self.assertEqual(boxed, copy)
        self.assertNotEqual(id(boxed), id(copy))

658
659
    def test_gtype(self):
        object_ = Everything.TestObj()
660
        self.assertEqual(object_.props.gtype, GObject.TYPE_INVALID)
661
        object_.props.gtype = int
662
        self.assertEqual(object_.props.gtype, GObject.TYPE_INT)
663

Martin Pitt's avatar
Martin Pitt committed
664
        object_ = Everything.TestObj(gtype=int)
665
        self.assertEqual(object_.props.gtype, GObject.TYPE_INT)
666
        object_.props.gtype = str
667
        self.assertEqual(object_.props.gtype, GObject.TYPE_STRING)
668

669
670
671
672
673
674
675
676
677
678
679
680
    def test_parent_class(self):
        class A(Everything.TestObj):
            prop1 = GObject.Property(type=int)

        a = A()
        a.props.int = 20
        self.assertEqual(a.props.int, 20)

        # test parent property which needs introspection
        a.props.list = ("str1", "str2")
        self.assertEqual(a.props.list, ["str1", "str2"])

681

682
@unittest.skipUnless(has_cairo, 'built without cairo support')
683
684
685
686
687
688
689
690
691
692
class TestTortureProfile(unittest.TestCase):
    def test_torture_profile(self):
        import time
        total_time = 0
        print("")
        object_ = Everything.TestObj()
        sys.stdout.write("\ttorture test 1 (10000 iterations): ")

        start_time = time.clock()
        for i in range(10000):
693
694
695
            (y, z, q) = object_.torture_signature_0(5000,
                                                    "Torture Test 1",
                                                    12345)
696
697
698
699
700
701
702
703
704
705

        end_time = time.clock()
        delta_time = end_time - start_time
        total_time += delta_time
        print("%f secs" % delta_time)

        sys.stdout.write("\ttorture test 2 (10000 iterations): ")

        start_time = time.clock()
        for i in range(10000):
706
707
            (y, z, q) = Everything.TestObj().torture_signature_0(
                5000, "Torture Test 2", 12345)
708
709
710
711
712
713
714
715
716
717

        end_time = time.clock()
        delta_time = end_time - start_time
        total_time += delta_time
        print("%f secs" % delta_time)

        sys.stdout.write("\ttorture test 3 (10000 iterations): ")
        start_time = time.clock()
        for i in range(10000):
            try:
718
719
                (y, z, q) = object_.torture_signature_1(
                    5000, "Torture Test 3", 12345)
720
721
722
723
724
725
726
727
            except:
                pass
        end_time = time.clock()
        delta_time = end_time - start_time
        total_time += delta_time
        print("%f secs" % delta_time)

        sys.stdout.write("\ttorture test 4 (10000 iterations): ")
728

729
730
731
        def callback(userdata):
            pass

732
        userdata = [1, 2, 3, 4]
733
734
        start_time = time.clock()
        for i in range(10000):
735
736
            (y, z, q) = Everything.test_torture_signature_2(
                5000, callback, userdata, "Torture Test 4", 12345)
737
738
739
740
741
742
743
        end_time = time.clock()
        delta_time = end_time - start_time
        total_time += delta_time
        print("%f secs" % delta_time)
        print("\t====")
        print("\tTotal: %f sec" % total_time)

744

745
@unittest.skipUnless(has_cairo, 'built without cairo support')
746
747
748
749
750
751
class TestAdvancedInterfaces(unittest.TestCase):
    def test_array_objs(self):
        obj1, obj2 = Everything.test_array_fixed_out_objects()
        self.assertTrue(isinstance(obj1, Everything.TestObj))
        self.assertTrue(isinstance(obj2, Everything.TestObj))
        self.assertNotEqual(obj1, obj2)
752
753

    def test_obj_skip_return_val(self):
Johan Dahlin's avatar
Johan Dahlin committed
754
755
        obj = Everything.TestObj()
        ret = obj.skip_return_val(50, 42.0, 60, 2, 3)
756
757
758
759
        self.assertEqual(len(ret), 3)
        self.assertEqual(ret[0], 51)
        self.assertEqual(ret[1], 61)
        self.assertEqual(ret[2], 32)
760

761
    def test_obj_skip_return_val_no_out(self):
Johan Dahlin's avatar
Johan Dahlin committed
762
        obj = Everything.TestObj()
763
764
765
766
        # raises an error for 0, succeeds for any other value
        self.assertRaises(GLib.GError, obj.skip_return_val_no_out, 0)

        ret = obj.skip_return_val_no_out(1)
767
        self.assertEqual(ret, None)
768

769

770
@unittest.skipUnless(has_cairo, 'built without cairo support')
771
772
class TestSignals(unittest.TestCase):
    def test_object_param_signal(self):
Johan Dahlin's avatar
Johan Dahlin committed
773
        obj = Everything.TestObj()
774

775
        def callback(obj, obj_param):
776
            self.assertEqual(obj_param.props.int, 3)
777
            self.assertGreater(obj_param.__grefcount__, 1)
778
            obj.called = True
779

780
        obj.called = False
781
782
        obj.connect('sig-with-obj', callback)
        obj.emit_sig_with_obj()
783
        self.assertTrue(obj.called)
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
    def test_int64_param_from_py(self):
        obj = Everything.TestObj()

        def callback(obj, i):
            obj.callback_i = i
            return i

        obj.callback_i = None
        obj.connect('sig-with-int64-prop', callback)
        rv = obj.emit('sig-with-int64-prop', GObject.G_MAXINT64)
        self.assertEqual(rv, GObject.G_MAXINT64)
        self.assertEqual(obj.callback_i, GObject.G_MAXINT64)

    def test_uint64_param_from_py(self):
        obj = Everything.TestObj()

        def callback(obj, i):
            obj.callback_i = i
            return i

        obj.callback_i = None
        obj.connect('sig-with-uint64-prop', callback)
        rv = obj.emit('sig-with-uint64-prop', GObject.G_MAXUINT64)
        self.assertEqual(rv, GObject.G_MAXUINT64)
        self.assertEqual(obj.callback_i, GObject.G_MAXUINT64)

    def test_int64_param_from_c(self):
        obj = Everything.TestObj()

        def callback(obj, i):
            obj.callback_i = i
            return i

        obj.callback_i = None

        obj.connect('sig-with-int64-prop', callback)
        obj.emit_sig_with_int64()
        self.assertEqual(obj.callback_i, GObject.G_MAXINT64)

    def test_uint64_param_from_c(self):
        obj = Everything.TestObj()

        def callback(obj, i):
            obj.callback_i = i
            return i

        obj.callback_i = None

        obj.connect('sig-with-uint64-prop', callback)
        obj.emit_sig_with_uint64()
        self.assertEqual(obj.callback_i, GObject.G_MAXUINT64)

837

838
839
@unittest.skipUnless(has_cairo, 'built without cairo support')
@unittest.skipUnless(Gtk, 'Gtk not available')
840
841
842
843
844
class TestPango(unittest.TestCase):
    def test_cairo_font_options(self):
        screen = Gtk.Window().get_screen()
        font_opts = screen.get_font_options()
        self.assertEqual(type(font_opts.get_subpixel_order()), int)