diff options
Diffstat (limited to 'spec/ruby/library/socket/udpsocket')
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/bind_spec.rb | 55 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/connect_spec.rb | 35 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/initialize_spec.rb | 53 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/local_address_spec.rb | 80 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/new_spec.rb | 22 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/open_spec.rb | 4 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb | 111 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/remote_address_spec.rb | 79 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/send_spec.rb | 92 | ||||
| -rw-r--r-- | spec/ruby/library/socket/udpsocket/write_spec.rb | 6 |
10 files changed, 509 insertions, 28 deletions
diff --git a/spec/ruby/library/socket/udpsocket/bind_spec.rb b/spec/ruby/library/socket/udpsocket/bind_spec.rb index be62608e1b..974e701e71 100644 --- a/spec/ruby/library/socket/udpsocket/bind_spec.rb +++ b/spec/ruby/library/socket/udpsocket/bind_spec.rb @@ -1,8 +1,7 @@ -require_relative '../../../spec_helper' +require_relative '../spec_helper' require_relative '../fixtures/classes' -describe "UDPSocket.bind" do - +describe "UDPSocket#bind" do before :each do @socket = UDPSocket.new end @@ -13,15 +12,15 @@ describe "UDPSocket.bind" do it "binds the socket to a port" do @socket.bind(SocketSpecs.hostname, 0) - @socket.addr[1].should be_kind_of(Integer) + @socket.addr[1].should.is_a?(Integer) end it "raises Errno::EINVAL when already bound" do @socket.bind(SocketSpecs.hostname, 0) - lambda { + -> { @socket.bind(SocketSpecs.hostname, @socket.addr[1]) - }.should raise_error(Errno::EINVAL) + }.should.raise(Errno::EINVAL) end it "receives a hostname and a port" do @@ -34,9 +33,51 @@ describe "UDPSocket.bind" do end it "binds to INADDR_ANY if the hostname is empty" do - @socket.bind("", 0) + @socket.bind("", 0).should == 0 port, host = Socket.unpack_sockaddr_in(@socket.getsockname) host.should == "0.0.0.0" port.should == @socket.addr[1] end end + +describe 'UDPSocket#bind' do + SocketSpecs.each_ip_protocol do |family, ip_address| + before do + @socket = UDPSocket.new(family) + end + + after do + @socket.close + end + + it 'binds to an address and port' do + @socket.bind(ip_address, 0).should == 0 + + @socket.local_address.ip_address.should == ip_address + @socket.local_address.ip_port.should > 0 + end + + it 'binds to an address and port using String arguments' do + @socket.bind(ip_address, '0').should == 0 + + @socket.local_address.ip_address.should == ip_address + @socket.local_address.ip_port.should > 0 + end + + it 'can receive data after being bound to an address' do + @socket.bind(ip_address, 0) + + addr = @socket.connect_address + client = UDPSocket.new(family) + + client.connect(addr.ip_address, addr.ip_port) + client.write('hello') + + begin + @socket.recv(6).should == 'hello' + ensure + client.close + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/connect_spec.rb b/spec/ruby/library/socket/udpsocket/connect_spec.rb new file mode 100644 index 0000000000..d92bdeb981 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/connect_spec.rb @@ -0,0 +1,35 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UDPSocket#connect' do + SocketSpecs.each_ip_protocol do |family, ip_address| + before do + @socket = UDPSocket.new(family) + end + + after do + @socket.close + end + + it 'connects to an address even when it is not used' do + @socket.connect(ip_address, 9996).should == 0 + end + + it 'can send data after connecting' do + receiver = UDPSocket.new(family) + + receiver.bind(ip_address, 0) + + addr = receiver.connect_address + + @socket.connect(addr.ip_address, addr.ip_port) + @socket.write('hello') + + begin + receiver.recv(6).should == 'hello' + ensure + receiver.close + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/initialize_spec.rb b/spec/ruby/library/socket/udpsocket/initialize_spec.rb new file mode 100644 index 0000000000..c040187400 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/initialize_spec.rb @@ -0,0 +1,53 @@ +require_relative '../spec_helper' + +describe 'UDPSocket#initialize' do + after do + @socket.close if @socket + end + + it 'initializes a new UDPSocket' do + @socket = UDPSocket.new + @socket.should.instance_of?(UDPSocket) + end + + it 'initializes a new UDPSocket using an Integer' do + @socket = UDPSocket.new(Socket::AF_INET) + @socket.should.instance_of?(UDPSocket) + end + + it 'initializes a new UDPSocket using a Symbol' do + @socket = UDPSocket.new(:INET) + @socket.should.instance_of?(UDPSocket) + end + + it 'initializes a new UDPSocket using a String' do + @socket = UDPSocket.new('INET') + @socket.should.instance_of?(UDPSocket) + end + + it 'sets the socket to binmode' do + @socket = UDPSocket.new(:INET) + @socket.binmode?.should == true + end + + platform_is_not :windows do + it 'sets the socket to nonblock' do + require 'io/nonblock' + @socket = UDPSocket.new(:INET) + @socket.should.nonblock? + end + end + + it 'sets the socket to close on exec' do + @socket = UDPSocket.new(:INET) + @socket.should.close_on_exec? + end + + it 'raises Errno::EAFNOSUPPORT or Errno::EPROTONOSUPPORT when given an invalid address family' do + -> { + UDPSocket.new(666) + }.should.raise(SystemCallError) { |e| + [Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT].should.include?(e.class) + } + end +end diff --git a/spec/ruby/library/socket/udpsocket/local_address_spec.rb b/spec/ruby/library/socket/udpsocket/local_address_spec.rb new file mode 100644 index 0000000000..868d2f537e --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/local_address_spec.rb @@ -0,0 +1,80 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UDPSocket#local_address' do + SocketSpecs.each_ip_protocol do |family, ip_address| + before do + @server = Socket.new(family, :DGRAM, Socket::IPPROTO_UDP) + + @server.bind(Socket.sockaddr_in(0, ip_address)) + + @host = @server.connect_address.ip_address + @port = @server.connect_address.ip_port + end + + after do + @server.close + end + + describe 'using an explicit hostname' do + before do + @sock = UDPSocket.new(family) + + @sock.connect(@host, @port) + end + + after do + @sock.close + end + + it 'returns an Addrinfo' do + @sock.local_address.should.instance_of?(Addrinfo) + end + + describe 'the returned Addrinfo' do + it 'uses the correct address family' do + @sock.local_address.afamily.should == family + end + + it 'uses the correct protocol family' do + @sock.local_address.pfamily.should == family + end + + it 'uses SOCK_DGRAM as the socket type' do + @sock.local_address.socktype.should == Socket::SOCK_DGRAM + end + + it 'uses the correct IP address' do + @sock.local_address.ip_address.should == @host + end + + it 'uses a randomly assigned local port' do + @sock.local_address.ip_port.should > 0 + @sock.local_address.ip_port.should_not == @port + end + + it 'uses 0 as the protocol' do + @sock.local_address.protocol.should == 0 + end + end + end + + describe 'using an implicit hostname' do + before do + @sock = UDPSocket.new(family) + + @sock.connect(nil, @port) + end + + after do + @sock.close + end + + describe 'the returned Addrinfo' do + it 'uses the correct IP address' do + @sock.local_address.ip_address.should == @host + end + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/new_spec.rb b/spec/ruby/library/socket/udpsocket/new_spec.rb index b2662277c4..aff111927c 100644 --- a/spec/ruby/library/socket/udpsocket/new_spec.rb +++ b/spec/ruby/library/socket/udpsocket/new_spec.rb @@ -1,4 +1,4 @@ -require_relative '../../../spec_helper' +require_relative '../spec_helper' require_relative '../fixtures/classes' describe 'UDPSocket.new' do @@ -8,27 +8,33 @@ describe 'UDPSocket.new' do it 'without arguments' do @socket = UDPSocket.new - @socket.should be_an_instance_of(UDPSocket) + @socket.should.instance_of?(UDPSocket) end - it 'using Fixnum argument' do + it 'using Integer argument' do @socket = UDPSocket.new(Socket::AF_INET) - @socket.should be_an_instance_of(UDPSocket) + @socket.should.instance_of?(UDPSocket) end it 'using Symbol argument' do @socket = UDPSocket.new(:INET) - @socket.should be_an_instance_of(UDPSocket) + @socket.should.instance_of?(UDPSocket) end it 'using String argument' do @socket = UDPSocket.new('INET') - @socket.should be_an_instance_of(UDPSocket) + @socket.should.instance_of?(UDPSocket) + end + + it "does not use the given block and warns to use UDPSocket::open" do + -> { + @socket = UDPSocket.new { raise } + }.should complain(/warning: UDPSocket::new\(\) does not take block; use UDPSocket::open\(\) instead/) end it 'raises Errno::EAFNOSUPPORT or Errno::EPROTONOSUPPORT if unsupported family passed' do - lambda { UDPSocket.new(-1) }.should raise_error(SystemCallError) { |e| - [Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT].should include(e.class) + -> { UDPSocket.new(-1) }.should.raise(SystemCallError) { |e| + [Errno::EAFNOSUPPORT, Errno::EPROTONOSUPPORT].should.include?(e.class) } end end diff --git a/spec/ruby/library/socket/udpsocket/open_spec.rb b/spec/ruby/library/socket/udpsocket/open_spec.rb index 2db17fe090..7c77855372 100644 --- a/spec/ruby/library/socket/udpsocket/open_spec.rb +++ b/spec/ruby/library/socket/udpsocket/open_spec.rb @@ -1,4 +1,4 @@ -require_relative '../../../spec_helper' +require_relative '../spec_helper' require_relative '../fixtures/classes' describe "UDPSocket.open" do @@ -8,6 +8,6 @@ describe "UDPSocket.open" do it "allows calls to open without arguments" do @socket = UDPSocket.open - @socket.should be_kind_of(UDPSocket) + @socket.should.is_a?(UDPSocket) end end diff --git a/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb b/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb new file mode 100644 index 0000000000..460cf2c9a2 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb @@ -0,0 +1,111 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UDPSocket#recvfrom_nonblock' do + SocketSpecs.each_ip_protocol do |family, ip_address, family_name| + before do + @server = UDPSocket.new(family) + @client = UDPSocket.new(family) + end + + after do + @client.close + @server.close + end + + platform_is_not :windows do + describe 'using an unbound socket' do + it 'raises IO::WaitReadable' do + -> { @server.recvfrom_nonblock(1) }.should.raise(IO::WaitReadable) + end + end + end + + describe 'using a bound socket' do + before do + @server.bind(ip_address, 0) + + addr = @server.connect_address + + @client.connect(addr.ip_address, addr.ip_port) + end + + describe 'without any data available' do + it 'raises IO::WaitReadable' do + -> { @server.recvfrom_nonblock(1) }.should.raise(IO::WaitReadable) + end + + it 'returns :wait_readable with exception: false' do + @server.recvfrom_nonblock(1, exception: false).should == :wait_readable + end + end + + platform_is_not :windows do + describe 'with data available' do + before do + @client.write('hello') + end + + it 'returns an Array containing the data and an Array' do + IO.select([@server]) + @server.recvfrom_nonblock(1).should.instance_of?(Array) + end + + it 'writes the data to the buffer when one is present' do + buffer = "".b + IO.select([@server]) + @server.recvfrom_nonblock(1, 0, buffer) + buffer.should == 'h' + end + + it "preserves the encoding of the given buffer" do + buffer = ''.encode(Encoding::ISO_8859_1) + IO.select([@server]) + message, = @server.recvfrom_nonblock(1, 0, buffer) + + message.should.equal?(buffer) + buffer.encoding.should == Encoding::ISO_8859_1 + end + + describe 'the returned Array' do + before do + IO.select([@server]) + @array = @server.recvfrom_nonblock(1) + end + + it 'contains the data at index 0' do + @array[0].should == 'h' + end + + it 'contains an Array at index 1' do + @array[1].should.instance_of?(Array) + end + end + + describe 'the returned address Array' do + before do + IO.select([@server]) + @addr = @server.recvfrom_nonblock(1)[1] + end + + it 'uses the correct address family' do + @addr[0].should == family_name + end + + it 'uses the port of the client' do + @addr[1].should == @client.local_address.ip_port + end + + it 'uses the hostname of the client' do + @addr[2].should == ip_address + end + + it 'uses the IP address of the client' do + @addr[3].should == ip_address + end + end + end + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/remote_address_spec.rb b/spec/ruby/library/socket/udpsocket/remote_address_spec.rb new file mode 100644 index 0000000000..d1310200fc --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/remote_address_spec.rb @@ -0,0 +1,79 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UDPSocket#remote_address' do + SocketSpecs.each_ip_protocol do |family, ip_address| + before do + @server = Socket.new(family, :DGRAM, Socket::IPPROTO_UDP) + + @server.bind(Socket.sockaddr_in(0, ip_address)) + + @host = @server.connect_address.ip_address + @port = @server.connect_address.ip_port + end + + after do + @server.close + end + + describe 'using an explicit hostname' do + before do + @sock = UDPSocket.new(family) + + @sock.connect(@host, @port) + end + + after do + @sock.close + end + + it 'returns an Addrinfo' do + @sock.remote_address.should.instance_of?(Addrinfo) + end + + describe 'the returned Addrinfo' do + it 'uses the correct address family' do + @sock.remote_address.afamily.should == family + end + + it 'uses the correct protocol family' do + @sock.remote_address.pfamily.should == family + end + + it 'uses SOCK_DGRAM as the socket type' do + @sock.remote_address.socktype.should == Socket::SOCK_DGRAM + end + + it 'uses the correct IP address' do + @sock.remote_address.ip_address.should == @host + end + + it 'uses the correct port' do + @sock.remote_address.ip_port.should == @port + end + + it 'uses 0 as the protocol' do + @sock.remote_address.protocol.should == 0 + end + end + end + + describe 'using an implicit hostname' do + before do + @sock = UDPSocket.new(family) + + @sock.connect(nil, @port) + end + + after do + @sock.close + end + + describe 'the returned Addrinfo' do + it 'uses the correct IP address' do + @sock.remote_address.ip_address.should == @host + end + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/send_spec.rb b/spec/ruby/library/socket/udpsocket/send_spec.rb index 0159e25214..63f5b0dcc6 100644 --- a/spec/ruby/library/socket/udpsocket/send_spec.rb +++ b/spec/ruby/library/socket/udpsocket/send_spec.rb @@ -1,7 +1,7 @@ -require_relative '../../../spec_helper' +require_relative '../spec_helper' require_relative '../fixtures/classes' -describe "UDPSocket.send" do +describe "UDPSocket#send" do before :each do @port = nil @server_thread = Thread.new do @@ -34,7 +34,7 @@ describe "UDPSocket.send" do @msg[0].should == "ad hoc" @msg[1][0].should == "AF_INET" - @msg[1][1].should be_kind_of(Fixnum) + @msg[1][1].should.is_a?(Integer) @msg[1][3].should == "127.0.0.1" end @@ -46,7 +46,7 @@ describe "UDPSocket.send" do @msg[0].should == "ad hoc" @msg[1][0].should == "AF_INET" - @msg[1][1].should be_kind_of(Fixnum) + @msg[1][1].should.is_a?(Integer) @msg[1][3].should == "127.0.0.1" end @@ -59,16 +59,16 @@ describe "UDPSocket.send" do @msg[0].should == "connection-based" @msg[1][0].should == "AF_INET" - @msg[1][1].should be_kind_of(Fixnum) + @msg[1][1].should.is_a?(Integer) @msg[1][3].should == "127.0.0.1" end - it "raises EMSGSIZE if data is too too big" do + it "raises EMSGSIZE if data is too big" do @socket = UDPSocket.open begin - lambda do + -> do @socket.send('1' * 100_000, 0, SocketSpecs.hostname, @port.to_s) - end.should raise_error(Errno::EMSGSIZE) + end.should.raise(Errno::EMSGSIZE) ensure @socket.send("ad hoc", 0, SocketSpecs.hostname, @port) @socket.close @@ -76,3 +76,79 @@ describe "UDPSocket.send" do end end end + +describe 'UDPSocket#send' do + SocketSpecs.each_ip_protocol do |family, ip_address| + before do + @server = UDPSocket.new(family) + @client = UDPSocket.new(family) + + @server.bind(ip_address, 0) + + @addr = @server.connect_address + end + + after do + @server.close + @client.close + end + + describe 'using a disconnected socket' do + describe 'without a destination address' do + it "raises #{SocketSpecs.dest_addr_req_error}" do + -> { @client.send('hello', 0) }.should.raise(SocketSpecs.dest_addr_req_error) + end + end + + describe 'with a destination address as separate arguments' do + it 'returns the amount of sent bytes' do + @client.send('hello', 0, @addr.ip_address, @addr.ip_port).should == 5 + end + + it 'does not persist the connection after sending data' do + @client.send('hello', 0, @addr.ip_address, @addr.ip_port) + + -> { @client.send('hello', 0) }.should.raise(SocketSpecs.dest_addr_req_error) + end + end + + describe 'with a destination address as a single String argument' do + it 'returns the amount of sent bytes' do + @client.send('hello', 0, @server.getsockname).should == 5 + end + end + end + + describe 'using a connected socket' do + describe 'without an explicit destination address' do + before do + @client.connect(@addr.ip_address, @addr.ip_port) + end + + it 'returns the amount of bytes written' do + @client.send('hello', 0).should == 5 + end + end + + describe 'with an explicit destination address' do + before do + @alt_server = UDPSocket.new(family) + + @alt_server.bind(ip_address, 0) + end + + after do + @alt_server.close + end + + it 'sends the data to the given address instead' do + @client.send('hello', 0, @alt_server.getsockname).should == 5 + + -> { @server.recv(5) }.should block_caller + + @alt_server.recv(5).should == 'hello' + end + end + end + end +end diff --git a/spec/ruby/library/socket/udpsocket/write_spec.rb b/spec/ruby/library/socket/udpsocket/write_spec.rb index c2a36eaa7a..d41ee078d8 100644 --- a/spec/ruby/library/socket/udpsocket/write_spec.rb +++ b/spec/ruby/library/socket/udpsocket/write_spec.rb @@ -1,4 +1,4 @@ -require_relative '../../../spec_helper' +require_relative '../spec_helper' require_relative '../fixtures/classes' describe "UDPSocket#write" do @@ -10,9 +10,9 @@ describe "UDPSocket#write" do s2 = UDPSocket.new s2.connect(host, s1.addr[1]) - lambda do + -> do s2.write('1' * 100_000) - end.should raise_error(Errno::EMSGSIZE) + end.should.raise(Errno::EMSGSIZE) ensure s1.close if s1 && !s1.closed? s2.close if s2 && !s2.closed? |
