1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Move spec/rubyspec to spec/ruby for consistency

* Other ruby implementations use the spec/ruby directory.
  [Misc #13792] [ruby-core:82287]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-09-20 20:18:52 +00:00
parent 75bfc6440d
commit 1d15d5f080
4370 changed files with 0 additions and 0 deletions

View file

@ -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

View file

@ -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", 0)
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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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(0)
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

View file

@ -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(0)
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

View file

@ -0,0 +1,39 @@
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', 0)
@port = @server.addr[1]
@socket = TCPSocket.new('127.0.0.1', @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", @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

View file

@ -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(0)
@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

View file

@ -0,0 +1,26 @@
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", 0)
@port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @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(@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

View file

@ -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", 0)
sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
sockaddr.should == [@socket.addr[1], "127.0.0.1"]
end
it "works on sockets listening in ipaddr_any" do
@socket = TCPServer.new(0)
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 == @socket.addr[1]
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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,96 @@
# -*- 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', 0)
@port = @server.addr[1]
end
after :each do
@server.close unless @server.closed?
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', @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', @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', @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', @port)
socket.write("data")
client = @server.accept
buf = "foo"
begin
client.recv(4, 0, buf)
ensure
client.close
end
buf.should == "data"
socket.close
end
end
end

View file

@ -0,0 +1,85 @@
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', 0)
@port = @server.addr[1]
@socket = TCPSocket.new('127.0.0.1', @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(@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

View file

@ -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

View file

@ -0,0 +1,6 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::BasicSocket#shutdown" do
end

View file

@ -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

View file

@ -0,0 +1,93 @@
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.reserved_unused_port
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
0
end
def self.sockaddr_in(port, host)
Socket::SockAddr_In.new(Socket.sockaddr_in(port, host))
end
def self.socket_path
path = tmp("unix.sock", false)
# Check for too long unix socket path (max 108 bytes including \0 => 107)
# Note that Linux accepts not null-terminated paths but the man page advises against it.
if path.bytesize > 107
path = "/tmp/unix_server_spec.socket"
end
rm_socket(path)
path
end
def self.rm_socket(path)
File.delete(path) if File.exist?(path)
end
# TCPServer echo server accepting one connection
class SpecTCPServer
attr_reader :hostname, :port
def initialize
@hostname = SocketSpecs.hostname
@server = TCPServer.new @hostname, 0
@port = @server.addr[1]
log "SpecTCPServer starting on #{@hostname}:#{@port}"
@thread = Thread.new do
socket = @server.accept
log "SpecTCPServer accepted connection: #{socket}"
service socket
end
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

View file

@ -0,0 +1 @@
This data is magic.

View file

@ -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", 0)
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 be_kind_of(Integer)
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 be_kind_of(Integer)
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 be_kind_of(Integer)
addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1"
end
end

View file

@ -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

View file

@ -0,0 +1,49 @@
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", 0)
@port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @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 == @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 == @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 == @port
addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1"
end
end

View file

@ -0,0 +1,72 @@
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", 0)
@port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @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
begin
data = client.recvfrom(6)
ensure
client.close
end
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
begin
data = client.recvfrom(3)
ensure
client.close
end
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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,13 @@
describe "partially closable sockets", shared: true do
it "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
it "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

View file

@ -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(0, "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(0, "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(0, "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(0, "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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -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(0, "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 already bound" 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(0, "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(0, "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 already bound" 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(0, "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

View file

@ -0,0 +1,73 @@
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"
@server = TCPServer.new(@hostname, 0) # started, but no accept
@addr = Socket.sockaddr_in(@server.addr[1], @hostname)
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
@thread = nil
end
after :each do
@socket.close
@server.close
@thread.join if @thread
end
it "connects the socket to the remote side" do
port = nil
accept = false
@thread = Thread.new do
server = TCPServer.new(@hostname, 0)
port = server.addr[1]
Thread.pass until accept
conn = server.accept
conn << "hello!"
conn.close
server.close
end
Thread.pass until port
addr = Socket.sockaddr_in(port, @hostname)
begin
@socket.connect_nonblock(addr)
rescue Errno::EINPROGRESS
end
accept = true
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

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -0,0 +1,31 @@
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", 0)
@port = @server.addr[1]
@client = TCPSocket.open("127.0.0.1", @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

View file

@ -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

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -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

View file

@ -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

View file

@ -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 3333, '127.0.0.1'
name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
name_info.should == ['127.0.0.1', "3333"]
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 3333, '127.0.0.1'
name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICSERV)
should_be_valid_dns_name(name_info[0])
name_info[1].should == 3333.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", 3333, '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
name_info.should == ['127.0.0.1', "3333"]
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", 3333, 'foo', '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
name_info.should == ['127.0.0.1', "3333"]
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

View file

@ -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

View file

@ -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(0, "127.0.0.1")
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
@socket.bind(sockaddr)
@socket.listen(1).should == 0
end
end

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)

View file

@ -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 3333, '127.0.0.1'
Socket.unpack_sockaddr_in(sockaddr).should == [3333, '127.0.0.1']
end
it "gets the hostname and port number from a passed Addrinfo" do
addrinfo = Addrinfo.tcp('127.0.0.1', 3333)
Socket.unpack_sockaddr_in(addrinfo).should == [3333, '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

View file

@ -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(0, '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', 0)
lambda { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
end
end
end

View file

@ -0,0 +1,50 @@
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", 0)
@port = @server.addr[1]
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", @port)
sleep 0.1
s = @server.accept_nonblock
port, address = Socket.unpack_sockaddr_in(s.getsockname)
port.should == @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

View file

@ -0,0 +1,65 @@
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", 0)
@port = @server.addr[1]
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', @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 = 0
while t.alive? and a < 5000
sleep 0.001
a += 1
end
a.should < 5000
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

View file

@ -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, 0)
end
after :each do
@server.close
end
it "raises Errno::ENOTCONN on gets" do
lambda { @server.gets }.should raise_error(Errno::ENOTCONN)
end
end

View file

@ -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, 0)
end
after :each do
@server.close unless @server.closed?
end
it 'returns 0' do
@server.listen(10).should == 0
end
end

View file

@ -0,0 +1,96 @@
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', 0)
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, 0)
addr = @server.addr
addr[1].should be_kind_of(Fixnum)
if addr[0] == 'AF_INET'
addr[2].should =~ /^#{SocketSpecs.hostname}\b/
addr[3].should == '127.0.0.1'
else
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('', 0)
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Fixnum)
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('', 0)
addr = @server.addr
addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Fixnum)
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
lambda { TCPServer.new(SocketSpecs.hostname, Object.new) }.should raise_error(TypeError)
port = Object.new
port.should_receive(:to_str).and_return("0")
@server = TCPServer.new(SocketSpecs.hostname, port)
addr = @server.addr
addr[1].should be_kind_of(Fixnum)
# 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", 0) }.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", 0)
}.should raise_error(SocketError)
end
end
it "raises Errno::EADDRINUSE when address is already in use" do
@server = TCPServer.new('127.0.0.1', 0)
lambda {
@server = TCPServer.new('127.0.0.1', @server.addr[1])
}.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', 0)
@server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00"
@server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0
end
end
end

View file

@ -0,0 +1,32 @@
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, 0)
@port = @server.addr[1]
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, @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

View file

@ -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

View file

@ -0,0 +1,5 @@
require File.expand_path('../shared/new', __FILE__)
describe "TCPSocket.new" do
it_behaves_like :tcpsocket_new, :new
end

View file

@ -0,0 +1,5 @@
require File.expand_path('../shared/new', __FILE__)
describe "TCPSocket.open" do
it_behaves_like :tcpsocket_new, :open
end

View file

@ -0,0 +1,21 @@
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
@server = TCPServer.new("127.0.0.1", 0)
@s1 = TCPSocket.new("127.0.0.1", @server.addr[1])
@s2 = @server.accept
end
after :each do
@server.close
@s1.close
@s2.close
end
it_should_behave_like "partially closable sockets"
end

View file

@ -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, @server.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, @server.port
@socket.recv_nonblock(50, exception: false).should == :wait_readable
end
end
end

View file

@ -0,0 +1,45 @@
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
@sock = TCPSocket.new @hostname, @server.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

View file

@ -0,0 +1,79 @@
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.reserved_unused_port)
end.should raise_error(SystemCallError) {|e|
[Errno::ECONNREFUSED, Errno::EADDRNOTAVAIL].should include(e.class)
}
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, @server.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, @server.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, @server.port, @hostname)
@socket.should be_an_instance_of(TCPSocket)
end
it "connects to a server when passed local_host and local_port arguments" do
server = TCPServer.new(SocketSpecs.hostname, 0)
begin
available_port = server.addr[1]
ensure
server.close
end
@socket = TCPSocket.send(@method, @hostname, @server.port,
@hostname, available_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, @server.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

View file

@ -0,0 +1,42 @@
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, 0)
@socket.addr[1].should be_kind_of(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)
end
it "receives a hostname and a port" do
@socket.bind(SocketSpecs.hostname, 0)
port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
host.should == "127.0.0.1"
port.should == @socket.addr[1]
end
it "binds to INADDR_ANY if the hostname is empty" do
@socket.bind("", 0)
port, host = Socket.unpack_sockaddr_in(@socket.getsockname)
host.should == "0.0.0.0"
port.should == @socket.addr[1]
end
end

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,78 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "UDPSocket.send" do
before :each do
@port = nil
@server_thread = Thread.new do
@server = UDPSocket.open
begin
@server.bind(nil, 0)
@port = @server.addr[1]
begin
@msg = @server.recvfrom_nonblock(64)
rescue IO::WaitReadable
IO.select([@server])
retry
end
ensure
@server.close if !@server.closed?
end
end
Thread.pass while @server_thread.status and !@port
end
after :each do
@server_thread.join
end
it "sends data in ad hoc mode" do
@socket = UDPSocket.open
@socket.send("ad hoc", 0, SocketSpecs.hostname, @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, @port.to_s)
@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, @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
it "raises EMSGSIZE if data is too too big" do
@socket = UDPSocket.open
begin
lambda do
@socket.send('1' * 100_000, 0, SocketSpecs.hostname, @port.to_s)
end.should raise_error(Errno::EMSGSIZE)
ensure
@socket.send("ad hoc", 0, SocketSpecs.hostname, @port)
@socket.close
@server_thread.join
end
end
end

View file

@ -0,0 +1,21 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "UDPSocket#write" do
it "raises EMSGSIZE if msg is too long" do
begin
host = SocketSpecs.hostname
s1 = UDPSocket.new
s1.bind(host, 0)
s2 = UDPSocket.new
s2.connect(host, s1.addr[1])
lambda do
s2.write('1' * 100_000)
end.should raise_error(Errno::EMSGSIZE)
ensure
s1.close if s1 && !s1.closed?
s2.close if s2 && !s2.closed?
end
end
end

View file

@ -0,0 +1,38 @@
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
@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
SocketSpecs.rm_socket @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

Some files were not shown because too many files have changed in this diff Show more