1# Some tests that verify that object identity is correctly retained
2# accross the bridge
3#
4# TODO:
5# - Add unittests here for every class that is treated specially by
6#   the bridge.
7# - Add unittests that test for "real-world" scenarios (writing stuff
8#   to plists, ...)
9# - Implement the required functionality
10
11import sys, os
12import objc
13from PyObjCTest.identity import *
14from PyObjCTools.TestSupport import *
15
16class TestPythonRoundTrip (TestCase):
17    # TODO: verify
18
19    def testBasicPython(self):
20
21        container = OC_TestIdentity.alloc().init()
22
23        for v in (self, object(), list, sum):
24            container.setStoredObject_(v)
25            self.assert_(v is container.storedObject(), repr(v))
26
27
28    def testPythonContainer(self):
29
30        container = OC_TestIdentity.alloc().init()
31
32        for v in ( [1, 2,3], (1,2,3), {1:2, 3:4} ):
33            container.setStoredObject_(v)
34            self.assert_(v is container.storedObject(), repr(v))
35
36    def dont_testPythonStrings(self):
37        # XXX: this test would always fail, this is by design.
38
39        container = OC_TestIdentity.alloc().init()
40
41        for v in ( u"Hello world", "Hello world" ):
42            container.setStoredObject_(v)
43            self.assert_(v is container.storedObject(), repr(v))
44
45    def dont_testPythonNumber(self):
46        # XXX: this test would always fail, need to move some code to C
47        # to fix (but not now)
48        container = OC_TestIdentity.alloc().init()
49
50        for v in (99999, 99999L, 10.0):
51            container.setStoredObject_(v)
52            self.assert_(v is container.storedObject, repr(v))
53
54
55class ObjCRoundTrip (TestCase):
56    # TODO: NSProxy
57
58    def testNSObject(self):
59        container = OC_TestIdentity.alloc().init()
60
61        cls = objc.lookUpClass("NSObject")
62        container.setStoredObjectToResultOf_on_("new", cls)
63
64        v = container.storedObject()
65        self.assert_(container.isSameObjectAsStored_(v), repr(v))
66
67        container.setStoredObjectToResultOf_on_("class", cls)
68        v = container.storedObject()
69        self.assert_(container.isSameObjectAsStored_(v), repr(v))
70
71    def testNSString(self):
72
73        container = OC_TestIdentity.alloc().init()
74
75        cls = objc.lookUpClass("NSObject")
76        container.setStoredObjectToResultOf_on_("description", cls)
77        v = container.storedObject()
78        self.assert_(container.isSameObjectAsStored_(v), repr(v))
79        self.assert_(isinstance(v, unicode))
80
81        cls = objc.lookUpClass("NSMutableString")
82        container.setStoredObjectToResultOf_on_("new", cls)
83        v = container.storedObject()
84        self.assert_(container.isSameObjectAsStored_(v), repr(v))
85        self.assert_(isinstance(v, unicode))
86
87    def testProtocol(self):
88        container = OC_TestIdentity.alloc().init()
89
90        container.setStoredObjectToAProtocol()
91        v = container.storedObject()
92        self.assert_(container.isSameObjectAsStored_(v), repr(v))
93        self.assert_(isinstance(v, objc.formal_protocol))
94
95    if sys.maxint < 2 ** 32:
96        def testObject(self):
97            container = OC_TestIdentity.alloc().init()
98            cls = objc.lookUpClass("Object")
99            container.setStoredObjectAnInstanceOfClassic_(cls)
100            v = container.storedObject()
101            self.assert_(container.isSameObjectAsStored_(v), repr(v))
102            self.assert_(isinstance(v, cls))
103
104    def testNSNumber(self):
105        container = OC_TestIdentity.alloc().init()
106
107        container.setStoredObjectToInteger_(10)
108        v = container.storedObject()
109        self.assert_(container.isSameObjectAsStored_(v), repr(v))
110
111        container.setStoredObjectToInteger_(-40)
112        v = container.storedObject()
113        self.assert_(container.isSameObjectAsStored_(v), repr(v))
114
115        container.setStoredObjectToUnsignedInteger_(40)
116        v = container.storedObject()
117        self.assert_(container.isSameObjectAsStored_(v), repr(v))
118
119        container.setStoredObjectToUnsignedInteger_(2 ** 32 - 4)
120        v = container.storedObject()
121        self.assert_(container.isSameObjectAsStored_(v), repr(v))
122
123        if sys.maxint < 2 ** 32:
124            container.setStoredObjectToLongLong_(sys.maxint * 2)
125            v = container.storedObject()
126            self.assert_(container.isSameObjectAsStored_(v), repr(v))
127
128        container.setStoredObjectToLongLong_(-sys.maxint)
129        v = container.storedObject()
130        self.assert_(container.isSameObjectAsStored_(v), repr(v))
131
132        container.setStoredObjectToUnsignedLongLong_(sys.maxint * 2)
133        v = container.storedObject()
134        self.assert_(container.isSameObjectAsStored_(v), repr(v))
135
136        container.setStoredObjectToFloat_(10.0)
137        v = container.storedObject()
138        self.assert_(container.isSameObjectAsStored_(v), repr(v))
139
140        container.setStoredObjectToDouble_(9999.0)
141        v = container.storedObject()
142        self.assert_(container.isSameObjectAsStored_(v), repr(v))
143
144    def testNSDecimalNumber(self):
145        container = OC_TestIdentity.alloc().init()
146        cls = objc.lookUpClass("NSDecimalNumber")
147        container.setStoredObjectToResultOf_on_("zero", cls)
148        v = container.storedObject()
149        self.assert_(container.isSameObjectAsStored_(v), repr(v))
150
151
152class ObjCtoPython (TestCase):
153    # TODO: NSProxy
154
155    def assertFetchingTwice(self, container, message = None):
156            v1 = container.storedObject()
157            v2 = container.storedObject()
158
159            self.assert_(v1 is v2, message)
160
161    def testNSObject(self):
162        container = OC_TestIdentity.alloc().init()
163
164        cls = objc.lookUpClass("NSObject")
165        container.setStoredObjectToResultOf_on_("new", cls)
166
167        self.assertFetchingTwice(container, repr(cls))
168
169        container.setStoredObjectToResultOf_on_("new", cls)
170        v1 = container.storedObject()
171        container.setStoredObjectToResultOf_on_("new", cls)
172        v2 = container.storedObject()
173        self.assert_(v1 is not v2, "different objects")
174
175    def dont_testNSString(self):
176        # This would always fail, NSStrings get a new proxy everytime
177        # they cross the bridge, otherwise it would be unnecessarily hard
178        # to get at the current value of NSMutableStrings.
179
180        container = OC_TestIdentity.alloc().init()
181
182        cls = objc.lookUpClass("NSObject")
183        container.setStoredObjectToResultOf_on_("description", cls)
184        self.assertFetchingTwice(container, "string")
185
186        cls = objc.lookUpClass("NSMutableString")
187        container.setStoredObjectToResultOf_on_("new", cls)
188        self.assertFetchingTwice(container, "mutable string")
189
190    def testProtocol(self):
191        container = OC_TestIdentity.alloc().init()
192
193        container.setStoredObjectToAProtocol()
194        v = container.storedObject()
195        self.assertFetchingTwice(container, "protocol")
196
197    if sys.maxint < 2**32:
198        def testObject(self):
199            container = OC_TestIdentity.alloc().init()
200
201            cls = objc.lookUpClass("Object")
202            container.setStoredObjectAnInstanceOfClassic_(cls)
203            self.assertFetchingTwice(container, "object")
204
205    def dont_testNSNumber(self):
206        # No unique proxies yet, due to the way these proxies are
207        # implemented. This needs to be fixed, but that does not have
208        # a high priority.
209        container = OC_TestIdentity.alloc().init()
210
211        container.setStoredObjectToInteger_(10)
212        self.assertFetchingTwice(container, "int 10")
213
214        container.setStoredObjectToInteger_(-40)
215        self.assertFetchingTwice(container, "int -40")
216
217        container.setStoredObjectToUnsignedInteger_(40)
218        self.assertFetchingTwice(container, "unsigned int 40")
219
220        container.setStoredObjectToUnsignedInteger_(sys.maxint * 2)
221        self.assertFetchingTwice(container, "unsigned int sys.maxint*2")
222
223        container.setStoredObjectToLongLong_(sys.maxint * 2)
224        self.assertFetchingTwice(container, "long long sys.maxint*2")
225
226        container.setStoredObjectToLongLong_(-sys.maxint)
227        self.assertFetchingTwice(container, "long long -sys.maxint")
228
229        container.setStoredObjectToUnsignedLongLong_(sys.maxint * 2)
230        self.assertFetchingTwice(container, "unsigned long long sys.maxint*2")
231
232        container.setStoredObjectToFloat_(10.0)
233        self.assertFetchingTwice(container, "float")
234
235        container.setStoredObjectToDouble_(9999.0)
236        self.assertFetchingTwice(container, "double")
237
238    def testNSDecimalNumber(self):
239        container = OC_TestIdentity.alloc().init()
240
241        cls = objc.lookUpClass("NSDecimalNumber")
242        container.setStoredObjectToResultOf_on_("zero", cls)
243        self.assertFetchingTwice(container, "decimal")
244
245class PythonToObjC (TestCase):
246    # TODO: verify
247
248    def testPlainObjects(self):
249        container = OC_TestIdentity.alloc().init()
250
251        for v in (self, object(), list, sum):
252            container.setStoredObject_(v)
253
254            self.assert_(container.isSameObjectAsStored_(v), repr(v))
255
256
257    def testContainers(self):
258        container = OC_TestIdentity.alloc().init()
259
260        for v in ([1,2,3], (1,2,3), {1:2, 3:4}):
261            container.setStoredObject_(v)
262
263            self.assert_(container.isSameObjectAsStored_(v), repr(v))
264
265    def dont_testStrings(self):
266        # These get converted, not proxied
267        container = OC_TestIdentity.alloc().init()
268
269        for v in ("hello world", u"a unicode string"):
270            container.setStoredObject_(v)
271
272            self.assert_(container.isSameObjectAsStored_(v), repr(v))
273
274    def dont_testNumbers(self):
275        # These get converted, not proxied
276        container = OC_TestIdentity.alloc().init()
277
278        for v in (1, 666666, 1L, 66666L, 1.0,):
279            container.setStoredObject_(v)
280
281            self.assert_(container.isSameObjectAsStored_(v), repr(v))
282
283class TestSerializingDataStructures (TestCase):
284    # OC_Python{Array,Dictionary} used to contain specialized
285    # identity-preservation code. It is unclear why this was added, it might
286    # have to do with writing data to plist files.
287    # This TestCase tries to trigger the problem that caused the addition of
288    # said code, although unsuccesfully...
289
290    def tearDown(self):
291        if os.path.exists("/tmp/pyPyObjCTest.identity"):
292            os.unlink("/tmp/pyPyObjCTest.identity")
293
294    def testMakePlist(self):
295        container = OC_TestIdentity.alloc().init()
296
297        value = [ 1, 2, 3, [ u"hello", [u"world", (u"in", 9 ) ], True, {u"aap":3}]]
298        value.append(value[3])
299
300        container.setStoredObject_(value)
301        container.writeStoredObjectToFile_(u"/tmp/pyPyObjCTest.identity")
302
303        value = {
304            u"hello": [ 1, 2, 3],
305            u"world": {
306                u"nl": u"wereld",
307                u"de": u"Welt",
308            }
309        }
310        container.setStoredObject_(value)
311        container.writeStoredObjectToFile_(u"/tmp/pyPyObjCTest.identity")
312
313
314
315if __name__ == "__main__":
316    main()
317