Skip to content

Commit f7c9c8c

Browse files
committed
Reinstate PR #19765
1 parent 5828347 commit f7c9c8c

File tree

2 files changed

+35
-98
lines changed

2 files changed

+35
-98
lines changed

WordPress/Classes/Utility/ContextManager.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ private extension ContextManager {
107107
}
108108
}
109109

110+
/// Ensure that the `context`'s concurrency type is not `confinementConcurrencyType`, since it will crash if `perform` or `performAndWait` is called.
111+
guard context.concurrencyType == .mainQueueConcurrencyType || context.concurrencyType == .privateQueueConcurrencyType else {
112+
block()
113+
return
114+
}
115+
110116
if wait {
111117
context.performAndWait(block)
112118
} else {
Lines changed: 29 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,43 @@
11
import XCTest
2+
import Nimble
23

34
@testable import WordPress
45

5-
final class ContainerContextFactoryTests: XCTestCase {
6+
final class ReaderPostBackupTests: XCTestCase {
7+
private let storeURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("ReaderPostBackup.sqlite")
8+
private let backupURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("ReaderPostBackup-backup.sqlite")
9+
private var coreDataStack: CoreDataStack!
610

7-
private var persistentContainer: NSPersistentContainer!
8-
private var factory: ContainerContextFactory!
9-
10-
override func setUp() {
11-
super.setUp()
12-
13-
persistentContainer = makeInMemoryContainer()
14-
factory = ContainerContextFactory(persistentContainer: persistentContainer)
15-
}
16-
17-
override func tearDown() {
18-
persistentContainer = nil
19-
factory = nil
20-
21-
super.tearDown()
22-
}
23-
24-
// MARK: - `save` Tests
25-
26-
func test_save_givenMainQueueConcurrencyType_shouldCallPerform() {
27-
let context = makeMockContext(concurrencyType: .mainQueueConcurrencyType)
28-
29-
factory.save(context, andWait: false, withCompletionBlock: nil)
30-
31-
XCTAssertTrue(context.performCalled)
32-
XCTAssertFalse(context.performAndWaitCalled)
33-
}
34-
35-
func test_save_givenMainQueueConcurrencyType_andWaitIsSetToTrue_shouldCallPerformAndWait() {
36-
let context = makeMockContext(concurrencyType: .mainQueueConcurrencyType)
37-
38-
factory.save(context, andWait: true, withCompletionBlock: nil)
39-
40-
XCTAssertFalse(context.performCalled)
41-
XCTAssertTrue(context.performAndWaitCalled)
42-
}
43-
44-
func test_save_givenPrivateQueueConcurrencyType_shouldCallPerform() {
45-
let context = makeMockContext(concurrencyType: .privateQueueConcurrencyType)
46-
47-
factory.save(context, andWait: false, withCompletionBlock: nil)
48-
49-
XCTAssertTrue(context.performCalled)
50-
XCTAssertFalse(context.performAndWaitCalled)
51-
}
52-
53-
func test_save_givenPrivateQueueConcurrencyType_andWaitIsSetToTrue_shouldCallPerformAndWait() {
54-
let context = makeMockContext(concurrencyType: .privateQueueConcurrencyType)
55-
56-
factory.save(context, andWait: true, withCompletionBlock: nil)
57-
58-
XCTAssertFalse(context.performCalled)
59-
XCTAssertTrue(context.performAndWaitCalled)
60-
}
61-
62-
func test_save_givenDeprecatedConcurrencyType_shouldNotCallPerform() {
63-
/// creates a context with `.confinementConcurrencyType`. The enum is created from its raw value
64-
/// to prevent Xcode from complaining since the enum value is deprecated.
65-
let context = makeMockContext(concurrencyType: NSManagedObjectContextConcurrencyType(rawValue: 0)!)
66-
67-
factory.save(context, andWait: false, withCompletionBlock: nil)
68-
69-
XCTAssertFalse(context.performCalled)
70-
XCTAssertFalse(context.performAndWaitCalled)
71-
}
72-
}
73-
74-
// MARK: - Private Helpers
75-
76-
private extension ContainerContextFactoryTests {
77-
78-
class MockManagedObjectContext: NSManagedObjectContext {
79-
80-
var performCalled = false
81-
var performAndWaitCalled = false
82-
83-
override func perform(_ block: @escaping () -> Void) {
84-
performCalled = true
11+
override func setUpWithError() throws {
12+
let fileManager = FileManager.default
13+
if fileManager.fileExists(at: storeURL) {
14+
try fileManager.removeItem(at: storeURL)
8515
}
86-
87-
override func performAndWait(_ block: () -> Void) {
88-
performAndWaitCalled = true
16+
if fileManager.fileExists(at: backupURL) {
17+
try fileManager.removeItem(at: backupURL)
8918
}
9019

91-
override func save() throws {
92-
// do nothing. let's make sure nothing gets saved.
93-
}
20+
coreDataStack = ContextManager(modelName: ContextManagerModelNameCurrent, store: storeURL)
9421
}
9522

96-
/// Creates an "in-memory" NSPersistentContainer.
97-
/// This follows the approach used in WWDC'18: https://developer.apple.com/videos/play/wwdc2018/224/
98-
///
99-
/// - Returns: An instance of NSPersistentContainer that stores data in memory.
100-
func makeInMemoryContainer() -> NSPersistentContainer {
101-
let container = NSPersistentContainer(name: "WordPress")
102-
let description = NSPersistentStoreDescription(url: .init(fileURLWithPath: "/dev/null"))
103-
container.persistentStoreDescriptions = [description]
104-
105-
return container
106-
}
23+
func testBackupReaderPost() {
24+
coreDataStack.performAndSave { context in
25+
let post: ReaderPost = ReaderPostBuilder(context).build()
26+
let card = ReaderCard(context: context)
27+
card.post = post
28+
post.content = "test post"
29+
post.card = [card]
30+
}
10731

108-
func makeMockContext(concurrencyType: NSManagedObjectContextConcurrencyType) -> MockManagedObjectContext {
109-
return MockManagedObjectContext(concurrencyType: concurrencyType)
32+
let migrator = DataMigrator(coreDataStack: coreDataStack, backupLocation: backupURL)
33+
waitUntil { done in
34+
migrator.exportData { result in
35+
XCTAssertNoThrow {
36+
try result.get()
37+
}
38+
done()
39+
}
40+
}
11041
}
11142

11243
}

0 commit comments

Comments
 (0)