-
Notifications
You must be signed in to change notification settings - Fork 948
Expand file tree
/
Copy pathMaterialisedEnumerationObserverTests.swift
More file actions
148 lines (119 loc) · 6.69 KB
/
MaterialisedEnumerationObserverTests.swift
File metadata and controls
148 lines (119 loc) · 6.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
// SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: LGPL-3.0-or-later
@preconcurrency import FileProvider
import Foundation
import NextcloudFileProviderKit
import NextcloudFileProviderKitMocks
import NextcloudKit
import RealmSwift
import TestInterface
import XCTest
final class MaterialisedEnumerationObserverTests: NextcloudFileProviderKitTestCase {
static let account = Account(
user: "testUser", id: "testUserId", serverUrl: "https://mock.nc.com", password: "abcd"
)
override func setUp() {
super.setUp()
Realm.Configuration.defaultConfiguration.inMemoryIdentifier = name
}
func testMaterialisedObserverWithNoPreexistingState() async {
let dbManager = FilesDatabaseManager(account: Self.account, databaseDirectory: makeDatabaseDirectory(), fileProviderDomainIdentifier: NSFileProviderDomainIdentifier("test"), log: FileProviderLogMock())
// The database is intentionally left empty.
let remoteInterface = MockRemoteInterface(account: Self.account)
let enumeratedFile =
SendableItemMetadata(ocId: "file1", fileName: "file1.txt", account: Self.account)
var enumeratedDir =
SendableItemMetadata(ocId: "dir1", fileName: "dir1", account: Self.account)
enumeratedDir.directory = true
let expect = XCTestExpectation(description: "Enumerator completion handler called")
// The observer's logic requires metadata to exist in the DB to update it.
let observer = MaterializedEnumerationObserver(account: Self.account, dbManager: dbManager, log: FileProviderLogMock()) { newlyMaterialisedIds, unmaterialisedIds in
XCTAssertTrue(
unmaterialisedIds.isEmpty,
"Unmaterialised set should be empty when DB starts empty."
)
// The items are correctly identified as newly materialized because they weren't in the
// DB's materialized list (which was empty).
XCTAssertEqual(
newlyMaterialisedIds.count,
2,
"Both enumerated items should be identified as newly materialised."
)
XCTAssertTrue(newlyMaterialisedIds.contains(NSFileProviderItemIdentifier("file1")))
XCTAssertTrue(newlyMaterialisedIds.contains(NSFileProviderItemIdentifier("dir1")))
// Verify that the database state is NOT updated
let fileMetadata = dbManager.itemMetadata(ocId: "file1")
XCTAssertNil(
fileMetadata,
"Metadata should NOT be in the DB, as the observer does not add missing items."
)
let dirMetadata = dbManager.itemMetadata(ocId: "dir1")
XCTAssertNil(
dirMetadata,
"Metadata should NOT be in the DB, as the observer does not add missing items."
)
expect.fulfill()
}
let enumerator = MockEnumerator(
account: Self.account, dbManager: dbManager, remoteInterface: remoteInterface
)
enumerator.enumeratorItems = [enumeratedFile, enumeratedDir]
enumerator.enumerateItems(for: observer, startingAt: NSFileProviderPage(Data(count: 1)))
await fulfillment(of: [expect], timeout: 1)
}
func testMaterialisedObserverWithMixedState() async {
// Setup a DB with a mix of materialized and non-materialised items.
var itemA = SendableItemMetadata(ocId: "itemA", fileName: "itemA", account: Self.account)
itemA.downloaded = true // Was materialised
var itemB = SendableItemMetadata(ocId: "itemB", fileName: "itemB", account: Self.account)
itemB.downloaded = false // Was NOT materialised
var itemC = SendableItemMetadata(ocId: "itemC", fileName: "itemC", account: Self.account)
itemC.downloaded = true // Was materialised
var dirD = SendableItemMetadata(ocId: "dirD", fileName: "dirD", account: Self.account)
dirD.directory = true
dirD.visitedDirectory = true // Was materialised
let dbManager = FilesDatabaseManager(account: Self.account, databaseDirectory: makeDatabaseDirectory(), fileProviderDomainIdentifier: NSFileProviderDomainIdentifier("test"), log: FileProviderLogMock())
dbManager.addItemMetadata(itemA)
dbManager.addItemMetadata(itemB)
dbManager.addItemMetadata(itemC)
dbManager.addItemMetadata(dirD)
let remoteInterface = MockRemoteInterface(account: Self.account)
let expect = XCTestExpectation(description: "Enumerator completion handler called")
let enumeratorItemsToReturn = [itemB, itemC]
let observer = MaterializedEnumerationObserver(account: Self.account, dbManager: dbManager, log: FileProviderLogMock()) { newlyMaterialisedIds, unmaterialisedIds in
// Unmaterialised: itemA and dirD were materialized but not in the latest enumeration.
XCTAssertEqual(
unmaterialisedIds.count, 2, "itemA and dirD should be reported as unmaterialised."
)
XCTAssertTrue(unmaterialisedIds.contains(NSFileProviderItemIdentifier("itemA")))
XCTAssertTrue(unmaterialisedIds.contains(NSFileProviderItemIdentifier("dirD")))
// Newly Materialised: itemB was NOT materialized but WAS in the latest enumeration.
XCTAssertEqual(
newlyMaterialisedIds.count, 1, "itemB should be reported as newly materialised."
)
XCTAssertEqual(newlyMaterialisedIds.first, NSFileProviderItemIdentifier("itemB"))
// Check final database state
let finalItemA = dbManager.itemMetadata(ocId: "itemA")
XCTAssertFalse(
finalItemA?.downloaded ?? true, "itemA should now be marked as not downloaded."
)
let finalItemB = dbManager.itemMetadata(ocId: "itemB")
XCTAssertTrue(
finalItemB?.downloaded ?? false, "itemB should now be marked as downloaded."
)
let finalItemC = dbManager.itemMetadata(ocId: "itemC")
XCTAssertTrue(finalItemC?.downloaded ?? false, "itemC should remain downloaded.")
let finalDirD = dbManager.itemMetadata(ocId: "dirD")
XCTAssertTrue(
finalDirD?.visitedDirectory ?? false, "dirD should be marked as visited."
)
expect.fulfill()
}
let enumerator = MockEnumerator(
account: Self.account, dbManager: dbManager, remoteInterface: remoteInterface
)
enumerator.enumeratorItems = enumeratorItemsToReturn
enumerator.enumerateItems(for: observer, startingAt: NSFileProviderPage(Data(count: 1)))
await fulfillment(of: [expect], timeout: 1)
}
}