Description
Hit on #346. Output:
Test Case 'HTTPClientTests.testFileDownload' started at 2021-03-16 07:45:24.473
/code/Tests/AsyncHTTPClientTests/HTTPClientTests.swift:505: error: HTTPClientTests.testFileDownload : XCTAssertEqual failed: ("Optional(50)") is not equal to ("Optional(45)") -
Test Case 'HTTPClientTests.testFileDownload' failed (0.779 seconds)
This test as crafted is inherently racy. The code in question is here:
async-http-client/Tests/AsyncHTTPClientTests/HTTPClientTests.swift
Lines 497 to 507 in 0dda95c
This code assumes that once the task future completes the data will all be written to disk. However, FileDownloadDelegate
does not guarantee this, and the delegate protocol we have provided makes it impossible to guarantee it. While the delegate protocol will exert backpressure on the response, it cannot prevent multiple events occurring at the same time. This means it is possible to see a situation where the same call to Channel.read
triggers both .body
and .end
. If that happens, the task promise will complete but we may not have performed the final write and file close yet.
This is revealed in this test by the fact that the checking of the file on disk revealed fewer than 50 bytes written, but the progress structure accounts for all 50. They'll get there eventually, but we can't guarantee they're there right away.
The solution to this issue likely involves adding a promise
to FileDownloadDelegate
that will be fulfilled when the FD is closed, such that we know no further I/O to the file is forthcoming.