| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- //
- // DiskStorageTests.swift
- // Kingfisher
- //
- // Created by Wei Wang on 2018/11/12.
- //
- // Copyright (c) 2019 Wei Wang <onevcat@gmail.com>
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- import XCTest
- @testable import Kingfisher
- #if compiler(>=6)
- extension String: @retroactive DataTransformable { }
- #else
- extension String: DataTransformable { }
- #endif
- extension String {
- public func toData() throws -> Data {
- return data(using: .utf8)!
- }
- public static func fromData(_ data: Data) throws -> String {
- return String(data: data, encoding: .utf8)!
- }
- public static var empty: String { return "" }
- }
- class DiskStorageTests: XCTestCase {
- var storage: DiskStorage.Backend<String>!
- override func setUp() {
- super.setUp()
- let uuid = UUID().uuidString
- let config = DiskStorage.Config(name: "test-\(uuid)", sizeLimit: 5)
- storage = try! DiskStorage.Backend<String>(config: config)
- }
- override func tearDown() {
- try! storage.removeAll(skipCreatingDirectory: true)
- super.tearDown()
- }
- func testStoreAndGet() {
- XCTAssertFalse(storage.isCached(forKey: "1"))
- try! storage.store(value: "1", forKey: "1")
- XCTAssertTrue(storage.isCached(forKey: "1"))
- let value = try! storage.value(forKey: "1")
- XCTAssertEqual(value, "1")
- }
- func testRemove() {
- XCTAssertFalse(storage.isCached(forKey: "1"))
- try! storage.store(value: "1", forKey: "1")
- try! storage.remove(forKey: "1")
- XCTAssertFalse(storage.isCached(forKey: "1"))
- }
- func testRemoveAll() {
- try! storage.store(value: "1", forKey: "1")
- try! storage.store(value: "2", forKey: "2")
- try! storage.store(value: "3", forKey: "3")
- try! storage.removeAll()
- XCTAssertFalse(storage.isCached(forKey: "1"))
- XCTAssertFalse(storage.isCached(forKey: "2"))
- XCTAssertFalse(storage.isCached(forKey: "3"))
- }
- func testTotalSize() {
- var size = try! storage.totalSize()
- XCTAssertEqual(size, 0)
- try! storage.store(value: "1", forKey: "1")
- size = try! storage.totalSize()
- XCTAssertEqual(size, 1)
- }
- func testSetExpiration() {
- let now = Date()
- try! storage.store(value: "1", forKey: "1", expiration: .seconds(1))
- XCTAssertTrue(storage.isCached(forKey: "1", referenceDate: now))
- XCTAssertFalse(storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(5)))
- }
- func testConfigExpiration() {
- let now = Date()
- storage.config.expiration = .seconds(1)
- try! storage.store(value: "1", forKey: "1")
- XCTAssertTrue(storage.isCached(forKey: "1", referenceDate: now))
- XCTAssertFalse(storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(5)))
- }
- func testExtendExpirationByAccessing() {
- let exp = expectation(description: #function)
- let now = Date()
- try! storage.store(value: "1", forKey: "1", expiration: .seconds(2))
- XCTAssertTrue(storage.isCached(forKey: "1"))
- XCTAssertFalse(storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(5)))
- delay(1) {
- let v = try! self.storage.value(forKey: "1")
- XCTAssertNotNil(v)
- // The meta extending happens on its own queue.
- self.storage.metaChangingQueue.async {
- XCTAssertTrue(self.storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(3)))
- XCTAssertFalse(self.storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(10)))
- exp.fulfill()
- }
- }
- waitForExpectations(timeout: 2, handler: nil)
- }
- func testNotExtendExpirationByAccessing() {
- let exp = expectation(description: #function)
- let now = Date()
- try! storage.store(value: "1", forKey: "1", expiration: .seconds(2))
- XCTAssertTrue(storage.isCached(forKey: "1"))
- XCTAssertFalse(storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(3)))
- delay(1) {
- let v = try! self.storage.value(forKey: "1", extendingExpiration: .none)
- XCTAssertNotNil(v)
- // The meta extending happens on its own queue.
- self.storage.metaChangingQueue.async {
- XCTAssertFalse(self.storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(3)))
- XCTAssertFalse(self.storage.isCached(forKey: "1", referenceDate: now.addingTimeInterval(10)))
- exp.fulfill()
- }
- }
- waitForExpectations(timeout: 2, handler: nil)
- }
- func testRemoveExpired() {
- let expiration = StorageExpiration.seconds(1)
- try! storage.store(value: "1", forKey: "1", expiration: expiration)
- try! storage.store(value: "2", forKey: "2", expiration: expiration)
- try! storage.store(value: "3", forKey: "3")
- let urls = try! self.storage.removeExpiredValues(referenceDate: Date().addingTimeInterval(2))
- XCTAssertEqual(urls.count, 2)
- XCTAssertTrue(self.storage.isCached(forKey: "3"))
- }
- func testRemoveSizeExceeded() {
- let count = 10
- for i in 0..<count {
- let s = String(i)
- try! storage.store(value: s, forKey: s)
- }
- let urls = try! storage.removeSizeExceededValues()
- XCTAssertTrue(urls.count < count)
- XCTAssertTrue(urls.count > 0)
- }
- func testConfigUsesHashedFileName() {
- let key = "test"
- // hashed fileName
- storage.config.usesHashedFileName = true
- let hashedFileName = storage.cacheFileName(forKey: key)
- XCTAssertNotEqual(hashedFileName, key)
- // validation sha256 hash of the key
- XCTAssertEqual(hashedFileName, key.kf.sha256)
- // fileName without hash
- storage.config.usesHashedFileName = false
- let originalFileName = storage.cacheFileName(forKey: key)
- XCTAssertEqual(originalFileName, key)
- }
- func testConfigUsesHashedFileNameWithAutoExt() {
- let key = "test.gif"
- // hashed fileName
- storage.config.usesHashedFileName = true
- storage.config.autoExtAfterHashedFileName = true
- let hashedFileName = storage.cacheFileName(forKey: key)
- XCTAssertNotEqual(hashedFileName, key)
- // validation sha256 hash of the key
- XCTAssertEqual(hashedFileName, key.kf.sha256 + ".gif")
- // fileName without hash
- storage.config.usesHashedFileName = false
- let originalFileName = storage.cacheFileName(forKey: key)
- XCTAssertEqual(originalFileName, key)
- }
-
- func testConfigUsesHashedFileNameWithAutoExtAndProcessor() {
- // The key of an image with processor will be as this format.
- let key = "test.jpeg@com.onevcat.Kingfisher.DownsamplingImageProcessor"
-
- // hashed fileName
- storage.config.usesHashedFileName = true
- storage.config.autoExtAfterHashedFileName = true
- let hashedFileName = storage.cacheFileName(forKey: key)
- XCTAssertNotEqual(hashedFileName, key)
- // validation sha256 hash of the key
- XCTAssertEqual(hashedFileName, key.kf.sha256 + ".jpeg")
- // fileName without hash
- storage.config.usesHashedFileName = false
- let originalFileName = storage.cacheFileName(forKey: key)
- XCTAssertEqual(originalFileName, key)
- }
- func testFileMetaOrder() {
- let urls = [URL(string: "test1")!, URL(string: "test2")!, URL(string: "test3")!]
- let now = Date()
- let file1 = DiskStorage.FileMeta(
- fileURL: urls[0],
- lastAccessDate: now,
- estimatedExpirationDate: now.addingTimeInterval(1),
- isDirectory: false,
- fileSize: 1)
- let file2 = DiskStorage.FileMeta(
- fileURL: urls[1],
- lastAccessDate: now.addingTimeInterval(1),
- estimatedExpirationDate: now.addingTimeInterval(2),
- isDirectory: false,
- fileSize: 1)
- let file3 = DiskStorage.FileMeta(
- fileURL: urls[2],
- lastAccessDate: now.addingTimeInterval(2),
- estimatedExpirationDate: now.addingTimeInterval(3),
- isDirectory: false,
- fileSize: 1)
- let ordered = [file2, file1, file3].sorted(by: DiskStorage.FileMeta.lastAccessDate)
- XCTAssertTrue(ordered[0].lastAccessDate! > ordered[1].lastAccessDate!)
- XCTAssertTrue(ordered[1].lastAccessDate! > ordered[2].lastAccessDate!)
- }
- }
|