ObjectAccessorTests.swift 17 KB

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