swift-server / swift-server/async-http-client

Flaky test 'HTTPClientTests.testFileDownload'

Open
#347 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/testing kind/bug
Dominant language
Swift
Stars
1.1k
Forks
156
PR merge metrics
No merged PRs in 30d

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:

https://github.com/swift-server/async-http-client/blob/0dda95cffcdf3d96ca551e5701efd1661cf31374/Tests/AsyncHTTPClientTests/HTTPClientTests.swift#L497-L507

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Tests/AsyncHTTPClientTests/HTTPClientTests.swift around lines 497-507 and reproduce HTTPClientTests.testFileDownload. Read FileDownloadDelegate and its delegate protocol to understand when the task future completes versus when the file descriptor is closed. Done means the test observes all 50 bytes on disk reliably after completion, with no race between final writes and file closing.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.