Fix tests for fast_fallback (#12406)

* TCPSocket.new: Close resources in ensure

* TCPSocket.new: Remove unnecessary comments

* Socket.tcp: Make assert_separately in TestSocket more readable

* Socket.tcp: Returning instead of exiting

* Socket.tcp: Close resources in ensure

* Socket.tcp: Avoid test failures on hosts that only support IPv4
This commit is contained in:
Misaki Shioi 2024-12-20 18:55:26 +09:00 committed by GitHub
parent 2f6c694977
commit b53a75230f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2025-05-14 12:41:59 +00:00
Merged-By: shioimm <shioi.mm@gmail.com>
2 changed files with 156 additions and 153 deletions

View File

@ -780,17 +780,18 @@ class TestSocket < Test::Unit::TestCase
def test_tcp_socket_v6_hostname_resolved_earlier
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
begin
# Verify that "localhost" can be resolved to an IPv6 address
Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
server = TCPServer.new("::1", 0)
rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
exit
rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
return
end
_, port, = server.addr
server_thread = Thread.new { server.accept }
port = server.addr[1]
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
case family
@ -801,19 +802,21 @@ class TestSocket < Test::Unit::TestCase
socket = Socket.tcp("localhost", port)
assert_true(socket.remote_address.ipv6?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
end;
ensure
server_thread&.value&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_v4_hostname_resolved_earlier
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
server = TCPServer.new("127.0.0.1", 0)
port = server.addr[1]
_, port, = server.addr
server_thread = Thread.new { server.accept }
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
case family
@ -822,27 +825,31 @@ class TestSocket < Test::Unit::TestCase
end
end
server_thread = Thread.new { server.accept }
socket = Socket.tcp("localhost", port)
assert_true(socket.remote_address.ipv4?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
end;
ensure
server_thread&.value&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_v6_hostname_resolved_in_resolution_delay
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
begin
# Verify that "localhost" can be resolved to an IPv6 address
Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
server = TCPServer.new("::1", 0)
rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
exit
rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
return
end
port = server.addr[1]
_, port, = server.addr
server_thread = Thread.new { server.accept }
delay_time = 0.025 # Socket::RESOLUTION_DELAY (private) is 0.05
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
@ -852,24 +859,25 @@ class TestSocket < Test::Unit::TestCase
end
end
server_thread = Thread.new { server.accept }
socket = Socket.tcp("localhost", port)
assert_true(socket.remote_address.ipv6?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
end;
ensure
server_thread&.value&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_v6_hostname_resolved_earlier_and_v6_server_is_not_listening
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
ipv4_address = "127.0.0.1"
ipv4_server = Socket.new(Socket::AF_INET, :STREAM)
ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address))
port = ipv4_server.connect_address.ip_port
server = Socket.new(Socket::AF_INET, :STREAM)
server.bind(Socket.pack_sockaddr_in(0, ipv4_address))
port = server.connect_address.ip_port
server_thread = Thread.new { server.listen(1); server.accept }
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
case family
@ -878,67 +886,71 @@ class TestSocket < Test::Unit::TestCase
end
end
ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept }
socket = Socket.tcp("localhost", port)
assert_equal(ipv4_address, socket.remote_address.ip_address)
accepted, _ = ipv4_server_thread.value
accepted.close
ipv4_server.close
socket.close if socket && !socket.closed?
end;
ensure
accepted, _ = server_thread&.value
accepted&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_resolv_timeout
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
assert_separately opts, <<~RUBY
begin
server = TCPServer.new("localhost", 0)
_, port, = server.addr
begin;
Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep }
port = TCPServer.new("localhost", 0).addr[1]
assert_raise(Errno::ETIMEDOUT) do
Socket.tcp("localhost", port, resolv_timeout: 0.01)
end
end;
ensure
server&.close
end
RUBY
end
def test_tcp_socket_resolv_timeout_with_connection_failure
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
assert_separately opts, <<~RUBY
server = TCPServer.new("127.0.0.1", 12345)
_, port, = server.addr
begin;
server = TCPServer.new("127.0.0.1", 12345)
_, port, = server.addr
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
if family == Socket::AF_INET6
sleep
else
[Addrinfo.tcp("127.0.0.1", port)]
end
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
if family == Socket::AF_INET6
sleep
else
[Addrinfo.tcp("127.0.0.1", port)]
end
end
server.close
server.close
assert_raise(Errno::ETIMEDOUT) do
Socket.tcp("localhost", port, resolv_timeout: 0.01)
end
end;
assert_raise(Errno::ETIMEDOUT) do
Socket.tcp("localhost", port, resolv_timeout: 0.01)
end
RUBY
end
def test_tcp_socket_one_hostname_resolution_succeeded_at_least
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
begin
# Verify that "localhost" can be resolved to an IPv6 address
Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
server = TCPServer.new("::1", 0)
rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
exit
rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
return
end
port = server.addr[1]
_, port, = server.addr
server_thread = Thread.new { server.accept }
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
case family
@ -947,63 +959,69 @@ class TestSocket < Test::Unit::TestCase
end
end
server_thread = Thread.new { server.accept }
socket = nil
assert_nothing_raised do
socket = Socket.tcp("localhost", port)
end
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
end;
ensure
server_thread&.value&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_all_hostname_resolution_failed
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
assert_separately opts, <<~RUBY
begin
server = TCPServer.new("localhost", 0)
_, port, = server.addr
begin;
Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
case family
when Socket::AF_INET6 then raise SocketError
when Socket::AF_INET then sleep(0.001); raise SocketError, "Last hostname resolution error"
end
end
port = TCPServer.new("localhost", 0).addr[1]
assert_raise_with_message(SocketError, "Last hostname resolution error") do
Socket.tcp("localhost", port)
end
end;
ensure
server&.close
end
RUBY
end
def test_tcp_socket_v6_address_passed
opts = %w[-rsocket -W1]
assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
begin;
assert_separately opts, <<~RUBY
begin
begin
# Verify that "localhost" can be resolved to an IPv6 address
Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
server = TCPServer.new("::1", 0)
rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
exit
rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
return
end
_, port, = server.addr
server_thread = Thread.new { server.accept }
Addrinfo.define_singleton_method(:getaddrinfo) do |*_|
[Addrinfo.tcp("::1", port)]
end
server_thread = Thread.new { server.accept }
socket = Socket.tcp("::1", port)
assert_true(socket.remote_address.ipv6?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
end;
ensure
server_thread&.value&.close
server&.close
socket&.close
end
RUBY
end
def test_tcp_socket_fast_fallback_is_false
@ -1011,11 +1029,11 @@ class TestSocket < Test::Unit::TestCase
_, port, = server.addr
server_thread = Thread.new { server.accept }
socket = Socket.tcp("127.0.0.1", port, fast_fallback: false)
assert_true(socket.remote_address.ipv4?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
ensure
server_thread&.value&.close
server&.close
socket&.close
end
def test_tcp_fast_fallback

View File

@ -142,7 +142,6 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
def test_initialize_v6_hostname_resolved_earlier
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
begin
@ -163,13 +162,13 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
test_mode_settings: { delay: { ipv4: 1000 } }
)
assert_true(socket.remote_address.ipv6?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
ensure
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_v4_hostname_resolved_earlier
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server = TCPServer.new("127.0.0.1", 0)
@ -182,15 +181,14 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
fast_fallback: true,
test_mode_settings: { delay: { ipv6: 1000 } }
)
assert_true(socket.remote_address.ipv4?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
ensure
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_v6_hostname_resolved_in_resolution_delay
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
begin
@ -212,21 +210,21 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
test_mode_settings: { delay: { ipv6: delay_time } }
)
assert_true(socket.remote_address.ipv6?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
ensure
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_v6_hostname_resolved_earlier_and_v6_server_is_not_listening
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
ipv4_address = "127.0.0.1"
ipv4_server = Socket.new(Socket::AF_INET, :STREAM)
ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address))
port = ipv4_server.connect_address.ip_port
server = Socket.new(Socket::AF_INET, :STREAM)
server.bind(Socket.pack_sockaddr_in(0, ipv4_address))
port = server.connect_address.ip_port
ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept }
server_thread = Thread.new { server.listen(1); server.accept }
socket = TCPSocket.new(
"localhost",
port,
@ -234,40 +232,36 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
test_mode_settings: { delay: { ipv4: 10 } }
)
assert_equal(ipv4_address, socket.remote_address.ip_address)
accepted, _ = ipv4_server_thread.value
accepted.close
ipv4_server.close
socket.close if socket && !socket.closed?
ensure
accepted, _ = server_thread&.value
accepted&.close
server&.close
socket&.close
end
def test_initialize_v6_hostname_resolved_later_and_v6_server_is_not_listening
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
ipv4_server = Socket.new(Socket::AF_INET, :STREAM)
ipv4_server.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
port = ipv4_server.connect_address.ip_port
server = Socket.new(Socket::AF_INET, :STREAM)
server.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
port = server.connect_address.ip_port
ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept }
server_thread = Thread.new { server.listen(1); server.accept }
socket = TCPSocket.new(
"localhost",
port,
fast_fallback: true,
test_mode_settings: { delay: { ipv6: 25 } }
)
assert_equal(
socket.remote_address.ipv4?,
true
)
accepted, _ = ipv4_server_thread.value
accepted.close
ipv4_server.close
socket.close if socket && !socket.closed?
assert_true(socket.remote_address.ipv4?)
ensure
accepted, _ = server_thread&.value
accepted&.close
server&.close
socket&.close
end
def test_initialize_v6_hostname_resolution_failed_and_v4_hostname_resolution_is_success
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server = TCPServer.new("127.0.0.1", 0)
@ -280,15 +274,14 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
fast_fallback: true,
test_mode_settings: { delay: { ipv4: 10 }, error: { ipv6: Socket::EAI_FAIL } }
)
assert_true(socket.remote_address.ipv4?)
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
ensure
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_resolv_timeout_with_connection_failure
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
begin
@ -312,7 +305,6 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
def test_initialize_with_hostname_resolution_failure_after_connection_failure
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
begin
@ -335,7 +327,6 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
def test_initialize_with_connection_failure_after_hostname_resolution_failure
# pend "to suppress the output of test failure logs in CI temporarily"
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server = TCPServer.new("127.0.0.1", 0)
@ -367,11 +358,9 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
socket = TCPSocket.new("::1", port)
assert_true(socket.remote_address.ipv6?)
ensure
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_v4_connected_socket_with_v4_address
@ -384,11 +373,9 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
socket = TCPSocket.new("127.0.0.1", port)
assert_true(socket.remote_address.ipv4?)
ensure
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
server_thread&.value&.close
server&.close
socket&.close
end
def test_initialize_fast_fallback_is_false
@ -401,10 +388,8 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
socket = TCPSocket.new("127.0.0.1", port, fast_fallback: false)
assert_true(socket.remote_address.ipv4?)
ensure
return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
server_thread.value.close
server.close
socket.close if socket && !socket.closed?
server_thread&.value&.close
server&.close
socket&.close
end
end if defined?(TCPSocket)