summaryrefslogtreecommitdiff
path: root/test/socket/test_tcp.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/socket/test_tcp.rb')
-rw-r--r--test/socket/test_tcp.rb292
1 files changed, 286 insertions, 6 deletions
diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb
index 6a016da71d..d689ab2376 100644
--- a/test/socket/test_tcp.rb
+++ b/test/socket/test_tcp.rb
@@ -18,6 +18,12 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
def test_initialize_failure
+ assert_raise(Socket::ResolutionError) do
+ t = TCPSocket.open(nil, nil)
+ ensure
+ t&.close
+ end
+
# These addresses are chosen from TEST-NET-1, TEST-NET-2, and TEST-NET-3.
# [RFC 5737]
# They are chosen because probably they are not used as a host address.
@@ -43,16 +49,14 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
server_addr = '127.0.0.1'
server_port = 80
- begin
+ e = assert_raise_kind_of(SystemCallError) do
# Since client_addr is not an IP address of this host,
# bind() in TCPSocket.new should fail as EADDRNOTAVAIL.
t = TCPSocket.new(server_addr, server_port, client_addr, client_port)
- flunk "expected SystemCallError"
- rescue SystemCallError => e
- assert_match "for \"#{client_addr}\" port #{client_port}", e.message
+ ensure
+ t&.close
end
- ensure
- t.close if t && !t.closed?
+ assert_include e.message, "for \"#{client_addr}\" port #{client_port}"
end
def test_initialize_resolv_timeout
@@ -69,6 +73,30 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
end
+ def test_tcp_initialize_open_timeout
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ port = server.connect_address.ip_port
+ server.close
+
+ assert_raise(IO::TimeoutError) do
+ TCPSocket.new(
+ "localhost",
+ port,
+ open_timeout: 0.01,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 1000 } }
+ )
+ end
+ end
+
+ def test_initialize_open_timeout_with_other_timeouts
+ assert_raise(ArgumentError) do
+ TCPSocket.new("localhost", 12345, open_timeout: 0.01, resolv_timeout: 0.01)
+ end
+ end
+
def test_initialize_connect_timeout
assert_raise(IO::TimeoutError, Errno::ENETUNREACH, Errno::EACCES) do
TCPSocket.new("192.0.2.1", 80, connect_timeout: 0)
@@ -140,4 +168,256 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
server_threads.each(&:join)
end
end
+
+ def test_initialize_v6_hostname_resolved_earlier
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ begin
+ # Verify that "localhost" can be resolved to an IPv6 address
+ Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
+ server = TCPServer.new("::1", 0)
+ rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
+ return
+ end
+
+ server_thread = Thread.new { server.accept }
+ port = server.addr[1]
+
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 1000 } }
+ )
+ assert_true(socket.remote_address.ipv6?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_v4_hostname_resolved_earlier
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ port = server.addr[1]
+
+ server_thread = Thread.new { server.accept }
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv6: 1000 } }
+ )
+ assert_true(socket.remote_address.ipv4?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_v6_hostname_resolved_in_resolution_delay
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ begin
+ # Verify that "localhost" can be resolved to an IPv6 address
+ Socket.getaddrinfo("localhost", 0, Socket::AF_INET6)
+ server = TCPServer.new("::1", 0)
+ rescue Socket::ResolutionError, Errno::EADDRNOTAVAIL # IPv6 is not supported
+ return
+ end
+
+ port = server.addr[1]
+ delay_time = 25 # Socket::RESOLUTION_DELAY (private) is 50ms
+
+ server_thread = Thread.new { server.accept }
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv6: delay_time } }
+ )
+ assert_true(socket.remote_address.ipv6?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_v6_hostname_resolved_earlier_and_v6_server_is_not_listening
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ ipv4_address = "127.0.0.1"
+ 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 }
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 10 } }
+ )
+ assert_equal(ipv4_address, socket.remote_address.ip_address)
+ 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
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = Socket.new(Socket::AF_INET, :STREAM)
+ server.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
+ port = server.connect_address.ip_port
+
+ server_thread = Thread.new { server.listen(1); server.accept }
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv6: 25 } }
+ )
+ 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
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ port = server.addr[1]
+
+ server_thread = Thread.new { server.accept }
+ socket = TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 10 }, error: { ipv6: Socket::EAI_FAIL } }
+ )
+ assert_true(socket.remote_address.ipv4?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_resolv_timeout_with_connection_failure
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ return
+ end
+
+ port = server.connect_address.ip_port
+ server.close
+
+ assert_raise(IO::TimeoutError) do
+ TCPSocket.new(
+ "localhost",
+ port,
+ resolv_timeout: 0.01,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 1000 } }
+ )
+ end
+ end
+
+ def test_initialize_with_hostname_resolution_failure_after_connection_failure
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ return
+ end
+
+ port = server.connect_address.ip_port
+ server.close
+
+ assert_raise(Errno::ECONNREFUSED) do
+ TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 100 }, error: { ipv4: Socket::EAI_FAIL } }
+ )
+ end
+ end
+
+ def test_initialize_with_connection_failure_after_hostname_resolution_failure
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ port = server.connect_address.ip_port
+ server.close
+
+ assert_raise(Errno::ECONNREFUSED) do
+ TCPSocket.new(
+ "localhost",
+ port,
+ fast_fallback: true,
+ test_mode_settings: { delay: { ipv4: 100 }, error: { ipv6: Socket::EAI_FAIL } }
+ )
+ end
+ end
+
+ def test_initialize_v6_connected_socket_with_v6_address
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ return
+ end
+
+ server_thread = Thread.new { server.accept }
+ port = server.addr[1]
+
+ socket = TCPSocket.new("::1", port)
+ assert_true(socket.remote_address.ipv6?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_v4_connected_socket_with_v4_address
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ server_thread = Thread.new { server.accept }
+ port = server.addr[1]
+
+ socket = TCPSocket.new("127.0.0.1", port)
+ assert_true(socket.remote_address.ipv4?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
+
+ def test_initialize_fast_fallback_is_false
+ return if RUBY_PLATFORM =~ /mswin|mingw|cygwin/
+
+ server = TCPServer.new("127.0.0.1", 0)
+ _, port, = server.addr
+ server_thread = Thread.new { server.accept }
+
+ socket = TCPSocket.new("127.0.0.1", port, fast_fallback: false)
+ assert_true(socket.remote_address.ipv4?)
+ ensure
+ server_thread&.value&.close
+ server&.close
+ socket&.close
+ end
end if defined?(TCPSocket)