diff options
Diffstat (limited to 'test/socket/test_tcp.rb')
| -rw-r--r-- | test/socket/test_tcp.rb | 292 |
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) |
