mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to ruby/spec@9be7c7e
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64180 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
aeeaadaad0
commit
b53cf149ad
246 changed files with 9108 additions and 548 deletions
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#close_read" do
|
||||
|
@ -15,13 +15,13 @@ describe "Socket::BasicSocket#close_read" do
|
|||
lambda { @server.read }.should raise_error(IOError)
|
||||
end
|
||||
|
||||
it "it works on sockets with closed ends" do
|
||||
it 'does not raise when called on a socket already closed for reading' do
|
||||
@server.close_read
|
||||
@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
|
||||
it 'does not fully close the socket' do
|
||||
@server.close_read
|
||||
@server.closed?.should be_false
|
||||
end
|
||||
|
@ -32,7 +32,7 @@ describe "Socket::BasicSocket#close_read" do
|
|||
@server.closed?.should be_true
|
||||
end
|
||||
|
||||
it "raises IOError on closed socket" do
|
||||
it 'raises IOError when called on a fully closed socket' do
|
||||
@server.close
|
||||
lambda { @server.close_read }.should raise_error(IOError)
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#close_write" do
|
||||
|
@ -15,13 +15,13 @@ describe "Socket::BasicSocket#close_write" do
|
|||
lambda { @server.write("foo") }.should raise_error(IOError)
|
||||
end
|
||||
|
||||
it "works on sockets with closed write ends" do
|
||||
it 'does not raise when called on a socket already closed for writing' do
|
||||
@server.close_write
|
||||
@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
|
||||
it 'does not fully close the socket' do
|
||||
@server.close_write
|
||||
@server.closed?.should be_false
|
||||
end
|
||||
|
@ -37,7 +37,7 @@ describe "Socket::BasicSocket#close_write" do
|
|||
@server.closed?.should be_true
|
||||
end
|
||||
|
||||
it "raises IOError on closed socket" do
|
||||
it 'raises IOError when called on a fully closed socket' do
|
||||
@server.close
|
||||
lambda { @server.close_write }.should raise_error(IOError)
|
||||
end
|
||||
|
|
150
spec/ruby/library/socket/basicsocket/connect_address_spec.rb
Normal file
150
spec/ruby/library/socket/basicsocket/connect_address_spec.rb
Normal file
|
@ -0,0 +1,150 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'Socket#connect_address' do
|
||||
describe 'using an unbound socket' do
|
||||
after do
|
||||
@sock.close
|
||||
end
|
||||
|
||||
it 'raises SocketError' do
|
||||
@sock = Socket.new(:INET, :STREAM)
|
||||
|
||||
lambda { @sock.connect_address }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a socket bound to 0.0.0.0' do
|
||||
before do
|
||||
@sock = Socket.new(:INET, :STREAM)
|
||||
@sock.bind(Socket.sockaddr_in(0, '0.0.0.0'))
|
||||
end
|
||||
|
||||
after do
|
||||
@sock.close
|
||||
end
|
||||
|
||||
it 'returns an Addrinfo' do
|
||||
@sock.connect_address.should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
it 'uses 127.0.0.1 as the IP address' do
|
||||
@sock.connect_address.ip_address.should == '127.0.0.1'
|
||||
end
|
||||
|
||||
it 'uses the correct port number' do
|
||||
@sock.connect_address.ip_port.should > 0
|
||||
end
|
||||
|
||||
it 'uses AF_INET as the address family' do
|
||||
@sock.connect_address.afamily.should == Socket::AF_INET
|
||||
end
|
||||
|
||||
it 'uses PF_INET as the address family' do
|
||||
@sock.connect_address.pfamily.should == Socket::PF_INET
|
||||
end
|
||||
|
||||
it 'uses SOCK_STREAM as the socket type' do
|
||||
@sock.connect_address.socktype.should == Socket::SOCK_STREAM
|
||||
end
|
||||
|
||||
it 'uses 0 as the protocol' do
|
||||
@sock.connect_address.protocol.should == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a socket bound to ::' do
|
||||
before do
|
||||
@sock = Socket.new(:INET6, :STREAM)
|
||||
@sock.bind(Socket.sockaddr_in(0, '::'))
|
||||
end
|
||||
|
||||
after do
|
||||
@sock.close
|
||||
end
|
||||
|
||||
it 'returns an Addrinfo' do
|
||||
@sock.connect_address.should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
it 'uses ::1 as the IP address' do
|
||||
@sock.connect_address.ip_address.should == '::1'
|
||||
end
|
||||
|
||||
it 'uses the correct port number' do
|
||||
@sock.connect_address.ip_port.should > 0
|
||||
end
|
||||
|
||||
it 'uses AF_INET6 as the address family' do
|
||||
@sock.connect_address.afamily.should == Socket::AF_INET6
|
||||
end
|
||||
|
||||
it 'uses PF_INET6 as the address family' do
|
||||
@sock.connect_address.pfamily.should == Socket::PF_INET6
|
||||
end
|
||||
|
||||
it 'uses SOCK_STREAM as the socket type' do
|
||||
@sock.connect_address.socktype.should == Socket::SOCK_STREAM
|
||||
end
|
||||
|
||||
it 'uses 0 as the protocol' do
|
||||
@sock.connect_address.protocol.should == 0
|
||||
end
|
||||
end
|
||||
|
||||
with_feature :unix_socket do
|
||||
describe 'using an unbound UNIX socket' do
|
||||
before do
|
||||
@path = SocketSpecs.socket_path
|
||||
@server = UNIXServer.new(@path)
|
||||
@client = UNIXSocket.new(@path)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
rm_r(@path)
|
||||
end
|
||||
|
||||
it 'raises SocketError' do
|
||||
lambda { @client.connect_address }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a bound UNIX socket' do
|
||||
before do
|
||||
@path = SocketSpecs.socket_path
|
||||
@sock = UNIXServer.new(@path)
|
||||
end
|
||||
|
||||
after do
|
||||
@sock.close
|
||||
rm_r(@path)
|
||||
end
|
||||
|
||||
it 'returns an Addrinfo' do
|
||||
@sock.connect_address.should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
it 'uses the correct socket path' do
|
||||
@sock.connect_address.unix_path.should == @path
|
||||
end
|
||||
|
||||
it 'uses AF_UNIX as the address family' do
|
||||
@sock.connect_address.afamily.should == Socket::AF_UNIX
|
||||
end
|
||||
|
||||
it 'uses PF_UNIX as the protocol family' do
|
||||
@sock.connect_address.pfamily.should == Socket::PF_UNIX
|
||||
end
|
||||
|
||||
it 'uses SOCK_STREAM as the socket type' do
|
||||
@sock.connect_address.socktype.should == Socket::SOCK_STREAM
|
||||
end
|
||||
|
||||
it 'uses 0 as the protocol' do
|
||||
@sock.connect_address.protocol.should == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket.do_not_reverse_lookup" do
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
|
||||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket#for_fd" do
|
||||
describe "BasicSocket.for_fd" do
|
||||
before :each do
|
||||
@server = TCPServer.new(0)
|
||||
@s2 = nil
|
||||
end
|
||||
|
||||
after :each do
|
||||
@socket1.close if @socket1
|
||||
@server.close if @server
|
||||
end
|
||||
|
||||
|
@ -18,4 +18,21 @@ describe "BasicSocket#for_fd" do
|
|||
@s2.should be_kind_of(TCPServer)
|
||||
@s2.fileno.should == @server.fileno
|
||||
end
|
||||
|
||||
it 'returns a new socket for a file descriptor' do
|
||||
@socket1 = Socket.new(:INET, :DGRAM)
|
||||
socket2 = Socket.for_fd(@socket1.fileno)
|
||||
socket2.autoclose = false
|
||||
|
||||
socket2.should be_an_instance_of(Socket)
|
||||
socket2.fileno.should == @socket1.fileno
|
||||
end
|
||||
|
||||
it 'sets the socket into binary mode' do
|
||||
@socket1 = Socket.new(:INET, :DGRAM)
|
||||
socket2 = Socket.for_fd(@socket1.fileno)
|
||||
socket2.autoclose = false
|
||||
|
||||
socket2.binmode?.should be_true
|
||||
end
|
||||
end
|
||||
|
|
36
spec/ruby/library/socket/basicsocket/getpeereid_spec.rb
Normal file
36
spec/ruby/library/socket/basicsocket/getpeereid_spec.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'BasicSocket#getpeereid' do
|
||||
with_feature :unix_socket do
|
||||
describe 'using a UNIXSocket' do
|
||||
before do
|
||||
@path = SocketSpecs.socket_path
|
||||
@server = UNIXServer.new(@path)
|
||||
@client = UNIXSocket.new(@path)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
|
||||
rm_r(@path)
|
||||
end
|
||||
|
||||
it 'returns an Array with the user and group ID' do
|
||||
@client.getpeereid.should == [Process.euid, Process.egid]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using an IPSocket' do
|
||||
after do
|
||||
@sock.close
|
||||
end
|
||||
|
||||
it 'raises NoMethodError' do
|
||||
@sock = TCPServer.new('127.0.0.1', 0)
|
||||
lambda { @sock.getpeereid }.should raise_error(NoMethodError)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#getpeername" do
|
||||
|
@ -19,8 +19,7 @@ describe "Socket::BasicSocket#getpeername" do
|
|||
@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)
|
||||
it 'raises Errno::ENOTCONN for a disconnected socket' do
|
||||
lambda { @server.getpeername }.should raise_error(Errno::ENOTCONN)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#getsockname" do
|
||||
|
@ -20,7 +20,7 @@ describe "Socket::BasicSocket#getsockname" do
|
|||
sockaddr[0].should == @socket.addr[1]
|
||||
end
|
||||
|
||||
it "returns empty sockaddr for unbinded sockets" do
|
||||
it 'returns a default socket address for a disconnected socket' 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"]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket#getsockopt" do
|
||||
|
@ -43,4 +43,146 @@ describe "BasicSocket#getsockopt" do
|
|||
it "raises a SystemCallError with an invalid socket option" do
|
||||
lambda { @sock.getsockopt Socket::SOL_SOCKET, -1 }.should raise_error(Errno::ENOPROTOOPT)
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option using a constant' do
|
||||
opt = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_TYPE)
|
||||
|
||||
opt.should be_an_instance_of(Socket::Option)
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for a boolean option' do
|
||||
opt = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR)
|
||||
|
||||
opt.bool.should == false
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for a numeric option' do
|
||||
opt = @sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL)
|
||||
|
||||
opt.int.should be_an_instance_of(Fixnum)
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for a struct option' do
|
||||
opt = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER)
|
||||
|
||||
opt.linger.should == [false, 0]
|
||||
end
|
||||
|
||||
it 'raises Errno::ENOPROTOOPT when requesting an invalid option' do
|
||||
lambda { @sock.getsockopt(Socket::SOL_SOCKET, -1) }.should raise_error(Errno::ENOPROTOOPT)
|
||||
end
|
||||
|
||||
describe 'using Symbols as arguments' do
|
||||
it 'returns a Socket::Option for arguments :SOCKET and :TYPE' do
|
||||
opt = @sock.getsockopt(:SOCKET, :TYPE)
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_TYPE
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments :IP and :TTL' do
|
||||
opt = @sock.getsockopt(:IP, :TTL)
|
||||
|
||||
opt.level.should == Socket::IPPROTO_IP
|
||||
opt.optname.should == Socket::IP_TTL
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments :SOCKET and :REUSEADDR' do
|
||||
opt = @sock.getsockopt(:SOCKET, :REUSEADDR)
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_REUSEADDR
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments :SOCKET and :LINGER' do
|
||||
opt = @sock.getsockopt(:SOCKET, :LINGER)
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_LINGER
|
||||
end
|
||||
|
||||
with_feature :udp_cork do
|
||||
it 'returns a Socket::Option for arguments :UDP and :CORK' do
|
||||
sock = Socket.new(:INET, :DGRAM)
|
||||
begin
|
||||
opt = sock.getsockopt(:UDP, :CORK)
|
||||
|
||||
opt.level.should == Socket::IPPROTO_UDP
|
||||
opt.optname.should == Socket::UDP_CORK
|
||||
ensure
|
||||
sock.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using Strings as arguments' do
|
||||
it 'returns a Socket::Option for arguments "SOCKET" and "TYPE"' do
|
||||
opt = @sock.getsockopt("SOCKET", "TYPE")
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_TYPE
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments "IP" and "TTL"' do
|
||||
opt = @sock.getsockopt("IP", "TTL")
|
||||
|
||||
opt.level.should == Socket::IPPROTO_IP
|
||||
opt.optname.should == Socket::IP_TTL
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments "SOCKET" and "REUSEADDR"' do
|
||||
opt = @sock.getsockopt("SOCKET", "REUSEADDR")
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_REUSEADDR
|
||||
end
|
||||
|
||||
it 'returns a Socket::Option for arguments "SOCKET" and "LINGER"' do
|
||||
opt = @sock.getsockopt("SOCKET", "LINGER")
|
||||
|
||||
opt.level.should == Socket::SOL_SOCKET
|
||||
opt.optname.should == Socket::SO_LINGER
|
||||
end
|
||||
|
||||
with_feature :udp_cork do
|
||||
it 'returns a Socket::Option for arguments "UDP" and "CORK"' do
|
||||
sock = Socket.new("INET", "DGRAM")
|
||||
begin
|
||||
opt = sock.getsockopt("UDP", "CORK")
|
||||
|
||||
opt.level.should == Socket::IPPROTO_UDP
|
||||
opt.optname.should == Socket::UDP_CORK
|
||||
ensure
|
||||
sock.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a String based option' do
|
||||
it 'allows unpacking of a boolean option' do
|
||||
opt = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR).to_s
|
||||
|
||||
opt.unpack('i').should == [0]
|
||||
end
|
||||
|
||||
it 'allows unpacking of a numeric option' do
|
||||
opt = @sock.getsockopt(Socket::IPPROTO_IP, Socket::IP_TTL).to_s
|
||||
array = opt.unpack('i')
|
||||
|
||||
array[0].should be_an_instance_of(Fixnum)
|
||||
array[0].should > 0
|
||||
end
|
||||
|
||||
it 'allows unpacking of a struct option' do
|
||||
opt = @sock.getsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER).to_s
|
||||
|
||||
if opt.bytesize == 8
|
||||
opt.unpack('ii').should == [0, 0]
|
||||
else
|
||||
opt.unpack('i').should == [0]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require 'socket'
|
||||
require_relative '../spec_helper'
|
||||
|
||||
describe "Socket::BasicSocket#ioctl" do
|
||||
platform_is :linux do
|
||||
|
|
|
@ -1,7 +1,65 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../shared/recv_nonblock'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#recv_nonblock" do
|
||||
it_behaves_like :socket_recv_nonblock, :recv_nonblock
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
before :each do
|
||||
@s1 = Socket.new(family, :DGRAM)
|
||||
@s2 = Socket.new(family, :DGRAM)
|
||||
end
|
||||
|
||||
after :each do
|
||||
@s1.close unless @s1.closed?
|
||||
@s2.close unless @s2.closed?
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using an unbound socket' do
|
||||
it 'raises an exception extending IO::WaitReadable' do
|
||||
lambda { @s1.recv_nonblock(1) }.should raise_error(IO::WaitReadable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "raises an exception extending IO::WaitReadable if there's no data available" do
|
||||
@s1.bind(Socket.pack_sockaddr_in(0, ip_address))
|
||||
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(0, ip_address))
|
||||
@s2.send("aaa", 0, @s1.getsockname)
|
||||
IO.select([@s1], nil, nil, 2)
|
||||
@s1.recv_nonblock(5).should == "aaa"
|
||||
end
|
||||
|
||||
it "allows an output buffer as third argument" do
|
||||
@s1.bind(Socket.pack_sockaddr_in(0, ip_address))
|
||||
@s2.send("data", 0, @s1.getsockname)
|
||||
IO.select([@s1], nil, nil, 2)
|
||||
|
||||
buf = "foo"
|
||||
@s1.recv_nonblock(5, 0, buf)
|
||||
buf.should == "data"
|
||||
end
|
||||
|
||||
it "does not block if there's no data available" do
|
||||
@s1.bind(Socket.pack_sockaddr_in(0, ip_address))
|
||||
@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
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# -*- encoding: binary -*-
|
||||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket#recv" do
|
||||
|
@ -92,3 +92,68 @@ describe "BasicSocket#recv" do
|
|||
socket.close
|
||||
end
|
||||
end
|
||||
|
||||
describe 'BasicSocket#recv' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
before do
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'using an unbound socket' do
|
||||
it 'blocks the caller' do
|
||||
lambda { @server.recv(4) }.should block_caller
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a bound socket' do
|
||||
before do
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
describe 'without any data available' do
|
||||
it 'blocks the caller' do
|
||||
lambda { @server.recv(4) }.should block_caller
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with data available' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
it 'reads the given amount of bytes' do
|
||||
@client.write('hello')
|
||||
|
||||
@server.recv(2).should == 'he'
|
||||
end
|
||||
|
||||
it 'reads the given amount of bytes when it exceeds the data size' do
|
||||
@client.write('he')
|
||||
|
||||
@server.recv(6).should == 'he'
|
||||
end
|
||||
|
||||
it 'blocks the caller when called twice without new data being available' do
|
||||
@client.write('hello')
|
||||
|
||||
@server.recv(2).should == 'he'
|
||||
|
||||
lambda { @server.recv(4) }.should block_caller
|
||||
end
|
||||
|
||||
it 'takes a peek at the data when using the MSG_PEEK flag' do
|
||||
@client.write('hello')
|
||||
|
||||
@server.recv(2, Socket::MSG_PEEK).should == 'he'
|
||||
@server.recv(2).should == 'he'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
204
spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb
Normal file
204
spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb
Normal file
|
@ -0,0 +1,204 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'BasicSocket#recvmsg_nonblock' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
describe 'using a disconnected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using an unbound socket' do
|
||||
it 'raises an exception extending IO::WaitReadable' do
|
||||
lambda { @server.recvmsg_nonblock }.should raise_error(IO::WaitReadable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a bound socket' do
|
||||
before do
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
describe 'without any data available' do
|
||||
it 'raises an exception extending IO::WaitReadable' do
|
||||
lambda { @server.recvmsg_nonblock }.should raise_error(IO::WaitReadable)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with data available' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
|
||||
@client.write('hello')
|
||||
|
||||
IO.select([@server], nil, nil, 5)
|
||||
end
|
||||
|
||||
it 'returns an Array containing the data, an Addrinfo and the flags' do
|
||||
@server.recvmsg_nonblock.should be_an_instance_of(Array)
|
||||
end
|
||||
|
||||
describe 'without a maximum message length' do
|
||||
it 'reads all the available data' do
|
||||
@server.recvmsg_nonblock[0].should == 'hello'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a maximum message length' do
|
||||
platform_is_not :windows do
|
||||
it 'reads up to the maximum amount of bytes' do
|
||||
@server.recvmsg_nonblock(2)[0].should == 'he'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the returned Array' do
|
||||
before do
|
||||
@array = @server.recvmsg_nonblock
|
||||
end
|
||||
|
||||
it 'stores the message at index 0' do
|
||||
@array[0].should == 'hello'
|
||||
end
|
||||
|
||||
it 'stores an Addrinfo at index 1' do
|
||||
@array[1].should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
it 'stores the flags at index 2' do
|
||||
@array[2].should be_an_instance_of(Fixnum)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the returned Addrinfo' do
|
||||
before do
|
||||
@addr = @array[1]
|
||||
end
|
||||
|
||||
it 'uses the IP address of the client' do
|
||||
@addr.ip_address.should == @client.local_address.ip_address
|
||||
end
|
||||
|
||||
it 'uses the correct address family' do
|
||||
@addr.afamily.should == family
|
||||
end
|
||||
|
||||
it 'uses the correct protocol family' do
|
||||
@addr.pfamily.should == family
|
||||
end
|
||||
|
||||
it 'uses the correct socket type' do
|
||||
@addr.socktype.should == Socket::SOCK_DGRAM
|
||||
end
|
||||
|
||||
it 'uses the port number of the client' do
|
||||
@addr.ip_port.should == @client.local_address.ip_port
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using a connected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :STREAM)
|
||||
@server = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without any data available' do
|
||||
it 'raises IO::WaitReadable' do
|
||||
lambda {
|
||||
socket, _ = @server.accept
|
||||
begin
|
||||
socket.recvmsg_nonblock
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
}.should raise_error(IO::WaitReadable)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with data available' do
|
||||
before do
|
||||
@client.write('hello')
|
||||
|
||||
@socket, _ = @server.accept
|
||||
end
|
||||
|
||||
after do
|
||||
@socket.close
|
||||
end
|
||||
|
||||
it 'returns an Array containing the data, an Addrinfo and the flags' do
|
||||
@socket.recvmsg_nonblock.should be_an_instance_of(Array)
|
||||
end
|
||||
|
||||
describe 'the returned Array' do
|
||||
before do
|
||||
@array = @socket.recvmsg_nonblock
|
||||
end
|
||||
|
||||
it 'stores the message at index 0' do
|
||||
@array[0].should == 'hello'
|
||||
end
|
||||
|
||||
it 'stores an Addrinfo at index 1' do
|
||||
@array[1].should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
it 'stores the flags at index 2' do
|
||||
@array[2].should be_an_instance_of(Fixnum)
|
||||
end
|
||||
|
||||
describe 'the returned Addrinfo' do
|
||||
before do
|
||||
@addr = @array[1]
|
||||
end
|
||||
|
||||
it 'raises when receiving the ip_address message' do
|
||||
lambda { @addr.ip_address }.should raise_error(SocketError)
|
||||
end
|
||||
|
||||
it 'uses the correct address family' do
|
||||
@addr.afamily.should == Socket::AF_UNSPEC
|
||||
end
|
||||
|
||||
it 'uses 0 for the protocol family' do
|
||||
@addr.pfamily.should == 0
|
||||
end
|
||||
|
||||
it 'uses the correct socket type' do
|
||||
@addr.socktype.should == Socket::SOCK_STREAM
|
||||
end
|
||||
|
||||
it 'raises when receiving the ip_port message' do
|
||||
lambda { @addr.ip_port }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
197
spec/ruby/library/socket/basicsocket/recvmsg_spec.rb
Normal file
197
spec/ruby/library/socket/basicsocket/recvmsg_spec.rb
Normal file
|
@ -0,0 +1,197 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'BasicSocket#recvmsg' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
describe 'using a disconnected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using an unbound socket' do
|
||||
it 'blocks the caller' do
|
||||
lambda { @server.recvmsg }.should block_caller
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a bound socket' do
|
||||
before do
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
describe 'without any data available' do
|
||||
it 'blocks the caller' do
|
||||
lambda { @server.recvmsg }.should block_caller
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with data available' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
|
||||
@client.write('hello')
|
||||
end
|
||||
|
||||
it 'returns an Array containing the data, an Addrinfo and the flags' do
|
||||
@server.recvmsg.should be_an_instance_of(Array)
|
||||
end
|
||||
|
||||
describe 'without a maximum message length' do
|
||||
it 'reads all the available data' do
|
||||
@server.recvmsg[0].should == 'hello'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a maximum message length' do
|
||||
it 'reads up to the maximum amount of bytes' do
|
||||
@server.recvmsg(2)[0].should == 'he'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the returned Array' do
|
||||
before do
|
||||
@array = @server.recvmsg
|
||||
end
|
||||
|
||||
it 'stores the message at index 0' do
|
||||
@array[0].should == 'hello'
|
||||
end
|
||||
|
||||
it 'stores an Addrinfo at index 1' do
|
||||
@array[1].should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
it 'stores the flags at index 2' do
|
||||
@array[2].should be_an_instance_of(Fixnum)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'the returned Addrinfo' do
|
||||
before do
|
||||
@addr = @array[1]
|
||||
end
|
||||
|
||||
it 'uses the IP address of the client' do
|
||||
@addr.ip_address.should == @client.local_address.ip_address
|
||||
end
|
||||
|
||||
it 'uses the correct address family' do
|
||||
@addr.afamily.should == family
|
||||
end
|
||||
|
||||
it 'uses the correct protocol family' do
|
||||
@addr.pfamily.should == family
|
||||
end
|
||||
|
||||
it 'uses the correct socket type' do
|
||||
@addr.socktype.should == Socket::SOCK_DGRAM
|
||||
end
|
||||
|
||||
it 'uses the port number of the client' do
|
||||
@addr.ip_port.should == @client.local_address.ip_port
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using a connected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :STREAM)
|
||||
@server = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without any data available' do
|
||||
it 'blocks the caller' do
|
||||
socket, _ = @server.accept
|
||||
begin
|
||||
lambda { socket.recvmsg }.should block_caller
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with data available' do
|
||||
before do
|
||||
@client.write('hello')
|
||||
@socket, _ = @server.accept
|
||||
end
|
||||
|
||||
after do
|
||||
@socket.close
|
||||
end
|
||||
|
||||
it 'returns an Array containing the data, an Addrinfo and the flags' do
|
||||
@socket.recvmsg.should be_an_instance_of(Array)
|
||||
end
|
||||
|
||||
describe 'the returned Array' do
|
||||
before do
|
||||
@array = @socket.recvmsg
|
||||
end
|
||||
|
||||
it 'stores the message at index 0' do
|
||||
@array[0].should == 'hello'
|
||||
end
|
||||
|
||||
it 'stores an Addrinfo at index 1' do
|
||||
@array[1].should be_an_instance_of(Addrinfo)
|
||||
end
|
||||
|
||||
it 'stores the flags at index 2' do
|
||||
@array[2].should be_an_instance_of(Fixnum)
|
||||
end
|
||||
|
||||
describe 'the returned Addrinfo' do
|
||||
before do
|
||||
@addr = @array[1]
|
||||
end
|
||||
|
||||
it 'raises when receiving the ip_address message' do
|
||||
lambda { @addr.ip_address }.should raise_error(SocketError)
|
||||
end
|
||||
|
||||
it 'uses the correct address family' do
|
||||
@addr.afamily.should == Socket::AF_UNSPEC
|
||||
end
|
||||
|
||||
it 'returns 0 for the protocol family' do
|
||||
@addr.pfamily.should == 0
|
||||
end
|
||||
|
||||
it 'uses the correct socket type' do
|
||||
@addr.socktype.should == Socket::SOCK_STREAM
|
||||
end
|
||||
|
||||
it 'raises when receiving the ip_port message' do
|
||||
lambda { @addr.ip_port }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket#send" do
|
||||
|
@ -83,3 +83,132 @@ describe "BasicSocket#send" do
|
|||
data.should == 'hello'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'BasicSocket#send' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
describe 'using a disconnected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without a destination address' do
|
||||
it "raises #{SocketSpecs.dest_addr_req_error}" do
|
||||
lambda { @client.send('hello', 0) }.should raise_error(SocketSpecs.dest_addr_req_error)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as a String' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.send('hello', 0, @server.getsockname).should == 5
|
||||
end
|
||||
|
||||
it 'does not persist the connection after writing to the socket' do
|
||||
@client.send('hello', 0, @server.getsockname)
|
||||
|
||||
lambda { @client.send('hello', 0) }.should raise_error(SocketSpecs.dest_addr_req_error)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as an Addrinfo' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.send('hello', 0, @server.connect_address).should == 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a connected UDP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without a destination address argument' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
it 'returns the amount of bytes written' do
|
||||
@client.send('hello', 0).should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address argument' do
|
||||
before do
|
||||
@alt_server = Socket.new(family, :DGRAM)
|
||||
|
||||
@alt_server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@alt_server.close
|
||||
end
|
||||
|
||||
it 'sends the message to the given address instead' do
|
||||
@client.send('hello', 0, @alt_server.getsockname).should == 5
|
||||
|
||||
lambda { @server.recv(5) }.should block_caller
|
||||
|
||||
@alt_server.recv(5).should == 'hello'
|
||||
end
|
||||
|
||||
it 'does not persist the alternative connection after writing to the socket' do
|
||||
@client.send('hello', 0, @alt_server.getsockname)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
@client.send('world', 0)
|
||||
|
||||
@server.recv(5).should == 'world'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using a connected TCP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :STREAM)
|
||||
@server = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'using the MSG_OOB flag' do
|
||||
it 'sends an out-of-band message' do
|
||||
@server.setsockopt(:SOCKET, :OOBINLINE, true)
|
||||
|
||||
@client.send('a', Socket::MSG_OOB).should == 1
|
||||
|
||||
socket, _ = @server.accept
|
||||
begin
|
||||
socket.recv(1, Socket::MSG_OOB).should == 'a'
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
104
spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb
Normal file
104
spec/ruby/library/socket/basicsocket/sendmsg_nonblock_spec.rb
Normal file
|
@ -0,0 +1,104 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'BasicSocket#sendmsg_nonblock' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
describe 'using a disconnected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without a destination address' do
|
||||
it "raises #{SocketSpecs.dest_addr_req_error}" do
|
||||
lambda { @client.sendmsg_nonblock('hello') }.should raise_error(SocketSpecs.dest_addr_req_error)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as a String' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.sendmsg_nonblock('hello', 0, @server.getsockname).should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as an Addrinfo' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.sendmsg_nonblock('hello', 0, @server.connect_address).should == 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a connected UDP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without a destination address argument' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
it 'returns the amount of bytes written' do
|
||||
@client.sendmsg_nonblock('hello').should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address argument' do
|
||||
before do
|
||||
@alt_server = Socket.new(family, :DGRAM)
|
||||
@alt_server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@alt_server.close
|
||||
end
|
||||
|
||||
it 'sends the message to the given address instead' do
|
||||
@client.sendmsg_nonblock('hello', 0, @alt_server.getsockname).should == 5
|
||||
lambda { @server.recv(5) }.should block_caller
|
||||
@alt_server.recv(5).should == 'hello'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'using a connected TCP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :STREAM)
|
||||
@server = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
it 'raises IO::WaitWritable when the underlying buffer is full' do
|
||||
lambda {
|
||||
10.times { @client.sendmsg_nonblock('hello' * 1_000_000) }
|
||||
}.should raise_error(IO::WaitWritable)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
111
spec/ruby/library/socket/basicsocket/sendmsg_spec.rb
Normal file
111
spec/ruby/library/socket/basicsocket/sendmsg_spec.rb
Normal file
|
@ -0,0 +1,111 @@
|
|||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe 'BasicSocket#sendmsg' do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
describe 'using a disconnected socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
describe 'without a destination address' do
|
||||
it "raises #{SocketSpecs.dest_addr_req_error}" do
|
||||
lambda { @client.sendmsg('hello') }.should raise_error(SocketSpecs.dest_addr_req_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as a String' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.sendmsg('hello', 0, @server.getsockname).should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address as an Addrinfo' do
|
||||
it 'returns the amount of sent bytes' do
|
||||
@client.sendmsg('hello', 0, @server.connect_address).should == 5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a connected UDP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :DGRAM)
|
||||
@server = Socket.new(family, :DGRAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'without a destination address argument' do
|
||||
before do
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
it 'returns the amount of bytes written' do
|
||||
@client.sendmsg('hello').should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with a destination address argument' do
|
||||
before do
|
||||
@alt_server = Socket.new(family, :DGRAM)
|
||||
|
||||
@alt_server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
end
|
||||
|
||||
after do
|
||||
@alt_server.close
|
||||
end
|
||||
|
||||
it 'sends the message to the given address instead' do
|
||||
@client.sendmsg('hello', 0, @alt_server.getsockname).should == 5
|
||||
|
||||
lambda { @server.recv(5) }.should block_caller
|
||||
|
||||
@alt_server.recv(5).should == 'hello'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do # spurious
|
||||
describe 'using a connected TCP socket' do
|
||||
before do
|
||||
@client = Socket.new(family, :STREAM)
|
||||
@server = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
it 'blocks when the underlying buffer is full' do
|
||||
# Buffer sizes may differ per platform, so sadly this is the only
|
||||
# reliable way of testing blocking behaviour.
|
||||
lambda do
|
||||
10.times { @client.sendmsg('hello' * 1_000_000) }
|
||||
end.should block_caller
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "BasicSocket#setsockopt" do
|
||||
|
@ -211,3 +211,124 @@ describe "BasicSocket#setsockopt" do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'BasicSocket#setsockopt' do
|
||||
describe 'using a STREAM socket' do
|
||||
before do
|
||||
@socket = Socket.new(:INET, :STREAM)
|
||||
end
|
||||
|
||||
after do
|
||||
@socket.close
|
||||
end
|
||||
|
||||
describe 'using separate arguments with Symbols' do
|
||||
it 'raises TypeError when the first argument is nil' do
|
||||
lambda { @socket.setsockopt(nil, :REUSEADDR, true) }.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it 'sets a boolean option' do
|
||||
@socket.setsockopt(:SOCKET, :REUSEADDR, true).should == 0
|
||||
@socket.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
|
||||
end
|
||||
|
||||
it 'sets an integer option' do
|
||||
@socket.setsockopt(:IP, :TTL, 255).should == 0
|
||||
@socket.getsockopt(:IP, :TTL).int.should == 255
|
||||
end
|
||||
|
||||
it 'sets an IPv6 boolean option' do
|
||||
socket = Socket.new(:INET6, :STREAM)
|
||||
begin
|
||||
socket.setsockopt(:IPV6, :V6ONLY, true).should == 0
|
||||
socket.getsockopt(:IPV6, :V6ONLY).bool.should == true
|
||||
ensure
|
||||
socket.close
|
||||
end
|
||||
end
|
||||
|
||||
platform_is_not :windows do
|
||||
it 'raises Errno::EINVAL when setting an invalid option value' do
|
||||
lambda { @socket.setsockopt(:SOCKET, :OOBINLINE, 'bla') }.should raise_error(Errno::EINVAL)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using separate arguments with Symbols' do
|
||||
it 'sets a boolean option' do
|
||||
@socket.setsockopt('SOCKET', 'REUSEADDR', true).should == 0
|
||||
@socket.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
|
||||
end
|
||||
|
||||
it 'sets an integer option' do
|
||||
@socket.setsockopt('IP', 'TTL', 255).should == 0
|
||||
@socket.getsockopt(:IP, :TTL).int.should == 255
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using separate arguments with constants' do
|
||||
it 'sets a boolean option' do
|
||||
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true).should == 0
|
||||
@socket.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
|
||||
end
|
||||
|
||||
it 'sets an integer option' do
|
||||
@socket.setsockopt(Socket::IPPROTO_IP, Socket::IP_TTL, 255).should == 0
|
||||
@socket.getsockopt(:IP, :TTL).int.should == 255
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using separate arguments with custom objects' do
|
||||
it 'sets a boolean option' do
|
||||
level = mock(:level)
|
||||
name = mock(:name)
|
||||
|
||||
level.stub!(:to_str).and_return('SOCKET')
|
||||
name.stub!(:to_str).and_return('REUSEADDR')
|
||||
|
||||
@socket.setsockopt(level, name, true).should == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a Socket::Option as the first argument' do
|
||||
it 'sets a boolean option' do
|
||||
@socket.setsockopt(Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)).should == 0
|
||||
@socket.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
|
||||
end
|
||||
|
||||
it 'sets an integer option' do
|
||||
@socket.setsockopt(Socket::Option.int(:INET, :IP, :TTL, 255)).should == 0
|
||||
@socket.getsockopt(:IP, :TTL).int.should == 255
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when passing 2 arguments' do
|
||||
option = Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)
|
||||
lambda { @socket.setsockopt(option, :REUSEADDR) }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'raises TypeError when passing 3 arguments' do
|
||||
option = Socket::Option.bool(:INET, :SOCKET, :REUSEADDR, true)
|
||||
lambda { @socket.setsockopt(option, :REUSEADDR, true) }.should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
with_feature :unix_socket do
|
||||
describe 'using a UNIX socket' do
|
||||
before do
|
||||
@path = SocketSpecs.socket_path
|
||||
@server = UNIXServer.new(@path)
|
||||
end
|
||||
|
||||
after do
|
||||
@server.close
|
||||
rm_r @path
|
||||
end
|
||||
|
||||
it 'sets a boolean option' do
|
||||
@server.setsockopt(:SOCKET, :REUSEADDR, true)
|
||||
@server.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,155 @@
|
|||
require_relative '../../../spec_helper'
|
||||
require_relative '../spec_helper'
|
||||
require_relative '../fixtures/classes'
|
||||
|
||||
describe "Socket::BasicSocket#shutdown" do
|
||||
platform_is_not :windows do # hangs
|
||||
describe "Socket::BasicSocket#shutdown" do
|
||||
SocketSpecs.each_ip_protocol do |family, ip_address|
|
||||
before do
|
||||
@server = Socket.new(family, :STREAM)
|
||||
@client = Socket.new(family, :STREAM)
|
||||
|
||||
@server.bind(Socket.sockaddr_in(0, ip_address))
|
||||
@server.listen(1)
|
||||
|
||||
@client.connect(@server.getsockname)
|
||||
end
|
||||
|
||||
after do
|
||||
@client.close
|
||||
@server.close
|
||||
end
|
||||
|
||||
describe 'using a Fixnum' do
|
||||
it 'shuts down a socket for reading' do
|
||||
@client.shutdown(Socket::SHUT_RD)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for writing' do
|
||||
@client.shutdown(Socket::SHUT_WR)
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading and writing' do
|
||||
@client.shutdown(Socket::SHUT_RDWR)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when using an invalid option' do
|
||||
lambda { @server.shutdown(666) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a Symbol' do
|
||||
it 'shuts down a socket for reading using :RD' do
|
||||
@client.shutdown(:RD)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading using :SHUT_RD' do
|
||||
@client.shutdown(:SHUT_RD)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for writing using :WR' do
|
||||
@client.shutdown(:WR)
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'shuts down a socket for writing using :SHUT_WR' do
|
||||
@client.shutdown(:SHUT_WR)
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading and writing' do
|
||||
@client.shutdown(:RDWR)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when using an invalid option' do
|
||||
lambda { @server.shutdown(:Nope) }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using a String' do
|
||||
it 'shuts down a socket for reading using "RD"' do
|
||||
@client.shutdown('RD')
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading using "SHUT_RD"' do
|
||||
@client.shutdown('SHUT_RD')
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for writing using "WR"' do
|
||||
@client.shutdown('WR')
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'shuts down a socket for writing using "SHUT_WR"' do
|
||||
@client.shutdown('SHUT_WR')
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
|
||||
it 'raises ArgumentError when using an invalid option' do
|
||||
lambda { @server.shutdown('Nope') }.should raise_error(SocketError)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using an object that responds to #to_str' do
|
||||
before do
|
||||
@dummy = mock(:dummy)
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading using "RD"' do
|
||||
@dummy.stub!(:to_str).and_return('RD')
|
||||
|
||||
@client.shutdown(@dummy)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading using "SHUT_RD"' do
|
||||
@dummy.stub!(:to_str).and_return('SHUT_RD')
|
||||
|
||||
@client.shutdown(@dummy)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
end
|
||||
|
||||
it 'shuts down a socket for reading and writing' do
|
||||
@dummy.stub!(:to_str).and_return('RDWR')
|
||||
|
||||
@client.shutdown(@dummy)
|
||||
|
||||
@client.recv(1).should be_empty
|
||||
|
||||
lambda { @client.write('hello') }.should raise_error(Errno::EPIPE)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'using an object that does not respond to #to_str' do
|
||||
it 'raises TypeError' do
|
||||
lambda { @server.shutdown(mock(:dummy)) }.should raise_error(TypeError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue