1from __future__ import unicode_literals 2from PyObjCTools.TestSupport import * 3from PyObjCTest import structargs 4from PyObjCTest import testbndl 5from PyObjCTest import copying 6 7import objc, sys 8from PyObjCTest.fnd import NSObject, NSAutoreleasePool 9 10rct = structargs.StructArgClass.someRect.__metadata__()['retval']['type'] 11 12class OCTestRegrWithGetItem (NSObject): 13 def objectForKey_(self, k): 14 return "ofk: %s"%(k,) 15 16 def __getitem__(self, k): 17 return "gi: %s"%(k,) 18 19class OCTestRegrWithGetItem2 (OCTestRegrWithGetItem): 20 def objectForKey_(self, k): 21 return "ofk2: %s"%(k,) 22 23class ReturnAStruct (NSObject): 24 def someRectWithRect_(self, aRect): 25 ((x, y), (h, w)) = aRect 26 return ((x,y),(h,w)) 27 someRectWithRect_ = objc.selector(someRectWithRect_, signature=rct + b'@:' + rct) 28 29 30class TestRegressions(TestCase): 31 def testNSObjectRespondsToCommonMethods(self): 32 self.assertTrue(NSObject.pyobjc_classMethods.respondsToSelector_('alloc')) 33 self.assertTrue(NSObject.instancesRespondToSelector_('init')) 34 self.assertFalse(NSObject.instancesRespondToSelector_('frodel')) 35 36 37 def testDeallocUninit(self): 38 import objc 39 40 import warnings 41 warnings.filterwarnings('ignore', 42 category=objc.UninitializedDeallocWarning) 43 44 try: 45 for clsName in [ 'NSURL', 'NSObject', 'NSArray' ]: 46 d = objc.lookUpClass(clsName).alloc() 47 del d 48 49 finally: 50 del warnings.filters[0] 51 52 # Check that we generate a warning for unitialized objects that 53 # get deallocated 54 import sys 55 if sys.version_info[0] == 2: 56 from StringIO import StringIO 57 else: 58 from io import StringIO 59 warnings.filterwarnings('always', 60 category=objc.UninitializedDeallocWarning) 61 sys.stderr = buf = StringIO() 62 try: 63 d = NSObject.alloc() 64 del d 65 66 finally: 67 del warnings.filters[0] 68 sys.stderr = sys.__stderr__ 69 70 # A warning is three lines: location info, source code, empty line 71 self.assertEqual(len(buf.getvalue().split('\n')), 3) 72 73 def testOneWayMethods(self): 74 # This one should be in test_methods*.py 75 from PyObjCTest.initialize import OC_TestInitialize 76 77 o = OC_TestInitialize.alloc().init() 78 self.assertEqual(objc.splitSignature(o.onewayVoidMethod.signature), (objc._C_ONEWAY + objc._C_VOID, objc._C_ID, objc._C_SEL)) 79 80 # Make sure we can call the method 81 o.onewayVoidMethod() 82 self.assertEqual(o.isInitialized(), -1) 83 84 85 def testNoneAsSelf (self): 86 class SelfIsNone (NSObject): 87 def f(x): 88 pass 89 90 self.assertRaises(TypeError, NSObject.pyobjc_instanceMethods.description, None) 91 self.assertRaises(TypeError, SelfIsNone.pyobjc_instanceMethods.f, None) 92 93 def testOneArgumentTooMany (self): 94 class ClsIsNone (NSObject): 95 @classmethod 96 def f(cls): 97 pass 98 99 object = NSObject.alloc().init() 100 101 self.assertRaises(TypeError, object.description, None) 102 self.assertRaises(TypeError, object.description, "twelf") 103 self.assertRaises(TypeError, NSObject.description, None) 104 self.assertRaises(TypeError, ClsIsNone.f, None) 105 106 107 def testStructArgs (self): 108 # Like AppKit.test.test_nsimage.TestNSImage.test_compositePoint 109 # unlike that this one doesn't crash on darwin/x86, makeing it less 110 # likely that libffi is at fault 111 112 o = structargs.StructArgClass.alloc().init() 113 v = o.compP_aRect_anOp_((1,2), ((3,4),(5,6)), 7) 114 self.assertEqual(v, "aP:{1, 2} aR:{{3, 4}, {5, 6}} anO:7") 115 116 def testInitialize(self): 117 calls=[] 118 self.assertEqual(len(calls), 0) 119 120 class InitializeTestClass (NSObject): 121 @classmethod 122 def initialize(cls): 123 calls.append(repr(cls)) 124 125 o = InitializeTestClass.new() 126 self.assertEqual(len(calls), 1) 127 o = InitializeTestClass.new() 128 self.assertEqual(len(calls), 1) 129 130 def testPrivateIntrospection(self): 131 o = testbndl.PyObjC_TestClass4.alloc().init() 132 self.assertEqual(o._privateMethodWithArg_(1.5), 1) 133 self.assertEqual(o._privateMethodWithArg_(-2.5), -2) 134 135 imp = testbndl.PyObjC_TestClass4.instanceMethodForSelector_('_privateMethodWithArg:') 136 self.assertEqual(imp.signature, b'i@:f') 137 138 sel = testbndl.PyObjC_TestClass4._privateMethodWithArg_ 139 self.assertEqual(sel.signature, b'i@:f') 140 141 def testStructReturnPy(self): 142 o = ReturnAStruct.alloc().init() 143 p = structargs.StructArgClass.alloc().init() 144 145 v = p.someRectWithObject_X_Y_H_W_(o, 1, 2, 3, 4) 146 self.assertEqual(v, ((1,2),(3,4))) 147 148 def testStructReturn(self): 149 o = structargs.StructArgClass.alloc().init() 150 v = o.someRect() 151 self.assertEqual(v, ((1,2),(3,4))) 152 153 154 155if sys.byteorder == 'little': 156 # i386 has specific stack alignment requirements. 157 158 class AlignmentTestClass(NSObject): 159 def testWithObject_(self, obj): 160 return obj.stackPtr() 161 162 163 def testStackPtr(self): 164 o = structargs.StructArgClass.alloc().init() 165 166 p = self.AlignmentTestClass.alloc().init() 167 self.assertEqual(p.testWithObject_(o) % 16, o.stackPtr() % 16) 168 169 170 171# 172# Regression in retainCount management when a Python object 173# is created from Objective-C. This only happened when the 174# Python class has an implementation of the designated initializer. 175# 176# Mentioned by Dirk Stoop on the Pyobjc-dev mailing-list. 177# 178 179gDeallocCounter = 0 180class OC_LeakTest_20090704_init (NSObject): 181 def init(self): 182 #self = super(OC_LeakTest_20090704_init, self).init() 183 return self 184 185 def dealloc(self): 186 global gDeallocCounter 187 gDeallocCounter += 1 188 189class OC_LeakTest_20090704_noinit (NSObject): 190 def dealloc(self): 191 global gDeallocCounter 192 gDeallocCounter += 1 193 194 195class TestInitMemoryLeak (TestCase): 196 def testNoPythonInit(self): 197 # This test is basicly a self-test of the test-case, the 198 # test even passed before the regression was fixed. 199 200 global gDeallocCounter 201 202 pool = NSAutoreleasePool.alloc().init() 203 try: 204 v = copying.OC_CopyHelper.newObjectOfClass_(OC_LeakTest_20090704_noinit) 205 self.assertIsInstance(v, OC_LeakTest_20090704_noinit) 206 207 gDeallocCounter = 0 208 del v 209 210 finally: 211 del pool 212 213 self.assertNotEqual(gDeallocCounter, 0) 214 215 def testWithPythonInit(self): 216 global gDeallocCounter 217 218 pool = NSAutoreleasePool.alloc().init() 219 try: 220 v = copying.OC_CopyHelper.newObjectOfClass_(OC_LeakTest_20090704_init) 221 self.assertIsInstance(v, OC_LeakTest_20090704_init) 222 223 gDeallocCounter = 0 224 del v 225 226 finally: 227 del pool 228 229 self.assertNotEqual(gDeallocCounter, 0) 230 231 def testInitFailureLeaks(self): 232 NSData = objc.lookUpClass('NSData') 233 import warnings 234 warnings.filterwarnings('error', 235 category=objc.UninitializedDeallocWarning) 236 237 try: 238 try: 239 v = NSData.alloc().initWithContentsOfFile_("/etc/no-such-file.txt") 240 finally: 241 del warnings.filters[0] 242 243 except objc.UninitializedDeallocWarning: 244 self.fail("Unexpected raising of UninitializedDeallocWarning") 245 246 self.assertFalse(v is not None) 247 248 def testExplicitGetItem(self): 249 v = OCTestRegrWithGetItem.alloc().init() 250 251 self.assertEqual(v.objectForKey_("foo"), "ofk: foo") 252 self.assertEqual(v["foo"], "gi: foo") 253 254 v = OCTestRegrWithGetItem2.alloc().init() 255 self.assertEqual(v.objectForKey_("foo"), "ofk2: foo") 256 self.assertEqual(v["foo"], "gi: foo") 257 258 259if __name__ == '__main__': 260 main() 261