""" Tests for the new-style metadata format interface. Note: Tests for calling from python into ObjC are in test_metadata.py TODO: -> OutputOptional version for TestByReference -> Testcode might need changes, C code definitely needs changes - Add more testcases: python methods that return the wrong value - The python->C interface (that is the contents of the metadata object) is likely to change when the bridge is feature-complete. - Probably need special-casing for arrays (numarray and array.array)! """ import objc from PyObjCTools.TestSupport import * from PyObjCTest.metadata import * # To ensure we have the right metadata import PyObjCTest.test_metadata from PyObjCTest.test_metadata_py import Py_MetaDataTest_AllArgs if 0: from PyObjCTest.test_metadata_py2 import Py_MetaDataTest_OutputOptional class TestArraysOut_AllArgs (TestCase): def testFixedSize(self): o = Py_MetaDataTest_AllArgs.new() v = o.fill4Tuple_() self.assertEqual(list(v), list(range(9, 13))) v = o.fill4Tuple_(None) self.assertEqual(list(v), list(range(9, 13))) self.assertRaises(ValueError, OC_MetaDataTest.fill4Tuple_on_, objc.NULL, o) n, v = o.nullfill4Tuple_() self.assertEqual(n, 1) self.assertEqual(list(v), list(range(1, 5))) n, v = o.nullfill4Tuple_(None) self.assertEqual(n, 1) self.assertEqual(list(v), list(range(1, 5))) n, v = o.nullfill4Tuple_(objc.NULL) self.assertEqual(n, 2) #self.assertIs(v, objc.NULL ) def testNullTerminated(self): o = Py_MetaDataTest_AllArgs.new() # Output only arrays of null-terminated arrays cannot be # wrapped automaticly. How is the bridge supposed to know # how much memory it should allocate for the C-array? #self.assertRaises(TypeError, o.fillStringArray_) #self.assertRaises(TypeError, o.fillStringArray_, None) #self.assertRaises(ValueError, o.fillStringArray_, objc.NULL) #self.assertRaises(TypeError, o.nullfillStringArray_) #self.assertRaises(TypeError, o.nullfillStringArray_, None) n, v = o.nullfillStringArray_(objc.NULL) self.assertEqual(n, 9) self.assertIs(v, objc.NULL) def testWithCount(self): o = Py_MetaDataTest_AllArgs.new() v = o.fillArray_count_(3) self.assertEqual(list(v), [10, 11, 12]) v = o.fillArray_count_(None, 3) self.assertEqual(list(v), [10, 11, 12]) v = o.fillArray_count_(5) self.assertEqual(list(v), [10, 11, 12, 13, 14]) v = o.fillArray_count_(0) self.assertEqual(list(v), []) #self.assertRaises(ValueError, o.fillArray_count_, objc.NULL, 0) n, v = o.nullfillArray_count_(3) self.assertEqual(n, 2) self.assertEqual(list(v), [30,31,32]) n, v = o.nullfillArray_count_(None, 3) self.assertEqual(n, 2) self.assertEqual(list(v), [30,31,32]) n, v = o.nullfillArray_count_(objc.NULL, 3) self.assertEqual(n, 1) #self.assertIs(v, objc.NULL ) def testWithCountInResult(self): o = Py_MetaDataTest_AllArgs.new() c, v = o.fillArray_uptoCount_(20) self.assertEqual(c, 10) self.assertEqual(list(v), [i+10 for i in range(10)]) c, v = o.maybeFillArray_() self.assertEqual(c, 2) self.assertEqual(list(v), [0, 1]) if 0: class TestArraysOut_OutputOptional (TestCase): def testFixedSize(self): o = Py_MetaDataTest_OutputOptional.new() v = o.fill4Tuple_() self.assertEqual(list(v), list(range(9, 13))) v = o.fill4Tuple_(None) self.assertEqual(list(v), list(range(9, 13))) self.assertRaises(ValueError, OC_MetaDataTest.fill4Tuple_on_, objc.NULL, o) n, v = o.nullfill4Tuple_() self.assertEqual(n, 1) self.assertEqual(list(v), list(range(1, 5))) n, v = o.nullfill4Tuple_(None) self.assertEqual(n, 1) self.assertEqual(list(v), list(range(1, 5))) n, v = o.nullfill4Tuple_(objc.NULL) #self.assertEqual(n, 2) #self.assertIs(v, objc.NULL) def testNullTerminated(self): o = Py_MetaDataTest_OutputOptional.new() # Output only arrays of null-terminated arrays cannot be # wrapped automaticly. How is the bridge supposed to know # how much memory it should allocate for the C-array? #self.assertRaises(TypeError, o.fillStringArray_) #self.assertRaises(TypeError, o.fillStringArray_, None) #self.assertRaises(ValueError, o.fillStringArray_, objc.NULL) #self.assertRaises(TypeError, o.nullfillStringArray_) #self.assertRaises(TypeError, o.nullfillStringArray_, None) #n, v = o.nullfillStringArray_(objc.NULL) #self.assertEqual(n, 9) #self.assertIs(v, objc.NULL) def testWithCount(self): o = Py_MetaDataTest_OutputOptional.new() v = o.fillArray_count_(3) self.assertEqual(list(v), [10, 11, 12]) v = o.fillArray_count_(None, 3) self.assertEqual(list(v), [10, 11, 12]) v = o.fillArray_count_(5) self.assertEqual(list(v), [10, 11, 12, 13, 14]) v = o.fillArray_count_(0) self.assertEqual(list(v), []) #self.assertRaises(ValueError, o.fillArray_count_, objc.NULL, 0) n, v = o.nullfillArray_count_(3) self.assertEqual(n, 2) self.assertEqual(list(v), [30,31,32]) n, v = o.nullfillArray_count_(None, 3) self.assertEqual(n, 2) self.assertEqual(list(v), [30,31,32]) n, v = o.nullfillArray_count_(objc.NULL, 3) #self.assertEqual(n, 1) #self.assertIs(v, objc.NULL) def testWithCountInResult(self): o = Py_MetaDataTest_OutputOptional.new() c, v = o.fillArray_uptoCount_(20) self.assertEqual(c, 10) self.assertEqual(list(v), [i+10 for i in range(10)]) c, v = o.maybeFillArray_() self.assertEqual(c, 2) self.assertEqual(list(v), [0, 1]) class TestArraysInOut_AllArgs (TestCase): def testFixedSize(self): o = Py_MetaDataTest_AllArgs.new() a = (1,2,3,4) v = o.reverse4Tuple_(a) self.assertEqual(a, (1,2,3,4)) self.assertEqual(list(v), [43, 44, 45, 46]) #self.assertRaises(ValueError, o.reverse4Tuple_, (1,2,3)) #self.assertRaises(ValueError, o.reverse4Tuple_, (1,2,3,4,5)) #self.assertRaises(ValueError, o.reverse4Tuple_, objc.NULL) a = (1,2,3,4) n, v = o.nullreverse4Tuple_(a) self.assertEqual(n, 1) self.assertEqual(a, (1,2,3,4)) self.assertEqual(list(v), [43, 44, 45, 46]) n, v = o.nullreverse4Tuple_(objc.NULL) self.assertEqual(n, -1) self.assertIs(v, objc.NULL) def testNullTerminated(self): o = Py_MetaDataTest_AllArgs.new() a = ('aap', 'boot', 'cello') v = o.reverseStrings_(a) self.assertEqual(a, ('aap', 'boot', 'cello')) self.assertEqual(list(v), ['paa', 'toob', 'ollec']) #self.assertRaises(ValueError, o.reverseStrings_, (1,2)) #self.assertRaises(ValueError, o.reverseStrings_, objc.NULL) a = ('aap', 'boot', 'cello') n, v = o.nullreverseStrings_(a) self.assertEqual(n, 10) self.assertEqual(a, ('aap', 'boot', 'cello')) self.assertEqual(list(v), ['paa', 'toob', 'ollec']) n, v = o.nullreverseStrings_(objc.NULL) self.assertEqual(n, 9) self.assertIs(v, objc.NULL) def testWithCount(self): o = Py_MetaDataTest_AllArgs.new() a = (1.0, 2.0, 3.0, 4.0, 5.0) v = o.reverseArray_count_(a, 4) self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) # Python->python: same semantics as normal python calls, therefore # the result is 5 long, and there is 2 added to the result (that is # the method sees the actual argument array instead of a truncated one) self.assertEqual(list(v[:4]), [3.0, 4.0, 5.0, 6.0]) a = (1.0, 2.0, 3.0, 4.0, 5.0) v = o.reverseArray_count_(a, 5) self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) self.assertEqual(list(v), [2.0, 3.0, 4.0, 5.0, 6.0]) # Nice to have, but doesn't work without major # surgery: #a = (1.0, 2.0, 3.0, 4.0, 5.0) #v = o.reverseArray_count_(a, None) #self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) #self.assertEqual(v, (2.0, 3.0, 4.0, 5.0, 6.0)) #self.assertRaises(ValueError, o.reverseArray_count_, (1.0, 2.0), 5) #self.assertRaises(ValueError, o.reverseArray_count_, objc.NULL, 0) a = (1.0, 2.0, 3.0, 4.0, 5.0) n, v = o.nullreverseArray_count_(a, 5) self.assertEqual(n, 9) self.assertEqual(a, (1.0, 2.0, 3.0, 4.0, 5.0)) self.assertEqual(list(v), [43.0, 44.0, 45.0, 46.0, 47.0]) n, v = o.nullreverseArray_count_(objc.NULL, 0) self.assertEqual(n, 2) self.assertIs(v, objc.NULL) def testWithCountInResult(self): o = Py_MetaDataTest_AllArgs.new() # XXX: caling python->python has the usual python semantics, hence # the argument won't be truncated! c, v = o.reverseArray_uptoCount_(range(10), 10) self.assertEqual(c, 5) self.assertEqual(len(v), 10) self.assertEqual(list(v)[:int(c)], [0, 10, 20, 30, 40]) c, v = o.maybeReverseArray_([1,2,3,4]) self.assertEqual(c, 2) self.assertEqual(len(v), 2) self.assertEqual(list(v), [45, 51]) class TestArraysIn_AllArgs (TestCase): def testFixedSize(self): o = Py_MetaDataTest_AllArgs.new() v, = o.make4Tuple_((1.0, 4.0, 8.0, 12.5)) self.assertEqual(len(v), 4) self.assertEqual(list(v), [1.0, 4.0, 8.0, 12.5]) v, = o.make4Tuple_((1, 2, 3, 4)) self.assertEqual(len(v), 4) self.assertEqual(list(v), [1.0, 2.0, 3.0, 4.0]) # XXX: Calling python->python has a the same semantics as a normal # python call. #self.assertRaises(ValueError, o.make4Tuple_, (1, 2, 3)) #self.assertRaises(ValueError, o.make4Tuple_, (1, 2, 3, 4, 5)) #self.assertRaises(ValueError, o.make4Tuple_, objc.NULL) v, = o.null4Tuple_(objc.NULL) self.assertIs(v, objc.NULL) def testNullTerminated(self): o = Py_MetaDataTest_AllArgs.new() v, = OC_MetaDataTest.makeStringArray_on_((b"hello", b"world", b"there"), o) self.assertEqual(len(v), 3) self.assertEqual(list(v), ["hello", "world", "there"]) NSObject = objc.lookUpClass('NSObject') p, q = NSObject.new(), NSObject.new() v, = o.makeObjectArray_((p, q)) self.assertEqual(len(v), 2) self.assertIs(v[0], p) self.assertIs(v[1], q) v, = OC_MetaDataTest.makeStringArray_on_((), o) self.assertEqual(len(v), 0) self.assertRaises(ValueError, OC_MetaDataTest.makeStringArray_on_, [1,2], o) self.assertRaises(ValueError, OC_MetaDataTest.makeStringArray_on_, objc.NULL, o) v, = OC_MetaDataTest.nullStringArray_on_(objc.NULL, o) self.assertEqual(v, objc.NULL) def testWithCount(self): o = Py_MetaDataTest_AllArgs.new() v, c = o.makeIntArray_count_((1,2,3,4), 3) self.assertEqual(c, 3) # Calling python -> python doesn't pass through C, hence the usual # python semantics are used which are slightly different from calling # into C or from C. self.assertEqual(len(v), 4) self.assertEqual(list(v)[:c], [1,2,3]) # XXX: This one would be nice to have, but not entirely trivial #v, c = o.makeIntArray_count_((1,2,3,4), None) #self.assertEqual(c, 3) #self.assertEqual(len(v), 3) #self.assertEqual(list(v), [1,2,3,4]) # See above #self.assertRaises(ValueError, o.makeIntArray_count_, [1,2,3], 4) #self.assertRaises(ValueError, o.makeIntArray_count_, objc.NULL, 0) #self.assertRaises(ValueError, o.makeIntArray_count_, objc.NULL, 1) v, c = o.nullIntArray_count_(objc.NULL, 0) self.assertEqual(c, 0) self.assertEqual(v, objc.NULL) # See above #self.assertRaises(ValueError, o.makeIntArray_count_, objc.NULL, 1) # Make sure this also works when the length is in a pass-by-reference argument v, c = o.makeIntArray_countPtr_((1,2,3,4), 4) self.assertEqual(c, 4) self.assertEqual(len(v), 4) self.assertEqual(list(v), [1,2,3,4]) class TestArrayReturns_AllArgs (TestCase): # TODO: # - Add null-terminated arrays of various supported types: # -> integers # -> CF-types def testFixedSize(self): o = Py_MetaDataTest_AllArgs.new() v = o.makeIntArrayOf5() self.assertEqual( len(v), 5 ) self.assertEqual( list(v), [100, 200, 300, 400, 500] ) v = o.nullIntArrayOf5() self.assertEqual(v, objc.NULL) def testSizeInArgument(self): o = Py_MetaDataTest_AllArgs.new() v = o.makeIntArrayOf_(3) self.assertEqual(len(v), 3) self.assertEqual(list(v), [20, 21, 22]) v = o.makeIntArrayOf_(10) self.assertEqual(len(v), 10) self.assertEqual(list(v), list(range(20, 30))) v = o.nullIntArrayOf_(100) self.assertEqual(v, objc.NULL) def testNULLterminated(self): o = Py_MetaDataTest_AllArgs.new() v = o.makeStringArray() self.assertEqual(len(v), 3) self.assertEqual(list(v), [ b"jaap", b"pieter", b"hans" ]) v = o.nullStringArray() self.assertEqual(v, objc.NULL) class TestByReference_AllArgs (TestCase): # Pass by reference arguments. # Note that these tests aren't exhaustive, we have test_methods and # test_methods2 for that :-) def testInput(self): o = Py_MetaDataTest_AllArgs.new() r = o.sumX_andY_(1, 2) self.assertEqual(r, 1**2+2**2) r = o.sumX_andY_(2535, 5325) self.assertEqual(r, 2535**2 + 5325**2) #self.assertRaises(ValueError, o.sumX_andY_, 42, objc.NULL) def testOutput(self): o = Py_MetaDataTest_AllArgs.new() div, rem = o.divBy5_remainder_(55) self.assertEqual(div, 55 / 7) self.assertEqual(rem, 55 % 7) div, rem = o.divBy5_remainder_(13) self.assertEqual(div, 13 / 7) self.assertEqual(rem, 13 % 7) # XXX: To be fixed: #self.assertRaises(ValueError, o.divBy5_remainder_, 42, objc.NULL) def testInputOutput(self): o = Py_MetaDataTest_AllArgs.new() x, y = o.swapX_andY_(42, 284) self.assertEqual(x, 284*2) self.assertEqual(y, 42*2) #self.assertRaises(ValueError, o.swapX_andY_, 42, objc.NULL) def testNullAccepted(self): # Note: the commented-out test-cases require a change in the pyobjc-core o = Py_MetaDataTest_AllArgs.new(); def makeNum(value): return int(value, 0) # All arguments present r, y, z = o.input_output_inputAndOutput_(1, 2) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 3) self.assertEqual(y, 9) self.assertEqual(z, 10) r, y, z = o.input_output_inputAndOutput_(1, None, 2) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 3) self.assertEqual(y, 9) self.assertEqual(z, 10) # Argument 1 is NULL r, y, z = o.input_output_inputAndOutput_(objc.NULL, 2) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) self.assertEqual(y, 11) self.assertEqual(z, 12) r, y, z = o.input_output_inputAndOutput_(objc.NULL, None, 2) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) self.assertEqual(y, 11) self.assertEqual(z, 12) # Argument 2 is NULL r, y, z = o.input_output_inputAndOutput_(1, objc.NULL, 2) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) self.assertEqual(y, 13) # objc.NULL ... self.assertEqual(z, 14) # Argument 3 is NULL r, y, z = o.input_output_inputAndOutput_(1, objc.NULL) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) self.assertEqual(y, 15) self.assertEqual(z, 16) # objc.NULL ... r, y, z = o.input_output_inputAndOutput_(1, None, objc.NULL) self.assertEqual(len(r), 3) self.assertEqual(len(list(filter(lambda x: x is not objc.NULL, r))), 2) self.assertEqual(y, 15) self.assertEqual(z, 16) # , objc.NULL) if __name__ == "__main__": main()