Skip to content

Commit d3ba26c

Browse files
Add test for HTTP/2 connection close with active streams.
1 parent 6b72bde commit d3ba26c

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# frozen_string_literal: true
2+
3+
# Released under the MIT License.
4+
# Copyright, 2026, by Samuel Williams.
5+
6+
require "async/http/protocol/http2"
7+
require "sus/fixtures/async/scheduler_context"
8+
require "socket"
9+
10+
describe Async::HTTP::Protocol::HTTP2 do
11+
include Sus::Fixtures::Async::SchedulerContext
12+
13+
with "connection closing with active streams" do
14+
let(:sockets) {Socket.pair(Socket::PF_UNIX, Socket::SOCK_STREAM)}
15+
let(:client_stream) {IO::Stream(sockets.first)}
16+
17+
it "raises error when connection closes with active streams waiting for headers" do
18+
Async do |task|
19+
# Create client connection
20+
client_connection = Async::HTTP::Protocol::HTTP2::Client.new(client_stream)
21+
# Open the connection (skip preface for unit test)
22+
client_connection.open!
23+
24+
# Create a response stream (simulating a request that's been sent but headers not yet received):
25+
response = client_connection.create_response
26+
27+
# Verify the response exists and has nil status (headers not received yet):
28+
expect(response.status).to be_nil
29+
expect(response.headers).to be_nil
30+
expect(response.body).to be_nil
31+
32+
# Verify there's an active stream:
33+
expect(client_connection.streams).not.to be(:empty?)
34+
expect(client_connection.streams.size).to be == 1
35+
36+
# Simulate connection closing cleanly (like EOF from server timeout)
37+
# This should generate an error for active streams
38+
client_connection.close(nil)
39+
40+
# The stream should have been notified with an error
41+
# Try to wait for the response - should raise EOFError
42+
expect do
43+
response.wait
44+
end.to raise_exception(EOFError, message: be =~ /Connection closed with .* active stream/)
45+
46+
# Verify the response still has nil values (it was never populated)
47+
expect(response.status).to be_nil
48+
expect(response.headers).to be_nil
49+
end.wait
50+
end
51+
52+
it "does not raise error when connection closes without active streams" do
53+
Async do |task|
54+
# Create client connection
55+
client_connection = Async::HTTP::Protocol::HTTP2::Client.new(client_stream)
56+
client_connection.open!
57+
58+
# Verify no active streams
59+
expect(client_connection.streams).to be(:empty?)
60+
61+
# Close the connection cleanly - should not raise
62+
client_connection.close(nil)
63+
64+
# Connection should be closed
65+
expect(client_connection).to be(:closed?)
66+
end.wait
67+
end
68+
end
69+
end

0 commit comments

Comments
 (0)