VideoCacheTests.swift (6047B)
1 // 2 // VideoCacheTests.swift 3 // damusTests 4 // 5 // Created by Daniel D’Aquino on 2024-04-03. 6 // 7 8 import Foundation 9 import XCTest 10 @testable import damus 11 12 // TODO: Reduce test dependency on external factors such as external URLs. 13 let TEST_VIDEO_URL = "http://cdn.jb55.com/s/zaps-build.mp4" 14 let LONG_TEST_EXPIRY_TIME: TimeInterval = 60 * 60 * 24 // A long expiry time for a video (in seconds). 15 let SHORT_TEST_EXPIRY_TIME: TimeInterval = 15 // A short expiry time for a video (in seconds). Must be as short as possible but large enough to allow some test operations to occur 16 let CACHE_SAVE_TIME_TIMEOUT: TimeInterval = 8 // How long the test will wait for the cache to save a file (in seconds) 17 let EXPIRY_TIME_MARGIN: TimeInterval = 3 // The extra time we will wait after expected expiry, to avoid test timing issues. (in seconds) 18 19 final class VideoCacheTests: XCTestCase { 20 21 func testCachedURLForExistingVideo() throws { 22 // Create a temporary directory for the cache 23 let test_cache_directory = FileManager.default.temporaryDirectory.appendingPathComponent("test_video_cache") 24 25 // Create a test video file 26 let original_video_url = URL(string: TEST_VIDEO_URL)! 27 FileManager.default.createFile(atPath: original_video_url.path, contents: Data(), attributes: nil) 28 29 // Create a VideoCache instance with the temporary cache directory 30 let test_expiry_time: TimeInterval = 10 31 let video_cache = try VideoCache(cache_url: test_cache_directory, expiry_time: test_expiry_time)! 32 33 // Call the maybe_cached_url_for method with the test video URL 34 let expected_cache_url = video_cache.url_to_cached_url(url: original_video_url) 35 let maybe_cached_url = try video_cache.maybe_cached_url_for(video_url: original_video_url) 36 37 // Assert that the returned URL is the same as the original 38 XCTAssertEqual(maybe_cached_url, original_video_url, "Returned URL should be the same as the original video URL on the first time we download it") 39 40 // Check that next time we get this video, we get the cached URL. 41 let cached_url_expectation = XCTestExpectation(description: "On second time we get a video, the cached URL should be returned") 42 let start_time = Date() 43 while Date().timeIntervalSince(start_time) < CACHE_SAVE_TIME_TIMEOUT { 44 let maybe_cached_url = try video_cache.maybe_cached_url_for(video_url: original_video_url) 45 if maybe_cached_url == expected_cache_url { 46 cached_url_expectation.fulfill() 47 break 48 } 49 sleep(1) 50 } 51 wait(for: [cached_url_expectation], timeout: CACHE_SAVE_TIME_TIMEOUT) 52 53 // Now wait for the remaining time until the expiry time + a margin 54 let remaining_time = test_expiry_time + EXPIRY_TIME_MARGIN - Date().timeIntervalSince(start_time) 55 56 // Wait for the expiry time to pass 57 sleep(UInt32(max(remaining_time, 0))) 58 59 // Call the periodic_purge method to purge expired video items 60 video_cache.periodic_purge() 61 62 // Call the maybe_cached_url_for method again 63 let maybe_cached_url_after_expiry = try video_cache.maybe_cached_url_for(video_url: original_video_url) 64 65 // Assert that the returned URL is the same as the original video URL, since the cache should have expired. 66 XCTAssertEqual(maybe_cached_url_after_expiry, original_video_url, "Video cache should expire after expiry time") 67 68 // Clean up the temporary files and directory 69 try FileManager.default.removeItem(at: test_cache_directory) 70 } 71 72 func testClearCache() throws { 73 // Create a temporary directory for the cache 74 let test_cache_directory = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("test_video_cache") 75 try FileManager.default.createDirectory(at: test_cache_directory, withIntermediateDirectories: true, attributes: nil) 76 77 // Create a test video file 78 let original_video_url = URL(string: TEST_VIDEO_URL)! 79 FileManager.default.createFile(atPath: original_video_url.path, contents: Data(), attributes: nil) 80 81 // Create a VideoCache instance with the temporary cache directory and a longer expiry time 82 let expiry_time: TimeInterval = LONG_TEST_EXPIRY_TIME 83 let video_cache = try VideoCache(cache_url: test_cache_directory, expiry_time: expiry_time)! 84 85 // Request the cached URL for the test video to create the cached file 86 let expected_cache_url = video_cache.url_to_cached_url(url: original_video_url) 87 let _ = try video_cache.maybe_cached_url_for(video_url: original_video_url) 88 89 // Check that next time we get this video, we get the cached URL. 90 let cached_url_expectation = XCTestExpectation(description: "On second time we get a video, the cached URL should be returned") 91 let start_time = Date() 92 while Date().timeIntervalSince(start_time) < CACHE_SAVE_TIME_TIMEOUT { 93 let maybe_cached_url = try video_cache.maybe_cached_url_for(video_url: original_video_url) 94 if maybe_cached_url == expected_cache_url { 95 cached_url_expectation.fulfill() 96 break 97 } 98 sleep(1) 99 } 100 wait(for: [cached_url_expectation], timeout: CACHE_SAVE_TIME_TIMEOUT) 101 102 // Call the periodic_purge method 103 DamusCacheManager.shared.clear_cache(damus_state: test_damus_state, completion: { 104 // Assert that fetching the cached URL after clearing cache will 105 let maybe_cached_url_after_purge = try? video_cache.maybe_cached_url_for(video_url: original_video_url) 106 XCTAssertEqual(maybe_cached_url_after_purge, original_video_url) 107 108 // Clean up the temporary directory 109 try? FileManager.default.removeItem(at: test_cache_directory) 110 }) 111 } 112 }