diff options
Diffstat (limited to 'test/socket/test_socket.rb')
| -rw-r--r-- | test/socket/test_socket.rb | 280 |
1 files changed, 181 insertions, 99 deletions
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index 6a057e866f..c42527f370 100644 --- a/test/socket/test_socket.rb +++ b/test/socket/test_socket.rb @@ -173,8 +173,11 @@ class TestSocket < Test::Unit::TestCase def errors_addrinuse errs = [Errno::EADDRINUSE] - # MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721" - errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM + # Windows can fail with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721" + # or "Test::Unit::ProxyError: Permission denied - bind(2) for 0.0.0.0:55333" + if /mswin|mingw/ =~ RUBY_PLATFORM + errs += [Errno::EACCES, Test::Unit::ProxyError] + end errs end @@ -489,7 +492,7 @@ class TestSocket < Test::Unit::TestCase end while IO.select([r], nil, nil, 0.1).nil? n end - timeout = (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? ? 120 : 30) # for --jit-wait + timeout = 30 assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout)) msg, _, _, stamp = s1.recvmsg assert_equal("a", msg) @@ -513,7 +516,7 @@ class TestSocket < Test::Unit::TestCase end def test_timestamp - return if /linux|freebsd|netbsd|openbsd|solaris|darwin/ !~ RUBY_PLATFORM + return if /linux|freebsd|netbsd|openbsd|darwin/ !~ RUBY_PLATFORM return if !defined?(Socket::AncillaryData) || !defined?(Socket::SO_TIMESTAMP) t1 = Time.now.strftime("%Y-%m-%d") stamp = nil @@ -780,17 +783,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 +805,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 +828,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 +862,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 +889,97 @@ 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 + assert_raise(IO::TimeoutError) 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;'}" - - begin; - server = TCPServer.new("127.0.0.1", 12345) - _, port, = server.addr + assert_separately opts, <<~RUBY + 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) + assert_raise(IO::TimeoutError) do + Socket.tcp("localhost", port, resolv_timeout: 0.01) + end + RUBY + end + + def test_tcp_socket_open_timeout + opts = %w[-rsocket -W1] + assert_separately opts, <<~RUBY + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + if family == Socket::AF_INET6 + sleep + else + [Addrinfo.tcp("127.0.0.1", 12345)] end - end; + end + + assert_raise(IO::TimeoutError) do + Socket.tcp("localhost", 12345, open_timeout: 0.01) + end + RUBY end - def test_tcp_socket_one_hostname_resolution_succeeded_at_least + def test_tcp_socket_open_timeout_with_other_timeouts opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + assert_separately opts, <<~RUBY + assert_raise(ArgumentError) do + Socket.tcp("localhost", 12345, open_timeout: 0.01, resolv_timout: 0.01) + end + RUBY + end - begin; + def test_tcp_socket_one_hostname_resolution_succeeded_at_least + opts = %w[-rsocket -W1] + 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 +988,91 @@ 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" + when Socket::AF_INET then sleep(0.01); 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 + def test_tcp_socket_hostname_resolution_failed_after_connection_failure opts = %w[-rsocket -W1] - assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}" + assert_separately opts, <<~RUBY + server = TCPServer.new("127.0.0.1", 0) + port = server.connect_address.ip_port + + Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_| + case family + when Socket::AF_INET6 then sleep(0.1); raise Socket::ResolutionError + when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)] + end + end - begin; + server.close + + # SystemCallError is a workaround for Windows environment + assert_raise(Errno::ECONNREFUSED, SystemCallError) do + Socket.tcp("localhost", port) + end + RUBY + end + + def test_tcp_socket_v6_address_passed + opts = %w[-rsocket -W1] + 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,10 +1080,23 @@ 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 + opts = %w[-rsocket -W1] + assert_separately opts, <<~RUBY + assert_true(Socket.tcp_fast_fallback) + + Socket.tcp_fast_fallback = false + assert_false(Socket.tcp_fast_fallback) + + Socket.tcp_fast_fallback = true + assert_true(Socket.tcp_fast_fallback) + RUBY end end if defined?(Socket) |
