test(https): give the TLS tests ports of their own

The new tests reused ports the existing suite already binds — 8095 with
ShouldSurviveAbuseHTTP1, and 8097/8098 with ShouldFallbackUnknownRoutes'
plaintext and HTTP/3 listeners. SO_REUSEADDR does not let two live
listeners share a port, so under the parallel runner whichever bound
second failed, and which test that was came down to scheduling. Move the
TLS tests to 8110-8114, which nothing else uses.

That collision also showed up as a SIGABRT rather than a reported error,
so harden the path it took: ~ListenerHTTP1 calls Stop(), which joins
threads and touches sockets and can therefore throw. A second listener
failing to bind unwinds past a live first one, and a throw out of its
destructor mid-unwind terminates the process — turning a diagnosable bind
failure into a crash. Swallow it there, where there is nothing left to
report it to.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-07-28 20:34:23 +00:00
commit 14e0a6bab1
4 changed files with 34 additions and 23 deletions

View file

@ -49,12 +49,12 @@ int main() {
// The listener mints an ephemeral certificate; the client is handed
// that same certificate as a trust anchor, so this exercises real
// chain *and* hostname verification rather than skipping both.
ListenerAsyncHTTP1 listener(8095, Routes(), TLSServerCredentials{ .selfSigned = true });
ListenerAsyncHTTP1 listener(8110, Routes(), TLSServerCredentials{ .selfSigned = true });
Check(listener.listener.Secure(), "the listener reports itself as https");
TLSClientCredentials credentials;
credentials.caPem = GetSelfSignedCertificatePem().certificate;
ClientHTTP1 client("localhost", 8095, credentials);
ClientHTTP1 client("localhost", 8110, credentials);
Check(client.Secure(), "the client reports itself as https");
HTTPResponse hello = client.Send(CreateRequestHTTP("GET", "/", "localhost"));
@ -110,7 +110,7 @@ int main() {
// Default credentials: system trust store only, so a self-signed
// certificate must be rejected rather than quietly accepted.
{
ClientHTTP1 strict("localhost", 8095, TLSClientCredentials{});
ClientHTTP1 strict("localhost", 8110, TLSClientCredentials{});
bool rejected = false;
try {
strict.Send(CreateRequestHTTP("GET", "/", "localhost"));
@ -128,7 +128,7 @@ int main() {
TLSClientCredentials mismatched;
mismatched.caPem = GetSelfSignedCertificatePem().certificate;
mismatched.serverName = "not-localhost.invalid";
ClientHTTP1 wrongName("localhost", 8095, mismatched);
ClientHTTP1 wrongName("localhost", 8110, mismatched);
bool rejected = false;
try {
wrongName.Send(CreateRequestHTTP("GET", "/", "localhost"));
@ -141,7 +141,7 @@ int main() {
// insecureNoServerValidation is the dev escape hatch; it has to work,
// because the alternative is people shipping their own worse one.
{
ClientHTTP1 insecure("localhost", 8095,
ClientHTTP1 insecure("localhost", 8110,
TLSClientCredentials{ .insecureNoServerValidation = true });
HTTPResponse response = insecure.Send(CreateRequestHTTP("GET", "/", "localhost"));
Check(response.body == "Hello World!", "insecureNoServerValidation talks to the same server");
@ -154,7 +154,7 @@ int main() {
{
const std::uint64_t before = listener.listener.HandshakeFailureCount();
try {
ClientHTTP1 plaintext("localhost", 8095);
ClientHTTP1 plaintext("localhost", 8110);
plaintext.Send(CreateRequestHTTP("GET", "/", "localhost"));
} catch (const std::exception&) {
// Expected: the listener drops it without answering.