This commit is contained in:
John Estropia
2026-07-15 11:50:43 +09:00
parent 7db1cfecfb
commit 890e150b95
135 changed files with 2895 additions and 2526 deletions
+3 -3
View File
@@ -24,11 +24,11 @@
//
import XCTest
import os
@testable
import CoreStore
#if !SWIFT_PACKAGE
extension Bundle {
@@ -196,7 +196,7 @@ final class TestLogger: CoreStoreLogger {
init(_ expectations: [Expectation: XCTestExpectation]) {
self.expectations = .init(initialState: expectations)
self.expectations = .init(expectations)
}
@@ -236,7 +236,7 @@ final class TestLogger: CoreStoreLogger {
// MARK: Private
private let expectations: OSAllocatedUnfairLock<[Expectation: XCTestExpectation]>
private let expectations: Internals.Mutex<[Expectation: XCTestExpectation]>
private func fulfill(_ expectation: Expectation) {
+1
View File
@@ -201,6 +201,7 @@ class Person: CoreStoreObject {
class DynamicModelTests: BaseTestDataTestCase {
@MainActor
@objc
dynamic func test_ThatDynamicModels_CanBeDeclaredCorrectly() {
+32 -12
View File
@@ -33,6 +33,7 @@ import CoreStore
final class FetchTests: BaseTestDataTestCase {
@MainActor
@objc
dynamic func test_ThatDataStacksAndTransactions_CanFetchOneExisting() {
@@ -103,14 +104,14 @@ final class FetchTests: BaseTestDataTestCase {
}
do {
let persistentID = object.persistentID()
let fetchExpectation = self.expectation(description: "fetch")
var existing1: TestEntity1?
stack.perform(
asynchronous: { (transaction) in
existing1 = transaction.fetchExisting(object)
let existing1 = transaction.fetchExisting(persistentID)
XCTAssertNotNil(existing1)
XCTAssertEqual(existing1!.objectID, object.objectID)
XCTAssertEqual(existing1!.persistentID(), persistentID)
XCTAssertEqual(existing1!.managedObjectContext, transaction.context)
try transaction.cancel()
@@ -123,9 +124,9 @@ final class FetchTests: BaseTestDataTestCase {
XCTAssertEqual(error, CoreStoreError.userCancelled)
let existing2 = stack.fetchExisting(existing1!)
let existing2 = stack.fetchExisting(persistentID)
XCTAssertNotNil(existing2)
XCTAssertEqual(existing2!.objectID, object.objectID)
XCTAssertEqual(existing2!.persistentID(), persistentID)
XCTAssertEqual(existing2!.managedObjectContext, stack.mainContext)
fetchExpectation.fulfill()
@@ -136,6 +137,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacksAndTransactions_CanFetchAllExisting() {
@@ -230,15 +232,15 @@ final class FetchTests: BaseTestDataTestCase {
}
do {
let persistentIDs = objects.map({ $0.persistentID() })
let fetchExpectation = self.expectation(description: "fetch")
var existing1 = [TestEntity1]()
stack.perform(
asynchronous: { (transaction) in
existing1 = transaction.fetchExisting(objects)
let existing1 = transaction.fetchExisting(persistentIDs)
XCTAssertEqual(
existing1.map { $0.objectID },
objects.map { $0.objectID }
existing1.map { $0.persistentID() },
persistentIDs
)
for object in existing1 {
@@ -254,10 +256,10 @@ final class FetchTests: BaseTestDataTestCase {
XCTAssertEqual(error, CoreStoreError.userCancelled)
let existing2 = stack.fetchExisting(existing1)
let existing2 = stack.fetchExisting(persistentIDs)
XCTAssertEqual(
existing2.map { $0.objectID },
objects.map { $0.objectID }
existing2.map { $0.persistentID() },
persistentIDs
)
for object in existing2 {
@@ -271,6 +273,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchOneFromDefaultConfiguration() {
@@ -404,6 +407,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchOneFromSingleConfiguration() {
@@ -581,6 +585,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchOneFromMultipleConfigurations() {
@@ -724,6 +729,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchAllFromDefaultConfiguration() {
@@ -912,6 +918,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchAllFromSingleConfiguration() {
@@ -1125,6 +1132,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchAllFromMultipleConfigurations() {
@@ -1306,6 +1314,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchCountFromDefaultConfiguration() {
@@ -1420,6 +1429,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchCountFromSingleConfiguration() {
@@ -1567,6 +1577,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatDataStacks_CanFetchCountFromMultipleConfigurations() {
@@ -1677,6 +1688,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchOneFromDefaultConfiguration() {
@@ -1818,6 +1830,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchOneFromSingleConfiguration() {
@@ -2006,6 +2019,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchOneFromMultipleConfigurations() {
@@ -2157,6 +2171,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchAllFromDefaultConfiguration() {
@@ -2353,6 +2368,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchAllFromSingleConfiguration() {
@@ -2589,6 +2605,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchAllFromMultipleConfigurations() {
@@ -2790,6 +2807,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchCountFromDefaultConfiguration() {
@@ -2918,6 +2936,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchCountFromSingleConfiguration() {
@@ -3076,6 +3095,7 @@ final class FetchTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatTransactions_CanFetchCountFromMultipleConfigurations() {
+4
View File
@@ -67,6 +67,7 @@ final class FromTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatFromClauses_ApplyToFetchRequestsCorrectlyForDefaultConfigurations() {
self.prepareStack { (dataStack) in
@@ -106,6 +107,7 @@ final class FromTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatFromClauses_ApplyToFetchRequestsCorrectlyForSingleConfigurations() {
self.prepareStack(configurations: ["Config1"]) { (dataStack) in
@@ -212,6 +214,7 @@ final class FromTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatFromClauses_ApplyToFetchRequestsCorrectlyForDefaultAndCustomConfigurations() {
self.prepareStack(configurations: [nil, "Config1"]) { (dataStack) in
@@ -316,6 +319,7 @@ final class FromTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatFromClauses_ApplyToFetchRequestsCorrectlyForMultipleConfigurations() {
self.prepareStack(configurations: ["Config1", "Config2"]) { (dataStack) in
+19 -5
View File
@@ -72,6 +72,7 @@ class ImportTests: BaseTestDataTestCase {
XCTAssertEqual(Double(MAXFLOAT).cs_toQueryableNativeType(), NSNumber(value: Double(MAXFLOAT)))
}
@MainActor
@objc
dynamic func test_ThatImportObject_CanSkipImport() {
@@ -107,6 +108,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportObject_CanThrowError() {
@@ -160,6 +162,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportObject_CanImportCorrectly() {
@@ -220,6 +223,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportObjects_CanSkipImport() {
@@ -275,6 +279,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportObjects_CanThrowError() {
@@ -339,6 +344,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportObjects_CanImportCorrectly() {
@@ -397,6 +403,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObject_CanSkipImport() {
@@ -466,6 +473,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObjects_ImportsLastOfImportSourcesWithSameIDs() {
@@ -523,7 +531,8 @@ class ImportTests: BaseTestDataTestCase {
}
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObjects_MaintainsOrderOfInputSourceArray() {
@@ -585,6 +594,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObject_CanThrowError() {
@@ -680,7 +690,8 @@ class ImportTests: BaseTestDataTestCase {
}
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObject_CanImportCorrectly() {
@@ -757,7 +768,8 @@ class ImportTests: BaseTestDataTestCase {
}
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObjects_CanSkipImport() {
@@ -815,7 +827,8 @@ class ImportTests: BaseTestDataTestCase {
}
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObjects_CanThrowError() {
@@ -977,6 +990,7 @@ class ImportTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatImportUniqueObjects_CanImportCorrectly() {
@@ -1065,7 +1079,7 @@ extension TestEntity1: ImportableUniqueObject {
// MARK: ImportableObject
typealias ImportSource = [String: Any]
typealias ImportSource = [String: any Sendable]
static func shouldInsert(from source: ImportSource, in transaction: BaseDataTransaction) -> Bool {
+230 -184
View File
@@ -34,6 +34,7 @@ import CoreStore
class ListObserverTests: BaseTestDataTestCase {
@MainActor
@objc
dynamic func test_ThatListObservers_CanReceiveInsertNotifications() {
@@ -51,20 +52,23 @@ class ListObserverTests: BaseTestDataTestCase {
XCTAssertFalse(monitor.hasObjects())
XCTAssertTrue(monitor.objectsInAllSections().isEmpty)
var events = 0
let events: Internals.Mutex<Int> = .init(0)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
}
return events == 0
}
return events == 0
}
)
_ = self.expectation(
@@ -72,51 +76,57 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 1)
XCTAssertEqual(
((note.userInfo as NSDictionary?) ?? [:]),
[
"sectionInfo": monitor.sectionInfo(at: 0),
"sectionIndex": 0
] as NSDictionary
)
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 1)
XCTAssertEqual(
((note.userInfo as NSDictionary?) ?? [:]),
[
"sectionInfo": monitor.sectionInfo(at: 0),
"sectionIndex": 0
] as NSDictionary
)
defer {
events += 1
}
return events == 1
}
return events == 1
}
)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitor:didInsertObject:toIndexPath:"),
object: observer,
handler: { (note) -> Bool in
handler: { [dateFormatter] (note) -> Bool in
XCTAssertEqual(events, 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 1))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!)
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 1))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, dateFormatter.date(from: "2000-01-01T00:00:00Z")!)
defer {
events += 1
}
return events == 2
}
return events == 2
}
)
_ = self.expectation(
@@ -125,16 +135,19 @@ class ListObserverTests: BaseTestDataTestCase {
handler: { (note) -> Bool in
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
defer {
events += 1
}
return events == 3
}
return events == 3
}
)
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
asynchronous: { [dateFormatter] (transaction) -> Bool in
let object = transaction.create(Into<TestEntity1>())
object.testBoolean = NSNumber(value: true)
@@ -142,7 +155,7 @@ class ListObserverTests: BaseTestDataTestCase {
object.testDecimal = NSDecimalNumber(string: "1")
object.testString = "nil:TestEntity1:1"
object.testData = ("nil:TestEntity1:1" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-01T00:00:00Z")!
object.testDate = dateFormatter.date(from: "2000-01-01T00:00:00Z")!
return transaction.hasChanges
},
@@ -160,6 +173,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatListObservers_CanReceiveUpdateNotifications() {
@@ -182,72 +196,78 @@ class ListObserverTests: BaseTestDataTestCase {
XCTAssertEqual(monitor.numberOfObjects(in: 0), 2)
XCTAssertEqual(monitor.numberOfObjects(in: 1), 3)
var events = 0
let events: Internals.Mutex<Int> = .init(0)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
}
return events == 0
}
return events == 0
}
)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitor:didUpdateObject:atIndexPath:"),
object: observer,
handler: { (note) -> Bool in
handler: { [dateFormatter] (note) -> Bool in
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
let object = userInfo?["object"] as? TestEntity1
switch object?.testEntityID {
return events.withLock { events in
case NSNumber(value: 101)?:
XCTAssertEqual(indexPath?.section, 1)
XCTAssertEqual(indexPath?.item, 0)
XCTAssert(events == 1 || events == 2)
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
case NSNumber(value: 102)?:
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
let indexPath = userInfo?["indexPath"] as? IndexPath
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
default:
XCTFail()
switch object?.testEntityID {
case NSNumber(value: 101)?:
XCTAssertEqual(indexPath?.section, 1)
XCTAssertEqual(indexPath?.item, 0)
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 11))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "11"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:11")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, dateFormatter.date(from: "2000-01-11T00:00:00Z")!)
case NSNumber(value: 102)?:
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
XCTAssertEqual(object?.testBoolean, NSNumber(value: false))
XCTAssertEqual(object?.testNumber, NSNumber(value: 22))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "22"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:22")
XCTAssertEqual(object?.testData, ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!)
XCTAssertEqual(object?.testDate, dateFormatter.date(from: "2000-01-22T00:00:00Z")!)
default:
XCTFail()
}
defer {
events += 1
}
return events == 1 || events == 2
}
defer {
events += 1
}
return events == 1 || events == 2
}
)
_ = self.expectation(
@@ -255,18 +275,21 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 3)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 3)
defer {
events += 1
}
return events == 3
}
return events == 3
}
)
let saveExpectation = self.expectation(description: "save")
stack.perform(
asynchronous: { (transaction) -> Bool in
asynchronous: { [dateFormatter] (transaction) -> Bool in
if let object = try transaction.fetchOne(
From<TestEntity1>(),
@@ -276,7 +299,7 @@ class ListObserverTests: BaseTestDataTestCase {
object.testDecimal = NSDecimalNumber(string: "11")
object.testString = "nil:TestEntity1:11"
object.testData = ("nil:TestEntity1:11" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-11T00:00:00Z")!
object.testDate = dateFormatter.date(from: "2000-01-11T00:00:00Z")!
}
else {
@@ -290,7 +313,7 @@ class ListObserverTests: BaseTestDataTestCase {
object.testDecimal = NSDecimalNumber(string: "22")
object.testString = "nil:TestEntity1:22"
object.testData = ("nil:TestEntity1:22" as NSString).data(using: String.Encoding.utf8.rawValue)!
object.testDate = self.dateFormatter.date(from: "2000-01-22T00:00:00Z")!
object.testDate = dateFormatter.date(from: "2000-01-22T00:00:00Z")!
}
else {
@@ -312,6 +335,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatListObservers_CanReceiveMoveNotifications() {
@@ -327,20 +351,23 @@ class ListObserverTests: BaseTestDataTestCase {
)
monitor.addObserver(observer)
var events = 0
let events: Internals.Mutex<Int> = .init(0)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
}
return events == 0
}
return events == 0
}
)
_ = self.expectation(
@@ -348,32 +375,35 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 1)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["fromIndexPath", "toIndexPath", "object"]
)
let fromIndexPath = userInfo?["fromIndexPath"] as? IndexPath
XCTAssertEqual(fromIndexPath?.section, 0)
XCTAssertEqual(fromIndexPath?.item, 0)
let toIndexPath = userInfo?["toIndexPath"] as? IndexPath
XCTAssertEqual(toIndexPath?.section, 1)
XCTAssertEqual(toIndexPath?.item, 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 1)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["fromIndexPath", "toIndexPath", "object"]
)
let fromIndexPath = userInfo?["fromIndexPath"] as? IndexPath
XCTAssertEqual(fromIndexPath?.section, 0)
XCTAssertEqual(fromIndexPath?.item, 0)
let toIndexPath = userInfo?["toIndexPath"] as? IndexPath
XCTAssertEqual(toIndexPath?.section, 1)
XCTAssertEqual(toIndexPath?.item, 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testEntityID, NSNumber(value: 102))
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
defer {
events += 1
}
return events == 1
}
return events == 1
}
)
_ = self.expectation(
@@ -381,13 +411,16 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 2)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 2)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
}
return events == 2
}
return events == 2
}
)
let saveExpectation = self.expectation(description: "save")
@@ -420,6 +453,7 @@ class ListObserverTests: BaseTestDataTestCase {
}
}
@MainActor
@objc
dynamic func test_ThatListObservers_CanReceiveDeleteNotifications() {
@@ -435,20 +469,23 @@ class ListObserverTests: BaseTestDataTestCase {
)
monitor.addObserver(observer)
var events = 0
let events: Internals.Mutex<Int> = .init(0)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 0)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
events += 1
}
return events == 0
}
return events == 0
}
)
_ = self.expectation(
@@ -456,28 +493,31 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssert(indexPath?.item == 0 || indexPath?.item == 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.isDeleted, true)
defer {
return events.withLock { events in
events += 1
XCTAssert(events == 1 || events == 2)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssert(indexPath?.item == 0 || indexPath?.item == 1)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.isDeleted, true)
defer {
events += 1
}
return events == 1 || events == 2
}
return events == 1 || events == 2
}
)
_ = self.expectation(
@@ -485,27 +525,30 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 3)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["sectionInfo", "sectionIndex"]
)
let sectionInfo = userInfo?["sectionInfo"] as? NSFetchedResultsSectionInfo
XCTAssertNotNil(sectionInfo)
XCTAssertEqual(sectionInfo?.name, "0")
let sectionIndex = userInfo?["sectionIndex"]
XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(value: 0))
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 3)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(userInfo?.keys.map({ $0 as! String }) ?? []),
["sectionInfo", "sectionIndex"]
)
let sectionInfo = userInfo?["sectionInfo"] as? NSFetchedResultsSectionInfo
XCTAssertNotNil(sectionInfo)
XCTAssertEqual(sectionInfo?.name, "0")
let sectionIndex = userInfo?["sectionIndex"]
XCTAssertEqual(sectionIndex as? NSNumber, NSNumber(value: 0))
defer {
events += 1
}
return events == 3
}
return events == 3
}
)
_ = self.expectation(
@@ -513,13 +556,16 @@ class ListObserverTests: BaseTestDataTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 4)
XCTAssertEqual((note.userInfo as NSDictionary?) ?? [:], NSDictionary())
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 4)
defer {
events += 1
}
return events == 4
}
return events == 4
}
)
let saveExpectation = self.expectation(description: "save")
@@ -551,7 +597,7 @@ class ListObserverTests: BaseTestDataTestCase {
// MARK: TestListObserver
class TestListObserver: ListSectionObserver {
final class TestListObserver: ListSectionObserver {
// MARK: ListObserver
+21 -19
View File
@@ -24,7 +24,6 @@
//
import XCTest
import os
@testable
import CoreStore
@@ -56,7 +55,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
XCTAssertEqual(monitor.object, object)
XCTAssertFalse(monitor.isObjectDeleted)
let events: OSAllocatedUnfairLock<Int> = .init(initialState: 0)
let events: Internals.Mutex<Int> = .init(0)
let persistentID = object.persistentID()
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "objectMonitor:willUpdateObject:"),
@@ -68,8 +68,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
XCTAssertEqual(events, 0)
XCTAssertEqual(
((note.userInfo as NSDictionary?) ?? [:]),
["object": object] as NSDictionary
(note.userInfo?["object"] as? TestEntity1)?.persistentID(),
persistentID
)
defer {
@@ -89,16 +89,17 @@ class ObjectObserverTests: BaseTestDataTestCase {
XCTAssertEqual(events, 1)
XCTAssertEqual(
((note.userInfo as NSDictionary?) ?? [:]),
[
"object": object,
"changedPersistentKeys": Set(
[
#keyPath(TestEntity1.testNumber),
#keyPath(TestEntity1.testString)
]
)
] as NSDictionary
(note.userInfo?["object"] as? TestEntity1)?.persistentID(),
persistentID
)
XCTAssertEqual(
note.userInfo?["changedPersistentKeys"] as? Set<String>,
Set(
[
#keyPath(TestEntity1.testNumber),
#keyPath(TestEntity1.testString)
]
)
)
let object = note.userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testNumber, NSNumber(value: 10))
@@ -116,7 +117,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
guard let object = transaction.edit(persistentID) else {
XCTFail()
try transaction.cancel()
@@ -162,7 +163,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
XCTAssertEqual(monitor.object, object)
XCTAssertFalse(monitor.isObjectDeleted)
let events: OSAllocatedUnfairLock<Int> = .init(initialState: 0)
let events: Internals.Mutex<Int> = .init(0)
let persistentID = object.persistentID()
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "objectMonitor:didDeleteObject:"),
@@ -174,8 +176,8 @@ class ObjectObserverTests: BaseTestDataTestCase {
XCTAssertEqual(events, 0)
XCTAssertEqual(
((note.userInfo as NSDictionary?) ?? [:]),
["object": object] as NSDictionary
(note.userInfo?["object"] as? TestEntity1)?.persistentID(),
persistentID
)
defer {
@@ -189,7 +191,7 @@ class ObjectObserverTests: BaseTestDataTestCase {
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
guard let object = transaction.edit(persistentID) else {
XCTFail()
try transaction.cancel()
+4 -2
View File
@@ -63,10 +63,11 @@ class ObjectPublisherTests: BaseTestDataTestCase {
}
let saveExpectation = self.expectation(description: "save")
let persistentID = object.persistentID()
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
guard let object = transaction.edit(persistentID) else {
XCTFail()
try transaction.cancel()
@@ -123,10 +124,11 @@ class ObjectPublisherTests: BaseTestDataTestCase {
}
let saveExpectation = self.expectation(description: "save")
let persistentID = object.persistentID()
stack.perform(
asynchronous: { (transaction) -> Bool in
guard let object = transaction.edit(object) else {
guard let object = transaction.edit(persistentID) else {
XCTFail()
try transaction.cancel()
+9
View File
@@ -35,6 +35,7 @@ import CoreStore
class QueryTests: BaseTestDataTestCase {
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryAttributeValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -219,6 +220,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryAverageValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -398,6 +400,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryCountValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -575,6 +578,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryMaximumValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -759,6 +763,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryMinimumValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -943,6 +948,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQuerySumValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -1121,6 +1127,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryObjectIDValue() {
let configurations: [ModelConfiguration] = [nil]
@@ -1289,6 +1296,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryAttributes() {
let configurations: [ModelConfiguration] = [nil]
@@ -1343,6 +1351,7 @@ class QueryTests: BaseTestDataTestCase {
}
@objc
@MainActor
dynamic func test_ThatDataStacks_CanQueryAggregates() {
let configurations: [ModelConfiguration] = [nil]
+1
View File
@@ -27,6 +27,7 @@ import CoreData
import XCTest
@testable
@_spi(Internals)
import CoreStore
+51 -32
View File
@@ -35,6 +35,7 @@ import CoreStore
final class TransactionTests: BaseTestCase {
@objc
@MainActor
dynamic func test_ThatSynchronousTransactions_CanPerformCRUDs() {
self.prepareStack { (stack) in
@@ -151,6 +152,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatSynchronousTransactions_CanPerformCRUDsInCorrectConfiguration() {
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
@@ -270,6 +272,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatSynchronousTransactions_CanDiscardUncommittedChanges() {
self.prepareStack { (stack) in
@@ -385,6 +388,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatSynchronousTransactions_CanCommitWithoutWaitingForMerges() {
self.prepareStack { (stack) in
@@ -398,19 +402,22 @@ final class TransactionTests: BaseTestCase {
XCTAssertFalse(monitor.hasObjects())
var events = 0
let events: Internals.Mutex<Int> = .init(0)
_ = self.expectation(
forNotification: NSNotification.Name(rawValue: "listMonitorWillChange:"),
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 0)
XCTAssertTrue(note.userInfo?.isEmpty != false)
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 0)
XCTAssertTrue(note.userInfo?.isEmpty != false)
defer {
events += 1
}
return events == 0
}
return events == 0
}
)
_ = self.expectation(
@@ -418,29 +425,32 @@ final class TransactionTests: BaseTestCase {
object: observer,
handler: { (note) -> Bool in
XCTAssertEqual(events, 1)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 1))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
defer {
return events.withLock { events in
events += 1
XCTAssertEqual(events, 1)
let userInfo = note.userInfo
XCTAssertNotNil(userInfo)
XCTAssertEqual(
Set(((userInfo as? [String: AnyObject]) ?? [:]).keys),
["indexPath", "object"]
)
let indexPath = userInfo?["indexPath"] as? IndexPath
XCTAssertEqual(indexPath?.section, 0)
XCTAssertEqual(indexPath?.item, 0)
let object = userInfo?["object"] as? TestEntity1
XCTAssertEqual(object?.testBoolean, NSNumber(value: true))
XCTAssertEqual(object?.testNumber, NSNumber(value: 1))
XCTAssertEqual(object?.testDecimal, NSDecimalNumber(string: "1"))
XCTAssertEqual(object?.testString, "nil:TestEntity1:1")
defer {
events += 1
}
return events == 1
}
return events == 1
}
)
_ = self.expectation(
@@ -449,11 +459,14 @@ final class TransactionTests: BaseTestCase {
handler: { (note) -> Bool in
XCTAssertTrue(note.userInfo?.isEmpty != false)
defer {
events += 1
return events.withLock { events in
defer {
events += 1
}
return events == 2
}
return events == 2
}
)
let saveExpectation = self.expectation(description: "save")
@@ -479,7 +492,7 @@ final class TransactionTests: BaseTestCase {
XCTFail()
}
XCTAssertEqual(events, 0)
XCTAssertEqual(events.withLock({ $0 }), 0)
XCTAssertEqual(monitor.numberOfObjects(), 0)
self.waitAndCheckExpectations()
}
@@ -487,6 +500,7 @@ final class TransactionTests: BaseTestCase {
@objc
@MainActor
dynamic func test_ThatAsynchronousTransactions_CanPerformCRUDs() {
self.prepareStack { (stack) in
@@ -626,6 +640,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatAsynchronousTransactions_CanPerformCRUDsInCorrectConfiguration() {
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
@@ -759,6 +774,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatAsynchronousTransactions_CanDiscardUncommittedChanges() {
self.prepareStack { (stack) in
@@ -900,6 +916,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatUnsafeTransactions_CanPerformCRUDs() {
self.prepareStack { (stack) in
@@ -995,6 +1012,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatUnsafeTransactions_CanPerformCRUDsInCorrectConfiguration() {
self.prepareStack(configurations: [nil, "Config1"]) { (stack) in
@@ -1083,6 +1101,7 @@ final class TransactionTests: BaseTestCase {
}
@objc
@MainActor
dynamic func test_ThatUnsafeTransactions_CanRollbackChanges() {
self.prepareStack { (stack) in
+2 -3
View File
@@ -37,18 +37,17 @@ final class TweakTests: XCTestCase {
@objc
dynamic func test_ThatTweakClauses_ApplyToFetchRequestsCorrectly() {
let predicate = NSPredicate(format: "%K == %@", "key", "value")
let tweak = Tweak {
$0.fetchOffset = 100
$0.fetchLimit = 200
$0.predicate = predicate
$0.predicate = NSPredicate(format: "%K == %@", "key", "value")
}
let request = Internals.CoreStoreFetchRequest<NSFetchRequestResult>()
tweak.applyToFetchRequest(request)
XCTAssertEqual(request.fetchOffset, 100)
XCTAssertEqual(request.fetchLimit, 200)
XCTAssertNotNil(request.predicate)
XCTAssertEqual(request.predicate, predicate)
XCTAssertEqual(request.predicate, NSPredicate(format: "%K == %@", "key", "value"))
}
}