Add fingerprint cache tests
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user