/test/test_socket.rb
Ruby | 449 lines | 335 code | 91 blank | 23 comment | 29 complexity | 24c0bb36258420af6e7625961194345f MD5 | raw file
Possible License(s): GPL-3.0, JSON
- require 'test/unit'
- require 'socket'
- require 'thread'
- require 'test/test_helper'
- require 'ipaddr'
- class SocketTest < Test::Unit::TestCase
- include TestHelper
- def test_multicast_send_and_receive
- multicast_addr = "225.4.5.6"
- port = 6789
- multicast_msg = "Hello from automated JRuby test suite"
- assert_nothing_raised do
- socket = UDPSocket.new
- ip = IPAddr.new(multicast_addr).hton + IPAddr.new("0.0.0.0").hton
- socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_ADD_MEMBERSHIP, ip)
- socket.bind(Socket::INADDR_ANY, port)
- socket.send(multicast_msg, 0, multicast_addr, port)
- msg, info = socket.recvfrom(1024)
- assert_equal(multicast_msg, msg)
- assert_equal(multicast_msg.size, msg.size)
- assert_equal(port, info[1])
- socket.close
- end
- end
- def test_tcp_socket_allows_nil_for_hostname
- assert_nothing_raised do
- server = TCPServer.new(nil, 7789)
- t = Thread.new do
- s = server.accept
- s.close
- end
- client = TCPSocket.new(nil, 7789)
- client.write ""
- t.join
- end
- end
- #JRUBY-3827
- def test_nil_hostname_and_passive_returns_inaddr_any
- assert_nothing_raised do
- addrs = Socket::getaddrinfo(nil, 7789, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0, Socket::AI_PASSIVE)
- assert_equal(1, addrs.size)
- assert_equal("0.0.0.0", addrs[0][2])
- assert_equal("0.0.0.0", addrs[0][3])
- end
- end
- def test_nil_hostname_and_no_flags_returns_localhost
- assert_nothing_raised do
- addrs = Socket::getaddrinfo(nil, 7789, Socket::AF_UNSPEC, Socket::SOCK_STREAM, 0)
- assert_equal(1, addrs.size)
-
- # FIXME, behaves differently on Windows, both JRuby and MRI.
- # JRuby returns "127.0.0.1", "127.0.0.1"
- # MRI returns "<actual_hostname>", "127.0.0.1"
- unless WINDOWS
- #assert_equal("localhost", addrs[0][2])
- assert_equal("127.0.0.1", addrs[0][3])
- end
- end
- end
- def test_basic_socket_reverse_lookup
- assert_nothing_raised do
- reverse = BasicSocket.do_not_reverse_lookup
- BasicSocket.do_not_reverse_lookup = !reverse
- assert_equal(reverse, !BasicSocket.do_not_reverse_lookup)
- BasicSocket.do_not_reverse_lookup = reverse
- end
- end
-
- #JRUBY-2147
- def test_tcp_close_read
- socket = TCPServer.new(nil, 9999)
- socket.close_read
- assert(!socket.closed?)
- socket.close
- end
-
- #JRUBY-2146
- def test_tcp_close_write
- socket = TCPServer.new(nil, 8888)
- socket.close_write
- assert(!socket.closed?)
- socket.close
- end
-
- def test_tcp_close_read_then_write_should_close_socket
- socket = TCPServer.new(nil, 7777)
- socket.close_write
- assert(!socket.closed?)
- socket.close_read
- assert(socket.closed?)
- end
- # JRUBY-2874
- def test_raises_socket_error_on_out_of_range_port
- [-2**16, -2**8, -2, -1, 2**16, 2**16 + 1, 2**17, 2**30 -1].each do |port|
- assert_raises(SocketError) do
- TCPSocket.new('localhost', port)
- end
- end
- end
- # JRUBY-4299
- def test_tcp_socket_reuse_addr
- socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
- socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
- assert_equal 1, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR).unpack('i')[0]
- ensure
- socket.close
- end
- # JRUBY-4299
- def test_udp_socket_reuse_addr
- socket = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
- socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
- assert_equal 1, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR).unpack('i')[0]
- ensure
- socket.close
- end
- # JRUBY-4868
- def test_getservbyname
- assert_equal(21, Socket.getservbyname('ftp'))
- assert_equal(21, Socket.getservbyname('21'))
- assert_equal(21, Socket.getservbyname(' 21'))
- end
- end
- class UNIXSocketTests < Test::Unit::TestCase
- # this is intentional, otherwise test run fails on windows
- def test_dummy; end
- if defined?(UNIXSocket)
- def test_unix_socket_path
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- server = UNIXServer.open(path)
- assert_equal path, server.path
-
- cli = UNIXSocket.open(path)
- assert_equal "", cli.path
-
- cli.close
- server.close
- File.unlink(path) if File.exist?(path)
- end
- def test_unix_socket_addr
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- server = UNIXServer.open(path)
- assert_equal ["AF_UNIX", path], server.addr
-
- cli = UNIXSocket.open(path)
- assert_equal ["AF_UNIX", ""], cli.addr
-
- cli.close
- server.close
- File.unlink(path) if File.exist?(path)
- end
- def test_unix_socket_peeraddr_raises_enotconn
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
- server = UNIXServer.open(path)
- assert_raises(Errno::ENOTCONN) do
- server.peeraddr
- end
- File.unlink(path) if File.exist?(path)
- end
- def test_unix_socket_peeraddr
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- server = UNIXServer.open(path)
- cli = UNIXSocket.open(path)
- ssrv = server.accept
-
- assert_equal ["AF_UNIX", ""], ssrv.peeraddr
- assert_equal ["AF_UNIX", path], cli.peeraddr
- ssrv.close
- cli.close
- server.close
- File.unlink(path) if File.exist?(path)
- end
- def test_unix_socket_raises_exception_on_too_long_path
- assert_raises(ArgumentError) do
- # on some platforms, 103 is invalid length (MacOS)
- # on others, 108 (Linux), we'll take the biggest one
- UNIXSocket.new("a" * 108)
- end
- end
-
- def test_unix_socket_raises_exception_on_path_that_cant_exist
- path = "a"
- File.unlink(path) if File.exist?(path)
- assert_raises(Errno::ENOENT) do
- UNIXSocket.new(path)
- end
- end
-
- def test_can_create_socket_server
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_accept_nonblocking
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- assert_raises(Errno::EAGAIN) do
- sock.accept_nonblock
- end
- cli = UNIXSocket.open(path)
- sock.accept_nonblock.close
-
- cli.close
-
- sock.close
- File.unlink(path) if File.exist?(path)
- end
-
- def test_can_create_socket_server_and_relisten
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- sock = UNIXServer.open(path)
-
- assert File.exist?(path)
- sock.listen(1)
- assert File.exist?(path)
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_client_connected_to_it
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
-
- sock = UNIXServer.open(path)
- assert File.exist?(path)
-
- cli = UNIXSocket.open(path)
- cli.close
-
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_client_connected_to_it_and_send_from_client_to_server
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- cli = UNIXSocket.open(path)
- servsock = sock.accept
- cli.send("hello",0)
- assert_equal "hello", servsock.recv(5)
- servsock.close
- cli.close
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_client_connected_to_it_and_send_from_server_to_client
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- cli = UNIXSocket.open(path)
- servsock = sock.accept
- servsock.send("hello",0)
- assert_equal "hello", cli.recv(5)
- servsock.close
- cli.close
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_client_connected_to_it_and_send_from_client_to_server_using_recvfrom
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- cli = UNIXSocket.open(path)
- servsock = sock.accept
- cli.send("hello",0)
- assert_equal ["hello", ["AF_UNIX", ""]], servsock.recvfrom(5)
- servsock.close
- cli.close
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socket_server_and_client_connected_to_it_and_send_from_server_to_client_using_recvfrom
- path = "/tmp/sample"
- File.unlink(path) if File.exist?(path)
- sock = UNIXServer.open(path)
- assert File.exist?(path)
- cli = UNIXSocket.open(path)
- servsock = sock.accept
- servsock.send("hello",0)
- data = cli.recvfrom(5)
- assert_equal "hello", data[0]
- assert_equal "AF_UNIX", data[1][0]
- servsock.close
- cli.close
- sock.close
- File.unlink(path) if File.exist?(path)
- end
- def test_can_create_socketpair_and_send_from_one_to_the_other
- sock1, sock2 = UNIXSocket.socketpair
-
- sock1.send("hello", 0)
- assert_equal "hello", sock2.recv(5)
-
- sock1.close
- sock2.close
- end
- def test_can_create_socketpair_and_can_send_from_the_other
- sock1, sock2 = UNIXSocket.socketpair
-
- sock2.send("hello", 0)
- assert_equal "hello", sock1.recv(5)
-
- sock2.close
- sock1.close
- end
- def test_can_create_socketpair_and_can_send_from_the_other_with_recvfrom
- sock1, sock2 = UNIXSocket.socketpair
-
- sock2.send("hello", 0)
- assert_equal ["hello", ["AF_UNIX", ""]], sock1.recvfrom(5)
-
- sock2.close
- sock1.close
- end
-
- def test_can_read_and_get_minus_one
- sock1, sock2 = UNIXSocket.socketpair
-
- sock2.send("hello", 0)
- assert_equal "hell", sock1.recv(4)
- assert_equal "", sock1.recv(0)
- assert_equal "o", sock1.recv(1)
- sock2.close
- sock1.close
-
- assert_raises(IOError) do
- sock1.recv(1)
- end
- end
- end
- end
- class ServerTest < Test::Unit::TestCase
- def test_server_close_interrupts_pending_accepts
- # unfortunately this test is going to not be 100% reliable
- # since it involves thread interaction and it's impossible to
- # do things like wait until the other thread blocks
- port = 41258
- server = TCPServer.new('localhost', port)
- queue = Queue.new
- thread = Thread.new do
- server.accept
- end
- # wait until the thread is sleeping (ready to accept)
- Thread.pass while thread.alive? && thread.status != "sleep"
- # close the server
- server.close
- # propagate the thread's termination error, checking it for IOError
- assert_raise(IOError) {thread.value}
- end
- # JRUBY-2874
- def test_raises_socket_error_on_out_of_range_port
- [-2**16, -2**8, -2, -1, 2**16, 2**16 + 1, 2**17, 2**30 -1].each do |port|
- assert_raises(SocketError) do
- TCPServer.new('localhost', port)
- end
- end
- end
- # JRUBY-4299
- def test_server_reuse_addr
- socket = TCPServer.new("127.0.0.1", 7777)
- socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
- assert_equal 1, socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR).unpack('i')[0]
- ensure
- socket.close
- end
- # JRUBY-5111
- def test_server_methods_with_closed_socket
- socket = TCPServer.new("127.0.0.1", 7777)
- socket.close
- assert_raises(IOError) { socket.addr }
- assert_raises(IOError) { socket.getsockname }
- assert_raises(IOError) { socket.__getsockname }
- end
- end