Skip to content

Commit

Permalink
Merge pull request #39 from Isvvc/cleanup-fixes
Browse files Browse the repository at this point in the history
Cleanup fixes
  • Loading branch information
skjiisa authored May 11, 2021
2 parents d79ed6d + 838d43e commit ef89fdc
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 31 deletions.
20 changes: 14 additions & 6 deletions Sources/WebDAV/WebDAV+DiskCache.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@ public extension WebDAV {
func cachedDataURL<A: WebDAVAccount>(forItemAtPath path: String, account: A) -> URL? {
guard let encodedDescription = UnwrappedAccount(account: account)?.encodedDescription,
let caches = cacheFolder else { return nil }
return caches
.appendingPathComponent(encodedDescription)
.appendingPathComponent(path.trimmingCharacters(in: AccountPath.slash))
let trimmedPath = path.trimmingCharacters(in: AccountPath.slash)

if trimmedPath.isEmpty {
return caches
.appendingPathComponent(encodedDescription)
} else {
return caches
.appendingPathComponent(encodedDescription)
.appendingPathComponent(trimmedPath)
}
}

/// Get the local cached data URL for the item at the specified path if there is cached data there.
Expand Down Expand Up @@ -178,13 +185,14 @@ extension WebDAV {

func cleanupDiskCache<A: WebDAVAccount>(at path: String, account: A, files: [WebDAVFile]) throws {
let fm = FileManager.default
guard let url = cachedDataURL(forItemAtPath: path, account: account),fm.fileExists(atPath: url.path) else { return }
guard let url = cachedDataURL(forItemAtPath: path, account: account),
fm.fileExists(atPath: url.path) else { return }

let goodFilePaths = Set(files.compactMap { cachedDataURL(forItemAtPath: $0.path, account: account)?.path })
let goodFilePaths = files.compactMap { cachedDataURL(forItemAtPath: $0.path, account: account)?.path }

let infoPlist = filesCacheURL?.path
for path in try fm.contentsOfDirectory(atPath: url.path).map({ url.appendingPathComponent($0).path })
where !goodFilePaths.contains(path)
where !goodFilePaths.contains(where: { path.starts(with: $0) })
&& path != infoPlist {
try fm.removeItem(atPath: path)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/WebDAV/WebDAV.swift
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ extension WebDAV {
for (key, _) in filesCache
where key.path != directory
&& key.path.starts(with: directory)
&& !files.contains(where: { key.path.starts(with: $0.path) }) {
&& !files.contains(where: { key.path.starts(with: $0.path.trimmingCharacters(in: AccountPath.slash)) }) {
filesCache.removeValue(forKey: key)
changed = true
}
Expand Down
138 changes: 114 additions & 24 deletions Tests/WebDAVTests/WebDAVTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -356,29 +356,46 @@ final class WebDAVTests: XCTestCase {
func testCleanupFilesCacheRoot() {
guard let (account, password) = getAccount() else { return XCTFail() }

let listRealDirExpectation = XCTestExpectation(description: "List files from real directory.")
let expectation = XCTestExpectation(description: "List files from WebDAV")

let path = UUID().uuidString
let accountPath = AccountPath(account: account, path: path)
let realDir = createFolder(account: account, password: password)
let realDirAccountPath = AccountPath(account: account, path: realDir)

let fakeDir = UUID().uuidString
let fakeDirAccountPath = AccountPath(account: account, path: fakeDir)

// Load real file into cache
uploadData(to: realDir, account: account, password: password)
webDAV.listFiles(atPath: realDir, account: account, password: password, caching: .doNotReturnCachedResult) { _, _ in
listRealDirExpectation.fulfill()
}

wait(for: [listRealDirExpectation], timeout: 10000.0)

XCTAssertNotNil(webDAV.filesCache[realDirAccountPath])

// Place fake cache

webDAV.filesCache[accountPath] = [WebDAVFile(path: path + "/fake.txt", id: "0", isDirectory: true, lastModified: Date(), size: 0, etag: "0")]
XCTAssertNotNil(webDAV.filesCache[accountPath])
webDAV.filesCache[fakeDirAccountPath] = [WebDAVFile(path: fakeDir + "/fake.txt", id: "0", isDirectory: true, lastModified: Date(), size: 0, etag: "0")]
XCTAssertNotNil(webDAV.filesCache[fakeDirAccountPath])

// List files

webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
webDAV.listFiles(atPath: "/", account: account, password: password, caching: .doNotReturnCachedResult) { files, error in
XCTAssertNotNil(files)
XCTAssertNil(error)
expectation.fulfill()
}

wait(for: [expectation], timeout: 10.0)
wait(for: [expectation], timeout: 10000.0)

// Check that the fake cached file was cleaned up
XCTAssertNil(webDAV.filesCache[fakeDirAccountPath])
// Check that the real file still exists
XCTAssertNotNil(webDAV.filesCache[realDirAccountPath])

XCTAssertNil(webDAV.filesCache[accountPath])
deleteFile(path: realDir, account: account, password: password)
}

func testCleanupFilesCacheSubdirectory() {
Expand All @@ -397,7 +414,7 @@ final class WebDAVTests: XCTestCase {

// List files

webDAV.listFiles(atPath: folder, account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
webDAV.listFiles(atPath: folder, account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
XCTAssertNotNil(files)
XCTAssertNil(error)
expectation.fulfill()
Expand All @@ -413,23 +430,31 @@ final class WebDAVTests: XCTestCase {

//MARK: Disk Cache Cleanup

func testCleanupDiskCacheFile() {
func testCleanupDiskCacheFileRoot() {
guard let (account, password) = getAccount() else { return XCTFail() }

let expectation = XCTestExpectation(description: "List files from WebDAV")

// Add dummy file to disk cache

let path = UUID().uuidString + ".txt"
let dummyPath = UUID().uuidString + ".txt"
let data = UUID().uuidString.data(using: .utf8)!
let tempFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
XCTAssertNoThrow(try webDAV.saveDataToDiskCache(data, url: tempFileURL))
let dummyFileURL = webDAV.cachedDataURL(forItemAtPath: dummyPath, account: account)!
XCTAssertNoThrow(try webDAV.saveDataToDiskCache(data, url: dummyFileURL))

XCTAssert(FileManager.default.fileExists(atPath: tempFileURL.path))
XCTAssert(FileManager.default.fileExists(atPath: dummyFileURL.path))

// Create real file

let realFile = uploadData(account: account, password: password)
let realFileURL = webDAV.cachedDataURL(forItemAtPath: realFile.fileName, account: account)!
downloadData(path: realFile.fileName, account: account, password: password)

XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))

// List files

webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
XCTAssertNotNil(files)
XCTAssertNil(error)
expectation.fulfill()
Expand All @@ -438,8 +463,11 @@ final class WebDAVTests: XCTestCase {
wait(for: [expectation], timeout: 10.0)

// Check that the fake cached file was cleaned up
XCTAssertFalse(FileManager.default.fileExists(atPath: dummyFileURL.path))
// Check that the real file still exists
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))

XCTAssertFalse(FileManager.default.fileExists(atPath: tempFileURL.path))
deleteFile(path: realFile.fileName, account: account, password: password)
}

func testCleanupDiskCacheFolder() {
Expand All @@ -450,13 +478,23 @@ final class WebDAVTests: XCTestCase {
// Add dummy folder to disk cache

let path = UUID().uuidString
let tempFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
XCTAssertNoThrow(try FileManager.default.createDirectory(at: tempFileURL, withIntermediateDirectories: true))
XCTAssert(FileManager.default.fileExists(atPath: tempFileURL.path))
let dummyFileURL = webDAV.cachedDataURL(forItemAtPath: path, account: account)!
XCTAssertNoThrow(try FileManager.default.createDirectory(at: dummyFileURL, withIntermediateDirectories: true))

XCTAssert(FileManager.default.fileExists(atPath: dummyFileURL.path))

// Create real folder

let folder = createFolder(account: account, password: password)
let realFile = uploadData(to: folder, account: account, password: password)
downloadData(path: realFile.fileName, account: account, password: password)
let realFileURL = webDAV.cachedDataURL(forItemAtPath: realFile.fileName, account: account)!

XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))

// List files

webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
webDAV.listFiles(atPath: "/", account: account, password: password, foldersFirst: false, caching: .doNotReturnCachedResult) { files, error in
XCTAssertNotNil(files)
XCTAssertNil(error)
expectation.fulfill()
Expand All @@ -465,8 +503,11 @@ final class WebDAVTests: XCTestCase {
wait(for: [expectation], timeout: 10.0)

// Check that the fake cached folder was cleaned up
XCTAssertFalse(FileManager.default.fileExists(atPath: dummyFileURL.path))
// Check that the real file still exists
XCTAssert(FileManager.default.fileExists(atPath: realFileURL.path))

XCTAssertFalse(FileManager.default.fileExists(atPath: tempFileURL.path))
deleteFile(path: folder, account: account, password: password)
}

func testCleanupDiskCacheWithGoodFile() {
Expand Down Expand Up @@ -496,7 +537,7 @@ final class WebDAVTests: XCTestCase {

// List files

webDAV.listFiles(atPath: directory.path, account: account, password: password, foldersFirst: false, caching: .ignoreCache) { files, error in
webDAV.listFiles(atPath: directory.path, account: account, password: password, caching: .doNotReturnCachedResult) { files, error in
XCTAssertNotNil(files)
XCTAssertNil(error)
expectation.fulfill()
Expand All @@ -511,6 +552,34 @@ final class WebDAVTests: XCTestCase {
XCTAssertNoThrow(try webDAV.deleteCachedData(forItemAtPath: imagePath, account: account))
}

func testCleanupDiskCacheKeepingThumbnail() {
guard let (account, password) = getAccount() else { return XCTFail() }
guard let imagePath = ProcessInfo.processInfo.environment["image_path"] else {
return XCTFail("You need to set the image_path in the environment.")
}

let expectation = XCTestExpectation(description: "List files from WebDAV")

// Download Thumbnail
downloadThumbnail(imagePath: imagePath, account: account, password: password)
let cachedThumbnailURL = webDAV.cachedThumbnailURL(forItemAtPath: imagePath, account: account, with: .default)!
XCTAssert(FileManager.default.fileExists(atPath: cachedThumbnailURL.path))

// List files

let imageURL = URL(fileURLWithPath: imagePath, isDirectory: false)
let directory = imageURL.deletingLastPathComponent()

webDAV.listFiles(atPath: directory.path, account: account, password: password, caching: .doNotReturnCachedResult) { _, _ in
expectation.fulfill()
}

wait(for: [expectation], timeout: 10.0)

// Check that the cached thumbnail still exists
XCTAssert(FileManager.default.fileExists(atPath: cachedThumbnailURL.path))
}

//MARK: Images

func testDownloadImage() {
Expand Down Expand Up @@ -719,11 +788,17 @@ final class WebDAVTests: XCTestCase {
wait(for: [expectation], timeout: 10.0)
}

private func uploadData(account: SimpleAccount, password: String) -> (name: String, fileName: String, content: String) {
@discardableResult
private func uploadData(to folder: String = "", account: SimpleAccount, password: String) -> (name: String, fileName: String, content: String) {
let expectation = XCTestExpectation(description: "Upload data")

let name = UUID().uuidString
let fileName = name + ".txt"
let fileName: String
if folder.isEmpty {
fileName = name + ".txt"
} else {
fileName = "\(folder)/\(name).txt"
}
let content = UUID().uuidString
let data = content.data(using: .utf8)!

Expand Down Expand Up @@ -763,6 +838,21 @@ final class WebDAVTests: XCTestCase {
return folder
}

private func downloadData(path file: String, account: SimpleAccount, password: String) {
let expectation = XCTestExpectation(description: "Download file from WebDAV")

try? webDAV.deleteCachedData(forItemAtPath: file, account: account)

webDAV.download(fileAtPath: file, account: account, password: password) { image, error in
XCTAssertNil(error)
XCTAssertNotNil(image)

expectation.fulfill()
}

wait(for: [expectation], timeout: 10.0)
}

private func downloadImage(imagePath: String, account: SimpleAccount, password: String) {
let expectation = XCTestExpectation(description: "Download image from WebDAV")

Expand Down Expand Up @@ -816,7 +906,7 @@ final class WebDAVTests: XCTestCase {
("testCleanupFilesCacheRoot", testCleanupFilesCacheRoot),
("testCleanupFilesCacheSubdirectory", testCleanupFilesCacheSubdirectory),
// Disk Cache Cleanup
("testCleanupDiskCacheFile", testCleanupDiskCacheFile),
("testCleanupDiskCacheFileRoot", testCleanupDiskCacheFileRoot),
("testCleanupDiskCacheFolder", testCleanupDiskCacheFolder),
("testCleanupDiskCacheWithGoodFile", testCleanupDiskCacheWithGoodFile),
// Image Cache
Expand Down

0 comments on commit ef89fdc

Please # to comment.