aboutsummaryrefslogtreecommitdiffstats
path: root/spec/rubyspec/library/socket
diff options
context:
space:
mode:
Diffstat (limited to 'spec/rubyspec/library/socket')
-rw-r--r--spec/rubyspec/library/socket/addrinfo/afamily_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/addrinfo/bind_spec.rb29
-rw-r--r--spec/rubyspec/library/socket/addrinfo/canonname_spec.rb19
-rw-r--r--spec/rubyspec/library/socket/addrinfo/initialize_spec.rb253
-rw-r--r--spec/rubyspec/library/socket/addrinfo/inspect_sockaddr_spec.rb25
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ip_address_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ip_port_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ip_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ip_unpack_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv4_loopback_spec.rb46
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv4_multicast_spec.rb46
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv4_private_spec.rb41
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv4_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv6_loopback_spec.rb46
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv6_multicast_spec.rb46
-rw-r--r--spec/rubyspec/library/socket/addrinfo/ipv6_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/addrinfo/pfamily_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/addrinfo/protocol_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/addrinfo/shared/to_sockaddr.rb35
-rw-r--r--spec/rubyspec/library/socket/addrinfo/socktype_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/addrinfo/tcp_spec.rb20
-rw-r--r--spec/rubyspec/library/socket/addrinfo/to_s_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/addrinfo/to_sockaddr_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/addrinfo/udp_spec.rb20
-rw-r--r--spec/rubyspec/library/socket/addrinfo/unix_path_spec.rb40
-rw-r--r--spec/rubyspec/library/socket/addrinfo/unix_spec.rb54
-rw-r--r--spec/rubyspec/library/socket/basicsocket/close_read_spec.rb43
-rw-r--r--spec/rubyspec/library/socket/basicsocket/close_write_spec.rb48
-rw-r--r--spec/rubyspec/library/socket/basicsocket/do_not_reverse_lookup_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/basicsocket/for_fd_spec.rb21
-rw-r--r--spec/rubyspec/library/socket/basicsocket/getpeername_spec.rb25
-rw-r--r--spec/rubyspec/library/socket/basicsocket/getsockname_spec.rb28
-rw-r--r--spec/rubyspec/library/socket/basicsocket/getsockopt_spec.rb46
-rw-r--r--spec/rubyspec/library/socket/basicsocket/ioctl_spec.rb43
-rw-r--r--spec/rubyspec/library/socket/basicsocket/recv_nonblock_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/basicsocket/recv_spec.rb93
-rw-r--r--spec/rubyspec/library/socket/basicsocket/send_spec.rb84
-rw-r--r--spec/rubyspec/library/socket/basicsocket/setsockopt_spec.rb213
-rw-r--r--spec/rubyspec/library/socket/basicsocket/shutdown_spec.rb6
-rw-r--r--spec/rubyspec/library/socket/constants/constants_spec.rb90
-rw-r--r--spec/rubyspec/library/socket/fixtures/classes.rb106
-rw-r--r--spec/rubyspec/library/socket/fixtures/send_io.txt1
-rw-r--r--spec/rubyspec/library/socket/ipsocket/addr_spec.rb42
-rw-r--r--spec/rubyspec/library/socket/ipsocket/getaddress_spec.rb27
-rw-r--r--spec/rubyspec/library/socket/ipsocket/peeraddr_spec.rb48
-rw-r--r--spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb65
-rw-r--r--spec/rubyspec/library/socket/option/bool_spec.rb25
-rw-r--r--spec/rubyspec/library/socket/option/inspect_spec.rb20
-rw-r--r--spec/rubyspec/library/socket/option/int_spec.rb28
-rw-r--r--spec/rubyspec/library/socket/option/linger_spec.rb62
-rw-r--r--spec/rubyspec/library/socket/option/new_spec.rb35
-rw-r--r--spec/rubyspec/library/socket/shared/pack_sockaddr.rb50
-rw-r--r--spec/rubyspec/library/socket/shared/partially_closable_sockets.rb13
-rw-r--r--spec/rubyspec/library/socket/shared/recv_nonblock.rb54
-rw-r--r--spec/rubyspec/library/socket/shared/socketpair.rb23
-rw-r--r--spec/rubyspec/library/socket/socket/accept_nonblock_spec.rb37
-rw-r--r--spec/rubyspec/library/socket/socket/accept_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/bind_spec.rb81
-rw-r--r--spec/rubyspec/library/socket/socket/connect_nonblock_spec.rb67
-rw-r--r--spec/rubyspec/library/socket/socket/connect_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/for_fd_spec.rb30
-rw-r--r--spec/rubyspec/library/socket/socket/getaddrinfo_spec.rb112
-rw-r--r--spec/rubyspec/library/socket/socket/gethostbyaddr_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/gethostbyname_spec.rb17
-rw-r--r--spec/rubyspec/library/socket/socket/gethostname_spec.rb8
-rw-r--r--spec/rubyspec/library/socket/socket/getnameinfo_spec.rb66
-rw-r--r--spec/rubyspec/library/socket/socket/getservbyname_spec.rb24
-rw-r--r--spec/rubyspec/library/socket/socket/listen_spec.rb22
-rw-r--r--spec/rubyspec/library/socket/socket/new_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/pack_sockaddr_in_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/pack_sockaddr_un_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/pair_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/recvfrom_nonblock_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/recvfrom_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/sockaddr_in_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/sockaddr_un_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/socket_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/socket/socketpair_spec.rb7
-rw-r--r--spec/rubyspec/library/socket/socket/sysaccept_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/socket/unpack_sockaddr_in_spec.rb29
-rw-r--r--spec/rubyspec/library/socket/socket/unpack_sockaddr_un_spec.rb26
-rw-r--r--spec/rubyspec/library/socket/tcpserver/accept_nonblock_spec.rb49
-rw-r--r--spec/rubyspec/library/socket/tcpserver/accept_spec.rb66
-rw-r--r--spec/rubyspec/library/socket/tcpserver/gets_spec.rb16
-rw-r--r--spec/rubyspec/library/socket/tcpserver/listen_spec.rb18
-rw-r--r--spec/rubyspec/library/socket/tcpserver/new_spec.rb97
-rw-r--r--spec/rubyspec/library/socket/tcpserver/output_spec.rb9
-rw-r--r--spec/rubyspec/library/socket/tcpserver/readpartial_spec.rb9
-rw-r--r--spec/rubyspec/library/socket/tcpserver/sysaccept_spec.rb31
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/gethostbyname_spec.rb51
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/new_spec.rb5
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/open_spec.rb5
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/partially_closable_spec.rb22
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb36
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb48
-rw-r--r--spec/rubyspec/library/socket/tcpsocket/shared/new.rb71
-rw-r--r--spec/rubyspec/library/socket/udpsocket/bind_spec.rb35
-rw-r--r--spec/rubyspec/library/socket/udpsocket/connect_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/udpsocket/new_spec.rb32
-rw-r--r--spec/rubyspec/library/socket/udpsocket/open_spec.rb13
-rw-r--r--spec/rubyspec/library/socket/udpsocket/recvfrom_nonblock_spec.rb2
-rw-r--r--spec/rubyspec/library/socket/udpsocket/send_spec.rb58
-rw-r--r--spec/rubyspec/library/socket/unixserver/accept_nonblock_spec.rb40
-rw-r--r--spec/rubyspec/library/socket/unixserver/accept_spec.rb66
-rw-r--r--spec/rubyspec/library/socket/unixserver/for_fd_spec.rb23
-rw-r--r--spec/rubyspec/library/socket/unixserver/new_spec.rb6
-rw-r--r--spec/rubyspec/library/socket/unixserver/open_spec.rb26
-rw-r--r--spec/rubyspec/library/socket/unixserver/shared/new.rb24
-rw-r--r--spec/rubyspec/library/socket/unixsocket/addr_spec.rb38
-rw-r--r--spec/rubyspec/library/socket/unixsocket/inspect_spec.rb17
-rw-r--r--spec/rubyspec/library/socket/unixsocket/new_spec.rb6
-rw-r--r--spec/rubyspec/library/socket/unixsocket/open_spec.rb27
-rw-r--r--spec/rubyspec/library/socket/unixsocket/pair_spec.rb39
-rw-r--r--spec/rubyspec/library/socket/unixsocket/partially_closable_spec.rb26
-rw-r--r--spec/rubyspec/library/socket/unixsocket/path_spec.rb30
-rw-r--r--spec/rubyspec/library/socket/unixsocket/peeraddr_spec.rb30
-rw-r--r--spec/rubyspec/library/socket/unixsocket/recv_io_spec.rb44
-rw-r--r--spec/rubyspec/library/socket/unixsocket/recvfrom_spec.rb49
-rw-r--r--spec/rubyspec/library/socket/unixsocket/send_io_spec.rb35
-rw-r--r--spec/rubyspec/library/socket/unixsocket/shared/new.rb24
120 files changed, 4324 insertions, 0 deletions
diff --git a/spec/rubyspec/library/socket/addrinfo/afamily_spec.rb b/spec/rubyspec/library/socket/addrinfo/afamily_spec.rb
new file mode 100644
index 0000000000..1845ab5e04
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/afamily_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#afamily" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::AF_INET" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::AF_INET6" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::AF_UNIX" do
+ @addrinfo.afamily.should == Socket::AF_UNIX
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/bind_spec.rb b/spec/rubyspec/library/socket/addrinfo/bind_spec.rb
new file mode 100644
index 0000000000..4afa3a0211
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/bind_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Addrinfo#bind" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ end
+
+ it "returns a bound socket when no block is given" do
+ @socket = @addrinfo.bind
+ @socket.should be_kind_of(Socket)
+ @socket.closed?.should be_false
+ end
+
+ it "yields the socket if a block is given" do
+ @addrinfo.bind do |sock|
+ @socket = sock
+ sock.should be_kind_of(Socket)
+ end
+ @socket.closed?.should be_true
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/canonname_spec.rb b/spec/rubyspec/library/socket/addrinfo/canonname_spec.rb
new file mode 100644
index 0000000000..15dfe86467
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/canonname_spec.rb
@@ -0,0 +1,19 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Addrinfo#canonname" do
+
+ before :each do
+ @addrinfos = Addrinfo.getaddrinfo("localhost", 80, :INET, :STREAM, nil, Socket::AI_CANONNAME)
+ end
+
+ it "returns the canonical name for a host" do
+ canonname = @addrinfos.map { |a| a.canonname }.find { |name| name and name.include?("localhost") }
+ if canonname
+ canonname.should include("localhost")
+ else
+ canonname.should == nil
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/initialize_spec.rb b/spec/rubyspec/library/socket/addrinfo/initialize_spec.rb
new file mode 100644
index 0000000000..254539f95e
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/initialize_spec.rb
@@ -0,0 +1,253 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#initialize" do
+
+ describe "with a sockaddr string" do
+
+ describe "without a family" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"))
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_UNSPEC
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family given" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family and socket type" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6, Socket::SOCK_STREAM)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family, socket type and protocol" do
+ before :each do
+ @addrinfo = Addrinfo.new(Socket.sockaddr_in("smtp", "2001:DB8::1"), Socket::PF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "2001:db8::1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 25
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET6
+ end
+
+ it "returns the specified socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the specified protocol" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+ end
+
+ describe "with a sockaddr array" do
+
+ describe "without a family" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"])
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family given" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == 0
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family and socket type" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET, Socket::SOCK_STREAM)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the 0 protocol" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+
+ describe "with a family, socket type and protocol" do
+ before :each do
+ @addrinfo = Addrinfo.new(["AF_INET", 46102, "localhost", "127.0.0.1"], Socket::PF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP)
+ end
+
+ it "stores the ip address from the sockaddr" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+
+ it "stores the port number from the sockaddr" do
+ @addrinfo.ip_port.should == 46102
+ end
+
+ it "returns the Socket::UNSPEC pfamily" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ it "returns the INET6 afamily" do
+ @addrinfo.afamily.should == Socket::AF_INET
+ end
+
+ it "returns the 0 socket type" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it "returns the specified protocol" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/inspect_sockaddr_spec.rb b/spec/rubyspec/library/socket/addrinfo/inspect_sockaddr_spec.rb
new file mode 100644
index 0000000000..c7d69db760
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/inspect_sockaddr_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+
+require 'socket'
+
+describe 'Addrinfo#inspect_sockaddr' do
+ it 'IPv4' do
+ Addrinfo.tcp('127.0.0.1', 80).inspect_sockaddr.should == '127.0.0.1:80'
+ Addrinfo.tcp('127.0.0.1', 0).inspect_sockaddr.should == '127.0.0.1'
+ end
+
+ it 'IPv6' do
+ Addrinfo.tcp('::1', 80).inspect_sockaddr.should == '[::1]:80'
+ Addrinfo.tcp('::1', 0).inspect_sockaddr.should == '::1'
+ ip = '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
+ Addrinfo.tcp(ip, 80).inspect_sockaddr.should == '[2001:db8:85a3::8a2e:370:7334]:80'
+ Addrinfo.tcp(ip, 0).inspect_sockaddr.should == '2001:db8:85a3::8a2e:370:7334'
+ end
+
+ platform_is_not :windows do
+ it 'UNIX' do
+ Addrinfo.unix('/tmp/sock').inspect_sockaddr.should == '/tmp/sock'
+ Addrinfo.unix('rel').inspect_sockaddr.should == 'UNIX rel'
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ip_address_spec.rb b/spec/rubyspec/library/socket/addrinfo/ip_address_spec.rb
new file mode 100644
index 0000000000..f82cef0812
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ip_address_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_address" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the ip address" do
+ @addrinfo.ip_address.should == "127.0.0.1"
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the ip address" do
+ @addrinfo.ip_address.should == "::1"
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_address }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ip_port_spec.rb b/spec/rubyspec/library/socket/addrinfo/ip_port_spec.rb
new file mode 100644
index 0000000000..e437b88ca1
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ip_port_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_port" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the port" do
+ @addrinfo.ip_port.should == 80
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the port" do
+ @addrinfo.ip_port.should == 80
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_port }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ip_spec.rb b/spec/rubyspec/library/socket/addrinfo/ip_spec.rb
new file mode 100644
index 0000000000..2e4b613ae5
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ip_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ip?.should be_true
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ip?.should be_true
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::AF_INET6" do
+ @addrinfo.ip?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ip_unpack_spec.rb b/spec/rubyspec/library/socket/addrinfo/ip_unpack_spec.rb
new file mode 100644
index 0000000000..2b4a9372cc
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ip_unpack_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ip_unpack" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns the ip address and port pair" do
+ @addrinfo.ip_unpack.should == ["127.0.0.1", 80]
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns the ip address and port pair" do
+ @addrinfo.ip_unpack.should == ["::1", 80]
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.ip_unpack }.should raise_error(SocketError)
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv4_loopback_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv4_loopback_spec.rb
new file mode 100644
index 0000000000..457bd7cebf
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv4_loopback_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_loopback?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("127.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @loopback.ipv4_loopback?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_loopback?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @loopback.ipv4_loopback?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_loopback?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_loopback?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv4_multicast_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv4_multicast_spec.rb
new file mode 100644
index 0000000000..01f6a6ebf7
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv4_multicast_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_multicast?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("224.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @multicast.ipv4_multicast?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_multicast?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("ff02::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @multicast.ipv4_multicast?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv4_multicast?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_multicast?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv4_private_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv4_private_spec.rb
new file mode 100644
index 0000000000..cf8bd8c1aa
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv4_private_spec.rb
@@ -0,0 +1,41 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4_private?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @private = Addrinfo.tcp("10.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for a private address" do
+ @private.ipv4_private?.should be_true
+ end
+
+ it "returns false for a public address" do
+ @other.ipv4_private?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false" do
+ @other.ipv4_private?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_private?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv4_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv4_spec.rb
new file mode 100644
index 0000000000..3d4560532e
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv4_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv4?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("10.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ipv4?.should be_true
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv6_loopback_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv6_loopback_spec.rb
new file mode 100644
index 0000000000..b0060378e6
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv6_loopback_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6_loopback?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("127.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @loopback.ipv6_loopback?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_loopback?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @loopback = Addrinfo.tcp("::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @loopback.ipv6_loopback?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_loopback?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_loopback?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv6_multicast_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv6_multicast_spec.rb
new file mode 100644
index 0000000000..d8b3a96ebb
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv6_multicast_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6_multicast?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("224.0.0.1", 80)
+ @other = Addrinfo.tcp("0.0.0.0", 80)
+ end
+
+ it "returns true for the loopback address" do
+ @multicast.ipv6_multicast?.should be_false
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_multicast?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @multicast = Addrinfo.tcp("ff02::1", 80)
+ @other = Addrinfo.tcp("::", 80)
+ end
+
+ it "returns false for the loopback address" do
+ @multicast.ipv6_multicast?.should be_true
+ end
+
+ it "returns false for another address" do
+ @other.ipv6_multicast?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_multicast?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/ipv6_spec.rb b/spec/rubyspec/library/socket/addrinfo/ipv6_spec.rb
new file mode 100644
index 0000000000..b66bc0d70b
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/ipv6_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#ipv6?" do
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("10.0.0.1", 80)
+ end
+
+ it "returns true" do
+ @addrinfo.ipv6?.should be_false
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6?.should be_true
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6?.should be_false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/pfamily_spec.rb b/spec/rubyspec/library/socket/addrinfo/pfamily_spec.rb
new file mode 100644
index 0000000000..d37ed73e1e
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/pfamily_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#pfamily" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::PF_INET" do
+ @addrinfo.pfamily.should == Socket::PF_INET
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::PF_INET6" do
+ @addrinfo.pfamily.should == Socket::PF_INET6
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::PF_UNIX" do
+ @addrinfo.pfamily.should == Socket::PF_UNIX
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/protocol_spec.rb b/spec/rubyspec/library/socket/addrinfo/protocol_spec.rb
new file mode 100644
index 0000000000..4ff11dc017
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/protocol_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#protocol" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::IPPROTO_TCP" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::IPPROTO_TCP" do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns 0" do
+ @addrinfo.protocol.should == 0
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/shared/to_sockaddr.rb b/spec/rubyspec/library/socket/addrinfo/shared/to_sockaddr.rb
new file mode 100644
index 0000000000..86819a31b0
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/shared/to_sockaddr.rb
@@ -0,0 +1,35 @@
+describe :socket_addrinfo_to_sockaddr, :shared => true do
+
+ describe "for an ipv4 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should be_kind_of(String)
+ end
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/socktype_spec.rb b/spec/rubyspec/library/socket/addrinfo/socktype_spec.rb
new file mode 100644
index 0000000000..e1c8c0f3f5
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/socktype_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo#socktype" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/tcp_spec.rb b/spec/rubyspec/library/socket/addrinfo/tcp_spec.rb
new file mode 100644
index 0000000000..b5c18cefea
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/tcp_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.tcp" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("localhost", "smtp")
+ end
+
+ it "creates a addrinfo for a tcp socket" do
+ ["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
+ [Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
+ @addrinfo.ip_port.should == 25
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ platform_is_not :solaris do
+ @addrinfo.protocol.should == Socket::IPPROTO_TCP
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/to_s_spec.rb b/spec/rubyspec/library/socket/addrinfo/to_s_spec.rb
new file mode 100644
index 0000000000..7205bdc823
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/to_s_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_sockaddr', __FILE__)
+require 'socket'
+
+describe "Addrinfo#to_s" do
+ it_behaves_like(:socket_addrinfo_to_sockaddr, :to_s)
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/to_sockaddr_spec.rb b/spec/rubyspec/library/socket/addrinfo/to_sockaddr_spec.rb
new file mode 100644
index 0000000000..f3f926c2b6
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/to_sockaddr_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/to_sockaddr', __FILE__)
+require 'socket'
+
+describe "Addrinfo#to_sockaddr" do
+ it_behaves_like(:socket_addrinfo_to_sockaddr, :to_sockaddr)
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/udp_spec.rb b/spec/rubyspec/library/socket/addrinfo/udp_spec.rb
new file mode 100644
index 0000000000..712d730e05
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/udp_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.udp" do
+
+ before :each do
+ @addrinfo = Addrinfo.udp("localhost", "daytime")
+ end
+
+ it "creates a addrinfo for a tcp socket" do
+ ["::1", "127.0.0.1"].should include(@addrinfo.ip_address)
+ [Socket::PF_INET, Socket::PF_INET6].should include(@addrinfo.pfamily)
+ @addrinfo.ip_port.should == 13
+ @addrinfo.socktype.should == Socket::SOCK_DGRAM
+ platform_is_not :solaris do
+ @addrinfo.protocol.should == Socket::IPPROTO_UDP
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/unix_path_spec.rb b/spec/rubyspec/library/socket/addrinfo/unix_path_spec.rb
new file mode 100644
index 0000000000..3f7e03dd7b
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/unix_path_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+platform_is_not :windows do
+ describe "Addrinfo#unix_path" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.unix_path }.should raise_error(SocketError)
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "raises an exception" do
+ lambda { @addrinfo.unix_path }.should raise_error(SocketError)
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns the socket path" do
+ @addrinfo.unix_path.should == "/tmp/sock"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/addrinfo/unix_spec.rb b/spec/rubyspec/library/socket/addrinfo/unix_spec.rb
new file mode 100644
index 0000000000..00eedc96e7
--- /dev/null
+++ b/spec/rubyspec/library/socket/addrinfo/unix_spec.rb
@@ -0,0 +1,54 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Addrinfo.unix" do
+
+ platform_is_not :windows do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "creates a addrinfo for a unix socket" do
+ @addrinfo.pfamily.should == Socket::PF_UNIX
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
+ @addrinfo.protocol.should == 0
+ @addrinfo.unix_path.should == "/tmp/sock"
+ end
+ end
+end
+
+describe "Addrinfo#unix?" do
+ describe "for an ipv4 socket" do
+
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.unix?.should be_false
+ end
+
+ end
+
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
+ end
+
+ it "returns false" do
+ @addrinfo.unix?.should be_false
+ end
+ end
+
+ platform_is_not :windows do
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns true" do
+ @addrinfo.unix?.should be_true
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/close_read_spec.rb b/spec/rubyspec/library/socket/basicsocket/close_read_spec.rb
new file mode 100644
index 0000000000..d0b73c88ad
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/close_read_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#close_read" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "closes the reading end of the socket" do
+ @server.close_read
+ lambda { @server.read }.should raise_error(IOError)
+ end
+
+ it "it works on sockets with closed ends" do
+ @server.close_read
+ lambda { @server.close_read }.should_not raise_error(Exception)
+ lambda { @server.read }.should raise_error(IOError)
+ end
+
+ it "does not close the socket" do
+ @server.close_read
+ @server.closed?.should be_false
+ end
+
+ it "fully closes the socket if it was already closed for writing" do
+ @server.close_write
+ @server.close_read
+ @server.closed?.should be_true
+ end
+
+ it "raises IOError on closed socket" do
+ @server.close
+ lambda { @server.close_read }.should raise_error(IOError)
+ end
+
+ it "returns nil" do
+ @server.close_read.should be_nil
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/close_write_spec.rb b/spec/rubyspec/library/socket/basicsocket/close_write_spec.rb
new file mode 100644
index 0000000000..7cba1caa8f
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/close_write_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#close_write" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "closes the writing end of the socket" do
+ @server.close_write
+ lambda { @server.write("foo") }.should raise_error(IOError)
+ end
+
+ it "works on sockets with closed write ends" do
+ @server.close_write
+ lambda { @server.close_write }.should_not raise_error(Exception)
+ lambda { @server.write("foo") }.should raise_error(IOError)
+ end
+
+ it "does not close the socket" do
+ @server.close_write
+ @server.closed?.should be_false
+ end
+
+ it "does not prevent reading" do
+ @server.close_write
+ @server.read(0).should == ""
+ end
+
+ it "fully closes the socket if it was already closed for reading" do
+ @server.close_read
+ @server.close_write
+ @server.closed?.should be_true
+ end
+
+ it "raises IOError on closed socket" do
+ @server.close
+ lambda { @server.close_write }.should raise_error(IOError)
+ end
+
+ it "returns nil" do
+ @server.close_write.should be_nil
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/do_not_reverse_lookup_spec.rb b/spec/rubyspec/library/socket/basicsocket/do_not_reverse_lookup_spec.rb
new file mode 100644
index 0000000000..0875c1eca1
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/do_not_reverse_lookup_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket.do_not_reverse_lookup" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ @socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @socket.close unless @socket.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "defaults to true" do
+ BasicSocket.do_not_reverse_lookup.should be_true
+ end
+
+ it "causes 'peeraddr' to avoid name lookups" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ @socket.peeraddr.should == ["AF_INET", SocketSpecs.port, "127.0.0.1", "127.0.0.1"]
+ end
+
+ it "looks for hostnames when set to false" do
+ @socket.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ @socket.peeraddr[2].should == SocketSpecs.hostname
+ end
+
+ it "looks for numeric addresses when set to true" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ @socket.peeraddr[2].should == "127.0.0.1"
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/for_fd_spec.rb b/spec/rubyspec/library/socket/basicsocket/for_fd_spec.rb
new file mode 100644
index 0000000000..5ad1ea84d0
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/for_fd_spec.rb
@@ -0,0 +1,21 @@
+
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#for_fd" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.port)
+ @s2 = nil
+ end
+
+ after :each do
+ @server.close if @server
+ end
+
+ it "return a Socket instance wrapped around the descriptor" do
+ @s2 = TCPServer.for_fd(@server.fileno)
+ @s2.autoclose = false
+ @s2.should be_kind_of(TCPServer)
+ @s2.fileno.should == @server.fileno
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/getpeername_spec.rb b/spec/rubyspec/library/socket/basicsocket/getpeername_spec.rb
new file mode 100644
index 0000000000..1edfbcd3ec
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/getpeername_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#getpeername" do
+
+ before :each do
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ @client = TCPSocket.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns the sockaddr of the other end of the connection" do
+ server_sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")
+ @client.getpeername.should == server_sockaddr
+ end
+
+ # Catch general exceptions to prevent NotImplementedError
+ it "raises an error if socket's not connected" do
+ lambda { @server.getpeername }.should raise_error(Exception)
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/getsockname_spec.rb b/spec/rubyspec/library/socket/basicsocket/getsockname_spec.rb
new file mode 100644
index 0000000000..6d30286733
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/getsockname_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#getsockname" do
+ after :each do
+ @socket.closed?.should be_false
+ @socket.close
+ end
+
+ it "returns the sockaddr associacted with the socket" do
+ @socket = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ sockaddr.should == [SocketSpecs.port, "127.0.0.1"]
+ end
+
+ it "works on sockets listening in ipaddr_any" do
+ @socket = TCPServer.new(SocketSpecs.port)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ ["::", "0.0.0.0", "::ffff:0.0.0.0"].include?(sockaddr[1]).should be_true
+ sockaddr[0].should == SocketSpecs.port
+ end
+
+ it "returns empty sockaddr for unbinded sockets" do
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
+ sockaddr.should == [0, "0.0.0.0"]
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/getsockopt_spec.rb b/spec/rubyspec/library/socket/basicsocket/getsockopt_spec.rb
new file mode 100644
index 0000000000..dc4fffa5c1
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/getsockopt_spec.rb
@@ -0,0 +1,46 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#getsockopt" do
+ before :each do
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ platform_is_not :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_TYPE, SO_OOBINLINE, SO_BROADCAST, etc.
+
+ it "gets a socket option Socket::SO_TYPE" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE).to_s
+ n.should == [Socket::SOCK_STREAM].pack("i")
+ end
+
+ it "gets a socket option Socket::SO_OOBINLINE" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "gets a socket option Socket::SO_LINGER" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ n.should == [0, 0].pack("ii")
+ else
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "gets a socket option Socket::SO_SNDBUF" do
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should > 0
+ end
+
+ it "raises a SystemCallError with an invalid socket option" do
+ lambda { @sock.getsockopt Socket::SOL_SOCKET, -1 }.should raise_error(Errno::ENOPROTOOPT)
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/ioctl_spec.rb b/spec/rubyspec/library/socket/basicsocket/ioctl_spec.rb
new file mode 100644
index 0000000000..9a7f535317
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/ioctl_spec.rb
@@ -0,0 +1,43 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require 'socket'
+
+describe "Socket::BasicSocket#ioctl" do
+ platform_is :linux do
+ it "passes data from and to a String correctly" do
+ s = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, 0
+ # /usr/include/net/if.h, structure ifreq
+ # The structure is 32 bytes on x86, 40 bytes on x86_64
+ if_name = ['lo'].pack('a16')
+ buffer = if_name + 'z' * 24
+ # SIOCGIFADDR in /usr/include/bits/ioctls.h
+ s.ioctl 0x8915, buffer
+ s.close
+
+ # Interface name should remain unchanged.
+ buffer[0, 16].should == if_name
+ # lo should have an IPv4 address of 127.0.0.1
+ buffer[16, 2].unpack('S!').first.should == Socket::AF_INET
+ buffer[20, 4].should == "\x7f\0\0\x01"
+ end
+ end
+
+ platform_is :freebsd do
+ it "passes data from and to a String correctly" do
+ s = Socket.new Socket::AF_INET, Socket::SOCK_DGRAM, 0
+ # /usr/include/net/if.h, structure ifreq
+ # The structure is 32 bytes on x86, 40 bytes on x86_64
+ if_name = ['lo0'].pack('a16')
+ buffer = if_name + 'z' * 24
+ # SIOCGIFADDR in /usr/include/bits/ioctls.h
+ s.ioctl 0xc0206921, buffer
+ s.close
+
+ # Interface name should remain unchanged.
+ buffer[0, 16].should == if_name
+ # lo should have an IPv4 address of 127.0.0.1
+ buffer[16, 1].unpack('C').first.should == 16
+ buffer[17, 1].unpack('C').first.should == Socket::AF_INET
+ buffer[20, 4].should == "\x7f\0\0\x01"
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/recv_nonblock_spec.rb b/spec/rubyspec/library/socket/basicsocket/recv_nonblock_spec.rb
new file mode 100644
index 0000000000..2c948eaa2f
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/recv_nonblock_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../shared/recv_nonblock', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#recv_nonblock" do
+ it_behaves_like :socket_recv_nonblock, :recv_nonblock
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/recv_spec.rb b/spec/rubyspec/library/socket/basicsocket/recv_spec.rb
new file mode 100644
index 0000000000..9f3227dc65
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/recv_spec.rb
@@ -0,0 +1,93 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#recv" do
+
+ before :each do
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ end
+
+ after :each do
+ @server.closed?.should be_false
+ @server.close
+ ScratchPad.clear
+ end
+
+ it "receives a specified number of bytes of a message from another socket" do
+ t = Thread.new do
+ client = @server.accept
+ ScratchPad.record client.recv(10)
+ client.recv(1) # this recv is important
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ socket.send('hello', 0)
+ socket.close
+
+ t.join
+ ScratchPad.recorded.should == 'hello'
+ end
+
+ platform_is_not :solaris do
+ it "accepts flags to specify unusual receiving behaviour" do
+ t = Thread.new do
+ client = @server.accept
+
+ # in-band data (TCP), doesn't receive the flag.
+ ScratchPad.record client.recv(10)
+
+ # this recv is important (TODO: explain)
+ client.recv(10)
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ socket.send('helloU', Socket::MSG_OOB)
+ socket.shutdown(1)
+ t.join
+ socket.close
+ ScratchPad.recorded.should == 'hello'
+ end
+ end
+
+ it "gets lines delimited with a custom separator" do
+ t = Thread.new do
+ client = @server.accept
+ ScratchPad.record client.gets("\377")
+
+ # this call is important (TODO: explain)
+ client.gets(nil)
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ socket.write("firstline\377secondline\377")
+ socket.close
+
+ t.join
+ ScratchPad.recorded.should == "firstline\377"
+ end
+
+ ruby_version_is "2.3" do
+ it "allows an output buffer as third argument" do
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ socket.write("data")
+
+ client = @server.accept
+ buf = "foo"
+ client.recv(4, 0, buf)
+ client.close
+ buf.should == "data"
+
+ socket.close
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/send_spec.rb b/spec/rubyspec/library/socket/basicsocket/send_spec.rb
new file mode 100644
index 0000000000..7822f4696b
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/send_spec.rb
@@ -0,0 +1,84 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#send" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ @socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ end
+
+ after :each do
+ @server.closed?.should be_false
+ @socket.closed?.should be_false
+
+ @server.close
+ @socket.close
+ end
+
+ it "sends a message to another socket and returns the number of bytes sent" do
+ data = ""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @socket.send('hello', 0).should == 5
+ @socket.shutdown(1) # indicate, that we are done sending
+ @socket.recv(10)
+
+ t.join
+ data.should == 'hello'
+ end
+
+ platform_is_not :solaris, :windows do
+ it "accepts flags to specify unusual sending behaviour" do
+ data = nil
+ peek_data = nil
+ t = Thread.new do
+ client = @server.accept
+ peek_data = client.recv(6, Socket::MSG_PEEK)
+ data = client.recv(6)
+ client.recv(10) # this recv is important
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @socket.send('helloU', Socket::MSG_PEEK | Socket::MSG_OOB).should == 6
+ @socket.shutdown # indicate, that we are done sending
+
+ t.join
+ peek_data.should == "hello"
+ data.should == 'hello'
+ end
+ end
+
+ it "accepts a sockaddr as recipient address" do
+ data = ""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")
+ @socket.send('hello', 0, sockaddr).should == 5
+ @socket.shutdown # indicate, that we are done sending
+
+ t.join
+ data.should == 'hello'
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/setsockopt_spec.rb b/spec/rubyspec/library/socket/basicsocket/setsockopt_spec.rb
new file mode 100644
index 0000000000..523a22d957
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/setsockopt_spec.rb
@@ -0,0 +1,213 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "BasicSocket#setsockopt" do
+
+ before :each do
+ @sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @sock.close unless @sock.closed?
+ end
+
+ it "sets the socket linger to 0" do
+ linger = [0, 0].pack("ii")
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ n.should == [0, 0].pack("ii")
+ else
+ n.should == [0].pack("i")
+ end
+ end
+
+ it "sets the socket linger to some positive value" do
+ linger = [64, 64].pack("ii")
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, linger).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
+ if (n.size == 8) # linger struct on some platforms, not just a value
+ a = n.unpack('ii')
+ a[0].should_not == 0
+ a[1].should == 64
+ else
+ n.should == [64].pack("i")
+ end
+ end
+
+ platform_is_not :windows do
+ it "raises EINVAL if passed wrong linger value" do
+ lambda do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, 0)
+ end.should raise_error(Errno::EINVAL)
+ end
+ end
+
+ platform_is_not :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_TYPE, SO_OOBINLINE, SO_BROADCAST, etc.
+
+ it "sets the socket option Socket::SO_OOBINLINE" do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, true).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, false).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 1).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 0).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, 2).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "blah").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "0")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00\x00").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "1")
+ }.should raise_error(SystemCallError)
+ end
+
+ platform_is_not :windows do
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, "\x00\x00\x00")
+ }.should raise_error(SystemCallError)
+ end
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [1].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [0].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should == [0].pack("i")
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE, [1000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_OOBINLINE).to_s
+ n.should_not == [0].pack("i")
+ end
+ end
+
+ it "sets the socket option Socket::SO_SNDBUF" do
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 4000).should == 0
+ sndbuf = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ # might not always be possible to set to exact size
+ sndbuf.unpack('i')[0].should >= 4000
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, true).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, nil).should == 0
+ }.should raise_error(TypeError)
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 1).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, 2).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 2
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "bla")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "0")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "1")
+ }.should raise_error(SystemCallError)
+
+ lambda {
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x00")
+ }.should raise_error(SystemCallError)
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, "\x00\x00\x01\x00").should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= "\x00\x00\x01\x00".unpack('i')[0]
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, [4000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 4000
+
+ @sock.setsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF, [1000].pack('i')).should == 0
+ n = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_SNDBUF).to_s
+ n.unpack('i')[0].should >= 1000
+ end
+
+ platform_is_not :aix do
+ describe 'accepts Socket::Option as argument' do
+ it 'boolean' do
+ option = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ @sock.setsockopt(option).should == 0
+ @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).bool.should == true
+ end
+
+ it 'int' do
+ option = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ @sock.setsockopt(option).should == 0
+ @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE).bool.should == true
+ end
+ end
+ end
+
+ platform_is :aix do
+ describe 'accepts Socket::Option as argument' do
+ it 'boolean' do
+ option = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ @sock.setsockopt(option).should == 0
+ end
+
+ it 'int' do
+ option = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
+ @sock.setsockopt(option).should == 0
+ end
+ end
+ end
+
+ describe 'accepts Socket::Option as argument' do
+ it 'linger' do
+ option = Socket::Option.linger(true, 10)
+ @sock.setsockopt(option).should == 0
+ onoff, seconds = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).linger
+ seconds.should == 10
+ # Both results can be produced depending on the OS and value of Socket::SO_LINGER
+ [true, Socket::SO_LINGER].should include(onoff)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/basicsocket/shutdown_spec.rb b/spec/rubyspec/library/socket/basicsocket/shutdown_spec.rb
new file mode 100644
index 0000000000..c874f08697
--- /dev/null
+++ b/spec/rubyspec/library/socket/basicsocket/shutdown_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::BasicSocket#shutdown" do
+
+end
diff --git a/spec/rubyspec/library/socket/constants/constants_spec.rb b/spec/rubyspec/library/socket/constants/constants_spec.rb
new file mode 100644
index 0000000000..9b8a0e55b3
--- /dev/null
+++ b/spec/rubyspec/library/socket/constants/constants_spec.rb
@@ -0,0 +1,90 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+include Socket::Constants
+
+describe "Socket::Constants" do
+ it "defines socket types" do
+ consts = ["SOCK_DGRAM", "SOCK_RAW", "SOCK_RDM", "SOCK_SEQPACKET", "SOCK_STREAM"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines protocol families" do
+ consts = ["PF_INET6", "PF_INET", "PF_UNIX", "PF_UNSPEC"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :aix do
+ it "defines PF_IPX protocol" do
+ Socket::Constants.should have_constant("PF_IPX")
+ end
+ end
+
+ it "defines address families" do
+ consts = ["AF_INET6", "AF_INET", "AF_UNIX", "AF_UNSPEC"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :aix do
+ it "defines AF_IPX address" do
+ Socket::Constants.should have_constant("AF_IPX")
+ end
+ end
+
+ it "defines send/receive options" do
+ consts = ["MSG_DONTROUTE", "MSG_OOB", "MSG_PEEK"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines socket level options" do
+ consts = ["SOL_SOCKET"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines socket options" do
+ consts = ["SO_BROADCAST", "SO_DEBUG", "SO_DONTROUTE", "SO_ERROR", "SO_KEEPALIVE", "SO_LINGER",
+ "SO_OOBINLINE", "SO_RCVBUF", "SO_REUSEADDR", "SO_SNDBUF", "SO_TYPE"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ it "defines multicast options" do
+ consts = ["IP_ADD_MEMBERSHIP",
+ "IP_MULTICAST_LOOP", "IP_MULTICAST_TTL"]
+ platform_is_not :windows do
+ consts += ["IP_DEFAULT_MULTICAST_LOOP", "IP_DEFAULT_MULTICAST_TTL"]
+ end
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+
+ platform_is_not :solaris, :windows, :aix do
+ it "defines multicast options" do
+ consts = ["IP_MAX_MEMBERSHIPS"]
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+ end
+
+ it "defines TCP options" do
+ consts = ["TCP_NODELAY"]
+ platform_is_not :windows do
+ consts << "TCP_MAXSEG"
+ end
+ consts.each do |c|
+ Socket::Constants.should have_constant(c)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/fixtures/classes.rb b/spec/rubyspec/library/socket/fixtures/classes.rb
new file mode 100644
index 0000000000..ddb2396731
--- /dev/null
+++ b/spec/rubyspec/library/socket/fixtures/classes.rb
@@ -0,0 +1,106 @@
+require 'socket'
+
+module SocketSpecs
+ # helper to get the hostname associated to 127.0.0.1
+ def self.hostname
+ # Calculate each time, without caching, since the result might
+ # depend on things like do_not_reverse_lookup mode, which is
+ # changing from test to test
+ Socket.getaddrinfo("127.0.0.1", nil)[0][2]
+ end
+
+ def self.hostnamev6
+ Socket.getaddrinfo("::1", nil)[0][2]
+ end
+
+ def self.addr(which=:ipv4)
+ case which
+ when :ipv4
+ host = "127.0.0.1"
+ when :ipv6
+ host = "::1"
+ end
+ Socket.getaddrinfo(host, nil)[0][3]
+ end
+
+ def self.find_available_port
+ begin
+ s = TCPServer.open(0)
+ port = s.addr[1]
+ s.close
+ port
+ rescue
+ 43191
+ end
+ end
+
+ def self.port
+ @@_port ||= find_available_port
+ end
+
+ def self.str_port
+ port.to_s
+ end
+
+ def self.local_port
+ find_available_port
+ end
+
+ def self.sockaddr_in(port, host)
+ Socket::SockAddr_In.new(Socket.sockaddr_in(port, host))
+ end
+
+ def self.socket_path
+ tmp("unix_server_spec.socket", false)
+ end
+
+ # TCPServer echo server accepting one connection
+ class SpecTCPServer
+ attr_accessor :hostname, :port, :logger
+
+ def initialize(host=nil, port=nil, logger=nil)
+ @hostname = host || SocketSpecs.hostname
+ @port = port || SocketSpecs.port
+ @logger = logger
+
+ start
+ end
+
+ def start
+ log "SpecTCPServer starting on #{@hostname}:#{@port}"
+ @server = TCPServer.new @hostname, @port
+
+ @thread = Thread.new do
+ socket = @server.accept
+ log "SpecTCPServer accepted connection: #{socket}"
+ service socket
+ end
+ self
+ end
+
+ def service(socket)
+ begin
+ data = socket.recv(1024)
+
+ return if data.empty?
+ log "SpecTCPServer received: #{data.inspect}"
+
+ return if data == "QUIT"
+
+ socket.send data, 0
+ ensure
+ socket.close
+ end
+ end
+
+ def shutdown
+ log "SpecTCPServer shutting down"
+ @thread.join
+ @server.close
+ end
+
+ def log(message)
+ @logger.puts message if @logger
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/fixtures/send_io.txt b/spec/rubyspec/library/socket/fixtures/send_io.txt
new file mode 100644
index 0000000000..eaaa1eb3ec
--- /dev/null
+++ b/spec/rubyspec/library/socket/fixtures/send_io.txt
@@ -0,0 +1 @@
+This data is magic.
diff --git a/spec/rubyspec/library/socket/ipsocket/addr_spec.rb b/spec/rubyspec/library/socket/ipsocket/addr_spec.rb
new file mode 100644
index 0000000000..2ac4c3d413
--- /dev/null
+++ b/spec/rubyspec/library/socket/ipsocket/addr_spec.rb
@@ -0,0 +1,42 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#addr" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @socket = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "returns an array with the socket's information" do
+ @socket.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ addrinfo = @socket.addr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == SocketSpecs.hostname
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an address in the array if do_not_reverse_lookup is true" do
+ @socket.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ addrinfo = @socket.addr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an address in the array if passed false" do
+ addrinfo = @socket.addr(false)
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+end
diff --git a/spec/rubyspec/library/socket/ipsocket/getaddress_spec.rb b/spec/rubyspec/library/socket/ipsocket/getaddress_spec.rb
new file mode 100644
index 0000000000..c574c7d267
--- /dev/null
+++ b/spec/rubyspec/library/socket/ipsocket/getaddress_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#getaddress" do
+
+ it "returns the IP address of hostname" do
+ addr_local = IPSocket.getaddress(SocketSpecs.hostname)
+ ["127.0.0.1", "::1"].include?(addr_local).should == true
+ end
+
+ it "returns the IP address when passed an IP" do
+ IPSocket.getaddress("127.0.0.1").should == "127.0.0.1"
+ IPSocket.getaddress("0.0.0.0").should == "0.0.0.0"
+ end
+
+ # There is no way to make this fail-proof on all machines, because
+ # DNS servers like opendns return A records for ANY host, including
+ # traditionally invalidly named ones.
+ quarantine! do
+ it "raises an error on unknown hostnames" do
+ lambda {
+ IPSocket.getaddress("rubyspecdoesntexist.fallingsnow.net")
+ }.should raise_error(SocketError)
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/ipsocket/peeraddr_spec.rb b/spec/rubyspec/library/socket/ipsocket/peeraddr_spec.rb
new file mode 100644
index 0000000000..01b697bd27
--- /dev/null
+++ b/spec/rubyspec/library/socket/ipsocket/peeraddr_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#peeraddr" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ @client = TCPSocket.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ it "raises error if socket is not connected" do
+ lambda { @server.peeraddr }.should raise_error
+ end
+
+ it "returns an array of information on the peer" do
+ @client.do_not_reverse_lookup = false
+ BasicSocket.do_not_reverse_lookup = false
+ addrinfo = @client.peeraddr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == SocketSpecs.hostname
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an IP instead of hostname if do_not_reverse_lookup is true" do
+ @client.do_not_reverse_lookup = true
+ BasicSocket.do_not_reverse_lookup = true
+ addrinfo = @client.peeraddr
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+
+ it "returns an IP instead of hostname if passed false" do
+ addrinfo = @client.peeraddr(false)
+ addrinfo[0].should == "AF_INET"
+ addrinfo[1].should == SocketSpecs.port
+ addrinfo[2].should == "127.0.0.1"
+ addrinfo[3].should == "127.0.0.1"
+ end
+end
diff --git a/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb b/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb
new file mode 100644
index 0000000000..565a1795e9
--- /dev/null
+++ b/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb
@@ -0,0 +1,65 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::IPSocket#recvfrom" do
+
+ before :each do
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ @client = TCPSocket.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "reads data from the connection" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ data = client.recvfrom(6)
+ client.close
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ # shutdown may raise Errno::ENOTCONN when sent data is pending.
+ t.join
+
+ data.first.should == 'hello'
+ end
+
+ it "reads up to len bytes" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ data = client.recvfrom(3)
+ client.close
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ t.join
+
+ data.first.should == 'hel'
+ end
+
+ it "returns an array with the data and connection info" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ data = client.recvfrom(3)
+ client.close
+ end
+
+ @client.send('hello', 0)
+ @client.shutdown rescue nil
+ t.join
+
+ data.size.should == 2
+ data.first.should == "hel"
+ # This does not apply to every platform, dependant on recvfrom(2)
+ # data.last.should == nil
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/option/bool_spec.rb b/spec/rubyspec/library/socket/option/bool_spec.rb
new file mode 100644
index 0000000000..74c832a0ad
--- /dev/null
+++ b/spec/rubyspec/library/socket/option/bool_spec.rb
@@ -0,0 +1,25 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.bool" do
+ it "creates a new Socket::Option" do
+ so = Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ so.data.should == [1].pack('i')
+ end
+end
+
+describe "Socket::Option#bool" do
+ it "returns boolean value" do
+ Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true).bool.should == true
+ Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false).bool.should == false
+ end
+
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.new(:UNSPEC, :SOCKET, :SO_LINGER, [0, 0].pack('i*'))
+ lambda { so.bool }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/library/socket/option/inspect_spec.rb b/spec/rubyspec/library/socket/option/inspect_spec.rb
new file mode 100644
index 0000000000..df72f227a9
--- /dev/null
+++ b/spec/rubyspec/library/socket/option/inspect_spec.rb
@@ -0,0 +1,20 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe 'Socket::Option#inspect' do
+ it 'correctly returns SO_LINGER value' do
+ value = Socket::Option.linger(nil, 0).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER off 0sec>'
+
+ value = Socket::Option.linger(false, 30).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER off 30sec>'
+
+ value = Socket::Option.linger(true, 0).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER on 0sec>'
+
+ value = Socket::Option.linger(true, 30).inspect
+ value.should == '#<Socket::Option: UNSPEC SOCKET LINGER on 30sec>'
+ end
+end
diff --git a/spec/rubyspec/library/socket/option/int_spec.rb b/spec/rubyspec/library/socket/option/int_spec.rb
new file mode 100644
index 0000000000..f926ff7968
--- /dev/null
+++ b/spec/rubyspec/library/socket/option/int_spec.rb
@@ -0,0 +1,28 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.int" do
+ it "creates a new Socket::Option" do
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 5)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::Constants::AF_INET
+ so.level.should == Socket::Constants::SOL_SOCKET
+ so.optname.should == Socket::Constants::SO_KEEPALIVE
+ so.data.should == [5].pack('i')
+ end
+end
+
+describe "Socket::Option#int" do
+ it "returns int value" do
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 17)
+ so.int.should == 17
+
+ so = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 32765)
+ so.int.should == 32765
+ end
+
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.new(:UNSPEC, :SOCKET, :SO_LINGER, [0, 0].pack('i*'))
+ lambda { so.int }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/rubyspec/library/socket/option/linger_spec.rb b/spec/rubyspec/library/socket/option/linger_spec.rb
new file mode 100644
index 0000000000..687d421af3
--- /dev/null
+++ b/spec/rubyspec/library/socket/option/linger_spec.rb
@@ -0,0 +1,62 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+option_pack = 'i*'
+platform_is :windows do
+ option_pack = 's*'
+end
+
+describe "Socket::Option.linger" do
+ it "creates a new Socket::Option for SO_LINGER" do
+ so = Socket::Option.linger(1, 10)
+ so.should be_an_instance_of(Socket::Option)
+ so.family.should == Socket::Constants::AF_UNSPEC
+ so.level.should == Socket::Constants::SOL_SOCKET
+ so.optname.should == Socket::Constants::SO_LINGER
+ so.data.should == [1, 10].pack(option_pack)
+ end
+
+ it "accepts boolean as onoff argument" do
+ so = Socket::Option.linger(false, 0)
+ so.data.should == [0, 0].pack(option_pack)
+
+ so = Socket::Option.linger(true, 1)
+ so.data.should == [1, 1].pack(option_pack)
+ end
+end
+
+describe "Socket::Option#linger" do
+ it "returns linger option" do
+ so = Socket::Option.linger(0, 5)
+ ary = so.linger
+ ary[0].should be_false
+ ary[1].should == 5
+
+ so = Socket::Option.linger(false, 4)
+ ary = so.linger
+ ary[0].should be_false
+ ary[1].should == 4
+
+ so = Socket::Option.linger(1, 10)
+ ary = so.linger
+ ary[0].should be_true
+ ary[1].should == 10
+
+ so = Socket::Option.linger(true, 9)
+ ary = so.linger
+ ary[0].should be_true
+ ary[1].should == 9
+ end
+
+ it "raises TypeError if not a SO_LINGER" do
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :KEEPALIVE, 1)
+ lambda { so.linger }.should raise_error(TypeError)
+ end
+
+ platform_is_not :windows do
+ it "raises TypeError if option has not good size" do
+ so = Socket::Option.int(:AF_UNSPEC, :SOL_SOCKET, :LINGER, 1)
+ lambda { so.linger }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/option/new_spec.rb b/spec/rubyspec/library/socket/option/new_spec.rb
new file mode 100644
index 0000000000..4f2d0c5386
--- /dev/null
+++ b/spec/rubyspec/library/socket/option/new_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::Option.new" do
+ it "should accept integers" do
+ so = Socket::Option.new(Socket::AF_INET, Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ end
+
+ it "should accept symbols" do
+ so = Socket::Option.new(:AF_INET, :SOL_SOCKET, :SO_KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+
+ so = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [0].pack('i'))
+ so.family.should == Socket::AF_INET
+ so.level.should == Socket::SOL_SOCKET
+ so.optname.should == Socket::SO_KEEPALIVE
+ end
+
+ it "should raise error on unknown family" do
+ lambda { Socket::Option.new(:INET4, :SOCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+
+ it "should raise error on unknown level" do
+ lambda { Socket::Option.new(:INET, :ROCKET, :KEEPALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+
+ it "should raise error on unknown option name" do
+ lambda { Socket::Option.new(:INET, :SOCKET, :ALIVE, [0].pack('i')) }.should raise_error(SocketError)
+ end
+end
diff --git a/spec/rubyspec/library/socket/shared/pack_sockaddr.rb b/spec/rubyspec/library/socket/shared/pack_sockaddr.rb
new file mode 100644
index 0000000000..4ffa02a8d8
--- /dev/null
+++ b/spec/rubyspec/library/socket/shared/pack_sockaddr.rb
@@ -0,0 +1,50 @@
+# coding: utf-8
+describe :socket_pack_sockaddr_in, shared: true do
+ it "packs and unpacks" do
+ sockaddr_in = Socket.public_send(@method, 0, nil)
+ port, addr = Socket.unpack_sockaddr_in(sockaddr_in)
+ ["127.0.0.1", "::1"].include?(addr).should == true
+ port.should == 0
+
+ sockaddr_in = Socket.public_send(@method, 0, '')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '0.0.0.0']
+
+ sockaddr_in = Socket.public_send(@method, 80, '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
+
+ sockaddr_in = Socket.public_send(@method, '80', '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
+
+ sockaddr_in = Socket.public_send(@method, nil, '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [0, '127.0.0.1']
+ end
+end
+
+describe :socket_pack_sockaddr_un, shared: true do
+ platform_is_not :windows do
+ it 'should be idempotent' do
+ bytes = Socket.public_send(@method, '/tmp/foo').bytes
+ bytes[2..9].should == [47, 116, 109, 112, 47, 102, 111, 111]
+ bytes[10..-1].all?(&:zero?).should == true
+ end
+
+ it "packs and unpacks" do
+ sockaddr_un = Socket.public_send(@method, '/tmp/s')
+ Socket.unpack_sockaddr_un(sockaddr_un).should == '/tmp/s'
+ end
+
+ it "handles correctly paths with multibyte chars" do
+ sockaddr_un = Socket.public_send(@method, '/home/вася/sock')
+ path = Socket.unpack_sockaddr_un(sockaddr_un).encode('UTF-8', 'UTF-8')
+ path.should == '/home/вася/sock'
+ end
+ end
+
+ platform_is_not :windows, :aix do
+ it "raises if path length exceeds max size" do
+ # AIX doesn't raise error
+ long_path = Array.new(512, 0).join
+ lambda { Socket.public_send(@method, long_path) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/shared/partially_closable_sockets.rb b/spec/rubyspec/library/socket/shared/partially_closable_sockets.rb
new file mode 100644
index 0000000000..1309f15f85
--- /dev/null
+++ b/spec/rubyspec/library/socket/shared/partially_closable_sockets.rb
@@ -0,0 +1,13 @@
+describe "partially closable sockets", shared: true do
+ specify "if the write end is closed then the other side can read past EOF without blocking" do
+ @s1.write("foo")
+ @s1.close_write
+ @s2.read("foo".size + 1).should == "foo"
+ end
+
+ specify "closing the write end ensures that the other side can read until EOF" do
+ @s1.write("hello world")
+ @s1.close_write
+ @s2.read.should == "hello world"
+ end
+end
diff --git a/spec/rubyspec/library/socket/shared/recv_nonblock.rb b/spec/rubyspec/library/socket/shared/recv_nonblock.rb
new file mode 100644
index 0000000000..4a63b16024
--- /dev/null
+++ b/spec/rubyspec/library/socket/shared/recv_nonblock.rb
@@ -0,0 +1,54 @@
+describe :socket_recv_nonblock, shared: true do
+ before :each do
+ @s1 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ @s2 = Socket.new(Socket::AF_INET, Socket::SOCK_DGRAM, 0)
+ end
+
+ after :each do
+ @s1.close unless @s1.closed?
+ @s2.close unless @s2.closed?
+ end
+
+ it "raises an exception extending IO::WaitReadable if there's no data available" do
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
+ lambda {
+ @s1.recv_nonblock(5)
+ }.should raise_error(IO::WaitReadable) { |e|
+ platform_is_not :windows do
+ e.should be_kind_of(Errno::EAGAIN)
+ end
+ platform_is :windows do
+ e.should be_kind_of(Errno::EWOULDBLOCK)
+ end
+ }
+ end
+
+ it "receives data after it's ready" do
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
+ @s2.send("aaa", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+ @s1.recv_nonblock(5).should == "aaa"
+ end
+
+ ruby_version_is "2.3" do
+ it "allows an output buffer as third argument" do
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
+ @s2.send("data", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+
+ buf = "foo"
+ @s1.recv_nonblock(5, 0, buf)
+ buf.should == "data"
+ end
+ end
+
+ it "does not block if there's no data available" do
+ @s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"))
+ @s2.send("a", 0, @s1.getsockname)
+ IO.select([@s1], nil, nil, 2)
+ @s1.recv_nonblock(1).should == "a"
+ lambda {
+ @s1.recv_nonblock(5)
+ }.should raise_error(IO::WaitReadable)
+ end
+end
diff --git a/spec/rubyspec/library/socket/shared/socketpair.rb b/spec/rubyspec/library/socket/shared/socketpair.rb
new file mode 100644
index 0000000000..03ee0e1a52
--- /dev/null
+++ b/spec/rubyspec/library/socket/shared/socketpair.rb
@@ -0,0 +1,23 @@
+describe :socket_socketpair, shared: true do
+ platform_is_not :windows do
+ it "ensures the returned sockets are connected" do
+ s1, s2 = Socket.public_send(@method, Socket::AF_UNIX, 1, 0)
+ s1.puts("test")
+ s2.gets.should == "test\n"
+ s1.close
+ s2.close
+ end
+
+ it "responses with array of two sockets" do
+ begin
+ s1, s2 = Socket.public_send(@method, :UNIX, :STREAM)
+
+ s1.should be_an_instance_of(Socket)
+ s2.should be_an_instance_of(Socket)
+ ensure
+ s1.close
+ s2.close
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/accept_nonblock_spec.rb b/spec/rubyspec/library/socket/socket/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..be0bbf5f03
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/accept_nonblock_spec.rb
@@ -0,0 +1,37 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#accept_nonblock" do
+ before :each do
+ @hostname = "127.0.0.1"
+ @addr = Socket.sockaddr_in(0, @hostname)
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ @socket.bind(@addr)
+ @socket.listen(1)
+ end
+
+ after :each do
+ @socket.close
+ end
+
+ it "raises IO::WaitReadable if the connection is not accepted yet" do
+ lambda {
+ @socket.accept_nonblock
+ }.should raise_error(IO::WaitReadable) { |e|
+ platform_is_not :windows do
+ e.should be_kind_of(Errno::EAGAIN)
+ end
+ platform_is :windows do
+ e.should be_kind_of(Errno::EWOULDBLOCK)
+ end
+ }
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @socket.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/accept_spec.rb b/spec/rubyspec/library/socket/socket/accept_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/accept_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/bind_spec.rb b/spec/rubyspec/library/socket/socket/bind_spec.rb
new file mode 100644
index 0000000000..57dff3bd6d
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/bind_spec.rb
@@ -0,0 +1,81 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+include Socket::Constants
+
+describe "Socket#bind on SOCK_DGRAM socket" do
+ before :each do
+ @sock = Socket.new(AF_INET, SOCK_DGRAM, 0);
+ @sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1");
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ it "binds to a port" do
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
+ end
+
+ it "returns 0 if successful" do
+ @sock.bind(@sockaddr).should == 0
+ end
+
+ it "raises Errno::EINVAL when binding to an already bound port" do
+ @sock.bind(@sockaddr);
+
+ lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL);
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
+ sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1");
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ platform_is_not :windows, :cygwin do
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1");
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES)
+ end
+ end
+end
+
+describe "Socket#bind on SOCK_STREAM socket" do
+ before :each do
+ @sock = Socket.new(AF_INET, SOCK_STREAM, 0);
+ @sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
+ @sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1");
+ end
+
+ after :each do
+ @sock.closed?.should be_false
+ @sock.close
+ end
+
+ it "binds to a port" do
+ lambda { @sock.bind(@sockaddr) }.should_not raise_error
+ end
+
+ it "returns 0 if successful" do
+ @sock.bind(@sockaddr).should == 0
+ end
+
+ it "raises Errno::EINVAL when binding to an already bound port" do
+ @sock.bind(@sockaddr);
+
+ lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL);
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
+ sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1");
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ platform_is_not :windows, :cygwin do
+ it "raises Errno::EACCES when the current user does not have permission to bind" do
+ sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1");
+ lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/connect_nonblock_spec.rb b/spec/rubyspec/library/socket/socket/connect_nonblock_spec.rb
new file mode 100644
index 0000000000..77c2340688
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/connect_nonblock_spec.rb
@@ -0,0 +1,67 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#connect_nonblock" do
+ before :each do
+ @hostname = "127.0.0.1"
+ @addr = Socket.sockaddr_in(SocketSpecs.port, @hostname)
+ @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
+ @thread = nil
+ end
+
+ after :each do
+ @socket.close
+ @thread.join if @thread
+ end
+
+ it "connects the socket to the remote side" do
+ ready = false
+ @thread = Thread.new do
+ server = TCPServer.new(@hostname, SocketSpecs.port)
+ ready = true
+ conn = server.accept
+ conn << "hello!"
+ conn.close
+ server.close
+ end
+
+ Thread.pass while (@thread.status and @thread.status != 'sleep') or !ready
+
+ begin
+ @socket.connect_nonblock(@addr)
+ rescue Errno::EINPROGRESS
+ end
+
+ IO.select nil, [@socket]
+
+ begin
+ @socket.connect_nonblock(@addr)
+ rescue Errno::EISCONN
+ # Not all OS's use this errno, so we trap and ignore it
+ end
+
+ @socket.read(6).should == "hello!"
+ end
+
+ platform_is_not :freebsd, :solaris, :aix do
+ it "raises Errno::EINPROGRESS when the connect would block" do
+ lambda do
+ @socket.connect_nonblock(@addr)
+ end.should raise_error(Errno::EINPROGRESS)
+ end
+
+ it "raises Errno::EINPROGRESS with IO::WaitWritable mixed in when the connect would block" do
+ lambda do
+ @socket.connect_nonblock(@addr)
+ end.should raise_error(IO::WaitWritable)
+ end
+
+ ruby_version_is "2.3" do
+ it "returns :wait_writable in exceptionless mode when the connect would block" do
+ @socket.connect_nonblock(@addr, exception: false).should == :wait_writable
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/connect_spec.rb b/spec/rubyspec/library/socket/socket/connect_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/connect_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/for_fd_spec.rb b/spec/rubyspec/library/socket/socket/for_fd_spec.rb
new file mode 100644
index 0000000000..7f3cfcceb4
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/for_fd_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Socket.for_fd" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ @client = TCPSocket.open("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @socket.close
+ @client.close
+ @host.close
+ @server.close
+ end
+
+ it "creates a new Socket that aliases the existing Socket's file descriptor" do
+ @socket = Socket.for_fd(@client.fileno)
+ @socket.autoclose = false
+ @socket.fileno.should == @client.fileno
+
+ @socket.send("foo", 0)
+ @client.send("bar", 0)
+
+ @host = @server.accept
+ @host.read(3).should == "foo"
+ @host.read(3).should == "bar"
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/getaddrinfo_spec.rb b/spec/rubyspec/library/socket/socket/getaddrinfo_spec.rb
new file mode 100644
index 0000000000..fa8112c010
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/getaddrinfo_spec.rb
@@ -0,0 +1,112 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#getaddrinfo" do
+ before :each do
+ @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
+ BasicSocket.do_not_reverse_lookup = true
+ end
+
+ after :each do
+ BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
+ end
+
+ platform_is_not :solaris, :windows do
+ it "gets the address information" do
+ expected = []
+ # The check for AP_INET6's class is needed because ipaddr.rb adds
+ # fake AP_INET6 even in case when IPv6 is not really supported.
+ # Without such check, this test might fail when ipaddr was required
+ # by some other specs.
+ if (Socket.constants.include? 'AF_INET6') &&
+ (Socket::AF_INET6.class != Object) then
+ expected.concat [
+ ['AF_INET6', 9, SocketSpecs.hostname, '::1', Socket::AF_INET6,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET6', 9, SocketSpecs.hostname, '::1', Socket::AF_INET6,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ['AF_INET6', 9, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET6', 9, SocketSpecs.hostname, 'fe80::1%lo0', Socket::AF_INET6,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ]
+ end
+
+ expected.concat [
+ ['AF_INET', 9, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
+ Socket::SOCK_DGRAM, Socket::IPPROTO_UDP],
+ ['AF_INET', 9, SocketSpecs.hostname, '127.0.0.1', Socket::AF_INET,
+ Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ]
+
+ addrinfo = Socket.getaddrinfo SocketSpecs.hostname, 'discard'
+ addrinfo.each do |a|
+ case a.last
+ when Socket::IPPROTO_UDP, Socket::IPPROTO_TCP
+ expected.should include(a)
+ else
+ # don't check this. It's some weird protocol we don't know about
+ # so we can't spec it.
+ end
+ end
+ end
+
+ # #getaddrinfo will return a INADDR_ANY address (0.0.0.0
+ # or "::") if it's a passive socket. In the case of non-passive
+ # sockets (AI_PASSIVE not set) it should return the loopback
+ # address (127.0.0.1 or "::1".
+
+ it "accepts empty addresses for IPv4 passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ Socket::AI_PASSIVE)
+
+ expected = [["AF_INET", 9, "0.0.0.0", "0.0.0.0", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
+ res.should == expected
+ end
+
+ it "accepts empty addresses for IPv4 non-passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ 0)
+
+ expected = [["AF_INET", 9, "127.0.0.1", "127.0.0.1", Socket::AF_INET, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]]
+ res.should == expected
+ end
+
+
+ it "accepts empty addresses for IPv6 passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET6,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ Socket::AI_PASSIVE)
+
+ expected = [
+ ["AF_INET6", 9, "::", "::", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ["AF_INET6", 9, "0:0:0:0:0:0:0:0", "0:0:0:0:0:0:0:0", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
+ ]
+ res.each { |a| expected.should include (a) }
+ end
+
+ it "accepts empty addresses for IPv6 non-passive sockets" do
+ res = Socket.getaddrinfo(nil, "discard",
+ Socket::AF_INET6,
+ Socket::SOCK_STREAM,
+ Socket::IPPROTO_TCP,
+ 0)
+
+ expected = [
+ ["AF_INET6", 9, "::1", "::1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP],
+ ["AF_INET6", 9, "0:0:0:0:0:0:0:1", "0:0:0:0:0:0:0:1", Socket::AF_INET6, Socket::SOCK_STREAM, Socket::IPPROTO_TCP]
+ ]
+ res.each { |a| expected.should include(a) }
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/gethostbyaddr_spec.rb b/spec/rubyspec/library/socket/socket/gethostbyaddr_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/gethostbyaddr_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/gethostbyname_spec.rb b/spec/rubyspec/library/socket/socket/gethostbyname_spec.rb
new file mode 100644
index 0000000000..a93c9ffb98
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/gethostbyname_spec.rb
@@ -0,0 +1,17 @@
+# -*- encoding: binary -*-
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket#gethostbyname" do
+ it "returns broadcast address info for '<broadcast>'" do
+ addr = Socket.gethostbyname('<broadcast>');
+ addr.should == ["255.255.255.255", [], 2, "\377\377\377\377"]
+ end
+
+ it "returns broadcast address info for '<any>'" do
+ addr = Socket.gethostbyname('<any>');
+ addr.should == ["0.0.0.0", [], 2, "\000\000\000\000"]
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/gethostname_spec.rb b/spec/rubyspec/library/socket/socket/gethostname_spec.rb
new file mode 100644
index 0000000000..c61e6b3eb4
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/gethostname_spec.rb
@@ -0,0 +1,8 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket.gethostname" do
+ it "returns the host name" do
+ Socket.gethostname.should == `hostname`.strip
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/getnameinfo_spec.rb b/spec/rubyspec/library/socket/socket/getnameinfo_spec.rb
new file mode 100644
index 0000000000..2b0ea4a723
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/getnameinfo_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "Socket.getnameinfo" do
+ before :each do
+ @reverse_lookup = BasicSocket.do_not_reverse_lookup
+ BasicSocket.do_not_reverse_lookup = true
+ end
+
+ after :each do
+ BasicSocket.do_not_reverse_lookup = @reverse_lookup
+ end
+
+ it "gets the name information and don't resolve it" do
+ sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "#{SocketSpecs.port}"]
+ end
+
+ def should_be_valid_dns_name(name)
+ # http://stackoverflow.com/questions/106179/regular-expression-to-match-hostname-or-ip-address
+ # ftp://ftp.rfc-editor.org/in-notes/rfc3696.txt
+ # http://domainkeys.sourceforge.net/underscore.html
+ valid_dns = /^(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\-_]*[a-zA-Z0-9_])\.)*([A-Za-z_]|[A-Za-z_][A-Za-z0-9\-_]*[A-Za-z0-9_])\.?$/
+ name.should =~ valid_dns
+ end
+
+ it "gets the name information and resolve the host" do
+ sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICSERV)
+ should_be_valid_dns_name(name_info[0])
+ name_info[1].should == SocketSpecs.port.to_s
+ end
+
+ it "gets the name information and resolves the service" do
+ sockaddr = Socket.sockaddr_in 9, '127.0.0.1'
+ name_info = Socket.getnameinfo(sockaddr)
+ name_info.size.should == 2
+ should_be_valid_dns_name(name_info[0])
+ # see http://www.iana.org/assignments/port-numbers
+ name_info[1].should == 'discard'
+ end
+
+ it "gets a 3-element array and doesn't resolve hostname" do
+ name_info = Socket.getnameinfo(["AF_INET", SocketSpecs.port, '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "#{SocketSpecs.port}"]
+ end
+
+ it "gets a 3-element array and resolves the service" do
+ name_info = Socket.getnameinfo ["AF_INET", 9, '127.0.0.1']
+ name_info[1].should == 'discard'
+ end
+
+ it "gets a 4-element array and doesn't resolve hostname" do
+ name_info = Socket.getnameinfo(["AF_INET", SocketSpecs.port, 'foo', '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
+ name_info.should == ['127.0.0.1', "#{SocketSpecs.port}"]
+ end
+
+ it "gets a 4-element array and resolves the service" do
+ name_info = Socket.getnameinfo ["AF_INET", 9, 'foo', '127.0.0.1']
+ name_info[1].should == 'discard'
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/socket/getservbyname_spec.rb b/spec/rubyspec/library/socket/socket/getservbyname_spec.rb
new file mode 100644
index 0000000000..a48b5753b4
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/getservbyname_spec.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket#getservbyname" do
+ it "returns the port for service 'discard'" do
+ Socket.getservbyname('discard').should == 9
+ end
+
+ it "returns the port for service 'discard' with protocol 'tcp'" do
+ Socket.getservbyname('discard', 'tcp').should == 9
+ end
+
+ it "returns the port for service 'domain' with protocol 'udp'" do
+ Socket.getservbyname('domain', 'udp').should == 53
+ end
+
+ it "returns the port for service 'daytime'" do
+ Socket.getservbyname('daytime').should == 13
+ end
+
+ it "raises a SocketError when the service or port is invalid" do
+ lambda { Socket.getservbyname('invalid') }.should raise_error(SocketError)
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/listen_spec.rb b/spec/rubyspec/library/socket/socket/listen_spec.rb
new file mode 100644
index 0000000000..ebc97954fb
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/listen_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+include Socket::Constants
+
+describe "Socket#listen" do
+ before :each do
+ @socket = Socket.new(AF_INET, SOCK_STREAM, 0)
+ end
+
+ after :each do
+ @socket.closed?.should be_false
+ @socket.close
+ end
+
+ it "verifies we can listen for incoming connections" do
+ sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")
+ @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
+ @socket.bind(sockaddr)
+ @socket.listen(1).should == 0
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/new_spec.rb b/spec/rubyspec/library/socket/socket/new_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/new_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/pack_sockaddr_in_spec.rb b/spec/rubyspec/library/socket/socket/pack_sockaddr_in_spec.rb
new file mode 100644
index 0000000000..8c95b948dc
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/pack_sockaddr_in_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#pack_sockaddr_in" do
+ it_behaves_like :socket_pack_sockaddr_in, :pack_sockaddr_in
+end
diff --git a/spec/rubyspec/library/socket/socket/pack_sockaddr_un_spec.rb b/spec/rubyspec/library/socket/socket/pack_sockaddr_un_spec.rb
new file mode 100644
index 0000000000..aacb6d54dc
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/pack_sockaddr_un_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#pack_sockaddr_un" do
+ it_behaves_like :socket_pack_sockaddr_un, :pack_sockaddr_un
+end
diff --git a/spec/rubyspec/library/socket/socket/pair_spec.rb b/spec/rubyspec/library/socket/socket/pair_spec.rb
new file mode 100644
index 0000000000..663ca3f183
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/pair_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/socketpair', __FILE__)
+
+describe "Socket#pair" do
+ it_behaves_like :socket_socketpair, :pair
+end
diff --git a/spec/rubyspec/library/socket/socket/recvfrom_nonblock_spec.rb b/spec/rubyspec/library/socket/socket/recvfrom_nonblock_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/recvfrom_nonblock_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/recvfrom_spec.rb b/spec/rubyspec/library/socket/socket/recvfrom_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/recvfrom_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/sockaddr_in_spec.rb b/spec/rubyspec/library/socket/socket/sockaddr_in_spec.rb
new file mode 100644
index 0000000000..59e0318fda
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/sockaddr_in_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#sockaddr_in" do
+ it_behaves_like :socket_pack_sockaddr_in, :sockaddr_in
+end
diff --git a/spec/rubyspec/library/socket/socket/sockaddr_un_spec.rb b/spec/rubyspec/library/socket/socket/sockaddr_un_spec.rb
new file mode 100644
index 0000000000..fa233587d9
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/sockaddr_un_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/pack_sockaddr', __FILE__)
+
+describe "Socket#sockaddr_un" do
+ it_behaves_like :socket_pack_sockaddr_un, :sockaddr_un
+end
diff --git a/spec/rubyspec/library/socket/socket/socket_spec.rb b/spec/rubyspec/library/socket/socket/socket_spec.rb
new file mode 100644
index 0000000000..dbaed17af4
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/socket_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket" do
+ it "inherits from BasicSocket and IO" do
+ Socket.superclass.should == BasicSocket
+ BasicSocket.superclass.should == IO
+ end
+end
+
+describe "The socket class hierarchy" do
+ it "has an IPSocket in parallel to Socket" do
+ Socket.ancestors.include?(IPSocket).should == false
+ IPSocket.ancestors.include?(Socket).should == false
+ IPSocket.superclass.should == BasicSocket
+ end
+
+ it "has TCPSocket and UDPSocket subclasses of IPSocket" do
+ TCPSocket.superclass.should == IPSocket
+ UDPSocket.superclass.should == IPSocket
+ end
+
+ platform_is_not :windows do
+ it "has a UNIXSocket in parallel to Socket" do
+ Socket.ancestors.include?(UNIXSocket).should == false
+ UNIXSocket.ancestors.include?(Socket).should == false
+ UNIXSocket.superclass.should == BasicSocket
+ end
+ end
+end
+
+platform_is_not :windows do
+ describe "Server class hierarchy" do
+ it "contains UNIXServer" do
+ UNIXServer.superclass.should == UNIXSocket
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/socket/socketpair_spec.rb b/spec/rubyspec/library/socket/socket/socketpair_spec.rb
new file mode 100644
index 0000000000..80b07170a6
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/socketpair_spec.rb
@@ -0,0 +1,7 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/socketpair', __FILE__)
+
+describe "Socket#socketpair" do
+ it_behaves_like :socket_socketpair, :socketpair
+end
diff --git a/spec/rubyspec/library/socket/socket/sysaccept_spec.rb b/spec/rubyspec/library/socket/socket/sysaccept_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/sysaccept_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/socket/unpack_sockaddr_in_spec.rb b/spec/rubyspec/library/socket/socket/unpack_sockaddr_in_spec.rb
new file mode 100644
index 0000000000..2df3b69a6d
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/unpack_sockaddr_in_spec.rb
@@ -0,0 +1,29 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require 'socket'
+
+describe "Socket.unpack_sockaddr_in" do
+
+ it "decodes the host name and port number of a packed sockaddr_in" do
+ sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1'
+ Socket.unpack_sockaddr_in(sockaddr).should == [SocketSpecs.port, '127.0.0.1']
+ end
+
+ it "gets the hostname and port number from a passed Addrinfo" do
+ addrinfo = Addrinfo.tcp('127.0.0.1', SocketSpecs.port)
+ Socket.unpack_sockaddr_in(addrinfo).should == [SocketSpecs.port, '127.0.0.1']
+ end
+
+ platform_is_not :windows do
+ it "raises an ArgumentError when the sin_family is not AF_INET" do
+ sockaddr = Socket.sockaddr_un '/tmp/x'
+ lambda { Socket.unpack_sockaddr_in sockaddr }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when passed addrinfo is not AF_INET/AF_INET6" do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ lambda { Socket.unpack_sockaddr_in(addrinfo) }.should raise_error(ArgumentError)
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/socket/unpack_sockaddr_un_spec.rb b/spec/rubyspec/library/socket/socket/unpack_sockaddr_un_spec.rb
new file mode 100644
index 0000000000..4d558c89c4
--- /dev/null
+++ b/spec/rubyspec/library/socket/socket/unpack_sockaddr_un_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe 'Socket.unpack_sockaddr_un' do
+ platform_is_not :windows do
+ it 'decodes sockaddr to unix path' do
+ sockaddr = Socket.sockaddr_un('/tmp/sock')
+ Socket.unpack_sockaddr_un(sockaddr).should == '/tmp/sock'
+ end
+
+ it 'returns unix path from a passed Addrinfo' do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock'
+ end
+
+ it 'raises an ArgumentError when the sin_family is not AF_UNIX' do
+ sockaddr = Socket.sockaddr_in(SocketSpecs.port, '127.0.0.1')
+ lambda { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError)
+ end
+
+ it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do
+ addrinfo = Addrinfo.tcp('127.0.0.1', SocketSpecs.port)
+ lambda { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/accept_nonblock_spec.rb b/spec/rubyspec/library/socket/tcpserver/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..d0f2673af3
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/accept_nonblock_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "Socket::TCPServer.accept_nonblock" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "accepts non blocking connections" do
+ @server.listen(5)
+ lambda {
+ @server.accept_nonblock
+ }.should raise_error(IO::WaitReadable)
+
+ c = TCPSocket.new("127.0.0.1", SocketSpecs.port)
+ sleep 0.1
+ s = @server.accept_nonblock
+
+ port, address = Socket.unpack_sockaddr_in(s.getsockname)
+
+ port.should == SocketSpecs.port
+ address.should == "127.0.0.1"
+ s.should be_kind_of(TCPSocket)
+
+ c.close
+ s.close
+ end
+
+ it "raises an IOError if the socket is closed" do
+ @server.close
+ lambda { @server.accept }.should raise_error(IOError)
+ end
+
+ describe 'without a connected client' do
+ it 'raises error' do
+ lambda { @server.accept_nonblock }.should raise_error(IO::WaitReadable)
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @server.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/accept_spec.rb b/spec/rubyspec/library/socket/tcpserver/accept_spec.rb
new file mode 100644
index 0000000000..cf1fbbd873
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/accept_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+
+describe "TCPServer#accept" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it "accepts a connection and returns a TCPSocket" do
+ data = nil
+ t = Thread.new do
+ client = @server.accept
+ client.should be_kind_of(TCPSocket)
+ data = client.read(5)
+ client << "goodbye"
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+
+ socket = TCPSocket.new('127.0.0.1', SocketSpecs.port)
+ socket.write('hello')
+ socket.shutdown(1) # we are done with sending
+ socket.read.should == 'goodbye'
+ t.join
+ data.should == 'hello'
+ socket.close
+ end
+
+ it "can be interrupted by Thread#kill" do
+ t = Thread.new { @server.accept }
+
+ Thread.pass while t.status and t.status != "sleep"
+
+ # kill thread, ensure it dies in a reasonable amount of time
+ t.kill
+ a = 1
+ while a < 2000
+ break unless t.alive?
+ Thread.pass
+ sleep 0.2
+ a += 1
+ end
+ a.should < 2000
+ end
+
+ it "can be interrupted by Thread#raise" do
+ t = Thread.new { @server.accept }
+
+ Thread.pass while t.status and t.status != "sleep"
+
+ # raise in thread, ensure the raise happens
+ ex = Exception.new
+ t.raise ex
+ lambda { t.join }.should raise_error(Exception)
+ end
+
+ it "raises an IOError if the socket is closed" do
+ @server.close
+ lambda { @server.accept }.should raise_error(IOError)
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/gets_spec.rb b/spec/rubyspec/library/socket/tcpserver/gets_spec.rb
new file mode 100644
index 0000000000..2f8e699a53
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/gets_spec.rb
@@ -0,0 +1,16 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer#gets" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close
+ end
+
+ it "raises Errno::ENOTCONN on gets" do
+ lambda { @server.gets }.should raise_error(Errno::ENOTCONN)
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/listen_spec.rb b/spec/rubyspec/library/socket/tcpserver/listen_spec.rb
new file mode 100644
index 0000000000..5e9b9c1090
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/listen_spec.rb
@@ -0,0 +1,18 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe 'TCPServer#listen' do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it 'returns 0' do
+ @server.listen(10).should == 0
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/new_spec.rb b/spec/rubyspec/library/socket/tcpserver/new_spec.rb
new file mode 100644
index 0000000000..4b7f53a397
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/new_spec.rb
@@ -0,0 +1,97 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer.new" do
+ after :each do
+ @server.close if @server && !@server.closed?
+ end
+
+ it "binds to a host and a port" do
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should be_kind_of(Fixnum)
+ # on some platforms (Mac), MRI
+ # returns comma at the end.
+ addr[2].should =~ /^#{SocketSpecs.hostname}\b/
+ addr[3].should == '127.0.0.1'
+ end
+
+ it "binds to localhost and a port with either IPv4 or IPv6" do
+ @server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port)
+ addr = @server.addr
+ if addr[0] == 'AF_INET'
+ addr[1].should == SocketSpecs.port
+ addr[2].should =~ /^#{SocketSpecs.hostname}\b/
+ addr[3].should == '127.0.0.1'
+ else
+ addr[1].should == SocketSpecs.port
+ addr[2].should =~ /^#{SocketSpecs.hostnamev6}\b/
+ addr[3].should == '::1'
+ end
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty" do
+ @server = TCPServer.new('', SocketSpecs.port)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should == SocketSpecs.port
+ addr[2].should == '0.0.0.0'
+ addr[3].should == '0.0.0.0'
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty and the port is a string" do
+ @server = TCPServer.new('', SocketSpecs.port.to_s)
+ addr = @server.addr
+ addr[0].should == 'AF_INET'
+ addr[1].should == SocketSpecs.port
+ addr[2].should == '0.0.0.0'
+ addr[3].should == '0.0.0.0'
+ end
+
+ it "coerces port to string, then determines port from that number or service name" do
+ t = Object.new
+ lambda { TCPServer.new(SocketSpecs.hostname, t) }.should raise_error(TypeError)
+
+ def t.to_str; SocketSpecs.port.to_s; end
+
+ @server = TCPServer.new(SocketSpecs.hostname, t)
+ addr = @server.addr
+ addr[1].should == SocketSpecs.port
+
+ # TODO: This should also accept strings like 'https', but I don't know how to
+ # pick such a service port that will be able to reliably bind...
+ end
+
+ it "raises Errno::EADDRNOTAVAIL when the adress is unknown" do
+ lambda { TCPServer.new("1.2.3.4", 4000) }.should raise_error(Errno::EADDRNOTAVAIL)
+ end
+
+ # There is no way to make this fail-proof on all machines, because
+ # DNS servers like opendns return A records for ANY host, including
+ # traditionally invalidly named ones.
+ quarantine! do
+ it "raises a SocketError when the host is unknown" do
+ lambda {
+ TCPServer.new("--notavalidname", 4000)
+ }.should raise_error(SocketError)
+ end
+ end
+
+ it "raises Errno::EADDRINUSE when address is already in use" do
+ lambda {
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ }.should raise_error(Errno::EADDRINUSE)
+ end
+
+ platform_is_not :windows, :aix do
+ # A known bug in AIX. getsockopt(2) does not properly set
+ # the fifth argument for SO_REUSEADDR.
+ it "sets SO_REUSEADDR on the resulting server" do
+ @server = TCPServer.new('127.0.0.1', SocketSpecs.port)
+ @server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00"
+ @server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/output_spec.rb b/spec/rubyspec/library/socket/tcpserver/output_spec.rb
new file mode 100644
index 0000000000..b193bb83ea
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/output_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer#<<" do
+ after :each do
+ @server.close if @server
+ @socket.close if @socket
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/readpartial_spec.rb b/spec/rubyspec/library/socket/tcpserver/readpartial_spec.rb
new file mode 100644
index 0000000000..35d07a0309
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/readpartial_spec.rb
@@ -0,0 +1,9 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPServer#readpartial" do
+ after :each do
+ @server.close if @server
+ @socket.close if @socket
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpserver/sysaccept_spec.rb b/spec/rubyspec/library/socket/tcpserver/sysaccept_spec.rb
new file mode 100644
index 0000000000..1cd1c1c719
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpserver/sysaccept_spec.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+require 'socket'
+
+describe "TCPServer#sysaccept" do
+ before :each do
+ @server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ it 'blocks if no connections' do
+ lambda { @server.sysaccept }.should block_caller
+ end
+
+ it 'returns file descriptor of an accepted connection' do
+ begin
+ sock = TCPSocket.new(SocketSpecs.hostname, SocketSpecs.port)
+
+ fd = @server.sysaccept
+
+ fd.should be_an_instance_of(Fixnum)
+ ensure
+ sock.close if sock && !sock.closed?
+ IO.for_fd(fd).close if fd
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/gethostbyname_spec.rb b/spec/rubyspec/library/socket/tcpsocket/gethostbyname_spec.rb
new file mode 100644
index 0000000000..11838aca27
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/gethostbyname_spec.rb
@@ -0,0 +1,51 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+# TODO: verify these for windows
+describe "TCPSocket#gethostbyname" do
+ before :each do
+ @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname)
+ end
+
+ it "returns an array elements of information on the hostname" do
+ @host_info.should be_kind_of(Array)
+ end
+
+ platform_is_not :windows do
+ it "returns the canonical name as first value" do
+ @host_info[0].should == SocketSpecs.hostname
+ end
+
+ it "returns the address type as the third value" do
+ address_type = @host_info[2]
+ [Socket::AF_INET, Socket::AF_INET6].include?(address_type).should be_true
+ end
+
+ it "returns the IP address as the fourth value" do
+ ip = @host_info[3]
+ ["127.0.0.1", "::1"].include?(ip).should be_true
+ end
+ end
+
+ platform_is :windows do
+ quarantine! do # name lookup seems not working on Windows CI
+ it "returns the canonical name as first value" do
+ host = "#{ENV['COMPUTERNAME'].downcase}"
+ host << ".#{ENV['USERDNSDOMAIN'].downcase}" if ENV['USERDNSDOMAIN']
+ @host_info[0].should == host
+ end
+ end
+
+ it "returns the address type as the third value" do
+ @host_info[2].should == Socket::AF_INET
+ end
+
+ it "returns the IP address as the fourth value" do
+ @host_info[3].should == "127.0.0.1"
+ end
+ end
+
+ it "returns any aliases to the address as second value" do
+ @host_info[1].should be_kind_of(Array)
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/new_spec.rb b/spec/rubyspec/library/socket/tcpsocket/new_spec.rb
new file mode 100644
index 0000000000..279576272b
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/new_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/new', __FILE__)
+
+describe "TCPSocket.new" do
+ it_behaves_like :tcpsocket_new, :new
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/open_spec.rb b/spec/rubyspec/library/socket/tcpsocket/open_spec.rb
new file mode 100644
index 0000000000..fb4cc4629a
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/open_spec.rb
@@ -0,0 +1,5 @@
+require File.expand_path('../shared/new', __FILE__)
+
+describe "TCPSocket.open" do
+ it_behaves_like :tcpsocket_new, :open
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/partially_closable_spec.rb b/spec/rubyspec/library/socket/tcpsocket/partially_closable_spec.rb
new file mode 100644
index 0000000000..f38b251090
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/partially_closable_spec.rb
@@ -0,0 +1,22 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+describe "TCPSocket partial closability" do
+
+ before :each do
+ port = SocketSpecs.find_available_port
+ @server = TCPServer.new("127.0.0.1", port)
+ @s1 = TCPSocket.new("127.0.0.1", port)
+ @s2 = @server.accept
+ end
+
+ after :each do
+ @server.close
+ @s1.close
+ @s2.close
+ end
+
+ it_should_behave_like "partially closable sockets"
+
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb b/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb
new file mode 100644
index 0000000000..1d89aa866c
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb
@@ -0,0 +1,36 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPSocket#recv_nonblock" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ end
+
+ after :each do
+ if @socket
+ @socket.write "QUIT"
+ @socket.close
+ end
+ @server.shutdown
+ end
+
+ it "returns a String read from the socket" do
+ @socket = TCPSocket.new @hostname, SocketSpecs.port
+ @socket.write "TCPSocket#recv_nonblock"
+
+ # Wait for the server to echo. This spec is testing the return
+ # value, not the non-blocking behavior.
+ #
+ # TODO: Figure out a good way to test non-blocking.
+ IO.select([@socket])
+ @socket.recv_nonblock(50).should == "TCPSocket#recv_nonblock"
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @socket = TCPSocket.new @hostname, SocketSpecs.port
+ @socket.recv_nonblock(50, exception: false).should == :wait_readable
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb b/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb
new file mode 100644
index 0000000000..e4d3da10d1
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb
@@ -0,0 +1,48 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "TCPSocket#setsockopt" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ end
+
+ before :each do
+ @sock = TCPSocket.new @hostname, SocketSpecs.port
+ end
+
+ after :each do
+ @sock.close unless @sock.closed?
+ @server.shutdown
+ end
+
+ describe "using constants" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1).should == 0
+ end
+ end
+
+ describe "using symbols" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(:IPPROTO_TCP, :TCP_NODELAY, 1).should == 0
+ end
+
+ context "without prefix" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt(:TCP, :NODELAY, 1).should == 0
+ end
+ end
+ end
+
+ describe "using strings" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt('IPPROTO_TCP', 'TCP_NODELAY', 1).should == 0
+ end
+
+ context "without prefix" do
+ it "sets the TCP nodelay to 1" do
+ @sock.setsockopt('TCP', 'NODELAY', 1).should == 0
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/spec/rubyspec/library/socket/tcpsocket/shared/new.rb b/spec/rubyspec/library/socket/tcpsocket/shared/new.rb
new file mode 100644
index 0000000000..b6f557fc18
--- /dev/null
+++ b/spec/rubyspec/library/socket/tcpsocket/shared/new.rb
@@ -0,0 +1,71 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+describe :tcpsocket_new, shared: true do
+ it "requires a hostname and a port as arguments" do
+ lambda { TCPSocket.send(@method) }.should raise_error(ArgumentError)
+ end
+
+ it "refuses the connection when there is no server to connect to" do
+ lambda do
+ TCPSocket.send(@method, SocketSpecs.hostname, SocketSpecs.local_port)
+ end.should raise_error(Errno::ECONNREFUSED)
+ end
+
+ describe "with a running server" do
+ before :each do
+ @server = SocketSpecs::SpecTCPServer.new
+ @hostname = @server.hostname
+ end
+
+ after :each do
+ if @socket
+ @socket.write "QUIT"
+ @socket.close
+ end
+ @server.shutdown
+ end
+
+ it "silently ignores 'nil' as the third parameter" do
+ @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port, nil)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a listening server with host and port" do
+ @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a server when passed local_host argument" do
+ @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port, @hostname)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "connects to a server when passed local_host and local_port arguments" do
+ @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port,
+ @hostname, SocketSpecs.local_port)
+ @socket.should be_an_instance_of(TCPSocket)
+ end
+
+ it "has an address once it has connected to a listening server" do
+ @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port)
+ @socket.should be_an_instance_of(TCPSocket)
+
+ # TODO: Figure out how to abstract this. You can get AF_INET
+ # from 'Socket.getaddrinfo(hostname, nil)[0][3]' but socket.addr
+ # will return AF_INET6. At least this check will weed out clearly
+ # erroneous values.
+ @socket.addr[0].should =~ /^AF_INET6?/
+
+ case @socket.addr[0]
+ when 'AF_INET'
+ @socket.addr[3].should == SocketSpecs.addr(:ipv4)
+ when 'AF_INET6'
+ @socket.addr[3].should == SocketSpecs.addr(:ipv6)
+ end
+
+ @socket.addr[1].should be_kind_of(Fixnum)
+ @socket.addr[2].should =~ /^#{@hostname}/
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/udpsocket/bind_spec.rb b/spec/rubyspec/library/socket/udpsocket/bind_spec.rb
new file mode 100644
index 0000000000..067baa2472
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/bind_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.bind" do
+
+ before :each do
+ @socket = UDPSocket.new
+ end
+
+ after :each do
+ @socket.close unless @socket.closed?
+ end
+
+ it "binds the socket to a port" do
+ @socket.bind(SocketSpecs.hostname, SocketSpecs.port)
+
+ lambda { @socket.bind(SocketSpecs.hostname, SocketSpecs.port) }.should raise_error
+ end
+
+ it "receives a hostname and a port" do
+ @socket.bind(SocketSpecs.hostname, SocketSpecs.port)
+
+ port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
+
+ host.should == "127.0.0.1"
+ port.should == SocketSpecs.port
+ end
+
+ it "binds to INADDR_ANY if the hostname is empty" do
+ @socket.bind("", SocketSpecs.port)
+ port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
+ host.should == "0.0.0.0"
+ port.should == SocketSpecs.port
+ end
+end
diff --git a/spec/rubyspec/library/socket/udpsocket/connect_spec.rb b/spec/rubyspec/library/socket/udpsocket/connect_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/connect_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/udpsocket/new_spec.rb b/spec/rubyspec/library/socket/udpsocket/new_spec.rb
new file mode 100644
index 0000000000..5a2e4e1f31
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/new_spec.rb
@@ -0,0 +1,32 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe 'UDPSocket.new' do
+ after :each do
+ @socket.close if @socket && !@socket.closed?
+ end
+
+ it 'without arguments' do
+ @socket = UDPSocket.new
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using Fixnum argument' do
+ @socket = UDPSocket.new(Socket::AF_INET)
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using Symbol argument' do
+ @socket = UDPSocket.new(:INET)
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'using String argument' do
+ @socket = UDPSocket.new('INET')
+ @socket.should be_an_instance_of(UDPSocket)
+ end
+
+ it 'raises Errno::EAFNOSUPPORT if unsupported family passed' do
+ lambda { UDPSocket.new(-1) }.should raise_error(Errno::EAFNOSUPPORT)
+ end
+end
diff --git a/spec/rubyspec/library/socket/udpsocket/open_spec.rb b/spec/rubyspec/library/socket/udpsocket/open_spec.rb
new file mode 100644
index 0000000000..188f879ed1
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/open_spec.rb
@@ -0,0 +1,13 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.open" do
+ after :each do
+ @socket.close if @socket && !@socket.closed?
+ end
+
+ it "allows calls to open without arguments" do
+ @socket = UDPSocket.open
+ @socket.should be_kind_of(UDPSocket)
+ end
+end
diff --git a/spec/rubyspec/library/socket/udpsocket/recvfrom_nonblock_spec.rb b/spec/rubyspec/library/socket/udpsocket/recvfrom_nonblock_spec.rb
new file mode 100644
index 0000000000..fcd29e1257
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/recvfrom_nonblock_spec.rb
@@ -0,0 +1,2 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
diff --git a/spec/rubyspec/library/socket/udpsocket/send_spec.rb b/spec/rubyspec/library/socket/udpsocket/send_spec.rb
new file mode 100644
index 0000000000..ad0e6a7f2f
--- /dev/null
+++ b/spec/rubyspec/library/socket/udpsocket/send_spec.rb
@@ -0,0 +1,58 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UDPSocket.send" do
+ before :each do
+ @ready = false
+ @server_thread = Thread.new do
+ @server = UDPSocket.open
+ @server.bind(nil, SocketSpecs.port)
+ @ready = true
+ begin
+ @msg = @server.recvfrom_nonblock(64)
+ rescue IO::WaitReadable
+ IO.select([@server])
+ retry
+ end
+ @server.close
+ end
+ Thread.pass while @server_thread.status and !@ready
+ end
+
+ it "sends data in ad hoc mode" do
+ @socket = UDPSocket.open
+ @socket.send("ad hoc", 0, SocketSpecs.hostname,SocketSpecs.port)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "ad hoc"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+
+ it "sends data in ad hoc mode (with port given as a String)" do
+ @socket = UDPSocket.open
+ @socket.send("ad hoc", 0, SocketSpecs.hostname,SocketSpecs.str_port)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "ad hoc"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+
+ it "sends data in connection mode" do
+ @socket = UDPSocket.open
+ @socket.connect(SocketSpecs.hostname,SocketSpecs.port)
+ @socket.send("connection-based", 0)
+ @socket.close
+ @server_thread.join
+
+ @msg[0].should == "connection-based"
+ @msg[1][0].should == "AF_INET"
+ @msg[1][1].should be_kind_of(Fixnum)
+ @msg[1][3].should == "127.0.0.1"
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixserver/accept_nonblock_spec.rb b/spec/rubyspec/library/socket/unixserver/accept_nonblock_spec.rb
new file mode 100644
index 0000000000..bad9139eea
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/accept_nonblock_spec.rb
@@ -0,0 +1,40 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXServer#accept_nonblock" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @socket = @server.accept_nonblock
+ @client.send("foobar", 0)
+ end
+
+ after :each do
+ @socket.close
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "accepts a connection in a non-blocking way" do
+ data = @socket.recvfrom(6).first
+ data.should == "foobar"
+ end
+
+ it "returns a UNIXSocket" do
+ @socket.should be_kind_of(UNIXSocket)
+ end
+
+ ruby_version_is '2.3' do
+ it 'returns :wait_readable in exceptionless mode' do
+ @server.accept_nonblock(exception: false).should == :wait_readable
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixserver/accept_spec.rb b/spec/rubyspec/library/socket/unixserver/accept_spec.rb
new file mode 100644
index 0000000000..6ce1f2c6db
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/accept_spec.rb
@@ -0,0 +1,66 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXServer#accept" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+ end
+
+ after :each do
+ rm_r @path
+ end
+
+ it "accepts what is written by the client" do
+ server = UNIXServer.open(SocketSpecs.socket_path)
+ client = UNIXSocket.open(SocketSpecs.socket_path)
+
+ client.send('hello', 0)
+
+ sock = server.accept
+ data, info = sock.recvfrom(5)
+
+ data.should == 'hello'
+ info.should_not be_empty
+
+ server.close
+ client.close
+ sock.close
+ end
+
+ it "can be interrupted by Thread#kill" do
+ server = UNIXServer.new(@path)
+ t = Thread.new {
+ server.accept
+ }
+ Thread.pass while t.status and t.status != "sleep"
+
+ # kill thread, ensure it dies in a reasonable amount of time
+ t.kill
+ a = 1
+ while a < 2000
+ break unless t.alive?
+ Thread.pass
+ sleep 0.2
+ a += 1
+ end
+ a.should < 2000
+ server.close
+ end
+
+ it "can be interrupted by Thread#raise" do
+ server = UNIXServer.new(@path)
+ t = Thread.new {
+ server.accept
+ }
+ Thread.pass while t.status and t.status != "sleep"
+
+ # raise in thread, ensure the raise happens
+ ex = Exception.new
+ t.raise ex
+ lambda { t.join }.should raise_error(Exception)
+ server.close
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixserver/for_fd_spec.rb b/spec/rubyspec/library/socket/unixserver/for_fd_spec.rb
new file mode 100644
index 0000000000..bf8aa41d40
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/for_fd_spec.rb
@@ -0,0 +1,23 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXServer#for_fd" do
+ before :each do
+ @unix_path = tmp("unix_socket")
+ @unix = UNIXServer.new(@unix_path)
+ end
+
+ after :each do
+ @unix.close if @unix
+ rm_r @unix_path
+ end
+
+ it "can calculate the path" do
+ b = UNIXServer.for_fd(@unix.fileno)
+ b.autoclose = false
+
+ b.path.should == @unix_path
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixserver/new_spec.rb b/spec/rubyspec/library/socket/unixserver/new_spec.rb
new file mode 100644
index 0000000000..d34aa0ca03
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/new_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXServer.new" do
+ it_behaves_like :unixserver_new, :new
+end
diff --git a/spec/rubyspec/library/socket/unixserver/open_spec.rb b/spec/rubyspec/library/socket/unixserver/open_spec.rb
new file mode 100644
index 0000000000..4401d9dda8
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/open_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXServer.open" do
+ it_behaves_like :unixserver_new, :open
+
+ platform_is_not :windows do
+ before :each do
+ @path = tmp("unixserver_spec")
+ rm_r @path
+ end
+
+ after :each do
+ @server.close if @server
+ @server = nil
+ rm_r @path
+ end
+
+ it "yields the new UNIXServer object to the block, if given" do
+ UNIXServer.open(@path) do |unix|
+ unix.path.should == @path
+ unix.addr.should == ["AF_UNIX", @path]
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixserver/shared/new.rb b/spec/rubyspec/library/socket/unixserver/shared/new.rb
new file mode 100644
index 0000000000..9b0798b828
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixserver/shared/new.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+require 'tempfile'
+
+describe :unixserver_new, shared: true do
+ platform_is_not :windows do
+ before :each do
+ @path = tmp("unixserver_spec")
+ rm_r @path
+ end
+
+ after :each do
+ @server.close if @server
+ @server = nil
+ rm_r @path
+ end
+
+ it "creates a new UNIXServer" do
+ @server = UNIXServer.send(@method, @path)
+ @server.path.should == @path
+ @server.addr.should == ["AF_UNIX", @path]
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/addr_spec.rb b/spec/rubyspec/library/socket/unixsocket/addr_spec.rb
new file mode 100644
index 0000000000..893a910e92
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/addr_spec.rb
@@ -0,0 +1,38 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#addr" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "returns the address family of this socket in an array" do
+ @client.addr[0].should == "AF_UNIX"
+ end
+
+ it "returns the path of the socket in an array if it's a server" do
+ @server.addr[1].should == @path
+ end
+
+ it "returns an empty string for path if it's a client" do
+ @client.addr[1].should == ""
+ end
+
+ it "returns an array" do
+ @client.addr.should be_kind_of(Array)
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/inspect_spec.rb b/spec/rubyspec/library/socket/unixsocket/inspect_spec.rb
new file mode 100644
index 0000000000..8ea25ec1e9
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/inspect_spec.rb
@@ -0,0 +1,17 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#inspect" do
+ platform_is_not :windows do
+ it "returns sockets fd for unnamed sockets" do
+ begin
+ s1, s2 = UNIXSocket.socketpair
+ s1.inspect.should == "#<UNIXSocket:fd #{s1.fileno}>"
+ s2.inspect.should == "#<UNIXSocket:fd #{s2.fileno}>"
+ ensure
+ s1.close
+ s2.close
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/new_spec.rb b/spec/rubyspec/library/socket/unixsocket/new_spec.rb
new file mode 100644
index 0000000000..7db8613b96
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/new_spec.rb
@@ -0,0 +1,6 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXSocket.new" do
+ it_behaves_like :unixsocket_new, :new
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/open_spec.rb b/spec/rubyspec/library/socket/unixsocket/open_spec.rb
new file mode 100644
index 0000000000..eb8ffbaf22
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/open_spec.rb
@@ -0,0 +1,27 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../shared/new', __FILE__)
+
+describe "UNIXSocket.open" do
+ it_behaves_like :unixsocket_new, :open
+end
+
+describe "UNIXSocket.open" do
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
+
+ after :each do
+ @server.close
+ rm_r @path
+ end
+
+ it "opens a unix socket on the specified file and yields it to the block" do
+ UNIXSocket.send(@method, @path) do |client|
+ client.addr[0].should == "AF_UNIX"
+ client.closed?.should == false
+ end
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/pair_spec.rb b/spec/rubyspec/library/socket/unixsocket/pair_spec.rb
new file mode 100644
index 0000000000..5cd75e2906
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/pair_spec.rb
@@ -0,0 +1,39 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+describe "UNIXSocket#pair" do
+ platform_is_not :windows do
+
+ it_should_behave_like "partially closable sockets"
+
+ before :each do
+ @s1, @s2 = UNIXSocket.pair
+ end
+
+ after :each do
+ @s1.close
+ @s2.close
+ end
+
+ it "returns a pair of connected sockets" do
+ @s1.puts "foo"
+ @s2.gets.should == "foo\n"
+ end
+
+ it "returns sockets with no name" do
+ @s1.path.should == @s2.path
+ @s1.path.should == ""
+ end
+
+ it "returns sockets with no address" do
+ @s1.addr.should == ["AF_UNIX", ""]
+ @s2.addr.should == ["AF_UNIX", ""]
+ end
+
+ it "returns sockets with no peeraddr" do
+ @s1.peeraddr.should == ["AF_UNIX", ""]
+ @s2.peeraddr.should == ["AF_UNIX", ""]
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/partially_closable_spec.rb b/spec/rubyspec/library/socket/unixsocket/partially_closable_spec.rb
new file mode 100644
index 0000000000..1123a23541
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/partially_closable_spec.rb
@@ -0,0 +1,26 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
+
+platform_is_not :windows do
+ describe "UNIXSocket partial closability" do
+
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+ @server = UNIXServer.open(@path)
+ @s1 = UNIXSocket.new(@path)
+ @s2 = @server.accept
+ end
+
+ after :each do
+ @server.close
+ @s1.close
+ @s2.close
+ rm_r @path
+ end
+
+ it_should_behave_like "partially closable sockets"
+
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/path_spec.rb b/spec/rubyspec/library/socket/unixsocket/path_spec.rb
new file mode 100644
index 0000000000..a9186854da
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/path_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#path" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "returns the path of the socket if it's a server" do
+ @server.path.should == @path
+ end
+
+ it "returns an empty string for path if it's a client" do
+ @client.path.should == ""
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/peeraddr_spec.rb b/spec/rubyspec/library/socket/unixsocket/peeraddr_spec.rb
new file mode 100644
index 0000000000..cd224540ef
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/peeraddr_spec.rb
@@ -0,0 +1,30 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#peeraddr" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "returns the address familly and path of the server end of the connection" do
+ @client.peeraddr.should == ["AF_UNIX", @path]
+ end
+
+ it "raises an error in server sockets" do
+ lambda { @server.peeraddr }.should raise_error
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/recv_io_spec.rb b/spec/rubyspec/library/socket/unixsocket/recv_io_spec.rb
new file mode 100644
index 0000000000..9fc4470572
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/recv_io_spec.rb
@@ -0,0 +1,44 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#recv_io" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__)
+ @file = File.open(@send_io_path)
+ end
+
+ after :each do
+ @io.close if @io
+ @socket.close if @socket
+
+ @file.close
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "reads an IO object across the socket" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io
+
+ @io.read.should == File.read(@send_io_path)
+ end
+
+ it "takes an optional class to use" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io(File)
+
+ @io.should be_kind_of(File)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/recvfrom_spec.rb b/spec/rubyspec/library/socket/unixsocket/recvfrom_spec.rb
new file mode 100644
index 0000000000..7ac002607c
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/recvfrom_spec.rb
@@ -0,0 +1,49 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#recvfrom" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ rm_r @path
+
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "receives len bytes from sock" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ sock.recvfrom(6).first.should == "foobar"
+ sock.close
+ end
+
+ it "returns an array with data and information on the sender" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ data = sock.recvfrom(6)
+ data.first.should == "foobar"
+ data.last.should == ["AF_UNIX", ""]
+ sock.close
+ end
+
+ it "uses different message options" do
+ @client.send("foobar", Socket::MSG_PEEK)
+ sock = @server.accept
+ peek_data = sock.recvfrom(6, Socket::MSG_PEEK) # Does not retrieve the message
+ real_data = sock.recvfrom(6)
+
+ real_data.should == peek_data
+ peek_data.should == ["foobar", ["AF_UNIX", ""]]
+ sock.close
+ end
+ end
+
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/send_io_spec.rb b/spec/rubyspec/library/socket/unixsocket/send_io_spec.rb
new file mode 100644
index 0000000000..fb6ce9ba17
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/send_io_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../../../spec_helper', __FILE__)
+require File.expand_path('../../fixtures/classes', __FILE__)
+
+describe "UNIXSocket#send_io" do
+
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+
+ @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__)
+ @file = File.open(@send_io_path)
+ end
+
+ after :each do
+ @io.close if @io
+ @socket.close if @socket
+
+ @file.close
+ @client.close
+ @server.close
+ rm_r @path
+ end
+
+ it "sends the fd for an IO object across the socket" do
+ @client.send_io(@file)
+
+ @socket = @server.accept
+ @io = @socket.recv_io
+
+ @io.read.should == File.read(@send_io_path)
+ end
+ end
+end
diff --git a/spec/rubyspec/library/socket/unixsocket/shared/new.rb b/spec/rubyspec/library/socket/unixsocket/shared/new.rb
new file mode 100644
index 0000000000..9d8fb809d2
--- /dev/null
+++ b/spec/rubyspec/library/socket/unixsocket/shared/new.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../../../../../spec_helper', __FILE__)
+require File.expand_path('../../../fixtures/classes', __FILE__)
+
+describe :unixsocket_new, shared: true do
+ platform_is_not :windows do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
+
+ after :each do
+ @client.close if @client
+ @server.close
+ rm_r @path
+ end
+
+ it "opens a unix socket on the specified file" do
+ @client = UNIXSocket.send(@method, @path)
+
+ @client.addr[0].should == "AF_UNIX"
+ @client.closed?.should == false
+ end
+ end
+end