SwiftSchemaTests.swift 7.0 KB

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