tests: a failed server check fails the test instead of hanging it, and the tls idle tests leave the handshake room

This commit is contained in:
2026-10-21 21:32:40 +02:00
parent 4916b01571
commit 5a51e2d6b9
6 changed files with 104 additions and 76 deletions
+43 -33
View File
@@ -326,9 +326,11 @@ fn bareHandler(up: *upstream_owner.Owner) handler.Handler {
const test_budget: std.Io.Clock.Duration = .{ .raw = .fromSeconds(5), .clock = .awake };
/// Short enough to keep the idle-timeout test quick, long enough that a
/// loopback handshake cannot lose to scheduling and time out on its own.
const short_idle: std.Io.Clock.Duration = .{ .raw = .fromMilliseconds(300), .clock = .awake };
/// The handshake runs inside this budget too: a Debug-build handshake takes
/// about 100 ms on an idle machine, and a loaded CI runner failed it at
/// 300 ms. `test_budget` still fails a server that never reclaims the
/// connection.
const short_idle: std.Io.Clock.Duration = .{ .raw = .fromSeconds(2), .clock = .awake };
/// What the store advertises in production; std.crypto.tls.Client cannot send
/// ALPN in 0.16, so this also proves no-ALPN clients still connect.
@@ -580,6 +582,14 @@ test "dot: two framed queries share one TLS connection" {
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
// Deferred so a failed check still stops the server: a `serve` left in
// accept makes `threaded.deinit` wait for it forever.
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotKeepAlive, .{ io, server_address });
@@ -591,11 +601,6 @@ test "dot: two framed queries share one TLS connection" {
try testing.expectEqual(@as(u64, 0), stats.idle_timeouts);
try testing.expectEqual(@as(u64, 0), stats.connection_errors);
try testing.expectEqual(@as(u64, 2), h.stats.queries.load(.monotonic));
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
test "dot: a transport EOF without close_notify is a connection error, not a crash" {
@@ -621,6 +626,12 @@ test "dot: a transport EOF without close_notify is a connection error, not a cra
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotDropWithoutCloseNotify, .{ io, server_address });
try waitForCounter(io, &server.core.stats.connection_errors, 1);
@@ -630,11 +641,6 @@ test "dot: a transport EOF without close_notify is a connection error, not a cra
try testing.expectEqual(@as(u64, 0), stats.tls_handshake_failures);
try testing.expectEqual(@as(u64, 1), stats.connection_errors);
try testing.expectEqual(@as(u64, 1), h.stats.queries.load(.monotonic));
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
test "dot: plain TCP bytes fail the handshake and are counted" {
@@ -660,6 +666,12 @@ test "dot: plain TCP bytes fail the handshake and are counted" {
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotGarbageHandshake, .{ io, server_address });
try waitForCounter(io, &server.stats.tls_handshake_failures, 1);
@@ -669,11 +681,6 @@ test "dot: plain TCP bytes fail the handshake and are counted" {
try testing.expectEqual(@as(u64, 1), stats.tls_handshake_failures);
try testing.expectEqual(@as(u64, 0), stats.connection_errors);
try testing.expectEqual(@as(u64, 0), h.stats.queries.load(.monotonic));
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
/// Ruling 6 across a live listener: a reload retires the old generation
@@ -747,6 +754,12 @@ test "dot: a reload serves new handshakes without breaking the old connection" {
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotReloadKeepsOldConnAndServesNew, .{ io, server_address, &env });
@@ -760,11 +773,6 @@ test "dot: a reload serves new handshakes without breaking the old connection" {
const store_stats = env.store.snapshotStats();
try testing.expectEqual(@as(u64, 1), store_stats.reloads);
try testing.expectEqual(@as(u64, 0), store_stats.reload_failures);
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
/// S3.4 across a live listener: a cert PATH change — new files, not rewritten
@@ -838,6 +846,12 @@ test "dot: a cert path change serves the new certificate on the next handshake"
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotPathChangeServesNewCert, .{ io, server_address, &env });
@@ -849,11 +863,6 @@ test "dot: a cert path change serves the new certificate on the next handshake"
const store_stats = env.store.snapshotStats();
try testing.expectEqual(@as(u64, 1), store_stats.reloads);
try testing.expectEqual(@as(u64, 0), store_stats.reload_failures);
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
test "dot: an idle connection is closed with close_notify and counted" {
@@ -882,6 +891,12 @@ test "dot: an idle connection is closed with close_notify and counted" {
var group: std.Io.Group = .init;
try group.concurrent(io, DotServer.serve, .{ &server, io });
defer {
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}
try bounded(io, dotIdleUntilServerCloses, .{ io, server_address });
@@ -890,9 +905,4 @@ test "dot: an idle connection is closed with close_notify and counted" {
try testing.expectEqual(@as(u64, 1), stats.idle_timeouts);
try testing.expectEqual(@as(u64, 0), stats.tls_handshake_failures);
try testing.expectEqual(@as(u64, 0), stats.connection_errors);
server.deinit(io);
group.await(io) catch |err| switch (err) {
error.Canceled => unreachable,
};
}