diff options
Diffstat (limited to 'spec/ruby/library/socket/udpsocket')
11 files changed, 469 insertions, 9 deletions
diff --git a/spec/ruby/library/socket/udpsocket/bind_spec.rb b/spec/ruby/library/socket/udpsocket/bind_spec.rb index be62608e1b..4dbdb285f6 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 @@ -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..5df3bf9800 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/initialize_spec.rb @@ -0,0 +1,36 @@ +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 be_an_instance_of(UDPSocket) + end + + it 'initializes a new UDPSocket using a Fixnum' do + @socket = UDPSocket.new(Socket::AF_INET) + @socket.should be_an_instance_of(UDPSocket) + end + + it 'initializes a new UDPSocket using a Symbol' do + @socket = UDPSocket.new(:INET) + @socket.should be_an_instance_of(UDPSocket) + end + + it 'initializes a new UDPSocket using a String' do + @socket = UDPSocket.new('INET') + @socket.should be_an_instance_of(UDPSocket) + end + + it 'sets the socket to binmode' do + @socket = UDPSocket.new(:INET) + @socket.binmode?.should be_true + end + + it 'raises Errno::EAFNOSUPPORT when given an invalid address family' do + lambda { UDPSocket.new(666) }.should raise_error(Errno::EAFNOSUPPORT) + end +end diff --git a/spec/ruby/library/socket/udpsocket/inspect_spec.rb b/spec/ruby/library/socket/udpsocket/inspect_spec.rb new file mode 100644 index 0000000000..201e8b3fc6 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/inspect_spec.rb @@ -0,0 +1,25 @@ +require_relative '../spec_helper' + +describe 'UDPSocket#inspect' do + before do + @socket = UDPSocket.new + @socket.bind('127.0.0.1', 0) + end + + after do + @socket.close + end + + ruby_version_is ""..."2.5" do + it 'returns a String with the fd' do + @socket.inspect.should == "#<UDPSocket:fd #{@socket.fileno}>" + end + end + + ruby_version_is "2.5" do + it 'returns a String with the fd, family, address and port' do + port = @socket.addr[1] + @socket.inspect.should == "#<UDPSocket:fd #{@socket.fileno}, AF_INET, 127.0.0.1, #{port}>" + end + 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..92e4cc10c7 --- /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 be_an_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..30e7103d16 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 diff --git a/spec/ruby/library/socket/udpsocket/open_spec.rb b/spec/ruby/library/socket/udpsocket/open_spec.rb index 2db17fe090..e4dbb2ee2a 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 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..48b7360035 --- /dev/null +++ b/spec/ruby/library/socket/udpsocket/recvfrom_nonblock_spec.rb @@ -0,0 +1,88 @@ +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 + lambda { @server.recvfrom_nonblock(1) }.should raise_error(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 + lambda { @server.recvfrom_nonblock(1) }.should raise_error(IO::WaitReadable) + 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 + @server.recvfrom_nonblock(1).should be_an_instance_of(Array) + end + + describe 'the returned Array' do + before do + @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 be_an_instance_of(Array) + end + end + + describe 'the returned address Array' do + before do + @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..94889ce560 --- /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 be_an_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..b84e84b056 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 @@ -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 + lambda { @client.send('hello', 0) }.should raise_error(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) + + lambda { @client.send('hello', 0) }.should raise_error(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 + + lambda { @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..e960de1baf 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 |