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