@@ -17,7 +17,7 @@ import XCTest
1717
1818@MainActor
1919@available ( iOS 15 . 0 , macOS 12 . 0 , tvOS 15 . 0 , visionOS 1 . 0 , watchOS 8 . 0 , * )
20- class LargeItemCacheTypeTests : TestCase {
20+ final class LargeItemCacheTypeTests : TestCase {
2121
2222 private var fileManager = FileManager . default
2323 private lazy var testDirectory = fileManager
@@ -26,7 +26,7 @@ class LargeItemCacheTypeTests: TestCase {
2626
2727 // MARK: - saveData Tests
2828
29- func test_saveData_writesDataToFile ( ) async throws {
29+ func testSaveDataWritesDataToFile ( ) async throws {
3030 let testData = " Hello, World! "
3131 let url = self . testDirectory. appendingPathComponent ( " test.txt " )
3232 let stream = createAsyncStream ( from: testData)
@@ -40,7 +40,47 @@ class LargeItemCacheTypeTests: TestCase {
4040 try fileManager. removeItem ( at: url)
4141 }
4242
43- func test_saveData_withValidChecksum_succeeds( ) async throws {
43+ func testSaveDataCreatesParentDirectoryIfNeeded( ) throws {
44+ let nonExistentSubdir = UUID ( ) . uuidString
45+ let url = self . testDirectory
46+ . appendingPathComponent ( nonExistentSubdir)
47+ . appendingPathComponent ( " nested_file.txt " )
48+ let testData = Data ( " test content " . utf8)
49+
50+ // Ensure the directory doesn't exist
51+ expect ( self . fileManager. fileExists ( atPath: url. deletingLastPathComponent ( ) . path) ) == false
52+
53+ try self . fileManager. saveData ( testData, to: url)
54+
55+ let savedData = try Data ( contentsOf: url)
56+ expect ( savedData) == testData
57+
58+ // Cleanup
59+ try fileManager. removeItem ( at: self . testDirectory. appendingPathComponent ( nonExistentSubdir) )
60+ }
61+
62+ func testSaveDataAsyncCreatesParentDirectoryIfNeeded( ) async throws {
63+ let nonExistentSubdir = UUID ( ) . uuidString
64+ let url = self . testDirectory
65+ . appendingPathComponent ( nonExistentSubdir)
66+ . appendingPathComponent ( " nested_async_file.txt " )
67+ let testData = " async test content "
68+ let stream = createAsyncStream ( from: testData)
69+
70+ // Ensure the directory doesn't exist
71+ expect ( self . fileManager. fileExists ( atPath: url. deletingLastPathComponent ( ) . path) ) == false
72+
73+ try await self . fileManager. saveData ( stream, to: url, checksum: nil )
74+
75+ let savedData = try Data ( contentsOf: url)
76+ let savedString = String ( data: savedData, encoding: . utf8)
77+ expect ( savedString) == testData
78+
79+ // Cleanup
80+ try fileManager. removeItem ( at: self . testDirectory. appendingPathComponent ( nonExistentSubdir) )
81+ }
82+
83+ func testSaveDataWithValidChecksumSucceeds( ) async throws {
4484 let testData = " Test data for checksum "
4585 let data = Data ( testData. utf8)
4686 let checksum = Checksum . generate ( from: data, with: . sha256)
@@ -54,7 +94,7 @@ class LargeItemCacheTypeTests: TestCase {
5494 try fileManager. removeItem ( at: url)
5595 }
5696
57- func test_saveData_withInvalidChecksum_throws ( ) async throws {
97+ func testSaveDataWithInvalidChecksumThrows ( ) async throws {
5898 let testData = " Test data "
5999 let wrongChecksum = Checksum . generate ( from: Data ( " Different data " . utf8) , with: . sha256)
60100 let url = self . testDirectory. appendingPathComponent ( " invalid_checksum.txt " )
@@ -71,7 +111,7 @@ class LargeItemCacheTypeTests: TestCase {
71111 expect ( self . fileManager. fileExists ( atPath: url. path) ) == false
72112 }
73113
74- func test_saveData_withLargeData_succeeds ( ) async throws {
114+ func testSaveDataWithLargeDataSucceeds ( ) async throws {
75115 // Create data larger than the buffer size (256KB)
76116 let largeData = String ( repeating: " A " , count: 500_000 )
77117 let url = self . testDirectory. appendingPathComponent ( " large_file.txt " )
@@ -88,7 +128,7 @@ class LargeItemCacheTypeTests: TestCase {
88128
89129 }
90130
91- func test_saveData_withMultipleChunks_writesCorrectly ( ) async throws {
131+ func testSaveDataWithMultipleChunksWritesCorrectly ( ) async throws {
92132 let testData = String ( repeating: " X " , count: 1_000_000 ) // 1MB
93133 let url = self . testDirectory. appendingPathComponent ( " chunked_file.txt " )
94134 let stream = createAsyncStream ( from: testData)
@@ -101,7 +141,7 @@ class LargeItemCacheTypeTests: TestCase {
101141
102142 }
103143
104- func test_saveData_withChecksumAlgorithms_succeeds ( ) async throws {
144+ func testSaveDataWithChecksumAlgorithmsSucceeds ( ) async throws {
105145 let testData = " Algorithm test "
106146 let data = Data ( testData. utf8)
107147 let algorithms : [ Checksum . Algorithm ] = [ . sha256, . sha384, . sha512, . md5]
@@ -122,7 +162,7 @@ class LargeItemCacheTypeTests: TestCase {
122162
123163 // MARK: - cachedContentExists Tests
124164
125- func test_cachedContentExists_returnsTrueForExistingFile ( ) throws {
165+ func testCachedContentExistsReturnsTrueForExistingFile ( ) throws {
126166 let url = self . testDirectory. appendingPathComponent ( " existing.txt " )
127167 let testData = " Existing content "
128168 try testData. write ( to: url, atomically: true , encoding: . utf8)
@@ -134,15 +174,15 @@ class LargeItemCacheTypeTests: TestCase {
134174
135175 }
136176
137- func test_cachedContentExists_returnsFalseForNonExistentFile ( ) {
177+ func testCachedContentExistsReturnsFalseForNonExistentFile ( ) {
138178 let url = self . testDirectory. appendingPathComponent ( " nonexistent.txt " )
139179
140180 let exists = self . fileManager. cachedContentExists ( at: url)
141181
142182 expect ( exists) == false
143183 }
144184
145- func test_cachedContentExists_returnsFalseForEmptyFile ( ) throws {
185+ func testCachedContentExistsReturnsFalseForEmptyFile ( ) throws {
146186 let url = self . testDirectory. appendingPathComponent ( " empty.txt " )
147187 try Data ( ) . write ( to: url)
148188
@@ -153,7 +193,7 @@ class LargeItemCacheTypeTests: TestCase {
153193
154194 }
155195
156- func test_cachedContentExists_returnsTrueForNonEmptyFile ( ) throws {
196+ func testCachedContentExistsReturnsTrueForNonEmptyFile ( ) throws {
157197 let url = self . testDirectory. appendingPathComponent ( " nonempty.txt " )
158198 try " A " . write ( to: url, atomically: true , encoding: . utf8)
159199
@@ -166,7 +206,7 @@ class LargeItemCacheTypeTests: TestCase {
166206
167207 // MARK: - loadFile Tests
168208
169- func test_loadFile_returnsCorrectData ( ) throws {
209+ func testLoadFileReturnsCorrectData ( ) throws {
170210 let url = self . testDirectory. appendingPathComponent ( " load_test.txt " )
171211 let testData = " Data to load "
172212 try testData. write ( to: url, atomically: true , encoding: . utf8)
@@ -179,15 +219,15 @@ class LargeItemCacheTypeTests: TestCase {
179219
180220 }
181221
182- func test_loadFile_throwsForNonExistentFile ( ) {
222+ func testLoadFileThrowsForNonExistentFile ( ) {
183223 let url = self . testDirectory. appendingPathComponent ( " missing.txt " )
184224
185225 expect {
186226 try self . fileManager. loadFile ( at: url)
187227 } . to ( throwError ( ) )
188228 }
189229
190- func test_loadFile_returnsEmptyDataForEmptyFile ( ) throws {
230+ func testLoadFileReturnsEmptyDataForEmptyFile ( ) throws {
191231 let url = self . testDirectory. appendingPathComponent ( " empty_load.txt " )
192232 try Data ( ) . write ( to: url)
193233
@@ -200,7 +240,7 @@ class LargeItemCacheTypeTests: TestCase {
200240
201241 // MARK: - createCacheDirectoryIfNeeded Tests
202242
203- func test_createCacheDirectoryIfNeeded_createsDirectory ( ) {
243+ func testCreateCacheDirectoryIfNeededCreatesDirectory ( ) {
204244 let basePath = " TestCache/Subdirectory "
205245
206246 let createdURL = self . fileManager. createCacheDirectoryIfNeeded ( basePath: basePath)
@@ -215,7 +255,7 @@ class LargeItemCacheTypeTests: TestCase {
215255
216256 }
217257
218- func test_createCacheDirectoryIfNeeded_createsIntermediateDirectories ( ) {
258+ func testCreateCacheDirectoryIfNeededCreatesIntermediateDirectories ( ) {
219259 let basePath = " TestCache/Level1/Level2/Level3 "
220260
221261 let createdURL = self . fileManager. createCacheDirectoryIfNeeded ( basePath: basePath)
@@ -230,9 +270,28 @@ class LargeItemCacheTypeTests: TestCase {
230270
231271 }
232272
273+ func testCreateCacheDirectoryIfNeededDoesNotFailWhenDirectoryExists( ) throws {
274+ let basePath = " TestCache/ \( UUID ( ) . uuidString) "
275+
276+ let firstURL = self . fileManager. createCacheDirectoryIfNeeded ( basePath: basePath)
277+ let secondURL = self . fileManager. createCacheDirectoryIfNeeded ( basePath: basePath)
278+
279+ expect ( firstURL) . toNot ( beNil ( ) )
280+ expect ( secondURL) . toNot ( beNil ( ) )
281+ expect ( secondURL? . standardizedFileURL. path) == firstURL? . standardizedFileURL. path
282+
283+ if let url = firstURL {
284+ var isDirectory : ObjCBool = false
285+ let exists = self . fileManager. fileExists ( atPath: url. path, isDirectory: & isDirectory)
286+ expect ( exists) == true
287+ expect ( isDirectory. boolValue) == true
288+ try self . fileManager. removeItem ( at: url)
289+ }
290+ }
291+
233292 // MARK: - Integration Tests
234293
235- func test_saveAndLoad_roundTrip ( ) async throws {
294+ func testSaveAndLoadRoundTrip ( ) async throws {
236295 let testData = " Round trip test "
237296 let url = self . testDirectory. appendingPathComponent ( " roundtrip.txt " )
238297 let stream = createAsyncStream ( from: testData)
@@ -246,7 +305,7 @@ class LargeItemCacheTypeTests: TestCase {
246305
247306 }
248307
249- func test_saveData_thenCheckExists ( ) async throws {
308+ func testSaveDataThenCheckExists ( ) async throws {
250309 let testData = " Existence test "
251310 let url = self . testDirectory. appendingPathComponent ( " exists_test.txt " )
252311 let stream = createAsyncStream ( from: testData)
@@ -261,7 +320,7 @@ class LargeItemCacheTypeTests: TestCase {
261320
262321 }
263322
264- func test_saveData_withChecksum_thenLoad ( ) async throws {
323+ func testSaveDataWithChecksumThenLoad ( ) async throws {
265324 let testData = " Checksum round trip "
266325 let data = Data ( testData. utf8)
267326 let checksum = Checksum . generate ( from: data, with: . sha256)
0 commit comments