ObjectAccessorTests.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2015 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. import XCTest
  19. import RealmSwift
  20. import Foundation
  21. class ObjectAccessorTests: TestCase {
  22. func setAndTestAllProperties(_ object: SwiftObject) {
  23. object.boolCol = true
  24. XCTAssertEqual(object.boolCol, true)
  25. object.boolCol = false
  26. XCTAssertEqual(object.boolCol, false)
  27. object.intCol = -1
  28. XCTAssertEqual(object.intCol, -1)
  29. object.intCol = 0
  30. XCTAssertEqual(object.intCol, 0)
  31. object.intCol = 1
  32. XCTAssertEqual(object.intCol, 1)
  33. object.floatCol = 20
  34. XCTAssertEqual(object.floatCol, 20 as Float)
  35. object.floatCol = 20.2
  36. XCTAssertEqual(object.floatCol, 20.2 as Float)
  37. object.floatCol = 16777217
  38. XCTAssertEqual(Double(object.floatCol), 16777216.0 as Double)
  39. object.doubleCol = 20
  40. XCTAssertEqual(object.doubleCol, 20)
  41. object.doubleCol = 20.2
  42. XCTAssertEqual(object.doubleCol, 20.2)
  43. object.doubleCol = 16777217
  44. XCTAssertEqual(object.doubleCol, 16777217)
  45. object.stringCol = ""
  46. XCTAssertEqual(object.stringCol, "")
  47. let utf8TestString = "值значен™👍☞⎠‱௹♣︎☐▼❒∑⨌⧭иеمرحبا"
  48. object.stringCol = utf8TestString
  49. XCTAssertEqual(object.stringCol, utf8TestString)
  50. let data = "b".data(using: String.Encoding.utf8, allowLossyConversion: false)!
  51. object.binaryCol = data
  52. XCTAssertEqual(object.binaryCol, data)
  53. let date = Date(timeIntervalSinceReferenceDate: 2)
  54. object.dateCol = date
  55. XCTAssertEqual(object.dateCol, date)
  56. object.objectCol = SwiftBoolObject(value: [true])
  57. XCTAssertEqual(object.objectCol!.boolCol, true)
  58. object.intEnumCol = .value1
  59. XCTAssertEqual(object.intEnumCol, .value1)
  60. object.intEnumCol = .value2
  61. XCTAssertEqual(object.intEnumCol, .value2)
  62. }
  63. func testUnmanagedAccessors() {
  64. let object = SwiftObject()
  65. setAndTestAllProperties(object)
  66. let optionalObject = SwiftOptionalObject()
  67. setAndTestAllOptionalProperties(optionalObject)
  68. }
  69. func testManagedAccessors() {
  70. let realm = try! Realm()
  71. realm.beginWrite()
  72. let object = realm.create(SwiftObject.self)
  73. let optionalObject = realm.create(SwiftOptionalObject.self)
  74. setAndTestAllProperties(object)
  75. setAndTestAllOptionalProperties(optionalObject)
  76. try! realm.commitWrite()
  77. }
  78. func testIntSizes() {
  79. let realm = realmWithTestPath()
  80. let v8 = Int8(1) << 6
  81. let v16 = Int16(1) << 12
  82. let v32 = Int32(1) << 30
  83. // 1 << 40 doesn't auto-promote to Int64 on 32-bit platforms
  84. let v64 = Int64(1) << 40
  85. try! realm.write {
  86. let obj = SwiftAllIntSizesObject()
  87. let testObject: () -> Void = {
  88. obj.objectSchema.properties.map { $0.name }.forEach { obj[$0] = 0 }
  89. obj["int8"] = NSNumber(value: v8)
  90. XCTAssertEqual((obj["int8"]! as! Int), Int(v8))
  91. obj["int16"] = NSNumber(value: v16)
  92. XCTAssertEqual((obj["int16"]! as! Int), Int(v16))
  93. obj["int32"] = NSNumber(value: v32)
  94. XCTAssertEqual((obj["int32"]! as! Int), Int(v32))
  95. obj["int64"] = NSNumber(value: v64)
  96. XCTAssertEqual((obj["int64"]! as! NSNumber), NSNumber(value: v64))
  97. obj.objectSchema.properties.map { $0.name }.forEach { obj[$0] = 0 }
  98. obj.setValue(NSNumber(value: v8), forKey: "int8")
  99. XCTAssertEqual((obj.value(forKey: "int8")! as! Int), Int(v8))
  100. obj.setValue(NSNumber(value: v16), forKey: "int16")
  101. XCTAssertEqual((obj.value(forKey: "int16")! as! Int), Int(v16))
  102. obj.setValue(NSNumber(value: v32), forKey: "int32")
  103. XCTAssertEqual((obj.value(forKey: "int32")! as! Int), Int(v32))
  104. obj.setValue(NSNumber(value: v64), forKey: "int64")
  105. XCTAssertEqual((obj.value(forKey: "int64")! as! NSNumber), NSNumber(value: v64))
  106. obj.objectSchema.properties.map { $0.name }.forEach { obj[$0] = 0 }
  107. obj.int8 = v8
  108. XCTAssertEqual(obj.int8, v8)
  109. obj.int16 = v16
  110. XCTAssertEqual(obj.int16, v16)
  111. obj.int32 = v32
  112. XCTAssertEqual(obj.int32, v32)
  113. obj.int64 = v64
  114. XCTAssertEqual(obj.int64, v64)
  115. }
  116. testObject()
  117. realm.add(obj)
  118. testObject()
  119. }
  120. let obj = realm.objects(SwiftAllIntSizesObject.self).first!
  121. XCTAssertEqual(obj.int8, v8)
  122. XCTAssertEqual(obj.int16, v16)
  123. XCTAssertEqual(obj.int32, v32)
  124. XCTAssertEqual(obj.int64, v64)
  125. }
  126. func testLongType() {
  127. let longNumber: Int64 = 17179869184
  128. let intNumber: Int64 = 2147483647
  129. let negativeLongNumber: Int64 = -17179869184
  130. let updatedLongNumber: Int64 = 8589934592
  131. let realm = realmWithTestPath()
  132. realm.beginWrite()
  133. realm.create(SwiftLongObject.self, value: [NSNumber(value: longNumber)])
  134. realm.create(SwiftLongObject.self, value: [NSNumber(value: intNumber)])
  135. realm.create(SwiftLongObject.self, value: [NSNumber(value: negativeLongNumber)])
  136. try! realm.commitWrite()
  137. let objects = realm.objects(SwiftLongObject.self)
  138. XCTAssertEqual(objects.count, Int(3), "3 rows expected")
  139. XCTAssertEqual(objects[0].longCol, longNumber, "2 ^ 34 expected")
  140. XCTAssertEqual(objects[1].longCol, intNumber, "2 ^ 31 - 1 expected")
  141. XCTAssertEqual(objects[2].longCol, negativeLongNumber, "-2 ^ 34 expected")
  142. realm.beginWrite()
  143. objects[0].longCol = updatedLongNumber
  144. try! realm.commitWrite()
  145. XCTAssertEqual(objects[0].longCol, updatedLongNumber, "After update: 2 ^ 33 expected")
  146. }
  147. func testListsDuringResultsFastEnumeration() {
  148. let realm = realmWithTestPath()
  149. let object1 = SwiftObject()
  150. let object2 = SwiftObject()
  151. let trueObject = SwiftBoolObject()
  152. trueObject.boolCol = true
  153. let falseObject = SwiftBoolObject()
  154. falseObject.boolCol = false
  155. object1.arrayCol.append(trueObject)
  156. object1.arrayCol.append(falseObject)
  157. object2.arrayCol.append(trueObject)
  158. object2.arrayCol.append(falseObject)
  159. try! realm.write {
  160. realm.add(object1)
  161. realm.add(object2)
  162. }
  163. let objects = realm.objects(SwiftObject.self)
  164. let firstObject = objects.first
  165. XCTAssertEqual(2, firstObject!.arrayCol.count)
  166. let lastObject = objects.last
  167. XCTAssertEqual(2, lastObject!.arrayCol.count)
  168. var iterator = objects.makeIterator()
  169. let next = iterator.next()!
  170. XCTAssertEqual(next.arrayCol.count, 2)
  171. for obj in objects {
  172. XCTAssertEqual(2, obj.arrayCol.count)
  173. }
  174. }
  175. func testSettingOptionalPropertyOnDeletedObjectsThrows() {
  176. let realm = try! Realm()
  177. try! realm.write {
  178. let obj = realm.create(SwiftOptionalObject.self)
  179. let copy = realm.objects(SwiftOptionalObject.self).first!
  180. realm.delete(obj)
  181. self.assertThrows(copy.optIntCol.value = 1)
  182. self.assertThrows(copy.optIntCol.value = nil)
  183. self.assertThrows(obj.optIntCol.value = 1)
  184. self.assertThrows(obj.optIntCol.value = nil)
  185. }
  186. }
  187. func setAndTestAllOptionalProperties(_ object: SwiftOptionalObject) {
  188. object.optNSStringCol = ""
  189. XCTAssertEqual(object.optNSStringCol!, "")
  190. let utf8TestString = "值значен™👍☞⎠‱௹♣︎☐▼❒∑⨌⧭иеمرحبا"
  191. object.optNSStringCol = utf8TestString as NSString?
  192. XCTAssertEqual(object.optNSStringCol! as String, utf8TestString)
  193. object.optNSStringCol = nil
  194. XCTAssertNil(object.optNSStringCol)
  195. object.optStringCol = ""
  196. XCTAssertEqual(object.optStringCol!, "")
  197. object.optStringCol = utf8TestString
  198. XCTAssertEqual(object.optStringCol!, utf8TestString)
  199. object.optStringCol = nil
  200. XCTAssertNil(object.optStringCol)
  201. let data = "b".data(using: String.Encoding.utf8, allowLossyConversion: false)!
  202. object.optBinaryCol = data
  203. XCTAssertEqual(object.optBinaryCol!, data)
  204. object.optBinaryCol = nil
  205. XCTAssertNil(object.optBinaryCol)
  206. let date = Date(timeIntervalSinceReferenceDate: 2)
  207. object.optDateCol = date
  208. XCTAssertEqual(object.optDateCol!, date)
  209. object.optDateCol = nil
  210. XCTAssertNil(object.optDateCol)
  211. object.optIntCol.value = Int.min
  212. XCTAssertEqual(object.optIntCol.value!, Int.min)
  213. object.optIntCol.value = 0
  214. XCTAssertEqual(object.optIntCol.value!, 0)
  215. object.optIntCol.value = Int.max
  216. XCTAssertEqual(object.optIntCol.value!, Int.max)
  217. object.optIntCol.value = nil
  218. XCTAssertNil(object.optIntCol.value)
  219. object.optInt8Col.value = Int8.min
  220. XCTAssertEqual(object.optInt8Col.value!, Int8.min)
  221. object.optInt8Col.value = 0
  222. XCTAssertEqual(object.optInt8Col.value!, 0)
  223. object.optInt8Col.value = Int8.max
  224. XCTAssertEqual(object.optInt8Col.value!, Int8.max)
  225. object.optInt8Col.value = nil
  226. XCTAssertNil(object.optInt8Col.value)
  227. object.optInt16Col.value = Int16.min
  228. XCTAssertEqual(object.optInt16Col.value!, Int16.min)
  229. object.optInt16Col.value = 0
  230. XCTAssertEqual(object.optInt16Col.value!, 0)
  231. object.optInt16Col.value = Int16.max
  232. XCTAssertEqual(object.optInt16Col.value!, Int16.max)
  233. object.optInt16Col.value = nil
  234. XCTAssertNil(object.optInt16Col.value)
  235. object.optInt32Col.value = Int32.min
  236. XCTAssertEqual(object.optInt32Col.value!, Int32.min)
  237. object.optInt32Col.value = 0
  238. XCTAssertEqual(object.optInt32Col.value!, 0)
  239. object.optInt32Col.value = Int32.max
  240. XCTAssertEqual(object.optInt32Col.value!, Int32.max)
  241. object.optInt32Col.value = nil
  242. XCTAssertNil(object.optInt32Col.value)
  243. object.optInt64Col.value = Int64.min
  244. XCTAssertEqual(object.optInt64Col.value!, Int64.min)
  245. object.optInt64Col.value = 0
  246. XCTAssertEqual(object.optInt64Col.value!, 0)
  247. object.optInt64Col.value = Int64.max
  248. XCTAssertEqual(object.optInt64Col.value!, Int64.max)
  249. object.optInt64Col.value = nil
  250. XCTAssertNil(object.optInt64Col.value)
  251. object.optFloatCol.value = -Float.greatestFiniteMagnitude
  252. XCTAssertEqual(object.optFloatCol.value!, -Float.greatestFiniteMagnitude)
  253. object.optFloatCol.value = 0
  254. XCTAssertEqual(object.optFloatCol.value!, 0)
  255. object.optFloatCol.value = Float.greatestFiniteMagnitude
  256. XCTAssertEqual(object.optFloatCol.value!, Float.greatestFiniteMagnitude)
  257. object.optFloatCol.value = nil
  258. XCTAssertNil(object.optFloatCol.value)
  259. object.optDoubleCol.value = -Double.greatestFiniteMagnitude
  260. XCTAssertEqual(object.optDoubleCol.value!, -Double.greatestFiniteMagnitude)
  261. object.optDoubleCol.value = 0
  262. XCTAssertEqual(object.optDoubleCol.value!, 0)
  263. object.optDoubleCol.value = Double.greatestFiniteMagnitude
  264. XCTAssertEqual(object.optDoubleCol.value!, Double.greatestFiniteMagnitude)
  265. object.optDoubleCol.value = nil
  266. XCTAssertNil(object.optDoubleCol.value)
  267. object.optBoolCol.value = true
  268. XCTAssertEqual(object.optBoolCol.value!, true)
  269. object.optBoolCol.value = false
  270. XCTAssertEqual(object.optBoolCol.value!, false)
  271. object.optBoolCol.value = nil
  272. XCTAssertNil(object.optBoolCol.value)
  273. object.optObjectCol = SwiftBoolObject(value: [true])
  274. XCTAssertEqual(object.optObjectCol!.boolCol, true)
  275. object.optObjectCol = nil
  276. XCTAssertNil(object.optObjectCol)
  277. object.optEnumCol.value = .value1
  278. XCTAssertEqual(object.optEnumCol.value, .value1)
  279. object.optEnumCol.value = .value2
  280. XCTAssertEqual(object.optEnumCol.value, .value2)
  281. object.optEnumCol.value = nil
  282. XCTAssertNil(object.optEnumCol.value)
  283. }
  284. func testLinkingObjectsDynamicGet() {
  285. let fido = SwiftDogObject()
  286. let owner = SwiftOwnerObject()
  287. owner.dog = fido
  288. owner.name = "JP"
  289. let realm = try! Realm()
  290. try! realm.write {
  291. realm.add([fido, owner])
  292. }
  293. // Get the linking objects property via subscript.
  294. let dynamicOwners = fido["owners"]
  295. guard let owners = dynamicOwners else {
  296. XCTFail("Got an unexpected nil for fido[\"owners\"]")
  297. return
  298. }
  299. XCTAssertTrue(owners is LinkingObjects<SwiftOwnerObject>)
  300. // Make sure the results actually functions.
  301. guard let firstOwner = (owners as? LinkingObjects<SwiftOwnerObject>)?.first else {
  302. XCTFail("Was not able to get first owner")
  303. return
  304. }
  305. XCTAssertEqual(firstOwner.name, "JP")
  306. }
  307. func testRenamedProperties() {
  308. let obj = SwiftRenamedProperties1()
  309. obj.propA = 5
  310. obj.propB = "a"
  311. let link = LinkToSwiftRenamedProperties1()
  312. link.linkA = obj
  313. link.array1.append(obj)
  314. let realm = try! Realm()
  315. try! realm.write {
  316. realm.add(link)
  317. }
  318. XCTAssertEqual(obj.propA, 5)
  319. XCTAssertEqual(obj.propB, "a")
  320. XCTAssertTrue(link.linkA!.isSameObject(as: obj))
  321. XCTAssertTrue(link.array1[0].isSameObject(as: obj))
  322. XCTAssertTrue(obj.linking1[0].isSameObject(as: link))
  323. XCTAssertEqual(obj["propA"]! as! Int, 5)
  324. XCTAssertEqual(obj["propB"]! as! String, "a")
  325. XCTAssertTrue((link["linkA"]! as! SwiftRenamedProperties1).isSameObject(as: obj))
  326. XCTAssertTrue((link["array1"]! as! List<SwiftRenamedProperties1>)[0].isSameObject(as: obj))
  327. XCTAssertTrue((obj["linking1"]! as! LinkingObjects<LinkToSwiftRenamedProperties1>)[0].isSameObject(as: link))
  328. XCTAssertTrue(link.dynamicList("array1")[0].isSameObject(as: obj))
  329. let obj2 = realm.objects(SwiftRenamedProperties2.self).first!
  330. let link2 = realm.objects(LinkToSwiftRenamedProperties2.self).first!
  331. XCTAssertEqual(obj2.propC, 5)
  332. XCTAssertEqual(obj2.propD, "a")
  333. XCTAssertTrue(link2.linkC!.isSameObject(as: obj))
  334. XCTAssertTrue(link2.array2[0].isSameObject(as: obj))
  335. XCTAssertTrue(obj2.linking1[0].isSameObject(as: link))
  336. XCTAssertEqual(obj2["propC"]! as! Int, 5)
  337. XCTAssertEqual(obj2["propD"]! as! String, "a")
  338. XCTAssertTrue((link2["linkC"]! as! SwiftRenamedProperties1).isSameObject(as: obj))
  339. XCTAssertTrue((link2["array2"]! as! List<SwiftRenamedProperties2>)[0].isSameObject(as: obj))
  340. XCTAssertTrue((obj2["linking1"]! as! LinkingObjects<LinkToSwiftRenamedProperties1>)[0].isSameObject(as: link))
  341. XCTAssertTrue(link2.dynamicList("array2")[0].isSameObject(as: obj))
  342. }
  343. func testPropertiesOutlivingParentObject() {
  344. var optional: RealmOptional<Int>!
  345. var list: List<Int>!
  346. let realm = try! Realm()
  347. try! realm.write {
  348. autoreleasepool {
  349. optional = realm.create(SwiftOptionalObject.self, value: ["optIntCol": 1]).optIntCol
  350. list = realm.create(SwiftListObject.self, value: ["int": [1]]).int
  351. }
  352. }
  353. // Verify that we can still read the correct value
  354. XCTAssertEqual(optional.value, 1)
  355. XCTAssertEqual(list.count, 1)
  356. XCTAssertEqual(list[0], 1)
  357. // Verify that we can modify the values via the standalone property objects and
  358. // have it properly update the parent
  359. try! realm.write {
  360. optional.value = 2
  361. list.append(2)
  362. }
  363. XCTAssertEqual(optional.value, 2)
  364. XCTAssertEqual(list.count, 2)
  365. XCTAssertEqual(list[0], 1)
  366. XCTAssertEqual(list[1], 2)
  367. autoreleasepool {
  368. XCTAssertEqual(realm.objects(SwiftOptionalObject.self).first!.optIntCol.value, 2)
  369. XCTAssertEqual(Array(realm.objects(SwiftListObject.self).first!.int), [1, 2])
  370. }
  371. try! realm.write {
  372. optional.value = nil
  373. list.removeAll()
  374. }
  375. XCTAssertEqual(optional.value, nil)
  376. XCTAssertEqual(list.count, 0)
  377. autoreleasepool {
  378. XCTAssertEqual(realm.objects(SwiftOptionalObject.self).first!.optIntCol.value, nil)
  379. XCTAssertEqual(Array(realm.objects(SwiftListObject.self).first!.int), [])
  380. }
  381. }
  382. }