1# Tests for interaction with ObjC "blocks".
2#
3# These tests are fairly minimal at the moment.
4from PyObjCTools.TestSupport import *
5from PyObjCTest.block import OCTestBlock
6import objc
7
8objc.parseBridgeSupport('''\
9    <?xml version='1.0'?>
10    <!DOCTYPE signatures SYSTEM "file://localhost/System/Library/DTDs/BridgeSupport.dtd">
11    <signatures version='1.0'>
12      <class name='OCTestBlock'>
13        <method selector='getIntBlock'>
14          <retval block='true' >
15              <retval type='i' />
16          </retval>
17        </method>
18        <method selector='getFloatBlock'>
19          <retval block='true' >
20              <retval type='d' />
21              <arg type='d' />
22              <arg type='d' />
23          </retval>
24        </method>
25        <method selector='callIntBlock:withValue:'>
26          <arg index='0' block='true' >
27              <retval type='v' />
28              <arg type='i' />
29          </arg>
30        </method>
31        <method selector='callDoubleBlock:withValue:andValue:'>
32          <arg index='0' block='true' >
33              <retval type='d' />
34              <arg type='d' />
35              <arg type='d' />
36          </arg>
37        </method>
38      </class>
39    </signatures>
40    ''', globals(), 'PyObjCTest')
41
42# The blocks tests can only run when PyObjC was compiled with
43# GCC 4.2 or later.
44v = OCTestBlock.alloc().init()
45if hasattr(v, 'getIntBlock'):
46    blocksEnabled = True
47else:
48    blocksEnabled = False
49del v
50
51class TestBlocks (TestCase):
52    @min_os_level('10.6')
53    @onlyIf(blocksEnabled, "no blocks")
54    def testBlockToObjC(self):
55        obj = OCTestBlock.alloc().init()
56
57        lst = []
58        def callback(v):
59            lst.append(v)
60
61        obj.callIntBlock_withValue_(callback, 42)
62        self.assertEqual(len(lst), 1)
63        obj.callIntBlock_withValue_(callback, 43)
64        self.assertEqual(len(lst), 2)
65
66        self.assertEqual(lst, [42, 43])
67
68    @min_os_level('10.6')
69    @onlyIf(blocksEnabled, "no blocks")
70    def testBlockToObjC2(self):
71        obj = OCTestBlock.alloc().init()
72
73        lst = []
74        def callback(a, b):
75            return a * b
76
77        self.assertEqual(obj.callDoubleBlock_withValue_andValue_(callback, 2.0, 3.5), 7.0)
78        self.assertEqual(obj.callDoubleBlock_withValue_andValue_(callback, 2.5, 10), 25.0)
79
80
81    @min_os_level('10.6')
82    @onlyIf(blocksEnabled, "no blocks")
83    def testBlockFromObjC(self):
84        obj = OCTestBlock.alloc().init()
85
86        block = obj.getIntBlock()
87        value = block()
88        self.assertEqual(value, 42)
89
90        value = block()
91        self.assertEqual(value, 42)
92
93    @min_os_level('10.6')
94    @onlyIf(blocksEnabled, "no blocks")
95    def testBlockFromObjC2(self):
96        obj = OCTestBlock.alloc().init()
97
98        block = obj.getFloatBlock()
99        value = block(1, 2)
100        self.assertEqual(value, 3.0)
101
102        value = block(2.5, 7.0)
103        self.assertEqual(value, 9.5)
104
105if __name__ == "__main__":
106    main()
107