SwiftSyncTestCase.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 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. class SwiftSyncObject: Object {
  21. @objc dynamic var stringProp: String = ""
  22. }
  23. class SwiftHugeSyncObject: Object {
  24. @objc dynamic var dataProp: NSData?
  25. required init() {
  26. super.init()
  27. let size = 1000000
  28. let ptr = malloc(size)
  29. dataProp = NSData(bytes: ptr, length: size)
  30. free(ptr)
  31. }
  32. required init(realm: RLMRealm, schema: RLMObjectSchema) {
  33. fatalError("init(realm:schema:) has not been implemented")
  34. }
  35. required init(value: Any, schema: RLMSchema) {
  36. fatalError("init(value:schema:) has not been implemented")
  37. }
  38. }
  39. class SwiftPartialSyncObjectA: Object {
  40. @objc dynamic var number: Int = 0
  41. @objc dynamic var string: String = ""
  42. convenience init(number: Int, string: String) {
  43. self.init()
  44. self.number = number
  45. self.string = string
  46. }
  47. }
  48. class SwiftPartialSyncObjectB: Object {
  49. @objc dynamic var number: Int = 0
  50. @objc dynamic var firstString: String = ""
  51. @objc dynamic var secondString: String = ""
  52. convenience init(number: Int, firstString: String, secondString: String) {
  53. self.init()
  54. self.number = number
  55. self.firstString = firstString
  56. self.secondString = secondString
  57. }
  58. }
  59. // MARK: Test case
  60. class SwiftSyncTestCase: RLMSyncTestCase {
  61. var task: Process?
  62. let authURL: URL = URL(string: "http://127.0.0.1:9080")!
  63. let slowConnectAuthURL: URL = URL(string: "http://127.0.0.1:9083")!
  64. let realmURL: URL = URL(string: "realm://127.0.0.1:9080/~/testBasicSync")!
  65. /// For testing, make a unique Realm URL of the form "realm://127.0.0.1:9080/~/X",
  66. /// where X is either a custom string passed as an argument, or an UUID string.
  67. static func uniqueRealmURL(customName: String? = nil) -> URL {
  68. return URL(string: "realm://127.0.0.1:9080/~/\(customName ?? UUID().uuidString)")!
  69. }
  70. func executeChild(file: StaticString = #file, line: UInt = #line) {
  71. XCTAssert(0 == runChildAndWait(), "Tests in child process failed", file: file, line: line)
  72. }
  73. func basicCredentials(register: Bool = true,
  74. usernameSuffix: String = "",
  75. file: StaticString = #file,
  76. line: UInt = #line) -> SyncCredentials {
  77. let filename = URL(fileURLWithPath: String(describing: file)).deletingPathExtension().lastPathComponent
  78. return .usernamePassword(username: "\(filename)\(line)\(usernameSuffix)", password: "a", register: register)
  79. }
  80. func synchronouslyOpenRealm(url: URL, user: SyncUser, file: StaticString = #file, line: UInt = #line) throws -> Realm {
  81. let config = user.configuration(realmURL: url, fullSynchronization: true)
  82. return try synchronouslyOpenRealm(configuration: config)
  83. }
  84. func synchronouslyOpenRealm(configuration: Realm.Configuration, file: StaticString = #file, line: UInt = #line) throws -> Realm {
  85. let semaphore = DispatchSemaphore(value: 0)
  86. let basicBlock = { (error: Error?) in
  87. if let error = error {
  88. let process = self.isParent ? "parent" : "child"
  89. XCTFail("Received an asynchronous error: \(error) (process: \(process))", file: file, line: line)
  90. }
  91. semaphore.signal()
  92. }
  93. SyncManager.shared.setSessionCompletionNotifier(basicBlock)
  94. let realm = try Realm(configuration: configuration)
  95. let result = semaphore.wait(timeout: .now() + DispatchTimeInterval.seconds(20))
  96. SyncManager.shared.setSessionCompletionNotifier(nil)
  97. XCTAssertEqual(result, .success)
  98. return realm
  99. }
  100. func immediatelyOpenRealm(url: URL, user: SyncUser) throws -> Realm {
  101. return try Realm(configuration: user.configuration(realmURL: url, fullSynchronization: true))
  102. }
  103. func synchronouslyLogInUser(for credentials: SyncCredentials,
  104. server url: URL,
  105. file: StaticString = #file,
  106. line: UInt = #line) throws -> SyncUser {
  107. let process = isParent ? "parent" : "child"
  108. var theUser: SyncUser?
  109. var theError: Error?
  110. let ex = expectation(description: "Should log in the user properly")
  111. SyncUser.logIn(with: credentials, server: url) { user, error in
  112. XCTAssertNotNil(user, file: file, line: line)
  113. XCTAssertNil(error,
  114. "Error when trying to log in a user: \(error!) (process: \(process))",
  115. file: file,
  116. line: line)
  117. theUser = user
  118. theError = error
  119. ex.fulfill()
  120. }
  121. waitForExpectations(timeout: 10, handler: nil)
  122. XCTAssertNotNil(theUser, file: file, line: line)
  123. XCTAssertEqual(theUser?.state, .active,
  124. "User should have been valid, but wasn't. (process: \(process), error: "
  125. + "\(theError != nil ? String(describing: theError!) : "n/a"))",
  126. file: file,
  127. line: line)
  128. return theUser!
  129. }
  130. func waitForUploads(for realm: Realm) {
  131. waitForUploads(for: ObjectiveCSupport.convert(object: realm))
  132. }
  133. func waitForDownloads(for realm: Realm) {
  134. waitForDownloads(for: ObjectiveCSupport.convert(object: realm))
  135. }
  136. func checkCount<T: Object>(expected: Int,
  137. _ realm: Realm,
  138. _ type: T.Type,
  139. file: StaticString = #file,
  140. line: UInt = #line) {
  141. let actual = realm.objects(type).count
  142. XCTAssert(actual == expected,
  143. "Error: expected \(expected) items, but got \(actual) (process: \(isParent ? "parent" : "child"))",
  144. file: file,
  145. line: line)
  146. }
  147. }