Prechádzať zdrojové kódy

Add clean notification and tests

onevcat 10 rokov pred
rodič
commit
b12121a661

+ 26 - 0
Kingfisher/ImageCache.swift

@@ -26,6 +26,9 @@
 
 import Foundation
 
+public let KingfisherDidCleanDiskCacheNotification = "com.onevcat.Kingfisher.KingfisherDidCleanDiskCacheNotification"
+public let KingfisherDiskCacheCleanedHashKey = "com.onevcat.Kingfisher.cleanedHash"
+
 private let defaultCacheName = "default"
 private let cacheReverseDNS = "com.onevcat.Kingfisher.ImageCache."
 private let ioQueueName = "com.onevcat.Kingfisher.ImageCache.ioQueue."
@@ -415,6 +418,9 @@ extension ImageCache {
                     
                     for fileURL in sortedFiles {
                         if (self.fileManager.removeItemAtURL(fileURL, error: nil)) {
+                            
+                            URLsToDelete.append(fileURL)
+                            
                             if let fileSize = cachedFiles[fileURL]?[NSURLTotalFileAllocatedSizeKey] as? NSNumber {
                                 diskCacheSize -= fileSize.unsignedLongValue
                             }
@@ -427,6 +433,15 @@ extension ImageCache {
                 }
                 
                 dispatch_async(dispatch_get_main_queue(), { () -> Void in
+                    
+                    if URLsToDelete.count != 0 {
+                        let cleanedHashes = URLsToDelete.map({ (url) -> String in
+                            return url.lastPathComponent!
+                        })
+                        
+                        NSNotificationCenter.defaultCenter().postNotificationName(KingfisherDidCleanDiskCacheNotification, object: self, userInfo: [KingfisherDiskCacheCleanedHashKey: cleanedHashes])
+                    }
+                    
                     if let completionHandler = completionHandler {
                         completionHandler()
                     }
@@ -499,6 +514,17 @@ public extension ImageCache {
         return CacheCheckResult(cached: false, cacheType: nil)
     }
     
+    /**
+    Get the hash for the key. This could be used for matching files.
+    
+    :param: key The key which is used for caching.
+    
+    :returns: Corresponding hash.
+    */
+    public func hashForKey(key: String) -> String {
+        return cacheFileNameForKey(key)
+    }
+    
     /**
     Calculate the disk size taken by cache. 
     It is the total allocated size of the cached files in bytes.

+ 27 - 2
KingfisherTests/ImageCacheTests.swift

@@ -34,6 +34,7 @@ private let cacheName = "com.onevcat.Kingfisher.ImageCache.test"
 class ImageCacheTests: XCTestCase {
 
     var cache: ImageCache!
+    var observer: NSObjectProtocol!
     
     override func setUp() {
         super.setUp()
@@ -46,6 +47,7 @@ class ImageCacheTests: XCTestCase {
         super.tearDown()
         cache.clearDiskCache()
         cache = nil
+        observer = nil
     }
     
     func testMaxCachePeriodInSecond() {
@@ -164,12 +166,35 @@ class ImageCacheTests: XCTestCase {
                     self.cache.retrieveImageInDiskCacheForKey(testKeys[0])
                 }
             })
-        
             expectation.fulfill()
+        }
+        
+        self.waitForExpectationsWithTimeout(15, handler: nil)
+    }
+    
+    func testCleanDiskCacheNotification() {
+        let expectation = expectationWithDescription("wait for retriving image")
+        
+        cache.storeImage(testImage, forKey: testKeys[0], toDisk: true) { () -> () in
+
+            self.observer = NSNotificationCenter.defaultCenter().addObserverForName(KingfisherDidCleanDiskCacheNotification, object: self.cache, queue: NSOperationQueue.mainQueue(), usingBlock: { (noti) -> Void in
+
+                XCTAssert(noti.object === self.cache, "The object of notification should be the cache object.")
+                
+                let hashes = noti.userInfo?[KingfisherDiskCacheCleanedHashKey] as! [String]
+                
+                XCTAssertEqual(1, hashes.count, "There should be one and only one file cleaned")
+                XCTAssertEqual(hashes.first!, self.cache.hashForKey(testKeys[0]), "The cleaned file should be the stored one.")
+                
+                NSNotificationCenter.defaultCenter().removeObserver(self.observer)
+                expectation.fulfill()
+            })
             
+            self.cache.maxCachePeriodInSecond = 0
+            self.cache.cleanExpiredDiskCache()
         }
         
-        self.waitForExpectationsWithTimeout(5, handler: nil)
+        waitForExpectationsWithTimeout(1, handler: nil)
     }
 
     // MARK: - Helper

+ 17 - 1
KingfisherTests/ImageDownloaderTests.swift

@@ -144,6 +144,22 @@ class ImageDownloaderTests: XCTestCase {
         waitForExpectationsWithTimeout(1, handler: nil)
     }
     
+    func testServerNotModifiedResponse() {
+        let expectation = expectationWithDescription("wait for server response 304")
+        
+        let URLString = testKeys[0]
+        stubRequest("GET", URLString).andReturn(304)
+        
+        downloader.downloadImageWithURL(NSURL(string: URLString)!, options: KingfisherManager.OptionsNone, progressBlock: { (receivedSize, totalSize) -> () in
+            
+        }) { (image, error, imageURL) -> () in
+            XCTAssertNotNil(error, "There should be an error since server returning 304 and no image downloaded.")
+            XCTAssertEqual(error!.code, KingfisherError.NotModified.rawValue, "The error should be NotModified.")
+            expectation.fulfill()
+        }
+        waitForExpectationsWithTimeout(1, handler: nil)
+    }
+    
     // Since we could not receive one challage, no test for trusted hosts currently.
     // See http://stackoverflow.com/questions/27065372/why-is-a-https-nsurlsession-connection-only-challenged-once-per-domain for more.
     func testSSLCertificateValidation() {
@@ -155,7 +171,7 @@ class ImageDownloaderTests: XCTestCase {
         
         downloader.downloadImageWithURL(URL, progressBlock: nil, completionHandler: { (image, error, imageURL) -> () in
             XCTAssertNotNil(error, "Error should not be nil")
-            XCTAssert(error?.code == NSURLErrorServerCertificateUntrusted, "Error should be NSURLErrorServerCertificateUntrusted")
+            XCTAssert(error?.code == NSURLErrorServerCertificateUntrusted, "Error should be NSURLErrorServerCertificateUntrusted, but \(error)")
             expectation.fulfill()
             LSNocilla.sharedInstance().start()
         })