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