Skip to content

Improve test coverage - #105

Open
aryan-25 wants to merge 3 commits into
swift-server:mainfrom
aryan-25:improve-test-coverage
Open

Improve test coverage#105
aryan-25 wants to merge 3 commits into
swift-server:mainfrom
aryan-25:improve-test-coverage

Conversation

@aryan-25

Copy link
Copy Markdown
Collaborator

Motivation:

All tests currently only test the plaintext or secure upgrade transport. It would be useful to also include the HTTP/3 transport in these tests. Due to the differences in setting up a secure upgrade client compared to an HTTP/3 client, this requires some refactoring to the test utilities.

Modifications:

  • Moved all test helpers from NIOHTTPServerTests to a new TestHelpers type to make accessing the helpers more convenient.
  • Renamed NegotiatedClientConnection to TestClientConnection and extended it to also wrap HTTP/3 connections.
  • Introduced convenience helpers for:
    • Setting up a client connection, or a request channel directly, through with-style helper methods.
    • Creating a server and a matching client configuration for a given transport.
  • Added a test HTTP/3 client.
  • Parameterised tests over HTTPVersion and removed some tests that became redundant as a result.

Result:

Better test coverage.

@aryan-25
aryan-25 requested a review from gjcairo July 30, 2026 15:29
@aryan-25 aryan-25 added the semver/none No version bump required. label Jul 30, 2026
self.quicHandler.createOutboundConnection(
serverName: serverName,
remoteAddress: remoteAddress,
connectionInitializer: { [connectionInitializer] connectionChannel, streamCreator in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I don't think this capture is needed, it will be implicitly captured anyways

Suggested change
connectionInitializer: { [connectionInitializer] connectionChannel, streamCreator in
connectionInitializer: { connectionChannel, streamCreator in

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we can't remove that because it would mean self (which is QUICConnectionCreator) would be captured inside the @Sendable closure. QUICConnectionCreator can't be made Sendable as it contains QUICHandler.

Comment thread Tests/NIOHTTPServerTests/Utilities/HTTPVersion.swift
case .http1(let asyncChannel):
do {
try await asyncChannel.channel.close()
} catch ChannelError.alreadyClosed {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay to swallow this error everywhere? why are we doing this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to swallow the alreadyClosed error, because in some tests, the connection may have already been closed by the server before we exit from the body closure. For example, in testServerCanContinueDespiteFailedConnection, the server closes the connection upon seeing the first request. Catching this error at the call site would complicate the tests in my opinion.

Comment thread Tests/NIOHTTPServerTests/NIOHTTPServer+ServiceLifecycleTests.swift
#endif

default:
throw NIOHTTPServerConfigurationError.incompatibleTransportSecurity

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should throw a test-specific error here instead of reusing this, since it could be mistaken from tests as an error coming from the actual business code.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 35aec7e.

) async throws -> NIOAsyncChannel<HTTPResponsePart, HTTPRequestPart> {
switch self.connectionProtocol {
case .http1(let http1Channel):
#expect(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These expects in this func should probably be requires instead, as anything that we assert after this will fail too anyways.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 7e364ed.


for expectedHeadPart in expectedHead {
let headResponsePart = try await responseIterator.next()
#expect(headResponsePart == .head(expectedHeadPart), sourceLocation: sourceLocation)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to my other comment elsewhere, I think these should be requires instead of expects

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 7e364ed.

@aryan-25
aryan-25 requested a review from gjcairo July 31, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver/none No version bump required.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants