-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathCoreDataTestSuite.swift
More file actions
151 lines (133 loc) · 5.69 KB
/
CoreDataTestSuite.swift
File metadata and controls
151 lines (133 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// CoreDataTestSuite.swift
// CoreDataRepository
//
// This source code is licensed under the MIT License (MIT) found in the
// LICENSE file in the root directory of this source tree.
import CoreData
import CoreDataRepository
import CustomDump
import Internal
import Testing
protocol CoreDataTestSuite {
var container: NSPersistentContainer { get }
var repositoryContext: NSManagedObjectContext { get }
var repository: CoreDataRepository { get }
mutating func extraSetup() async throws
init() async throws
init(container: NSPersistentContainer, repositoryContext: NSManagedObjectContext, repository: CoreDataRepository)
}
extension CoreDataTestSuite {
init() async throws {
let stack = CoreDataStack(
storeName: "coredata_repository_tests",
type: .sqliteEphemeral,
container: CoreDataStack.persistentContainer(
storeName: "coredata_repository_tests",
type: .sqliteEphemeral,
model: .model_UuidId
)
)
let _container = stack.container
let _repositoryContext = _container.newBackgroundContext()
_repositoryContext.automaticallyMergesChangesFromParent = true
let _repository = CoreDataRepository(context: _repositoryContext)
self.init(container: _container, repositoryContext: _repositoryContext, repository: _repository)
try await extraSetup()
}
mutating func extraSetup() async throws {
// empty by default
}
func verify<T>(_ item: T) async throws where T: FetchableUnmanagedModel, T: Equatable {
repositoryContext.performAndWait { [repositoryContext] in
var managed: T.ManagedModel?
do {
managed = try repositoryContext.fetch(T.managedFetchRequest()).first { try T(managed: $0) == item }
} catch {
Issue.record(
"Failed to verify item in store because fetching failed. Error: \(error.localizedDescription)"
)
return
}
guard managed != nil else {
Issue.record("Failed to verify item in store because it was not found.")
return
}
}
}
func verify<T>(_ item: T) async throws where T: ReadableUnmanagedModel, T: Equatable {
try repositoryContext.performAndWait { [repositoryContext] in
var _managed: T.ManagedModel?
do {
_managed = try item.readManaged(from: repositoryContext)
} catch {
Issue.record(
"Failed to verify item in store because reading it failed. Error: \(error.localizedDescription)"
)
return
}
guard let managed = _managed else {
Issue.record("Failed to verify item in store because it was not found.")
return
}
try expectNoDifference(item, T(managed: managed))
}
}
func verify(transactionAuthor: String?, timeStamp: Date) throws {
try repositoryContext.performAndWait { [repositoryContext] in
let historyRequest = NSPersistentHistoryChangeRequest.fetchHistory(after: timeStamp)
let historyResult = try #require(repositoryContext.execute(historyRequest) as? NSPersistentHistoryResult)
let history = try #require(historyResult.result as? [NSPersistentHistoryTransaction])
#expect(history.count > 0)
for historyTransaction in history {
#expect(historyTransaction.author == transactionAuthor)
}
}
}
func verifyDoesNotExist<T>(_ item: T) async throws where T: FetchableUnmanagedModel, T: Equatable {
repositoryContext.performAndWait { [repositoryContext] in
var _managed: T.ManagedModel?
do {
_managed = try repositoryContext.fetch(T.managedFetchRequest()).first { try T(managed: $0) == item }
} catch {
return
}
if let _managed, !_managed.isDeleted {
Issue.record("Item does exist and is not deleted which is not expected")
}
}
}
func verifyDoesNotExist<T>(_ item: T) async throws where T: ReadableUnmanagedModel, T: Equatable {
repositoryContext.performAndWait { [repositoryContext] in
var _managed: T.ManagedModel?
do {
_managed = try item.readManaged(from: repositoryContext)
} catch {
return
}
if let _managed, !_managed.isDeleted {
Issue.record("Item does exist and is not deleted which is not expected")
}
}
}
func verifyDoesNotExist(transactionAuthor: String?, timeStamp: Date) throws {
try repositoryContext.performAndWait { [repositoryContext] in
let historyRequest = NSPersistentHistoryChangeRequest.fetchHistory(after: timeStamp)
let historyResult = try #require(repositoryContext.execute(historyRequest) as? NSPersistentHistoryResult)
let history = try #require(historyResult.result as? [NSPersistentHistoryTransaction])
if transactionAuthor == nil {
#expect(history.count == 0)
} else {
for historyTransaction in history {
#expect(historyTransaction.author != transactionAuthor)
}
}
}
}
func delete(managedId: NSManagedObjectID) throws {
try repositoryContext.performAndWait { [repositoryContext] in
let managed = repositoryContext.object(with: managedId)
repositoryContext.delete(managed)
try repositoryContext.save()
}
}
}