SwiftSyncTestCase.swift 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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 realmURL: URL = URL(string: "realm://127.0.0.1:9080/~/testBasicSync")!
  64. /// For testing, make a unique Realm URL of the form "realm://127.0.0.1:9080/~/X",
  65. /// where X is either a custom string passed as an argument, or an UUID string.
  66. static func uniqueRealmURL(customName: String? = nil) -> URL {
  67. return URL(string: "realm://127.0.0.1:9080/~/\(customName ?? UUID().uuidString)")!
  68. }
  69. func executeChild(file: StaticString = #file, line: UInt = #line) {
  70. XCTAssert(0 == runChildAndWait(), "Tests in child process failed", file: file, line: line)
  71. }
  72. func basicCredentials(register: Bool = true,
  73. usernameSuffix: String = "",
  74. file: StaticString = #file,
  75. line: UInt = #line) -> SyncCredentials {
  76. let filename = URL(fileURLWithPath: String(describing: file)).deletingPathExtension().lastPathComponent
  77. return .usernamePassword(username: "\(filename)\(line)\(usernameSuffix)", password: "a", register: register)
  78. }
  79. func synchronouslyOpenRealm(url: URL, user: SyncUser, file: StaticString = #file, line: UInt = #line) throws -> Realm {
  80. let config = user.configuration(realmURL: url, fullSynchronization: true)
  81. return try synchronouslyOpenRealm(configuration: config)
  82. }
  83. func synchronouslyOpenRealm(configuration: Realm.Configuration, file: StaticString = #file, line: UInt = #line) throws -> Realm {
  84. let semaphore = DispatchSemaphore(value: 0)
  85. let basicBlock = { (error: Error?) in
  86. if let error = error {
  87. let process = self.isParent ? "parent" : "child"
  88. XCTFail("Received an asynchronous error: \(error) (process: \(process))", file: file, line: line)
  89. }
  90. semaphore.signal()
  91. }
  92. SyncManager.shared.setSessionCompletionNotifier(basicBlock)
  93. let realm = try Realm(configuration: configuration)
  94. let result = semaphore.wait(timeout: .now() + DispatchTimeInterval.seconds(20))
  95. XCTAssertEqual(result, .success)
  96. return realm
  97. }
  98. func immediatelyOpenRealm(url: URL, user: SyncUser) throws -> Realm {
  99. return try Realm(configuration: user.configuration(realmURL: url, fullSynchronization: true))
  100. }
  101. func synchronouslyLogInUser(for credentials: SyncCredentials,
  102. server url: URL,
  103. file: StaticString = #file,
  104. line: UInt = #line) throws -> SyncUser {
  105. let process = isParent ? "parent" : "child"
  106. var theUser: SyncUser?
  107. var theError: Error?
  108. let ex = expectation(description: "Should log in the user properly")
  109. SyncUser.logIn(with: credentials, server: url) { user, error in
  110. XCTAssertNotNil(user, file: file, line: line)
  111. XCTAssertNil(error,
  112. "Error when trying to log in a user: \(error!) (process: \(process))",
  113. file: file,
  114. line: line)
  115. theUser = user
  116. theError = error
  117. ex.fulfill()
  118. }
  119. waitForExpectations(timeout: 10, handler: nil)
  120. XCTAssertNotNil(theUser, file: file, line: line)
  121. XCTAssertEqual(theUser?.state, .active,
  122. "User should have been valid, but wasn't. (process: \(process), error: "
  123. + "\(theError != nil ? String(describing: theError!) : "n/a"))",
  124. file: file,
  125. line: line)
  126. return theUser!
  127. }
  128. func waitForUploads(for realm: Realm) {
  129. waitForUploads(for: ObjectiveCSupport.convert(object: realm))
  130. }
  131. func waitForDownloads(for realm: Realm) {
  132. waitForDownloads(for: ObjectiveCSupport.convert(object: realm))
  133. }
  134. func checkCount<T: Object>(expected: Int,
  135. _ realm: Realm,
  136. _ type: T.Type,
  137. file: StaticString = #file,
  138. line: UInt = #line) {
  139. let actual = realm.objects(type).count
  140. XCTAssert(actual == expected,
  141. "Error: expected \(expected) items, but got \(actual) (process: \(isParent ? "parent" : "child"))",
  142. file: file,
  143. line: line)
  144. }
  145. }