1""" 2Tests for the new-style metadata format interface. 3 4Note: Tests for calling from ObjC into python are in test_metadata_py.py 5 6TODO: 7- Add tests for calling functions instead of methods 8- The python->C interface (that is the contents of the metadata object) is 9 likely to change when the bridge is feature-complete. 10- Probably need special-casing for arrays (numarray and array.array)! 11""" 12from __future__ import unicode_literals 13import objc 14from PyObjCTools.TestSupport import * 15 16from PyObjCTest.metadata import * 17import PyObjCTest.test_metadata # to get the right metadata 18import warnings 19 20import sys 21if sys.version_info[0] == 3: 22 unicode = str 23 24 25class TestArrayDefault (TestCase): 26 # TODO: what is the default anyway? 27 pass 28 29class TestArraysOut (TestCase): 30 def testFixedSize(self): 31 o = OC_MetaDataTest.new() 32 m = o.methodForSelector_('fill4Tuple:') 33 34 v = m(o, None) 35 self.assertEqual(list(v), [0, -1, -8, -27]) 36 37 self.assertRaises(ValueError, m, o, objc.NULL) 38 39 m = o.methodForSelector_('nullfill4Tuple:') 40 n, v = m(o, None) 41 self.assertEqual(n, 1) 42 self.assertEqual(list(v), [0, -1, -8, -27]) 43 44 n, v = m(o, None) 45 self.assertEqual(n, 1) 46 self.assertEqual(list(v), [0, -1, -8, -27]) 47 48 n, v = m(o, objc.NULL) 49 self.assertEqual(n, 0) 50 self.assertIs(v, objc.NULL) 51 52 def testNullTerminated(self): 53 o = OC_MetaDataTest.new() 54 m = o.methodForSelector_('fillStringArray:') 55 56 57 # Output only arrays of null-terminated arrays cannot be 58 # wrapped automaticly. How is the bridge supposed to know 59 # how much memory it should allocate for the C-array? 60 self.assertRaises(TypeError, m, o, None) 61 self.assertRaises(ValueError, m, o, objc.NULL) 62 63 m = o.methodForSelector_('fillStringArray:') 64 self.assertRaises(TypeError, m, o) 65 self.assertRaises(TypeError, m, o, None) 66 n, v = o.nullfillStringArray_(objc.NULL) 67 self.assertEqual(n, 0) 68 self.assertIs(v, objc.NULL) 69 70 def testWithCount(self): 71 o = OC_MetaDataTest.new() 72 m = o.methodForSelector_('fillArray:count:') 73 74 v = m(o, None, 3) 75 self.assertEqual(list(v), [0,1,4]) 76 77 v = m(o, None, 3) 78 self.assertEqual(list(v), [0,1,4]) 79 80 v = m(o, None, 5) 81 self.assertEqual(list(v), [0,1,4,9,16]) 82 83 v = m(o, None, 0) 84 self.assertEqual(list(v), []) 85 86 self.assertRaises(ValueError, m, o, objc.NULL, 0) 87 88 m = o.methodForSelector_('nullfillArray:count:') 89 n, v = m(o, None, 3) 90 self.assertEqual(n, 1) 91 self.assertEqual(list(v), [0,1,4]) 92 n, v = m(o, None, 3) 93 self.assertEqual(n, 1) 94 self.assertEqual(list(v), [0,1,4]) 95 96 97 n, v = m(o, objc.NULL, 3) 98 self.assertEqual(n, 0) 99 self.assertIs(v, objc.NULL) 100 101 def testWithCountInResult(self): 102 o = OC_MetaDataTest.new() 103 m = o.methodForSelector_('fillArray:uptoCount:') 104 105 c, v = m(o, None, 20) 106 self.assertEqual(c, 10) 107 self.assertEqual(list(v), [i+2 for i in range(10)]) 108 109 m = o.methodForSelector_('maybeFillArray:') 110 c, v = m(o, None) 111 self.assertEqual(c, 2) 112 self.assertEqual(list(v), [10, 11]) 113 114 115 116class TestArraysInOut (TestCase): 117 def testFixedSize(self): 118 o = OC_MetaDataTest.new() 119 m = o.methodForSelector_('reverse4Tuple:') 120 121 a = (1,2,3,4) 122 v = m(o, a) 123 self.assertEqual(a, (1,2,3,4)) 124 self.assertEqual(v, (4,3,2,1)) 125 126 self.assertRaises(ValueError, m, o, (1,2,3)) 127 self.assertRaises(ValueError, m, o, (1,2,3,4,5)) 128 self.assertRaises(ValueError, m, o, objc.NULL) 129 130 m = o.methodForSelector_('nullreverse4Tuple:') 131 a = (1,2,3,4) 132 n, v = m(o, a) 133 self.assertEqual(n, 1) 134 self.assertEqual(a, (1,2,3,4)) 135 self.assertEqual(v, (4,3,2,1)) 136 137 n, v = m(o, objc.NULL) 138 self.assertEqual(n, 0) 139 self.assertIs(v, objc.NULL) 140 141 def testNullTerminated(self): 142 o = OC_MetaDataTest.new() 143 m = o.methodForSelector_('reverseStrings:') 144 145 a = (b'a', b'b', b'c') 146 v = m(o, a) 147 self.assertEqual(a, (b'a', b'b', b'c')) 148 self.assertEqual(v, (b'c', b'b', b'a')) 149 150 self.assertRaises(ValueError, m, o, (1,2)) 151 self.assertRaises(ValueError, m, o, objc.NULL) 152 153 m = o.methodForSelector_('nullreverseStrings:') 154 a = (b'a', b'b', b'c') 155 n, v = m(o, a) 156 self.assertEqual(n, 1) 157 self.assertEqual(a, (b'a', b'b', b'c')) 158 self.assertEqual(v, (b'c', b'b', b'a')) 159 160 n, v = m(o, objc.NULL) 161 self.assertEqual(n, 0) 162 self.assertIs(v, objc.NULL) 163 164 def testWithCount(self): 165 o = OC_MetaDataTest.new() 166 m = o.methodForSelector_('reverseArray:count:') 167 168 a = (1.0, 2.0, 3.0, 4.0, 5.0) 169 v = m(o, a, 4) 170 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 171 self.assertEqual(v, (4.0, 3.0, 2.0, 1.0)) 172 173 a = (1.0, 2.0, 3.0, 4.0, 5.0) 174 v = m(o, a, 5) 175 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 176 self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 177 178 # Nice to have, but doesn't work without major 179 # surgery: 180 #a = (1.0, 2.0, 3.0, 4.0, 5.0) 181 #v = m(o, a, None) 182 #self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 183 #self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 184 185 self.assertRaises(ValueError, m, o, (1.0, 2.0), 5) 186 self.assertRaises(ValueError, m, o, objc.NULL, 0) 187 188 m = o.methodForSelector_('nullreverseArray:count:') 189 a = (1.0, 2.0, 3.0, 4.0, 5.0) 190 n, v = m(o, a, 5) 191 self.assertEqual(n, 1) 192 self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) 193 self.assertEqual(v, (5.0, 4.0, 3.0, 2.0, 1.0)) 194 195 n, v = m(o, objc.NULL, 0) 196 self.assertEqual(n, 0) 197 self.assertIs(v, objc.NULL) 198 199 def testWithCountInResult(self): 200 o = OC_MetaDataTest.new() 201 m = o.methodForSelector_('reverseArray:uptoCount:') 202 203 c, v = m(o, range(10), 10) 204 self.assertEqual(c, 5) 205 self.assertEqual(len(v), 5) 206 self.assertEqual(list(v), [9, 8, 7, 6, 5]) 207 208 m = o.methodForSelector_('maybeReverseArray:') 209 c, v = m(o, [1,2,3,4]) 210 self.assertEqual(c, 2) 211 self.assertEqual(len(v), 2) 212 self.assertEqual(list(v), [4, 3]) 213 214class TestArraysIn (TestCase): 215 def testFixedSize(self): 216 o = OC_MetaDataTest.new() 217 m = o.methodForSelector_('make4Tuple:') 218 219 v = m(o, (1.0, 4.0, 8.0, 12.5)) 220 self.assertEqual(len(v), 4) 221 self.assertEqual(list(v), [1.0, 4.0, 8.0, 12.5]) 222 223 v = m(o, (1, 2, 3, 4)) 224 self.assertEqual(len(v), 4) 225 self.assertEqual(list(v), [1.0, 2.0, 3.0, 4.0]) 226 227 self.assertRaises(ValueError, m, o, (1, 2, 3)) 228 self.assertRaises(ValueError, m, o, (1, 2, 3, 4, 5)) 229 self.assertRaises(ValueError, m, o, objc.NULL) 230 231 m = o.methodForSelector_('null4Tuple:') 232 v = m(o, objc.NULL) 233 self.assertIsNone(v) 234 235 def testNullTerminated(self): 236 o = OC_MetaDataTest.new() 237 238 m = o.methodForSelector_('makeStringArray:') 239 240 v = m(o, (b"hello", b"world", b"there")) 241 self.assertEqual(len(v), 3) 242 self.assertEqual(list(v), ["hello", "world", "there"]) 243 self.assertIsInstance(v, objc.lookUpClass("NSArray")) 244 self.assertIsInstance(v[0], unicode) 245 246 m = o.methodForSelector_('makeObjectArray:') 247 248 NSObject = objc.lookUpClass('NSObject') 249 p, q, r = NSObject.new(), NSObject.new(), NSObject.new() 250 v = m(o, (p, q, r)) 251 self.assertEqual(len(v), 3) 252 self.assertIs(v[0], p) 253 self.assertIs(v[1], q) 254 self.assertIs(v[2], r) 255 256 m = o.methodForSelector_('makeStringArray:') 257 258 v = m(o, ()) 259 self.assertEqual(len(v), 0) 260 261 self.assertRaises(ValueError, m, o, [1,2]) 262 self.assertRaises(ValueError, m, o, objc.NULL) 263 264 m = o.methodForSelector_('nullStringArray:') 265 v = m(o, objc.NULL) 266 self.assertEqual(v, None) 267 268 def testWithCount(self): 269 o = OC_MetaDataTest.new() 270 m = o.methodForSelector_('makeIntArray:count:') 271 272 v = m(o, (1,2,3,4), 3) 273 self.assertEqual(len(v), 3) 274 self.assertEqual(list(v), [1,2,3]) 275 276 # XXX: This one would be nice to have, but not entirely trivial 277 #v = m(o, (1,2,3,4), None) 278 #self.assertEqual(len(v), 3) 279 #self.assertEqual(list(v), [1,2,3,4]) 280 281 self.assertRaises(ValueError, m, o, [1,2,3], 4) 282 self.assertRaises(ValueError, m, o, objc.NULL, 0) 283 self.assertRaises(ValueError, m, o, objc.NULL, 1) 284 285 self.assertRaises(ValueError, m, o, objc.NULL, 1) 286 287 m = o.methodForSelector_('nullIntArray:count:') 288 v = m(o, objc.NULL, 0) 289 self.assertEqual(v, None) 290 291 292 # Make sure this also works when the length is in a pass-by-reference argument 293 m = o.methodForSelector_('makeIntArray:countPtr:') 294 v = m(o, (1,2,3,4), 4) 295 self.assertEqual(len(v), 4) 296 self.assertEqual(list(v), [1,2,3,4]) 297 298class TestArrayReturns (TestCase): 299 # TODO: 300 # - Add null-terminated arrays of various supported types: 301 # -> integers 302 # -> CF-types 303 def testFixedSize(self): 304 o = OC_MetaDataTest.new() 305 m = o.methodForSelector_(b'makeIntArrayOf5') 306 307 v = m(o) 308 self.assertEqual( len(v), 5 ) 309 self.assertEqual( v[0], 0 ) 310 self.assertEqual( v[1], 1 ) 311 self.assertEqual( v[2], 4 ) 312 self.assertEqual( v[3], 9 ) 313 self.assertEqual( v[4], 16 ) 314 315 m = o.methodForSelector_(b'nullIntArrayOf5') 316 v = m(o) 317 self.assertEqual(v, objc.NULL) 318 319 def testSizeInArgument(self): 320 o = OC_MetaDataTest.new() 321 m = o.methodForSelector_(b'makeIntArrayOf:') 322 323 v = m(o, 3) 324 self.assertEqual(len(v), 3) 325 self.assertEqual(v[0], 0) 326 self.assertEqual(v[1], 1) 327 self.assertEqual(v[2], 8) 328 329 v = m(o, 10) 330 self.assertEqual(len(v), 10) 331 for i in range(10): 332 self.assertEqual(v[i], i**3) 333 334 m = o.methodForSelector_(b'nullIntArrayOf:') 335 v = m(o, 100) 336 self.assertEqual(v, objc.NULL) 337 338 def testNULLterminated(self): 339 o = OC_MetaDataTest.new() 340 m = o.methodForSelector_(b'makeStringArray') 341 342 v = m(o) 343 self.assertEqual(len(v), 4) 344 self.assertEqual(list(v), [b"hello", b"world", b"out", b"there"]) 345 346 m = o.methodForSelector_(b'nullStringArray') 347 v = m(o) 348 self.assertEqual(v, objc.NULL) 349 350class TestByReference (TestCase): 351 # Pass by reference arguments. 352 # Note that these tests aren't exhaustive, we have test_methods and 353 # test_methods2 for that :-) 354 355 def testInput(self): 356 o = OC_MetaDataTest.new() 357 m = o.methodForSelector_('sumX:andY:') 358 359 r = m(o, 1, 2) 360 self.assertEqual(r, 1+2) 361 362 r = m(o, 2535, 5325) 363 self.assertEqual(r, 2535 + 5325) 364 365 self.assertRaises(ValueError, m, o, 42, objc.NULL) 366 367 def testOutput(self): 368 o = OC_MetaDataTest.new() 369 m = o.methodForSelector_('divBy5:remainder:') 370 371 div, rem = m(o, 55, None) 372 self.assertEqual(div, 11) 373 self.assertEqual(rem, 0) 374 375 div, rem = m(o, 13, None) 376 self.assertEqual(div, 2) 377 self.assertEqual(rem, 3) 378 379 # To be fixed: 380 #self.assertRaises(ValueError, m, o, 42, objc.NULL) 381 382 def testInputOutput(self): 383 o = OC_MetaDataTest.new() 384 m = o.methodForSelector_('swapX:andY:') 385 386 x, y = m(o, 42, 284) 387 self.assertEqual(x, 284) 388 self.assertEqual(y, 42) 389 390 self.assertRaises(ValueError, m, o, 42, objc.NULL) 391 392 def testNullAccepted(self): 393 # Note: the commented-out test-cases require a change in the pyobjc-core 394 o = OC_MetaDataTest.new(); 395 m = o.methodForSelector_('input:output:inputAndOutput:') 396 397 def makeNum(value): 398 return int(value, 0) 399 400 # All arguments present 401 r, y, z = m(o, 1, None, 2) 402 self.assertEqual(len(r), 3) 403 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 3) 404 self.assertEqual(y, 3) 405 self.assertEqual(z, -1) 406 407 r, y, z = m(o, 1, None, 2) 408 self.assertEqual(len(r), 3) 409 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 3) 410 self.assertEqual(y, 3) 411 self.assertEqual(z, -1) 412 413 # Argument 1 is NULL 414 r, y, z = m(o, objc.NULL, None, 2) 415 self.assertEqual(len(r), 3) 416 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 417 self.assertEqual(y, 40) 418 self.assertEqual(z, -2) 419 420 r, y, z = m(o, objc.NULL, None, 2) 421 self.assertEqual(len(r), 3) 422 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 423 self.assertEqual(y, 40) 424 self.assertEqual(z, -2) 425 426 # Argument 2 is NULL 427 r, y, z = m(o, 1, objc.NULL, 2) 428 self.assertEqual(len(r), 3) 429 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 430 self.assertEqual(y, objc.NULL) 431 self.assertEqual(z, -1) 432 433 # Argument 3 is NULL 434 r, y, z = m(o, 1, None, objc.NULL) 435 self.assertEqual(len(r), 3) 436 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 437 self.assertEqual(y, 43) 438 self.assertEqual(z, objc.NULL) 439 440 r, y, z = m(o, 1, None, objc.NULL) 441 self.assertEqual(len(r), 3) 442 self.assertEqual(len(list(filter(None, map(makeNum, r)))), 2) 443 self.assertEqual(y, 43) 444 self.assertEqual(z, objc.NULL) 445 446 447if __name__ == "__main__": 448 main() 449