82 lines
3.2 KiB
Swift
82 lines
3.2 KiB
Swift
import Foundation
|
|
import Testing
|
|
import Vision
|
|
|
|
@testable import Photochk
|
|
|
|
@Suite("キャッシュ")
|
|
struct FingerprintCacheTests {
|
|
private func makeFile(at directory: URL) throws -> ScannedFile {
|
|
let url = directory.appendingPathComponent("cached.jpg")
|
|
try TestImages.writeJPEG(TestImages.pattern(seed: 3), to: url, quality: 0.9)
|
|
|
|
let values = try url.resourceValues(forKeys: [.fileSizeKey, .contentModificationDateKey])
|
|
return ScannedFile(
|
|
url: url,
|
|
fileSize: Int64(values.fileSize ?? 0),
|
|
modificationDate: values.contentModificationDate ?? Date(),
|
|
creationDate: nil
|
|
)
|
|
}
|
|
|
|
@Test("dHash と feature print がディスクを経由して復元できる")
|
|
func roundTrip() async throws {
|
|
let directory = try TestImages.makeTemporaryDirectory()
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
|
|
let file = try makeFile(at: directory)
|
|
let cacheURL = directory.appendingPathComponent("cache.plist")
|
|
|
|
let basics = try #require(DHash.compute(for: file.url))
|
|
let print = try await FeaturePrinter.compute(for: file.url)
|
|
|
|
let writer = FingerprintCache(fileURL: cacheURL)
|
|
await writer.store(basics: [file.url: basics], for: [file])
|
|
await writer.store(featurePrints: [file.url: print], for: [file])
|
|
await writer.save()
|
|
|
|
let reader = FingerprintCache(fileURL: cacheURL)
|
|
let restoredBasics = await reader.basics(for: [file])
|
|
let restoredPrints = await reader.featurePrints(for: [file])
|
|
|
|
#expect(restoredBasics[file.url]?.dHash == basics.dHash)
|
|
let restoredPrint = try #require(restoredPrints[file.url])
|
|
// 同一の特徴量なので距離は 0
|
|
#expect(try restoredPrint.distance(to: print) == 0)
|
|
}
|
|
|
|
@Test("ファイルが更新されていたらキャッシュは使われない")
|
|
func invalidatesOnChange() async throws {
|
|
let directory = try TestImages.makeTemporaryDirectory()
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
|
|
let file = try makeFile(at: directory)
|
|
let cache = FingerprintCache(fileURL: nil)
|
|
let basics = try #require(DHash.compute(for: file.url))
|
|
await cache.store(basics: [file.url: basics], for: [file])
|
|
|
|
let changed = ScannedFile(
|
|
url: file.url,
|
|
fileSize: file.fileSize + 100,
|
|
modificationDate: file.modificationDate,
|
|
creationDate: nil
|
|
)
|
|
#expect(await cache.basics(for: [changed]).isEmpty)
|
|
#expect(await cache.basics(for: [file]).count == 1)
|
|
}
|
|
|
|
@Test("消えたファイルのエントリは prune で捨てられる")
|
|
func prunesMissingFiles() async throws {
|
|
let directory = try TestImages.makeTemporaryDirectory()
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
|
|
let file = try makeFile(at: directory)
|
|
let cache = FingerprintCache(fileURL: nil)
|
|
let basics = try #require(DHash.compute(for: file.url))
|
|
await cache.store(basics: [file.url: basics], for: [file])
|
|
|
|
await cache.prune(keeping: [])
|
|
#expect(await cache.basics(for: [file]).isEmpty)
|
|
}
|
|
}
|