123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- import XCTest
- import RealmSwift
- class ThreadSafeReferenceTests: TestCase {
-
- func assertResolve<T>(_ realm: Realm, _ reference: ThreadSafeReference<T>) -> T? {
- XCTAssertFalse(reference.isInvalidated)
- let object = realm.resolve(reference)
- XCTAssert(reference.isInvalidated)
- assertThrows(realm.resolve(reference), reason: "Can only resolve a thread safe reference once")
- return object
- }
- func testInvalidThreadSafeReferenceConstruction() {
- let stringObject = SwiftStringObject()
- let arrayParent = SwiftArrayPropertyObject(value: ["arrayObject", [["a"]], []])
- let arrayObject = arrayParent.array
- assertThrows(ThreadSafeReference(to: stringObject), reason: "Cannot construct reference to unmanaged object")
- assertThrows(ThreadSafeReference(to: arrayObject), reason: "Cannot construct reference to unmanaged object")
- let realm = try! Realm()
- realm.beginWrite()
- realm.add(stringObject)
- realm.add(arrayParent)
- realm.deleteAll()
- try! realm.commitWrite()
- assertThrows(ThreadSafeReference(to: stringObject), reason: "Cannot construct reference to invalidated object")
- assertThrows(ThreadSafeReference(to: arrayObject), reason: "Cannot construct reference to invalidated object")
- }
- func testInvalidThreadSafeReferenceUsage() {
- let realm = try! Realm()
- realm.beginWrite()
- let stringObject = realm.create(SwiftStringObject.self, value: ["stringCol": "hello"])
- assertThrows(ThreadSafeReference(to: stringObject),
- reason: "Cannot obtain thread safe reference during a write transaction")
- try! realm.commitWrite()
- let ref1 = ThreadSafeReference(to: stringObject)
- let ref2 = ThreadSafeReference(to: stringObject)
- let ref3 = ThreadSafeReference(to: stringObject)
- dispatchSyncNewThread {
- self.assertThrows(self.realmWithTestPath().resolve(ref1),
- reason: "Cannot resolve thread safe reference in Realm with different configuration than the source Realm")
- let realm = try! Realm()
- realm.beginWrite()
- self.assertThrows(realm.resolve(ref2),
- reason: "Cannot resolve thread safe reference during a write transaction")
- self.assertThrows(realm.resolve(ref2),
- reason: "Can only resolve a thread safe reference once")
- realm.cancelWrite()
- self.assertThrows(realm.resolve(ref2),
- reason: "Can only resolve a thread safe reference once")
-
- XCTAssertEqual(self.assertResolve(realm, ref3)!.stringCol, "hello")
- }
- }
- func testPassThreadSafeReferenceToDeletedObject() {
- let realm = try! Realm()
- let intObject = SwiftIntObject()
- try! realm.write {
- realm.add(intObject)
- }
- let ref1 = ThreadSafeReference(to: intObject)
- let ref2 = ThreadSafeReference(to: intObject)
- XCTAssertEqual(0, intObject.intCol)
- try! realm.write {
- realm.delete(intObject)
- }
- dispatchSyncNewThread {
- let realm = try! Realm()
- XCTAssertEqual(self.assertResolve(realm, ref1)!.intCol, 0)
- realm.refresh()
- XCTAssertNil(self.assertResolve(realm, ref2))
- }
- }
- func testPassThreadSafeReferencesToMultipleObjects() {
- let realm = try! Realm()
- let (stringObject, intObject) = (SwiftStringObject(), SwiftIntObject())
- try! realm.write {
- realm.add(stringObject)
- realm.add(intObject)
- }
- let stringObjectRef = ThreadSafeReference(to: stringObject)
- let intObjectRef = ThreadSafeReference(to: intObject)
- XCTAssertEqual("", stringObject.stringCol)
- XCTAssertEqual(0, intObject.intCol)
- dispatchSyncNewThread {
- let realm = try! Realm()
- let stringObject = self.assertResolve(realm, stringObjectRef)!
- let intObject = self.assertResolve(realm, intObjectRef)!
- try! realm.write {
- stringObject.stringCol = "the meaning of life"
- intObject.intCol = 42
- }
- }
- XCTAssertEqual("", stringObject.stringCol)
- XCTAssertEqual(0, intObject.intCol)
- realm.refresh()
- XCTAssertEqual("the meaning of life", stringObject.stringCol)
- XCTAssertEqual(42, intObject.intCol)
- }
- func testPassThreadSafeReferenceToList() {
- let realm = try! Realm()
- let company = SwiftCompanyObject()
- try! realm.write {
- realm.add(company)
- company.employees.append(SwiftEmployeeObject(value: ["name": "jg"]))
- }
- XCTAssertEqual(1, company.employees.count)
- XCTAssertEqual("jg", company.employees[0].name)
- let listRef = ThreadSafeReference(to: company.employees)
- dispatchSyncNewThread {
- let realm = try! Realm()
- let employees = self.assertResolve(realm, listRef)!
- XCTAssertEqual(1, employees.count)
- XCTAssertEqual("jg", employees[0].name)
- try! realm.write {
- employees.removeAll()
- employees.append(SwiftEmployeeObject(value: ["name": "jp"]))
- employees.append(SwiftEmployeeObject(value: ["name": "az"]))
- }
- XCTAssertEqual(2, employees.count)
- XCTAssertEqual("jp", employees[0].name)
- XCTAssertEqual("az", employees[1].name)
- }
- XCTAssertEqual(1, company.employees.count)
- XCTAssertEqual("jg", company.employees[0].name)
- realm.refresh()
- XCTAssertEqual(2, company.employees.count)
- XCTAssertEqual("jp", company.employees[0].name)
- XCTAssertEqual("az", company.employees[1].name)
- }
- func testPassThreadSafeReferenceToResults() {
- let realm = try! Realm()
- let allObjects = realm.objects(SwiftStringObject.self)
- let results = allObjects
- .filter("stringCol != 'C'")
- .sorted(byKeyPath: "stringCol", ascending: false)
- let resultsRef = ThreadSafeReference(to: results)
- try! realm.write {
- realm.create(SwiftStringObject.self, value: ["A"])
- realm.create(SwiftStringObject.self, value: ["B"])
- realm.create(SwiftStringObject.self, value: ["C"])
- realm.create(SwiftStringObject.self, value: ["D"])
- }
- XCTAssertEqual(4, allObjects.count)
- XCTAssertEqual(3, results.count)
- XCTAssertEqual("D", results[0].stringCol)
- XCTAssertEqual("B", results[1].stringCol)
- XCTAssertEqual("A", results[2].stringCol)
- dispatchSyncNewThread {
- let realm = try! Realm()
- let results = self.assertResolve(realm, resultsRef)!
- let allObjects = realm.objects(SwiftStringObject.self)
- XCTAssertEqual(0, allObjects.count)
- XCTAssertEqual(0, results.count)
- realm.refresh()
- XCTAssertEqual(4, allObjects.count)
- XCTAssertEqual(3, results.count)
- XCTAssertEqual("D", results[0].stringCol)
- XCTAssertEqual("B", results[1].stringCol)
- XCTAssertEqual("A", results[2].stringCol)
- try! realm.write {
- realm.delete(results[2])
- realm.delete(results[0])
- realm.create(SwiftStringObject.self, value: ["E"])
- }
- XCTAssertEqual(3, allObjects.count)
- XCTAssertEqual(2, results.count)
- XCTAssertEqual("E", results[0].stringCol)
- XCTAssertEqual("B", results[1].stringCol)
- }
- XCTAssertEqual(4, allObjects.count)
- XCTAssertEqual(3, results.count)
- XCTAssertEqual("D", results[0].stringCol)
- XCTAssertEqual("B", results[1].stringCol)
- XCTAssertEqual("A", results[2].stringCol)
- realm.refresh()
- XCTAssertEqual(3, allObjects.count)
- XCTAssertEqual(2, results.count)
- XCTAssertEqual("E", results[0].stringCol)
- XCTAssertEqual("B", results[1].stringCol)
- }
- func testPassThreadSafeReferenceToLinkingObjects() {
- let realm = try! Realm()
- let dogA = SwiftDogObject(value: ["dogName": "Cookie", "age": 10])
- let unaccessedDogB = SwiftDogObject(value: ["dogName": "Skipper", "age": 7])
-
- try! realm.write {
- realm.add(SwiftOwnerObject(value: ["name": "Andrea", "dog": dogA]))
- realm.add(SwiftOwnerObject(value: ["name": "Mike", "dog": unaccessedDogB]))
- }
- XCTAssertEqual(1, dogA.owners.count)
- XCTAssertEqual("Andrea", dogA.owners[0].name)
- let ownersARef = ThreadSafeReference(to: dogA.owners)
- let ownersBRef = ThreadSafeReference(to: unaccessedDogB.owners)
- dispatchSyncNewThread {
- let realm = try! Realm()
- let ownersA = self.assertResolve(realm, ownersARef)!
- let ownersB = self.assertResolve(realm, ownersBRef)!
- XCTAssertEqual(1, ownersA.count)
- XCTAssertEqual("Andrea", ownersA[0].name)
- XCTAssertEqual(1, ownersB.count)
- XCTAssertEqual("Mike", ownersB[0].name)
- try! realm.write {
- (ownersA[0].dog, ownersB[0].dog) = (ownersB[0].dog, ownersA[0].dog)
- }
- XCTAssertEqual(1, ownersA.count)
- XCTAssertEqual("Mike", ownersA[0].name)
- XCTAssertEqual(1, ownersB.count)
- XCTAssertEqual("Andrea", ownersB[0].name)
- }
- XCTAssertEqual(1, dogA.owners.count)
- XCTAssertEqual("Andrea", dogA.owners[0].name)
- XCTAssertEqual(1, unaccessedDogB.owners.count)
- XCTAssertEqual("Mike", unaccessedDogB.owners[0].name)
- realm.refresh()
- XCTAssertEqual(1, dogA.owners.count)
- XCTAssertEqual("Mike", dogA.owners[0].name)
- XCTAssertEqual(1, unaccessedDogB.owners.count)
- XCTAssertEqual("Andrea", unaccessedDogB.owners[0].name)
- }
- func testPassThreadSafeReferenceToAnyRealmCollection() {
- let realm = try! Realm()
- let company = SwiftCompanyObject()
- try! realm.write {
- realm.add(company)
- company.employees.append(SwiftEmployeeObject(value: ["name": "A"]))
- company.employees.append(SwiftEmployeeObject(value: ["name": "B"]))
- company.employees.append(SwiftEmployeeObject(value: ["name": "C"]))
- company.employees.append(SwiftEmployeeObject(value: ["name": "D"]))
- }
- let results = AnyRealmCollection(realm.objects(SwiftEmployeeObject.self)
- .filter("name != 'C'")
- .sorted(byKeyPath: "name", ascending: false))
- let list = AnyRealmCollection(company.employees)
- XCTAssertEqual(3, results.count)
- XCTAssertEqual("D", results[0].name)
- XCTAssertEqual("B", results[1].name)
- XCTAssertEqual("A", results[2].name)
- XCTAssertEqual(4, list.count)
- XCTAssertEqual("A", list[0].name)
- XCTAssertEqual("B", list[1].name)
- XCTAssertEqual("C", list[2].name)
- XCTAssertEqual("D", list[3].name)
- let resultsRef = ThreadSafeReference(to: results)
- let listRef = ThreadSafeReference(to: list)
- dispatchSyncNewThread {
- let realm = try! Realm()
- let results = self.assertResolve(realm, resultsRef)!
- let list = self.assertResolve(realm, listRef)!
- XCTAssertEqual(3, results.count)
- XCTAssertEqual("D", results[0].name)
- XCTAssertEqual("B", results[1].name)
- XCTAssertEqual("A", results[2].name)
- XCTAssertEqual(4, list.count)
- XCTAssertEqual("A", list[0].name)
- XCTAssertEqual("B", list[1].name)
- XCTAssertEqual("C", list[2].name)
- XCTAssertEqual("D", list[3].name)
- }
- }
- }
|