SwiftSchemaTests.swift 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  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 Realm
  20. import Realm.Private
  21. class InitLinkedToClass: RLMObject {
  22. @objc dynamic var value = SwiftIntObject(value: [0])
  23. }
  24. class SwiftNonDefaultObject: RLMObject {
  25. @objc dynamic var value = 0
  26. public override class func shouldIncludeInDefaultSchema() -> Bool {
  27. return false
  28. }
  29. }
  30. class SwiftLinkedNonDefaultObject: RLMObject {
  31. @objc dynamic var obj: SwiftNonDefaultObject?
  32. public override class func shouldIncludeInDefaultSchema() -> Bool {
  33. return false
  34. }
  35. }
  36. class SwiftNonDefaultArrayObject: RLMObject {
  37. @objc dynamic var array = RLMArray<SwiftNonDefaultObject>(objectClassName: SwiftNonDefaultObject.className())
  38. public override class func shouldIncludeInDefaultSchema() -> Bool {
  39. return false
  40. }
  41. }
  42. class SwiftMutualLink1Object: RLMObject {
  43. @objc dynamic var object: SwiftMutualLink2Object?
  44. public override class func shouldIncludeInDefaultSchema() -> Bool {
  45. return false
  46. }
  47. }
  48. class SwiftMutualLink2Object: RLMObject {
  49. @objc dynamic var object: SwiftMutualLink1Object?
  50. public override class func shouldIncludeInDefaultSchema() -> Bool {
  51. return false
  52. }
  53. }
  54. class IgnoredLinkPropertyObject : RLMObject {
  55. @objc dynamic var value = 0
  56. var obj = SwiftIntObject()
  57. override class func ignoredProperties() -> [String] {
  58. return ["obj"]
  59. }
  60. }
  61. class SwiftRecursingSchemaTestObject : RLMObject {
  62. @objc dynamic var propertyWithIllegalDefaultValue: SwiftIntObject? = {
  63. if mayAccessSchema {
  64. let realm = RLMRealm.default()
  65. return SwiftIntObject.allObjects().firstObject() as! SwiftIntObject?
  66. } else {
  67. return nil
  68. }
  69. }()
  70. static var mayAccessSchema = false
  71. }
  72. class InvalidArrayType: FakeObject {
  73. @objc dynamic var array = RLMArray<SwiftIntObject>(objectClassName: "invalid class")
  74. }
  75. class InitAppendsToArrayProperty : RLMObject {
  76. @objc dynamic var propertyWithIllegalDefaultValue: RLMArray<SwiftIntObject> = {
  77. if mayAppend {
  78. let array = RLMArray<SwiftIntObject>(objectClassName: SwiftIntObject.className())
  79. array.add(SwiftIntObject())
  80. return array
  81. } else {
  82. return RLMArray<SwiftIntObject>(objectClassName: SwiftIntObject.className())
  83. }
  84. }()
  85. static var mayAppend = false
  86. }
  87. class SwiftSchemaTests: RLMMultiProcessTestCase {
  88. func testWorksAtAll() {
  89. if isParent {
  90. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  91. }
  92. }
  93. func testSchemaInitWithLinkedToObjectUsingInitWithValue() {
  94. if isParent {
  95. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  96. return
  97. }
  98. let config = RLMRealmConfiguration.default()
  99. config.objectClasses = [IgnoredLinkPropertyObject.self]
  100. config.inMemoryIdentifier = #function
  101. let r = try! RLMRealm(configuration: config)
  102. try! r.transaction {
  103. _ = IgnoredLinkPropertyObject.create(in: r, withValue: [1])
  104. }
  105. }
  106. func testCreateUnmanagedObjectWithUninitializedSchema() {
  107. if isParent {
  108. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  109. return
  110. }
  111. // Object in default schema
  112. _ = SwiftIntObject()
  113. // Object not in default schema
  114. _ = SwiftNonDefaultObject()
  115. }
  116. func testCreateUnmanagedObjectWithNestedObjectWithUninitializedSchema() {
  117. if isParent {
  118. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  119. return
  120. }
  121. // Objects in default schema
  122. // Should not throw (or crash) despite creating an object with an
  123. // unintialized schema during schema init
  124. _ = InitLinkedToClass()
  125. // Again with an object that links to an unintialized type
  126. // rather than creating one
  127. _ = SwiftCompanyObject()
  128. // Objects not in default schema
  129. _ = SwiftLinkedNonDefaultObject(value: [[1]])
  130. _ = SwiftNonDefaultArrayObject(value: [[[1]]])
  131. _ = SwiftMutualLink1Object(value: [[[:]]])
  132. }
  133. func testCreateUnmanagedObjectWhichCreatesAnotherClassViaInitWithValueDuringSchemaInit() {
  134. if isParent {
  135. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  136. return
  137. }
  138. _ = InitLinkedToClass(value: [[0]])
  139. _ = SwiftCompanyObject(value: [[["Jaden", 20, false]]])
  140. }
  141. func testInitUnmanagedObjectNotInClassSubsetDuringSchemaInit() {
  142. if isParent {
  143. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  144. return
  145. }
  146. let config = RLMRealmConfiguration.default()
  147. config.objectClasses = [IgnoredLinkPropertyObject.self]
  148. config.inMemoryIdentifier = #function
  149. _ = try! RLMRealm(configuration: config)
  150. let r = try! RLMRealm(configuration: RLMRealmConfiguration.default())
  151. try! r.transaction {
  152. _ = IgnoredLinkPropertyObject.create(in: r, withValue: [1])
  153. }
  154. }
  155. func testPreventsDeadLocks() {
  156. if isParent {
  157. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  158. return
  159. }
  160. SwiftRecursingSchemaTestObject.mayAccessSchema = true
  161. assertThrowsWithReasonMatching(RLMSchema.shared(), ".*recursive.*")
  162. }
  163. func testAccessSchemaCreatesObjectWhichAttempsInsertionsToArrayProperty() {
  164. if isParent {
  165. XCTAssertEqual(0, runChildAndWait(), "Tests in child process failed")
  166. return
  167. }
  168. // This is different from the above tests in that it is a to-many link
  169. // and it only occurs while the schema is initializing
  170. InitAppendsToArrayProperty.mayAppend = true
  171. assertThrowsWithReasonMatching(RLMSchema.shared(), ".*unless the schema is initialized.*")
  172. }
  173. func testInvalidObjectTypeForRLMArray() {
  174. RLMSetTreatFakeObjectAsRLMObject(true)
  175. assertThrowsWithReasonMatching(RLMObjectSchema(forObjectClass: InvalidArrayType.self),
  176. "RLMArray\\<invalid class\\>")
  177. RLMSetTreatFakeObjectAsRLMObject(false)
  178. }
  179. }