1from PyObjCTools.TestSupport import * 2import objc 3 4 5objc.registerMetaDataForSelector( 6 b"OC_CallbackTest", b"selWithSEL:SEL:andObject:", { 7 "arguments": { 8 2: { 9 "sel_of_type": b"q@:q", 10 }, 11 3: { 12 "sel_of_type": b"v@:@@^v", 13 } 14 } 15 } 16) 17 18objc.registerMetaDataForSelector( 19 b"OC_CallbackTest", b"selWithCallback:", { 20 "arguments": { 21 2: { 22 "callable": { 23 "retval": { "type": b"q", }, 24 "arguments": { 25 "0": { "type": b"@", }, 26 "1": { "type": b"i", }, 27 } 28 } 29 }, 30 } 31 } 32) 33 34objc.registerMetaDataForSelector( 35 b"OC_CallbackTest", b"selWithCallback2:", { 36 "arguments": { 37 2: { 38 "callable": { 39 "retval": { "type": b"d", }, 40 "arguments": { 41 } 42 } 43 }, 44 } 45 } 46) 47 48objc.registerMetaDataForSelector( 49 b"OC_CallbackTest", b"selWithCallback:andCallback:", { 50 "arguments": { 51 2: { 52 "callable": { 53 "arguments": { 54 "0": { "type": b"@", }, 55 } 56 } 57 }, 58 3: { 59 "callable": { 60 "retval": { "type": b"@", }, 61 "arguments": { 62 "0": { "type": b"q", }, 63 "1": { "type": b"^v", }, 64 } 65 } 66 }, 67 } 68 } 69) 70 71class OC_CallbackTest (objc.lookUpClass("NSObject")): 72 @objc.typedSelector(b"v@:" + objc._C_SEL + objc._C_SEL + b"@") 73 def selWithSEL_SEL_andObject_(self, s1, s2, o): 74 pass 75 76 @objc.typedSelector(b"v@:" + objc._C_SEL) 77 def selWithoutSEL_(self, o): 78 pass 79 80 @objc.typedSelector(b"v@:?") 81 def selWithCallback_(self, cb): 82 pass 83 84 @objc.typedSelector(b"v@:?") 85 def selWithCallback2_(self, cb): 86 pass 87 88 @objc.typedSelector(b"v@:??") 89 def selWithCallback_andCallback_(self, cb1, cb2): 90 pass 91 92 93 94 95class TestClosure (TestCase): 96 # tests for objc._makeClosure 97 # (note: as the name indicates _makeClosure is not a public API) 98 def testCallbackForUnsupported(self): 99 def function(arg): 100 pass 101 102 self.assertRaises(TypeError, objc._makeClosure, function, dir, -1) 103 self.assertRaises(TypeError, objc._makeClosure, function, function, -1) 104 self.assertRaises(TypeError, objc._makeClosure, function, 42, -1) 105 self.assertRaises(ValueError, objc._makeClosure, function, OC_CallbackTest.selWithSEL_SEL_andObject_, -1) 106 self.assertRaises(ValueError, objc._makeClosure, function, OC_CallbackTest.selWithoutSEL_, -1) 107 108 def testCreatingCallbacks(self): 109 def function(*arg): 110 pass 111 cl = objc._makeClosure(function, OC_CallbackTest.selWithCallback_, -1) 112 self.assertIn(' "objc.__imp__" ', repr(cl)) 113 cl = objc._makeClosure(function, OC_CallbackTest.selWithCallback2_, -1) 114 self.assertIn(' "objc.__imp__" ', repr(cl)) 115 cl = objc._makeClosure(function, OC_CallbackTest.selWithCallback_andCallback_, -1) 116 self.assertIn(' "objc.__imp__" ', repr(cl)) 117 cl = objc._makeClosure(function, OC_CallbackTest.selWithCallback_andCallback_, 2) 118 self.assertIn(' "objc.__imp__" ', repr(cl)) 119 cl = objc._makeClosure(function, OC_CallbackTest.selWithCallback_andCallback_, 3) 120 self.assertIn(' "objc.__imp__" ', repr(cl)) 121 122 self.assertRaises(objc.BadPrototypeError, objc._makeClosure, lambda a: None, OC_CallbackTest.selWithCallback_, -1) 123 objc._makeClosure(lambda a, b: None, OC_CallbackTest.selWithCallback_, -1) 124 self.assertRaises(objc.BadPrototypeError, objc._makeClosure, lambda a, b, c: None, OC_CallbackTest.selWithCallback_, -1) 125 126 # TODO: Verify that C code has proper coverage 127 128 129class TestCallbackFor (TestCase): 130 # tests for objc.callbackFor 131 def testCallbackForUnsupported(self): 132 def function(arg): 133 pass 134 135 self.assertRaises(TypeError, objc.callbackFor(dir), function) 136 self.assertRaises(TypeError, objc.callbackFor(function), function) 137 self.assertRaises(TypeError, objc.callbackFor(42), function) 138 self.assertRaises(ValueError, objc.callbackFor(OC_CallbackTest.selWithSEL_SEL_andObject_), function) 139 self.assertRaises(ValueError, objc.callbackFor(OC_CallbackTest.selWithoutSEL_), function) 140 141 def testCreatingCallbacks(self): 142 def function(*arg): 143 pass 144 145 @objc.callbackFor(OC_CallbackTest.selWithCallback_) 146 def function(arg1, arg2): 147 pass 148 self.assertIn(' "objc.__imp__" ', repr(function.pyobjc_closure)) 149 150 @objc.callbackFor(OC_CallbackTest.selWithCallback2_) 151 def function(): 152 pass 153 self.assertIn(' "objc.__imp__" ', repr(function.pyobjc_closure)) 154 155 @objc.callbackFor(OC_CallbackTest.selWithCallback_andCallback_, -1) 156 def function(a): 157 pass 158 self.assertIn(' "objc.__imp__" ', repr(function.pyobjc_closure)) 159 160 @objc.callbackFor(OC_CallbackTest.selWithCallback_andCallback_, 2) 161 def function(a): 162 pass 163 self.assertIn(' "objc.__imp__" ', repr(function.pyobjc_closure)) 164 165 @objc.callbackFor(OC_CallbackTest.selWithCallback_andCallback_, 3) 166 def function(a, b): 167 pass 168 self.assertIn(' "objc.__imp__" ', repr(function.pyobjc_closure)) 169 170 self.assertRaises(objc.BadPrototypeError, objc.callbackFor(OC_CallbackTest.selWithCallback_), lambda a: None) 171 self.assertRaises(objc.BadPrototypeError, objc.callbackFor(OC_CallbackTest.selWithCallback_), lambda a,b,c: None) 172 173 # TODO: add tests that actually call the callback 174 175class TestSelectorFor (TestCase): 176 # tests for objc.selectorFor 177 def test_consistency(self): 178 self.assertEqual(OC_CallbackTest.selWithSEL_SEL_andObject_.signature, 179 b"v@:::@") 180 181 def testNotSelector(self): 182 self.assertRaises(ValueError, objc.selectorFor, OC_CallbackTest.selWithSEL_SEL_andObject_, 4) 183 self.assertRaises(ValueError, objc.selectorFor, OC_CallbackTest.selWithSEL_SEL_andObject_, 8) 184 self.assertRaises(ValueError, objc.selectorFor, OC_CallbackTest.selWithoutSEL_) 185 186 def testDefault(self): 187 @objc.selectorFor(OC_CallbackTest.selWithSEL_SEL_andObject_) 188 def selector(self, a): 189 pass 190 191 self.assertEqual(selector.signature, b"q@:q") 192 193 def testExplicit(self): 194 195 @objc.selectorFor(OC_CallbackTest.selWithSEL_SEL_andObject_, 2) 196 def selector(self, a): 197 pass 198 199 self.assertEqual(selector.signature, b"q@:q") 200 201 @objc.selectorFor(OC_CallbackTest.selWithSEL_SEL_andObject_, 3) 202 def selector(self, a): 203 pass 204 205 self.assertEqual(selector.signature, b"v@:@@^v") 206 207 208if __name__ == "__main__": 209 main() 210