# -*- Mode: Python; py-indent-offset: 4 -*- # coding=utf-8 # vim: tabstop=4 shiftwidth=4 expandtab import unittest import traceback import ctypes import warnings import sys try: import cairo has_cairo = True from gi.repository import Regress as Everything except ImportError: has_cairo = False #import gi from gi.repository import GObject from gi.repository import GLib from gi.repository import Gio try: from gi.repository import Gtk Gtk # pyflakes except: Gtk = None if sys.version_info < (3, 0): UNICHAR = "\xe2\x99\xa5" PY2_UNICODE_UNICHAR = unicode(UNICHAR, 'UTF-8') else: UNICHAR = "♥" class RawGList(ctypes.Structure): _fields_ = [('data', ctypes.c_void_p), ('next', ctypes.c_void_p), ('prev', ctypes.c_void_p)] @classmethod def from_wrapped(cls, obj): offset = sys.getsizeof(object()) # size of PyObject_HEAD return ctypes.POINTER(cls).from_address(id(obj) + offset) @unittest.skipUnless(has_cairo, 'built without cairo support') 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)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) surface = Everything.test_cairo_surface_full_return() self.assertTrue(isinstance(surface, cairo.ImageSurface)) self.assertTrue(isinstance(surface, cairo.Surface)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) 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)) self.assertEqual(surface.get_format(), cairo.FORMAT_ARGB32) self.assertEqual(surface.get_width(), 10) self.assertEqual(surface.get_height(), 10) def test_bool(self): self.assertEqual(Everything.test_boolean(False), False) self.assertEqual(Everything.test_boolean(True), True) self.assertEqual(Everything.test_boolean('hello'), True) self.assertEqual(Everything.test_boolean(''), False) self.assertEqual(Everything.test_boolean_true(True), True) self.assertEqual(Everything.test_boolean_false(False), False) def test_int8(self): self.assertEqual(Everything.test_int8(GObject.G_MAXINT8), GObject.G_MAXINT8) self.assertEqual(Everything.test_int8(GObject.G_MININT8), GObject.G_MININT8) self.assertRaises(OverflowError, Everything.test_int8, GObject.G_MAXINT8 + 1) self.assertEqual(Everything.test_uint8(GObject.G_MAXUINT8), GObject.G_MAXUINT8) self.assertEqual(Everything.test_uint8(0), 0) self.assertRaises(OverflowError, Everything.test_uint8, -1) self.assertRaises(OverflowError, Everything.test_uint8, GObject.G_MAXUINT8 + 1) def test_int16(self): self.assertEqual(Everything.test_int16(GObject.G_MAXINT16), GObject.G_MAXINT16) self.assertEqual(Everything.test_int16(GObject.G_MININT16), GObject.G_MININT16) self.assertRaises(OverflowError, Everything.test_int16, GObject.G_MAXINT16 + 1) self.assertEqual(Everything.test_uint16(GObject.G_MAXUINT16), GObject.G_MAXUINT16) self.assertEqual(Everything.test_uint16(0), 0) self.assertRaises(OverflowError, Everything.test_uint16, -1) self.assertRaises(OverflowError, Everything.test_uint16, GObject.G_MAXUINT16 + 1) def test_int32(self): self.assertEqual(Everything.test_int32(GObject.G_MAXINT32), GObject.G_MAXINT32) self.assertEqual(Everything.test_int32(GObject.G_MININT32), GObject.G_MININT32) self.assertRaises(OverflowError, Everything.test_int32, GObject.G_MAXINT32 + 1) self.assertEqual(Everything.test_uint32(GObject.G_MAXUINT32), GObject.G_MAXUINT32) self.assertEqual(Everything.test_uint32(0), 0) self.assertRaises(OverflowError, Everything.test_uint32, -1) self.assertRaises(OverflowError, Everything.test_uint32, GObject.G_MAXUINT32 + 1) def test_int64(self): self.assertEqual(Everything.test_int64(GObject.G_MAXINT64), GObject.G_MAXINT64) self.assertEqual(Everything.test_int64(GObject.G_MININT64), GObject.G_MININT64) self.assertRaises(OverflowError, Everything.test_int64, GObject.G_MAXINT64 + 1) self.assertEqual(Everything.test_uint64(GObject.G_MAXUINT64), GObject.G_MAXUINT64) self.assertEqual(Everything.test_uint64(0), 0) self.assertRaises(OverflowError, Everything.test_uint64, -1) self.assertRaises(OverflowError, Everything.test_uint64, GObject.G_MAXUINT64 + 1) def test_int(self): self.assertEqual(Everything.test_int(GObject.G_MAXINT), GObject.G_MAXINT) self.assertEqual(Everything.test_int(GObject.G_MININT), GObject.G_MININT) self.assertRaises(OverflowError, Everything.test_int, GObject.G_MAXINT + 1) self.assertEqual(Everything.test_uint(GObject.G_MAXUINT), GObject.G_MAXUINT) self.assertEqual(Everything.test_uint(0), 0) self.assertRaises(OverflowError, Everything.test_uint, -1) self.assertRaises(OverflowError, Everything.test_uint, GObject.G_MAXUINT + 1) def test_short(self): self.assertEqual(Everything.test_short(GObject.G_MAXSHORT), GObject.G_MAXSHORT) self.assertEqual(Everything.test_short(GObject.G_MINSHORT), GObject.G_MINSHORT) self.assertRaises(OverflowError, Everything.test_short, GObject.G_MAXSHORT + 1) self.assertEqual(Everything.test_ushort(GObject.G_MAXUSHORT), GObject.G_MAXUSHORT) self.assertEqual(Everything.test_ushort(0), 0) self.assertRaises(OverflowError, Everything.test_ushort, -1) self.assertRaises(OverflowError, Everything.test_ushort, GObject.G_MAXUSHORT + 1) def test_long(self): self.assertEqual(Everything.test_long(GObject.G_MAXLONG), GObject.G_MAXLONG) self.assertEqual(Everything.test_long(GObject.G_MINLONG), GObject.G_MINLONG) self.assertRaises(OverflowError, Everything.test_long, GObject.G_MAXLONG + 1) self.assertEqual(Everything.test_ulong(GObject.G_MAXULONG), GObject.G_MAXULONG) self.assertEqual(Everything.test_ulong(0), 0) self.assertRaises(OverflowError, Everything.test_ulong, -1) self.assertRaises(OverflowError, Everything.test_ulong, GObject.G_MAXULONG + 1) def test_size(self): self.assertEqual(Everything.test_ssize(GObject.G_MAXSSIZE), GObject.G_MAXSSIZE) self.assertEqual(Everything.test_ssize(GObject.G_MINSSIZE), GObject.G_MINSSIZE) self.assertRaises(OverflowError, Everything.test_ssize, GObject.G_MAXSSIZE + 1) self.assertEqual(Everything.test_size(GObject.G_MAXSIZE), GObject.G_MAXSIZE) self.assertEqual(Everything.test_size(0), 0) self.assertRaises(OverflowError, Everything.test_size, -1) self.assertRaises(OverflowError, Everything.test_size, GObject.G_MAXSIZE + 1) def test_timet(self): self.assertEqual(Everything.test_timet(42), 42) self.assertRaises(OverflowError, Everything.test_timet, GObject.G_MAXUINT64 + 1) def test_unichar(self): self.assertEqual("c", Everything.test_unichar("c")) if sys.version_info < (3, 0): self.assertEqual(UNICHAR, Everything.test_unichar(PY2_UNICODE_UNICHAR)) self.assertEqual(UNICHAR, Everything.test_unichar(UNICHAR)) self.assertRaises(TypeError, Everything.test_unichar, "") self.assertRaises(TypeError, Everything.test_unichar, "morethanonechar") def test_float(self): self.assertEqual(Everything.test_float(GObject.G_MAXFLOAT), GObject.G_MAXFLOAT) self.assertEqual(Everything.test_float(GObject.G_MINFLOAT), GObject.G_MINFLOAT) self.assertRaises(OverflowError, Everything.test_float, GObject.G_MAXFLOAT * 2) def test_double(self): self.assertEqual(Everything.test_double(GObject.G_MAXDOUBLE), GObject.G_MAXDOUBLE) self.assertEqual(Everything.test_double(GObject.G_MINDOUBLE), GObject.G_MINDOUBLE) (two, three) = Everything.test_multi_double_args(2.5) self.assertAlmostEqual(two, 5.0) self.assertAlmostEqual(three, 7.5) def test_value(self): self.assertEqual(Everything.test_int_value_arg(GObject.G_MAXINT), GObject.G_MAXINT) self.assertEqual(Everything.test_value_return(GObject.G_MAXINT), GObject.G_MAXINT) def test_variant(self): v = Everything.test_gvariant_i() self.assertEqual(v.get_type_string(), 'i') self.assertEqual(v.get_int32(), 1) v = Everything.test_gvariant_s() self.assertEqual(v.get_type_string(), 's') self.assertEqual(v.get_string(), 'one') v = Everything.test_gvariant_v() self.assertEqual(v.get_type_string(), 'v') vi = v.get_variant() self.assertEqual(vi.get_type_string(), 's') self.assertEqual(vi.get_string(), 'contents') v = Everything.test_gvariant_as() self.assertEqual(v.get_type_string(), 'as') self.assertEqual(v.get_strv(), ['one', 'two', 'three']) v = Everything.test_gvariant_asv() self.assertEqual(v.get_type_string(), 'a{sv}') self.assertEqual(v.lookup_value('nosuchkey', None), None) name = v.lookup_value('name', None) self.assertEqual(name.get_string(), 'foo') timeout = v.lookup_value('timeout', None) self.assertEqual(timeout.get_int32(), 10) def test_string(self): const_str = b'const \xe2\x99\xa5 utf8' if sys.version_info >= (3, 0): const_str = const_str.decode('UTF-8') noconst_str = 'non' + const_str self.assertEqual(Everything.test_utf8_const_return(), const_str) self.assertEqual(Everything.test_utf8_nonconst_return(), noconst_str) self.assertEqual(Everything.test_utf8_out(), noconst_str) Everything.test_utf8_const_in(const_str) self.assertEqual(Everything.test_utf8_inout(const_str), noconst_str) self.assertEqual(Everything.test_filename_return(), ['åäö', '/etc/fstab']) # returns g_utf8_strlen() in out argument self.assertEqual(Everything.test_int_out_utf8(''), 0) self.assertEqual(Everything.test_int_out_utf8('hello world'), 11) self.assertEqual(Everything.test_int_out_utf8('åäö'), 3) self.assertEqual(Everything.test_utf8_out_out(), ('first', 'second')) self.assertEqual(Everything.test_utf8_out_nonconst_return(), ('first', 'second')) def test_enum(self): self.assertEqual(Everything.test_enum_param(Everything.TestEnum.VALUE1), 'value1') self.assertEqual(Everything.test_enum_param(Everything.TestEnum.VALUE3), 'value3') self.assertRaises(TypeError, Everything.test_enum_param, 'hello') # FIXME: ValueError: invalid enum value: 2147483648 @unittest.expectedFailure def test_enum_unsigned(self): self.assertEqual(Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE1), 'value1') self.assertEqual(Everything.test_unsigned_enum_param(Everything.TestEnumUnsigned.VALUE3), 'value3') self.assertRaises(TypeError, Everything.test_unsigned_enum_param, 'hello') def test_flags(self): result = Everything.global_get_flags_out() # assert that it's not an int self.assertEqual(type(result), Everything.TestFlags) self.assertEqual(result, Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3) def test_floating(self): e = Everything.TestFloating() self.assertEqual(e.__grefcount__, 1) e = GObject.new(Everything.TestFloating) self.assertEqual(e.__grefcount__, 1) e = Everything.TestFloating.new() self.assertEqual(e.__grefcount__, 1) 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) 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) 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) 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) struct_a = Everything.test_struct_a_parse('ignored') self.assertEqual(struct_a.some_int, 23) def test_wrong_type_of_arguments(self): try: Everything.test_int8() except TypeError: (e_type, e) = sys.exc_info()[:2] self.assertEqual(e.args, ("test_int8() takes exactly 1 argument (0 given)",)) def test_gtypes(self): gchararray_gtype = GObject.type_from_name('gchararray') gtype = Everything.test_gtype(str) self.assertEqual(gchararray_gtype, gtype) gtype = Everything.test_gtype('gchararray') self.assertEqual(gchararray_gtype, gtype) gobject_gtype = GObject.GObject.__gtype__ gtype = Everything.test_gtype(GObject.GObject) self.assertEqual(gobject_gtype, gtype) gtype = Everything.test_gtype('GObject') self.assertEqual(gobject_gtype, gtype) 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') self.assertEqual(ARegisteredClass.__gtype__, gtype) gtype = Everything.test_gtype(ARegisteredClass) self.assertEqual(ARegisteredClass.__gtype__, gtype) self.assertRaises(TypeError, Everything.test_gtype, 'ARegisteredClass') def test_dir(self): attr_list = dir(Everything) # test that typelib attributes are listed self.assertTrue('TestStructA' in attr_list) # 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) # test that instance members are listed self.assertTrue('_namespace' in attr_list) self.assertTrue('_version' in attr_list) # test that there are no duplicates returned self.assertEqual(len(attr_list), len(set(attr_list))) def test_array(self): self.assertEqual(Everything.test_array_int_in([]), 0) self.assertEqual(Everything.test_array_int_in([1, 5, -2]), 4) self.assertEqual(Everything.test_array_int_out(), [0, 1, 2, 3, 4]) self.assertEqual(Everything.test_array_int_full_out(), [0, 1, 2, 3, 4]) self.assertEqual(Everything.test_array_int_none_out(), [1, 2, 3, 4, 5]) self.assertEqual(Everything.test_array_int_inout([1, 5, 42, -8]), [6, 43, -7]) if sys.version_info >= (3, 0): self.assertEqual(Everything.test_array_gint8_in(b'\x01\x03\x05'), 9) self.assertEqual(Everything.test_array_gint8_in([1, 3, 5, -50]), -41) self.assertEqual(Everything.test_array_gint16_in([256, 257, -1000, 10000]), 9513) self.assertEqual(Everything.test_array_gint32_in([30000, 1, -2]), 29999) self.assertEqual(Everything.test_array_gint64_in([2 ** 33, 2 ** 34]), 2 ** 33 + 2 ** 34) self.assertEqual(Everything.test_array_gtype_in( [GObject.TYPE_STRING, GObject.TYPE_UINT64, GObject.TYPE_VARIANT]), '[gchararray,guint64,GVariant,]') def test_array_fixed_size(self): # fixed length of 5 self.assertEqual(Everything.test_array_fixed_size_int_in([1, 2, -10, 5, 3]), 1) self.assertRaises(ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4]) self.assertRaises(ValueError, Everything.test_array_fixed_size_int_in, [1, 2, 3, 4, 5, 6]) self.assertEqual(Everything.test_array_fixed_size_int_out(), [0, 1, 2, 3, 4]) self.assertEqual(Everything.test_array_fixed_size_int_return(), [0, 1, 2, 3, 4]) def test_ptrarray(self): # transfer container result = Everything.test_garray_container_return() self.assertEqual(result, ['regress']) result = None # transfer full result = Everything.test_garray_full_return() self.assertEqual(result, ['regress']) result = None def test_strv(self): self.assertEqual(Everything.test_strv_out(), ['thanks', 'for', 'all', 'the', 'fish']) self.assertEqual(Everything.test_strv_out_c(), ['thanks', 'for', 'all', 'the', 'fish']) self.assertEqual(Everything.test_strv_out_container(), ['1', '2', '3']) self.assertEqual(Everything.test_strv_outarg(), ['1', '2', '3']) self.assertEqual(Everything.test_strv_in_gvalue(), ['one', 'two', 'three']) Everything.test_strv_in(['1', '2', '3']) def test_glist(self): self.assertEqual(Everything.test_glist_nothing_return(), ['1', '2', '3']) self.assertEqual(Everything.test_glist_nothing_return2(), ['1', '2', '3']) self.assertEqual(Everything.test_glist_container_return(), ['1', '2', '3']) self.assertEqual(Everything.test_glist_everything_return(), ['1', '2', '3']) Everything.test_glist_nothing_in(['1', '2', '3']) Everything.test_glist_nothing_in2(['1', '2', '3']) def test_gslist(self): self.assertEqual(Everything.test_gslist_nothing_return(), ['1', '2', '3']) self.assertEqual(Everything.test_gslist_nothing_return2(), ['1', '2', '3']) self.assertEqual(Everything.test_gslist_container_return(), ['1', '2', '3']) self.assertEqual(Everything.test_gslist_everything_return(), ['1', '2', '3']) Everything.test_gslist_nothing_in(['1', '2', '3']) Everything.test_gslist_nothing_in2(['1', '2', '3']) def test_hash_return(self): expected = {'foo': 'bar', 'baz': 'bat', 'qux': 'quux'} self.assertEqual(Everything.test_ghash_null_return(), None) self.assertEqual(Everything.test_ghash_nothing_return(), expected) self.assertEqual(Everything.test_ghash_nothing_return(), expected) self.assertEqual(Everything.test_ghash_container_return(), expected) self.assertEqual(Everything.test_ghash_everything_return(), expected) result = Everything.test_ghash_gvalue_return() self.assertEqual(result['integer'], 12) self.assertEqual(result['boolean'], True) self.assertEqual(result['string'], 'some text') self.assertEqual(result['strings'], ['first', 'second', 'third']) self.assertEqual(result['flags'], Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3) self.assertEqual(result['enum'], Everything.TestEnum.VALUE2) result = None # FIXME: CRITICAL **: Unsupported type ghash def disabled_test_hash_return_nested(self): self.assertEqual(Everything.test_ghash_nested_everything_return(), {}) self.assertEqual(Everything.test_ghash_nested_everything_return2(), {}) def test_hash_in(self): expected = {'foo': 'bar', 'baz': 'bat', 'qux': 'quux'} Everything.test_ghash_nothing_in(expected) Everything.test_ghash_nothing_in2(expected) def test_hash_in_with_typed_strv(self): class GStrv(list): __gtype__ = GObject.TYPE_STRV data = {'integer': 12, 'boolean': True, 'string': 'some text', 'strings': GStrv(['first', 'second', 'third']), 'flags': Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3, 'enum': Everything.TestEnum.VALUE2, } Everything.test_ghash_gvalue_in(data) data = None def test_hash_in_with_gvalue_strv(self): data = {'integer': 12, 'boolean': True, 'string': 'some text', 'strings': GObject.Value(GObject.TYPE_STRV, ['first', 'second', 'third']), 'flags': Everything.TestFlags.FLAG1 | Everything.TestFlags.FLAG3, 'enum': Everything.TestEnum.VALUE2, } Everything.test_ghash_gvalue_in(data) data = None def test_struct_gpointer(self): glist = GLib.List() raw = RawGList.from_wrapped(glist) # Note that pointer fields use 0 for NULL in PyGObject and None in ctypes self.assertEqual(glist.data, 0) self.assertEqual(raw.contents.data, None) glist.data = 123 self.assertEqual(glist.data, 123) self.assertEqual(raw.contents.data, 123) glist.data = None self.assertEqual(glist.data, 0) self.assertEqual(raw.contents.data, None) # Setting to anything other than an int should raise self.assertRaises(TypeError, setattr, glist.data, 'nan') self.assertRaises(TypeError, setattr, glist.data, object()) self.assertRaises(TypeError, setattr, glist.data, 123.321) 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') 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)) self.assertTrue('tests/test_everything.py", line' in tb, tb) @unittest.skipUnless(has_cairo, 'built without cairo support') 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) Everything.test_gslist_null_in([]) Everything.test_glist_null_in([]) def test_in_nullable_array(self): Everything.test_array_int_null_in(None) Everything.test_array_int_null_in([]) def test_in_nullable_string(self): Everything.test_utf8_null_in(None) def test_in_nullable_object(self): Everything.func_obj_null_in(None) def test_out_nullable_hash(self): self.assertEqual(None, Everything.test_ghash_null_out()) def test_out_nullable_list(self): self.assertEqual([], Everything.test_gslist_null_out()) self.assertEqual([], Everything.test_glist_null_out()) def test_out_nullable_array(self): self.assertEqual([], Everything.test_array_int_null_out()) def test_out_nullable_string(self): self.assertEqual(None, Everything.test_utf8_null_out()) def test_out_nullable_object(self): self.assertEqual(None, Everything.TestObj.null_out()) @unittest.skipUnless(has_cairo, 'built without cairo support') class TestCallbacks(unittest.TestCase): called = False main_loop = GLib.MainLoop() def test_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True Everything.test_simple_callback(callback) self.assertTrue(TestCallbacks.called) def test_callback_exception(self): """ 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 self.fail('unexpected surviving zero divsion:' + str(x)) # 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) def test_double_callback_exception(self): """ 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 self.fail('unexpected surviving zero divsion:' + str(x)) def callback(): Everything.test_boolean(True) Everything.test_boolean(False) Everything.test_simple_callback(badcallback()) # 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) def test_return_value_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True return 44 self.assertEqual(Everything.test_callback(callback), 44) self.assertTrue(TestCallbacks.called) def test_callback_scope_async(self): TestCallbacks.called = False ud = 'Test Value 44' def callback(user_data): self.assertEqual(user_data, ud) TestCallbacks.called = True return 44 ud_refcount = sys.getrefcount(ud) callback_refcount = sys.getrefcount(callback) 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) self.assertTrue(TestCallbacks.called) # 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. TestCallbacks.called = 0 def callback(): TestCallbacks.called += 1 return TestCallbacks.called refcount = sys.getrefcount(callback) result = Everything.test_multi_callback(callback) # first callback should give 1, second 2, and the function sums them up self.assertEqual(result, 3) self.assertEqual(TestCallbacks.called, 2) self.assertEqual(sys.getrefcount(callback), refcount) def test_callback_scope_call_array(self): # This tests a callback that gets called multiple times from a # single scope call in python with array arguments TestCallbacks.callargs = [] # FIXME: would be cleaner without the explicit length args: # def callback(one, two): def callback(one, one_length, two, two_length): TestCallbacks.callargs.append((one, two)) return len(TestCallbacks.callargs) refcount = sys.getrefcount(callback) result = Everything.test_array_callback(callback) # first callback should give 1, second 2, and the function sums them up self.assertEqual(result, 3) self.assertEqual(TestCallbacks.callargs, [([-1, 0, 1, 2], ['one', 'two', 'three'])] * 2) self.assertEqual(sys.getrefcount(callback), refcount) def test_callback_userdata(self): TestCallbacks.called = 0 def callback(userdata): self.assertEqual(userdata, "Test%d" % TestCallbacks.called) TestCallbacks.called += 1 return TestCallbacks.called for i in range(100): val = Everything.test_callback_user_data(callback, "Test%d" % i) self.assertEqual(val, i + 1) self.assertEqual(TestCallbacks.called, 100) def test_async_ready_callback(self): TestCallbacks.called = False TestCallbacks.main_loop = GLib.MainLoop() 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) def test_callback_scope_notified_with_destroy(self): TestCallbacks.called = 0 ud = 'Test scope notified data 33' def callback(user_data): self.assertEqual(user_data, ud) TestCallbacks.called += 1 return 33 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) def test_callback_in_methods(self): object_ = Everything.TestObj() def callback(): TestCallbacks.called = True return 42 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): TestCallbacks.called += 1 return 42 TestCallbacks.called = 0 Everything.TestObj.new_callback(callbackWithUserData, None) 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) def test_callback_none(self): # make sure this doesn't assert or crash Everything.test_simple_callback(None) def test_callback_gerror(self): 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) 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) def test_callback_owned_gerror(self): 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) def test_callback_hashtable(self): def callback(data): self.assertEqual(data, mydict) mydict['new'] = 42 TestCallbacks.called = True mydict = {'foo': 1, 'bar': 2} TestCallbacks.called = False Everything.test_hash_table_callback(mydict, callback) self.assertTrue(TestCallbacks.called) self.assertEqual(mydict, {'foo': 1, 'bar': 2, 'new': 42}) @unittest.skipUnless(has_cairo, 'built without cairo support') class TestClosures(unittest.TestCase): def test_no_arg(self): def callback(): self.called = True return 42 self.called = False result = Everything.test_closure(callback) self.assertTrue(self.called) self.assertEqual(result, 42) def test_int_arg(self): def callback(num): self.called = True return num + 1 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 if variant is None: return None self.assertEqual(variant.get_type_string(), 'i') 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) 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) def test_variant_wrong_return_type(self): def callback(variant): return 'no_variant' # reset last error sys.last_type = None # this does not directly raise an exception (see # https://bugzilla.gnome.org/show_bug.cgi?id=616279) result = Everything.test_closure_variant(callback, GLib.Variant('i', 42)) # ... but the result shouldn't be a string self.assertEqual(result, None) # and the error should be shown self.assertEqual(sys.last_type, TypeError) self.assertTrue('return value' in str(sys.last_value), sys.last_value) @unittest.skipUnless(has_cairo, 'built without cairo support') class TestProperties(unittest.TestCase): def test_basic(self): object_ = Everything.TestObj() self.assertEqual(object_.props.int, 0) object_.props.int = 42 self.assertTrue(isinstance(object_.props.int, int)) self.assertEqual(object_.props.int, 42) self.assertEqual(object_.props.float, 0.0) object_.props.float = 42.42 self.assertTrue(isinstance(object_.props.float, float)) self.assertAlmostEqual(object_.props.float, 42.42, places=5) self.assertEqual(object_.props.double, 0.0) object_.props.double = 42.42 self.assertTrue(isinstance(object_.props.double, float)) self.assertAlmostEqual(object_.props.double, 42.42, places=5) self.assertEqual(object_.props.string, None) object_.props.string = 'mec' self.assertTrue(isinstance(object_.props.string, str)) self.assertEqual(object_.props.string, 'mec') self.assertEqual(object_.props.gtype, GObject.TYPE_INVALID) object_.props.gtype = int self.assertEqual(object_.props.gtype, GObject.TYPE_INT) def test_hash_table(self): object_ = Everything.TestObj() self.assertEqual(object_.props.hash_table, None) object_.props.hash_table = {'mec': 56} self.assertTrue(isinstance(object_.props.hash_table, dict)) self.assertEqual(list(object_.props.hash_table.items())[0], ('mec', 56)) def test_list(self): object_ = Everything.TestObj() self.assertEqual(object_.props.list, []) object_.props.list = ['1', '2', '3'] self.assertTrue(isinstance(object_.props.list, list)) self.assertEqual(object_.props.list, ['1', '2', '3']) def test_boxed(self): object_ = Everything.TestObj() self.assertEqual(object_.props.boxed, None) boxed = Everything.TestBoxed() boxed.some_int8 = 42 object_.props.boxed = boxed self.assertTrue(isinstance(object_.props.boxed, Everything.TestBoxed)) self.assertEqual(object_.props.boxed.some_int8, 42) def test_boxed_alternative_constructor(self): boxed = Everything.TestBoxed.new_alternative_constructor1(5) self.assertEqual(boxed.some_int8, 5) boxed = Everything.TestBoxed.new_alternative_constructor2(5, 3) self.assertEqual(boxed.some_int8, 8) boxed = Everything.TestBoxed.new_alternative_constructor3("-3") self.assertEqual(boxed.some_int8, -3) def test_boxed_equality(self): boxed42 = Everything.TestBoxed.new_alternative_constructor1(42) boxed5 = Everything.TestBoxed.new_alternative_constructor1(5) boxed42_2 = Everything.TestBoxed.new_alternative_constructor2(41, 1) self.assertFalse(boxed42.equals(boxed5)) self.assertTrue(boxed42.equals(boxed42_2)) self.assertTrue(boxed42_2.equals(boxed42)) self.assertTrue(boxed42.equals(boxed42)) def test_boxed_c_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)) def test_gtype(self): object_ = Everything.TestObj() self.assertEqual(object_.props.gtype, GObject.TYPE_INVALID) object_.props.gtype = int self.assertEqual(object_.props.gtype, GObject.TYPE_INT) object_ = Everything.TestObj(gtype=int) self.assertEqual(object_.props.gtype, GObject.TYPE_INT) object_.props.gtype = str self.assertEqual(object_.props.gtype, GObject.TYPE_STRING) 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"]) @unittest.skipUnless(has_cairo, 'built without cairo support') 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): (y, z, q) = object_.torture_signature_0(5000, "Torture Test 1", 12345) 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): (y, z, q) = Everything.TestObj().torture_signature_0( 5000, "Torture Test 2", 12345) 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: (y, z, q) = object_.torture_signature_1( 5000, "Torture Test 3", 12345) 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): ") def callback(userdata): pass userdata = [1, 2, 3, 4] start_time = time.clock() for i in range(10000): (y, z, q) = Everything.test_torture_signature_2( 5000, callback, userdata, "Torture Test 4", 12345) 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) @unittest.skipUnless(has_cairo, 'built without cairo support') 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) def test_obj_skip_return_val(self): obj = Everything.TestObj() ret = obj.skip_return_val(50, 42.0, 60, 2, 3) self.assertEqual(len(ret), 3) self.assertEqual(ret[0], 51) self.assertEqual(ret[1], 61) self.assertEqual(ret[2], 32) def test_obj_skip_return_val_no_out(self): obj = Everything.TestObj() # 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) self.assertEqual(ret, None) @unittest.skipUnless(has_cairo, 'built without cairo support') class TestSignals(unittest.TestCase): def test_object_param_signal(self): obj = Everything.TestObj() def callback(obj, obj_param): self.assertEqual(obj_param.props.int, 3) self.assertGreater(obj_param.__grefcount__, 1) obj.called = True obj.called = False obj.connect('sig-with-obj', callback) obj.emit_sig_with_obj() self.assertTrue(obj.called) def test_connect_after(self): obj = Everything.TestObj() def callback(obj, obj_param): obj.called = True obj.called = False obj.connect_after('sig-with-obj', callback) obj.emit_sig_with_obj() self.assertTrue(obj.called) def test_connect_object(self): obj = Everything.TestObj() def callback(obj, obj_param): obj.called = True obj.called = False obj.connect_object('sig-with-obj', callback, obj) obj.emit_sig_with_obj() self.assertTrue(obj.called) def test_connect_object_after(self): obj = Everything.TestObj() def callback(obj, obj_param): obj.called = True obj.called = False obj.connect_object_after('sig-with-obj', callback, obj) obj.emit_sig_with_obj() self.assertTrue(obj.called) 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) def test_intarray_ret(self): obj = Everything.TestObj() def callback(obj, i): obj.callback_i = i return [i, i + 1] obj.callback_i = None try: obj.connect('sig-with-intarray-ret', callback) except TypeError as e: # compat with g-i 1.34.x if 'unknown signal' in str(e): return raise rv = obj.emit('sig-with-intarray-ret', 42) self.assertEqual(obj.callback_i, 42) self.assertEqual(type(rv), GLib.Array) self.assertEqual(rv.len, 2) @unittest.skipUnless(has_cairo, 'built without cairo support') @unittest.skipUnless(Gtk, 'Gtk not available') 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)