Skip to content
This repository was archived by the owner on Sep 15, 2025. It is now read-only.

Commit 25b4ca5

Browse files
committed
Add unit tests to ensure temp files are deleted after request completed
1 parent 9abe323 commit 25b4ca5

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

WordPressKitTests/Utilities/URLSessionHelperTests.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,80 @@ class URLSessionHelperTests: XCTestCase {
256256
)
257257
}
258258

259+
func testTempFileRemovedAfterMultipartUpload() async throws {
260+
stub(condition: isPath("/upload")) { _ in
261+
HTTPStubsResponse(data: "success".data(using: .utf8)!, statusCode: 200, headers: nil)
262+
}
263+
264+
// Create a large file which will be uploaded
265+
let file = try self.createLargeFile(megaBytes: 100)
266+
defer {
267+
try? FileManager.default.removeItem(at: file)
268+
}
269+
270+
// Capture a list of files in temp dirs, before calling the upload function.
271+
let tempFilesBeforeUpload = existingTempFiles()
272+
273+
// Perform upload HTTP request
274+
let builder = try HTTPRequestBuilder(url: URL(string: "https://wordpress.org/upload")!)
275+
.method(.post)
276+
.body(form: [MultipartFormField(fileAtPath: file.path, name: "file", filename: "file.txt", mimeType: "text/plain")])
277+
let _ = await session.perform(request: builder, errorType: TestError.self)
278+
279+
// Capture a list of files in the temp dirs, after calling the upload function.
280+
let tempFilesAfterUpload = existingTempFiles()
281+
282+
// There should be no new files after the HTTP request returns. This assertion relies on an implementation detail
283+
// where the multipart form content is put into a file in temp dirs.
284+
let newFiles = tempFilesAfterUpload.subtracting(tempFilesBeforeUpload)
285+
XCTAssertEqual(newFiles.count, 0)
286+
}
287+
288+
func testTempFileRemovedAfterMultipartUploadError() async throws {
289+
stub(condition: isPath("/upload")) { _ in
290+
HTTPStubsResponse(error: URLError(.networkConnectionLost))
291+
}
292+
293+
// Create a large file which will be uploaded
294+
let file = try self.createLargeFile(megaBytes: 100)
295+
defer {
296+
try? FileManager.default.removeItem(at: file)
297+
}
298+
299+
// Capture a list of files in temp dirs, before calling the upload function.
300+
let tempFilesBeforeUpload = existingTempFiles()
301+
302+
// Perform upload HTTP request
303+
let builder = try HTTPRequestBuilder(url: URL(string: "https://wordpress.org/upload")!)
304+
.method(.post)
305+
.body(form: [MultipartFormField(fileAtPath: file.path, name: "file", filename: "file.txt", mimeType: "text/plain")])
306+
let _ = await session.perform(request: builder, errorType: TestError.self)
307+
308+
// Capture a list of files in the temp dirs, after calling the upload function.
309+
let tempFilesAfterUpload = existingTempFiles()
310+
311+
// There should be no new files after the HTTP request returns. This assertion relies on an implementation detail
312+
// where the multipart form content is put into a file in temp dirs.
313+
let newFiles = tempFilesAfterUpload.subtracting(tempFilesBeforeUpload)
314+
XCTAssertEqual(newFiles.count, 0)
315+
}
316+
317+
private func existingTempFiles() -> Set<String> {
318+
let fm = FileManager.default
319+
let enumerators = [
320+
fm.enumerator(atPath: NSTemporaryDirectory()),
321+
fm.enumerator(atPath: fm.temporaryDirectory.path)
322+
].compactMap { $0 }
323+
324+
var result: Set<String> = []
325+
for enumerator in enumerators {
326+
while let file = enumerator.nextObject() as? String {
327+
result.insert(file)
328+
}
329+
}
330+
return result
331+
}
332+
259333
private func createLargeFile(megaBytes: Int) throws -> URL {
260334
let fileManager = FileManager.default
261335
let file = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)

0 commit comments

Comments
 (0)