diff options
Diffstat (limited to 'spec/ruby/library/socket/unixsocket')
17 files changed, 766 insertions, 0 deletions
diff --git a/spec/ruby/library/socket/unixsocket/addr_spec.rb b/spec/ruby/library/socket/unixsocket/addr_spec.rb new file mode 100644 index 0000000000..b3ae2af5d8 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/addr_spec.rb @@ -0,0 +1,33 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe "UNIXSocket#addr" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + end + + after :each do + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "returns an array" do + @client.addr.should.is_a?(Array) + end + + it "returns the address family of this socket in an array" do + @client.addr[0].should == "AF_UNIX" + @server.addr[0].should == "AF_UNIX" + end + + it "returns the path of the socket in an array if it's a server" do + @server.addr[1].should == @path + end + + it "returns an empty string for path if it's a client" do + @client.addr[1].should == "" + end +end diff --git a/spec/ruby/library/socket/unixsocket/initialize_spec.rb b/spec/ruby/library/socket/unixsocket/initialize_spec.rb new file mode 100644 index 0000000000..ac30b93de0 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/initialize_spec.rb @@ -0,0 +1,56 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UNIXSocket#initialize' do + describe 'using a non existing path' do + platform_is_not :windows do + it 'raises Errno::ENOENT' do + -> { UNIXSocket.new(SocketSpecs.socket_path) }.should.raise(Errno::ENOENT) + end + end + + platform_is :windows do + # Why, Windows, why? + it 'raises Errno::ECONNREFUSED' do + -> { UNIXSocket.new(SocketSpecs.socket_path) }.should.raise(Errno::ECONNREFUSED) + end + end + end + + describe 'using an existing socket path' do + before do + @path = SocketSpecs.socket_path + @server = UNIXServer.new(@path) + @socket = UNIXSocket.new(@path) + end + + after do + @socket.close + @server.close + rm_r(@path) + end + + it 'returns a new UNIXSocket' do + @socket.should.instance_of?(UNIXSocket) + end + + it 'sets the socket path to an empty String' do + @socket.path.should == '' + end + + it 'sets the socket to binmode' do + @socket.binmode?.should == true + end + + platform_is_not :windows do + it 'sets the socket to nonblock' do + require 'io/nonblock' + @socket.should.nonblock? + end + end + + it 'sets the socket to close on exec' do + @socket.should.close_on_exec? + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/inspect_spec.rb b/spec/ruby/library/socket/unixsocket/inspect_spec.rb new file mode 100644 index 0000000000..77bb521069 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/inspect_spec.rb @@ -0,0 +1,15 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe "UNIXSocket#inspect" do + it "returns sockets fd for unnamed sockets" do + begin + s1, s2 = UNIXSocket.socketpair + s1.inspect.should == "#<UNIXSocket:fd #{s1.fileno}>" + s2.inspect.should == "#<UNIXSocket:fd #{s2.fileno}>" + ensure + s1.close + s2.close + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/local_address_spec.rb b/spec/ruby/library/socket/unixsocket/local_address_spec.rb new file mode 100644 index 0000000000..fc504698c3 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/local_address_spec.rb @@ -0,0 +1,92 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UNIXSocket#local_address' do + before do + @path = SocketSpecs.socket_path + @server = UNIXServer.new(@path) + @client = UNIXSocket.new(@path) + end + + after do + @client.close + @server.close + + rm_r(@path) + end + + it 'returns an Addrinfo' do + @client.local_address.should.instance_of?(Addrinfo) + end + + describe 'the returned Addrinfo' do + platform_is_not :aix do + it 'uses AF_UNIX as the address family' do + @client.local_address.afamily.should == Socket::AF_UNIX + end + + it 'uses PF_UNIX as the protocol family' do + @client.local_address.pfamily.should == Socket::PF_UNIX + end + end + + it 'uses SOCK_STREAM as the socket type' do + @client.local_address.socktype.should == Socket::SOCK_STREAM + end + + platform_is_not :aix do + it 'uses an empty socket path' do + @client.local_address.unix_path.should == '' + end + end + + it 'uses 0 as the protocol' do + @client.local_address.protocol.should == 0 + end + end +end + +describe 'UNIXSocket#local_address with a UNIX socket pair' do + before :each do + @sock, @sock2 = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM) + end + + after :each do + @sock.close + @sock2.close + end + + it 'returns an Addrinfo' do + @sock.local_address.should.instance_of?(Addrinfo) + end + + describe 'the returned Addrinfo' do + it 'uses AF_UNIX as the address family' do + @sock.local_address.afamily.should == Socket::AF_UNIX + end + + it 'uses PF_UNIX as the protocol family' do + @sock.local_address.pfamily.should == Socket::PF_UNIX + end + + it 'uses SOCK_STREAM as the socket type' do + @sock.local_address.socktype.should == Socket::SOCK_STREAM + end + + it 'raises SocketError for #ip_address' do + -> { + @sock.local_address.ip_address + }.should.raise(SocketError, "need IPv4 or IPv6 address") + end + + it 'raises SocketError for #ip_port' do + -> { + @sock.local_address.ip_port + }.should.raise(SocketError, "need IPv4 or IPv6 address") + end + + it 'uses 0 as the protocol' do + @sock.local_address.protocol.should == 0 + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/new_spec.rb b/spec/ruby/library/socket/unixsocket/new_spec.rb new file mode 100644 index 0000000000..fea2c1e2b7 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/new_spec.rb @@ -0,0 +1,12 @@ +require_relative '../spec_helper' +require_relative 'shared/new' + +describe "UNIXSocket.new" do + it_behaves_like :unixsocket_new, :new + + it "does not use the given block and warns to use UNIXSocket::open" do + -> { + @client = UNIXSocket.new(@path) { raise } + }.should complain(/warning: UNIXSocket::new\(\) does not take block; use UNIXSocket::open\(\) instead/) + end +end diff --git a/spec/ruby/library/socket/unixsocket/open_spec.rb b/spec/ruby/library/socket/unixsocket/open_spec.rb new file mode 100644 index 0000000000..b5e8c6c23a --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/open_spec.rb @@ -0,0 +1,26 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' +require_relative 'shared/new' + +describe "UNIXSocket.open" do + it_behaves_like :unixsocket_new, :open +end + +describe "UNIXSocket.open" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + end + + after :each do + @server.close + SocketSpecs.rm_socket @path + end + + it "opens a unix socket on the specified file and yields it to the block" do + UNIXSocket.open(@path) do |client| + client.addr[0].should == "AF_UNIX" + client.should_not.closed? + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/pair_spec.rb b/spec/ruby/library/socket/unixsocket/pair_spec.rb new file mode 100644 index 0000000000..9690142668 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/pair_spec.rb @@ -0,0 +1,18 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' +require_relative '../shared/partially_closable_sockets' +require_relative 'shared/pair' + +describe "UNIXSocket.pair" do + it_should_behave_like :unixsocket_pair + it_should_behave_like :partially_closable_sockets + + before :each do + @s1, @s2 = UNIXSocket.pair + end + + after :each do + @s1.close + @s2.close + end +end diff --git a/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb new file mode 100644 index 0000000000..108a6c3063 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb @@ -0,0 +1,21 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' +require_relative '../shared/partially_closable_sockets' + +describe "UNIXSocket partial closability" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @s1 = UNIXSocket.new(@path) + @s2 = @server.accept + end + + after :each do + @server.close + @s1.close + @s2.close + SocketSpecs.rm_socket @path + end + + it_should_behave_like :partially_closable_sockets +end diff --git a/spec/ruby/library/socket/unixsocket/path_spec.rb b/spec/ruby/library/socket/unixsocket/path_spec.rb new file mode 100644 index 0000000000..ffe7e4bea2 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/path_spec.rb @@ -0,0 +1,24 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe "UNIXSocket#path" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + end + + after :each do + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "returns the path of the socket if it's a server" do + @server.path.should == @path + end + + it "returns an empty string for path if it's a client" do + @client.path.should == "" + end +end diff --git a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb new file mode 100644 index 0000000000..b586b1fcbb --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb @@ -0,0 +1,26 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe "UNIXSocket#peeraddr" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + end + + after :each do + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "returns the address family and path of the server end of the connection" do + @client.peeraddr.should == ["AF_UNIX", @path] + end + + it "raises an error in server sockets" do + -> { + @server.peeraddr + }.should.raise(Errno::ENOTCONN) + end +end diff --git a/spec/ruby/library/socket/unixsocket/recv_io_spec.rb b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb new file mode 100644 index 0000000000..ac9d892375 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb @@ -0,0 +1,84 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +platform_is_not :windows do + describe "UNIXSocket#recv_io" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + + @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__) + @file = File.open(@send_io_path) + end + + after :each do + @io.close if @io + @socket.close if @socket + + @file.close + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "reads an IO object across the socket" do + @client.send_io(@file) + + @socket = @server.accept + @io = @socket.recv_io + + @io.read.should == File.read(@send_io_path) + end + + it "takes an optional class to use" do + @client.send_io(@file) + + @socket = @server.accept + @io = @socket.recv_io(File) + + @io.should.instance_of?(File) + end + end + + describe 'UNIXSocket#recv_io' do + before do + @file = File.open('/dev/null', 'w') + @client, @server = UNIXSocket.socketpair + end + + after do + @client.close + @server.close + @io.close if @io + @file.close + end + + describe 'without a custom class' do + it 'returns an IO' do + @client.send_io(@file) + + @io = @server.recv_io + @io.should.instance_of?(IO) + end + end + + describe 'with a custom class' do + it 'returns an instance of the custom class' do + @client.send_io(@file) + + @io = @server.recv_io(File) + @io.should.instance_of?(File) + end + end + + describe 'with a custom mode' do + it 'opens the IO using the given mode' do + @client.send_io(@file) + + @io = @server.recv_io(File, File::WRONLY) + @io.should.instance_of?(File) + end + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb new file mode 100644 index 0000000000..9ae3777961 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb @@ -0,0 +1,174 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe "UNIXSocket#recvfrom" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + end + + after :each do + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "receives len bytes from sock, returning an array containing sent data as first element" do + @client.send("foobar", 0) + sock = @server.accept + sock.recvfrom(6).first.should == "foobar" + sock.close + end + + context "when called on a server's socket" do + platform_is_not :windows do + it "returns an array containing basic information on the client as second element" do + @client.send("foobar", 0) + sock = @server.accept + data = sock.recvfrom(6) + data.last.should == ["AF_UNIX", ""] + sock.close + end + end + + guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do + it "returns an array containing basic information on the client as second element" do + @client.send("foobar", 0) + sock = @server.accept + data = sock.recvfrom(6) + data.last.should == ["AF_UNIX", ""] + sock.close + end + end + end + + context "when called on a client's socket" do + platform_is :linux do + it "returns an array containing server's address as second element" do + @client.send("", 0) + sock = @server.accept + sock.send("barfoo", 0) + @client.recvfrom(6).last.should == ["AF_UNIX", @server.local_address.unix_path] + sock.close + end + end + + guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do + it "returns an array containing server's address as second element" do + @client.send("", 0) + sock = @server.accept + sock.send("barfoo", 0) + # This may not be correct, depends on what underlying recvfrom actually returns. + @client.recvfrom(6).last.should == ["AF_UNIX", @server.local_address.unix_path] + sock.close + end + end + + platform_is :darwin do + it "returns an array containing basic information on the server as second element" do + @client.send("", 0) + sock = @server.accept + sock.send("barfoo", 0) + @client.recvfrom(6).last.should == ["AF_UNIX", ""] + sock.close + end + end + end + + it "allows an output buffer as third argument" do + buffer = +'' + + @client.send("foobar", 0) + sock = @server.accept + message, = sock.recvfrom(6, 0, buffer) + sock.close + + message.should.equal?(buffer) + buffer.should == "foobar" + end + + it "preserves the encoding of the given buffer" do + buffer = ''.encode(Encoding::ISO_8859_1) + + @client.send("foobar", 0) + sock = @server.accept + sock.recvfrom(6, 0, buffer) + sock.close + + buffer.encoding.should == Encoding::ISO_8859_1 + end + + platform_is_not :windows do + it "uses different message options" do + @client.send("foobar", Socket::MSG_PEEK) + sock = @server.accept + peek_data = sock.recvfrom(6, Socket::MSG_PEEK) # Does not retrieve the message + real_data = sock.recvfrom(6) + + real_data.should == peek_data + peek_data.should == ["foobar", ["AF_UNIX", ""]] + sock.close + end + end +end + +describe 'UNIXSocket#recvfrom' do + describe 'using a socket pair' do + before do + @client, @server = UNIXSocket.socketpair + @client.write('hello') + end + + after do + @client.close + @server.close + end + + platform_is_not :windows do + it 'returns an Array containing the data and address information' do + @server.recvfrom(5).should == ['hello', ['AF_UNIX', '']] + end + end + + guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do + it 'returns an Array containing the data and address information' do + @server.recvfrom(5).should == ['hello', ['AF_UNIX', '']] + end + end + end + + platform_is_not :windows do + # These specs are taken from the rdoc examples on UNIXSocket#recvfrom. + describe 'using a UNIX socket constructed using UNIXSocket.for_fd' do + before do + @path1 = SocketSpecs.socket_path + @path2 = SocketSpecs.socket_path.chop + '2' + rm_r(@path2) + + @client_raw = Socket.new(:UNIX, :DGRAM) + @client_raw.bind(Socket.sockaddr_un(@path1)) + + @server_raw = Socket.new(:UNIX, :DGRAM) + @server_raw.bind(Socket.sockaddr_un(@path2)) + + @socket = UNIXSocket.for_fd(@server_raw.fileno) + @socket.autoclose = false + end + + after do + @client_raw.close + @server_raw.close # also closes @socket + + rm_r @path1 + rm_r @path2 + end + + it 'returns an Array containing the data and address information' do + @client_raw.send('hello', 0, Socket.sockaddr_un(@path2)) + + @socket.recvfrom(5).should == ['hello', ['AF_UNIX', @path1]] + end + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/remote_address_spec.rb b/spec/ruby/library/socket/unixsocket/remote_address_spec.rb new file mode 100644 index 0000000000..d2303a6587 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/remote_address_spec.rb @@ -0,0 +1,43 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +describe 'UNIXSocket#remote_address' do + before do + @path = SocketSpecs.socket_path + @server = UNIXServer.new(@path) + @client = UNIXSocket.new(@path) + end + + after do + @client.close + @server.close + + rm_r(@path) + end + + it 'returns an Addrinfo' do + @client.remote_address.should.instance_of?(Addrinfo) + end + + describe 'the returned Addrinfo' do + it 'uses AF_UNIX as the address family' do + @client.remote_address.afamily.should == Socket::AF_UNIX + end + + it 'uses PF_UNIX as the protocol family' do + @client.remote_address.pfamily.should == Socket::PF_UNIX + end + + it 'uses SOCK_STREAM as the socket type' do + @client.remote_address.socktype.should == Socket::SOCK_STREAM + end + + it 'uses the correct socket path' do + @client.remote_address.unix_path.should == @path + end + + it 'uses 0 as the protocol' do + @client.remote_address.protocol.should == 0 + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/send_io_spec.rb b/spec/ruby/library/socket/unixsocket/send_io_spec.rb new file mode 100644 index 0000000000..0063fc7d3f --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/send_io_spec.rb @@ -0,0 +1,55 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' + +platform_is_not :windows do + describe "UNIXSocket#send_io" do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + @client = UNIXSocket.open(@path) + + @send_io_path = File.expand_path('../../fixtures/send_io.txt', __FILE__) + @file = File.open(@send_io_path) + end + + after :each do + @io.close if @io + @socket.close if @socket + + @file.close + @client.close + @server.close + SocketSpecs.rm_socket @path + end + + it "sends the fd for an IO object across the socket" do + @client.send_io(@file) + + @socket = @server.accept + @io = @socket.recv_io + + @io.read.should == File.read(@send_io_path) + end + end + + describe 'UNIXSocket#send_io' do + before do + @file = File.open('/dev/null', 'w') + @client, @server = UNIXSocket.socketpair + end + + after do + @client.close + @server.close + @io.close if @io + @file.close + end + + it 'sends an IO object' do + @client.send_io(@file) + + @io = @server.recv_io + @io.should.instance_of?(IO) + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/shared/new.rb b/spec/ruby/library/socket/unixsocket/shared/new.rb new file mode 100644 index 0000000000..f075b03c5e --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/shared/new.rb @@ -0,0 +1,22 @@ +require_relative '../../spec_helper' +require_relative '../../fixtures/classes' + +describe :unixsocket_new, shared: true do + before :each do + @path = SocketSpecs.socket_path + @server = UNIXServer.open(@path) + end + + after :each do + @client.close if @client + @server.close + SocketSpecs.rm_socket @path + end + + it "opens a unix socket on the specified file" do + @client = UNIXSocket.send(@method, @path) + + @client.addr[0].should == "AF_UNIX" + @client.should_not.closed? + end +end diff --git a/spec/ruby/library/socket/unixsocket/shared/pair.rb b/spec/ruby/library/socket/unixsocket/shared/pair.rb new file mode 100644 index 0000000000..49b6a6a413 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/shared/pair.rb @@ -0,0 +1,47 @@ +require_relative '../../spec_helper' +require_relative '../../fixtures/classes' + +describe :unixsocket_pair, shared: true do + it "returns two UNIXSockets" do + @s1.should.instance_of?(UNIXSocket) + @s2.should.instance_of?(UNIXSocket) + end + + it "returns a pair of connected sockets" do + @s1.puts "foo" + @s2.gets.should == "foo\n" + end + + platform_is_not :windows do + it "sets the socket paths to empty Strings" do + @s1.path.should == "" + @s2.path.should == "" + end + + it "sets the socket addresses to empty Strings" do + @s1.addr.should == ["AF_UNIX", ""] + @s2.addr.should == ["AF_UNIX", ""] + end + + it "sets the socket peer addresses to empty Strings" do + @s1.peeraddr.should == ["AF_UNIX", ""] + @s2.peeraddr.should == ["AF_UNIX", ""] + end + end + + platform_is :windows do + it "emulates unnamed sockets with a temporary file with a path" do + @s1.addr.should == ["AF_UNIX", @s1.path] + @s2.peeraddr.should == ["AF_UNIX", @s1.path] + end + + it "sets the peer address of first socket to an empty string" do + @s1.peeraddr.should == ["AF_UNIX", ""] + end + + it "sets the address and path of second socket to an empty string" do + @s2.addr.should == ["AF_UNIX", ""] + @s2.path.should == "" + end + end +end diff --git a/spec/ruby/library/socket/unixsocket/socketpair_spec.rb b/spec/ruby/library/socket/unixsocket/socketpair_spec.rb new file mode 100644 index 0000000000..c61fc00be4 --- /dev/null +++ b/spec/ruby/library/socket/unixsocket/socketpair_spec.rb @@ -0,0 +1,18 @@ +require_relative '../spec_helper' +require_relative '../fixtures/classes' +require_relative '../shared/partially_closable_sockets' +require_relative 'shared/pair' + +describe "UNIXSocket.socketpair" do + it_should_behave_like :unixsocket_pair + it_should_behave_like :partially_closable_sockets + + before :each do + @s1, @s2 = UNIXSocket.socketpair + end + + after :each do + @s1.close + @s2.close + end +end |
