summaryrefslogtreecommitdiff
path: root/test/socket
diff options
context:
space:
mode:
Diffstat (limited to 'test/socket')
-rw-r--r--test/socket/test_addrinfo.rb6
-rw-r--r--test/socket/test_nonblock.rb4
-rw-r--r--test/socket/test_socket.rb123
-rw-r--r--test/socket/test_tcp.rb42
-rw-r--r--test/socket/test_unix.rb21
5 files changed, 122 insertions, 74 deletions
diff --git a/test/socket/test_addrinfo.rb b/test/socket/test_addrinfo.rb
index c61764d76d..0c9529090e 100644
--- a/test/socket/test_addrinfo.rb
+++ b/test/socket/test_addrinfo.rb
@@ -360,6 +360,12 @@ class TestSocketAddrinfo < Test::Unit::TestCase
assert_raise(Socket::ResolutionError) { Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("::1", 80) }
end
+ def test_ractor_shareable
+ assert_ractor(<<~'RUBY', require: 'socket', timeout: 60)
+ Ractor.make_shareable Addrinfo.new "\x10\x02\x14\xE9\xE0\x00\x00\xFB\x00\x00\x00\x00\x00\x00\x00\x00".b
+ RUBY
+ end
+
def random_port
# IANA suggests dynamic port for 49152 to 65535
# http://www.iana.org/assignments/port-numbers
diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb
index 5a4688bac3..68fefc44b3 100644
--- a/test/socket/test_nonblock.rb
+++ b/test/socket/test_nonblock.rb
@@ -104,7 +104,7 @@ class TestSocketNonblock < Test::Unit::TestCase
assert_raise(IO::WaitReadable) { u1.recvfrom_nonblock(100) }
u2.send("", 0, u1.getsockname)
assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
- Timeout.timeout(1) { IO.select [u1] }
+ Timeout.timeout(30) { IO.select [u1] }
}
mesg, inet_addr = u1.recvfrom_nonblock(100)
assert_equal("", mesg)
@@ -126,7 +126,7 @@ class TestSocketNonblock < Test::Unit::TestCase
assert_raise(IO::WaitReadable) { u1.recv_nonblock(100) }
u2.send("", 0, u1.getsockname)
assert_nothing_raised("cygwin 1.5.19 has a problem to send an empty UDP packet. [ruby-dev:28915]") {
- Timeout.timeout(1) { IO.select [u1] }
+ Timeout.timeout(30) { IO.select [u1] }
}
mesg = u1.recv_nonblock(100)
assert_equal("", mesg)
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
diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb
index e6a41f5660..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)
@@ -293,7 +321,7 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
port = server.connect_address.ip_port
server.close
- assert_raise(Errno::ETIMEDOUT) do
+ assert_raise(IO::TimeoutError) do
TCPSocket.new(
"localhost",
port,
diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb
index 3e7d85befc..e239e3935b 100644
--- a/test/socket/test_unix.rb
+++ b/test/socket/test_unix.rb
@@ -146,6 +146,7 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
end
def test_fd_passing_race_condition
+ omit 'randomly crashes on macOS' if RUBY_PLATFORM =~ /darwin/
r1, w = IO.pipe
s1, s2 = UNIXSocket.pair
s1.nonblock = s2.nonblock = true
@@ -292,14 +293,18 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
File.unlink path if path && File.socket?(path)
end
- def test_open_nul_byte
- tmpfile = Tempfile.new("s")
- path = tmpfile.path
- tmpfile.close(true)
- assert_raise(ArgumentError) {UNIXServer.open(path+"\0")}
- assert_raise(ArgumentError) {UNIXSocket.open(path+"\0")}
- ensure
- File.unlink path if path && File.socket?(path)
+ def test_open_argument
+ assert_raise(TypeError) {UNIXServer.new(nil)}
+ assert_raise(TypeError) {UNIXServer.new(1)}
+ Tempfile.create("s") do |s|
+ path = s.path
+ s.close
+ File.unlink(path)
+ assert_raise(ArgumentError) {UNIXServer.open(path+"\0")}
+ assert_raise(ArgumentError) {UNIXSocket.open(path+"\0")}
+ arg = Struct.new(:to_path).new(path)
+ assert_equal(path, UNIXServer.open(arg) { |server| server.path })
+ end
end
def test_addr