diff options
Diffstat (limited to 'test/socket/test_socket.rb')
| -rw-r--r-- | test/socket/test_socket.rb | 123 |
1 files changed, 66 insertions, 57 deletions
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb index b15cf63297..3b5f5b9d74 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 @@ -415,12 +418,16 @@ class TestSocket < Test::Unit::TestCase ping_p = false th = Thread.new { - Socket.udp_server_loop_on(sockets) {|msg, msg_src| - break if msg == "exit" - rmsg = Marshal.dump([msg, msg_src.remote_address, msg_src.local_address]) - ping_p = true - msg_src.reply rmsg - } + begin + Socket.udp_server_loop_on(sockets) {|msg, msg_src| + break if msg == "exit" + rmsg = Marshal.dump([msg, msg_src.remote_address, msg_src.local_address]) + ping_p = true + msg_src.reply rmsg + } + rescue Errno::ENOBUFS + # transient OS error on macOS CI, let client timeout and omit + end } ifaddrs.each {|ifa| @@ -478,9 +485,11 @@ class TestSocket < Test::Unit::TestCase } end - def timestamp_retry_rw(s1, s2, t1, type) + def timestamp_retry_rw(s1, type) IO.pipe do |r,w| + t1 = Time.now # UDP may not be reliable, keep sending until recvmsg returns: + s2 = Socket.new(:INET, :DGRAM, 0) th = Thread.new do n = 0 begin @@ -493,80 +502,54 @@ class TestSocket < Test::Unit::TestCase assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout)) msg, _, _, stamp = s1.recvmsg assert_equal("a", msg) - assert(stamp.cmsg_is?(:SOCKET, type)) + assert_send([stamp, :cmsg_is?, :SOCKET, type]) w.close # stop th n = th.value th = nil n > 1 and warn "UDP packet loss for #{type} over loopback, #{n} tries needed" - t2 = Time.now.strftime("%Y-%m-%d") - pat = Regexp.union([t1, t2].uniq) - assert_match(pat, stamp.inspect) - t = stamp.timestamp - assert_match(pat, t.strftime("%Y-%m-%d")) + t2 = Time.now + assert_include(t1..t2, stamp.timestamp) stamp ensure if th and !th.join(10) th.kill.join(10) end + s2.close end 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 Addrinfo.udp("127.0.0.1", 0).bind {|s1| - Addrinfo.udp("127.0.0.1", 0).bind {|s2| - s1.setsockopt(:SOCKET, :TIMESTAMP, true) - stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMP) - } + s1.setsockopt(:SOCKET, :TIMESTAMP, true) + timestamp_retry_rw(s1, :TIMESTAMP) } - t = stamp.timestamp - pat = /\.#{"%06d" % t.usec}/ - assert_match(pat, stamp.inspect) end def test_timestampns return if /linux/ !~ RUBY_PLATFORM || !defined?(Socket::SO_TIMESTAMPNS) - t1 = Time.now.strftime("%Y-%m-%d") - stamp = nil Addrinfo.udp("127.0.0.1", 0).bind {|s1| - Addrinfo.udp("127.0.0.1", 0).bind {|s2| - begin - s1.setsockopt(:SOCKET, :TIMESTAMPNS, true) - rescue Errno::ENOPROTOOPT - # SO_TIMESTAMPNS is available since Linux 2.6.22 - return - end - stamp = timestamp_retry_rw(s1, s2, t1, :TIMESTAMPNS) - } + begin + s1.setsockopt(:SOCKET, :TIMESTAMPNS, true) + rescue Errno::ENOPROTOOPT + # SO_TIMESTAMPNS is available since Linux 2.6.22 + return + end + timestamp_retry_rw(s1, :TIMESTAMPNS) } - t = stamp.timestamp - pat = /\.#{"%09d" % t.nsec}/ - assert_match(pat, stamp.inspect) end def test_bintime return if /freebsd/ !~ RUBY_PLATFORM - t1 = Time.now.strftime("%Y-%m-%d") - stamp = nil - Addrinfo.udp("127.0.0.1", 0).bind {|s1| - Addrinfo.udp("127.0.0.1", 0).bind {|s2| - s1.setsockopt(:SOCKET, :BINTIME, true) - s2.send "a", 0, s1.local_address - msg, _, _, stamp = s1.recvmsg - assert_equal("a", msg) - assert(stamp.cmsg_is?(:SOCKET, :BINTIME)) - } + stamp = Addrinfo.udp("127.0.0.1", 0).bind {|s1| + s1.setsockopt(:SOCKET, :BINTIME, true) + timestamp_retry_rw(s1, :BINTIME) } - t2 = Time.now.strftime("%Y-%m-%d") - pat = Regexp.union([t1, t2].uniq) - assert_match(pat, stamp.inspect) t = stamp.timestamp - assert_match(pat, t.strftime("%Y-%m-%d")) - assert_equal(stamp.data[-8,8].unpack("Q")[0], t.subsec * 2**64) + data = stamp.data + assert_equal(data.unpack1("Q", offset: data.bytesize-8), t.subsec * 2**64) end def test_closed_read @@ -906,7 +889,7 @@ class TestSocket < Test::Unit::TestCase Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep } - assert_raise(Errno::ETIMEDOUT) do + assert_raise(IO::TimeoutError) do Socket.tcp("localhost", port, resolv_timeout: 0.01) end ensure @@ -931,12 +914,38 @@ class TestSocket < Test::Unit::TestCase server.close - assert_raise(Errno::ETIMEDOUT) do + 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 + + assert_raise(IO::TimeoutError) do + Socket.tcp("localhost", 12345, open_timeout: 0.01) + end + RUBY + end + + def test_tcp_socket_open_timeout_with_other_timeouts + opts = %w[-rsocket -W1] + assert_separately opts, <<~RUBY + assert_raise(ArgumentError) do + Socket.tcp("localhost", 12345, open_timeout: 0.01, resolv_timout: 0.01) + end + RUBY + end + def test_tcp_socket_one_hostname_resolution_succeeded_at_least opts = %w[-rsocket -W1] assert_separately opts, <<~RUBY @@ -982,7 +991,7 @@ class TestSocket < Test::Unit::TestCase 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 |
