1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59093 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2017-06-15 12:48:52 +00:00
parent 5ccf36c7ec
commit 2bdce358e6
53 changed files with 319 additions and 426 deletions

View file

@ -7,11 +7,12 @@ environment:
install: install:
- SET PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - SET PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
- ruby --version - ruby --version
- call "C:\Ruby23-x64\DevKit\devkitvars.bat"
- git clone https://github.com/ruby/mspec.git ../mspec - git clone https://github.com/ruby/mspec.git ../mspec
build: off build: off
test_script: test_script:
- SET CHECK_LEAKS=true - SET CHECK_LEAKS=true
- ../mspec/bin/mspec -ff command_line language core library - ../mspec/bin/mspec -ff
branches: branches:
only: only:
- master - master

View file

@ -213,22 +213,6 @@ module KernelSpecs
end end
end end
module KernelBlockGiven
def self.accept_block
Kernel.block_given?
end
def self.accept_block_as_argument(&block)
Kernel.block_given?
end
class << self
define_method(:defined_block) do
Kernel.block_given?
end
end
end
module SelfBlockGiven module SelfBlockGiven
def self.accept_block def self.accept_block
self.send(:block_given?) self.send(:block_given?)

View file

@ -0,0 +1,26 @@
require File.expand_path('../../../spec_helper', __FILE__)
has_yield_self = VersionGuard.new("2.5").match? || PlatformGuard.implementation?(:truffleruby)
if has_yield_self
describe "Kernel#yield_self" do
it "yields self" do
object = Object.new
object.yield_self { |o| o.should equal object }
end
it "returns the block return value" do
object = Object.new
object.yield_self { 42 }.should equal 42
end
it "returns a sized Enumerator when no block given" do
object = Object.new
enum = object.yield_self
enum.should be_an_instance_of Enumerator
enum.size.should equal 1
enum.peek.should equal object
enum.first.should equal object
end
end
end

View file

@ -300,6 +300,10 @@ describe "String#split with Regexp" do
"AabB".split(/([a-z])+/).should == ["A", "b", "B"] "AabB".split(/([a-z])+/).should == ["A", "b", "B"]
end end
it "applies the limit to the number of split substrings, without counting captures" do
"aBaBa".split(/(B)()()/, 2).should == ["a", "B", "", "", "aBa"]
end
it "does not include non-matching captures in the result array" do it "does not include non-matching captures in the result array" do
"hello".split(/(el)|(xx)/).should == ["h", "el", "lo"] "hello".split(/(el)|(xx)/).should == ["h", "el", "lo"]
end end

View file

@ -8,9 +8,9 @@ module NetFTPSpecs
# port number # port number
attr_reader :server_port attr_reader :server_port
def initialize(hostname = "localhost", server_port = 0) def initialize
@hostname = hostname @hostname = "localhost"
@server = TCPServer.new(@hostname, server_port) @server = TCPServer.new(@hostname, 0)
@server_port = @server.addr[1] @server_port = @server.addr[1]
@handlers = {} @handlers = {}

View file

@ -47,7 +47,8 @@ module NetHTTPSpecs
@server_thread = nil @server_thread = nil
def port def port
@server ? @server.config[:Port] : 3333 raise "server not started" unless @server
@server.config[:Port]
end end
def start_server def start_server
@ -79,9 +80,11 @@ module NetHTTPSpecs
rescue Errno::EPIPE rescue Errno::EPIPE
# Because WEBrick is not thread-safe and only catches IOError # Because WEBrick is not thread-safe and only catches IOError
end end
@server = nil
end end
if @server_thread if @server_thread
@server_thread.join @server_thread.join
@server_thread = nil
end end
timeout = WEBrick::Utils::TimeoutHandler timeout = WEBrick::Utils::TimeoutHandler
timeout.terminate if timeout.respond_to?(:terminate) timeout.terminate if timeout.respond_to?(:terminate)

View file

@ -1,13 +1,11 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
unless MSpec.retrieve(:features).key?(:readline) begin
begin require 'readline'
require 'readline' rescue LoadError
rescue LoadError else
else # rb-readline behaves quite differently
# rb-readline behaves quite differently unless defined?(RbReadline)
if $".grep(/\brbreadline\.rb$/).empty? MSpec.enable_feature :readline
MSpec.enable_feature :readline
end
end end
end end

View file

@ -5,7 +5,7 @@ require 'socket'
describe "Addrinfo#bind" do describe "Addrinfo#bind" do
before :each do before :each do
@addrinfo = Addrinfo.tcp("127.0.0.1", SocketSpecs.port) @addrinfo = Addrinfo.tcp("127.0.0.1", 0)
end end
after :each do after :each do

View file

@ -3,7 +3,7 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::BasicSocket#close_read" do describe "Socket::BasicSocket#close_read" do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.port) @server = TCPServer.new(0)
end end
after :each do after :each do

View file

@ -3,7 +3,7 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::BasicSocket#close_write" do describe "Socket::BasicSocket#close_write" do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.port) @server = TCPServer.new(0)
end end
after :each do after :each do

View file

@ -4,8 +4,9 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "BasicSocket.do_not_reverse_lookup" do describe "BasicSocket.do_not_reverse_lookup" do
before :each do before :each do
@do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', 0)
@socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) @port = @server.addr[1]
@socket = TCPSocket.new('127.0.0.1', @port)
end end
after :each do after :each do
@ -21,7 +22,7 @@ describe "BasicSocket.do_not_reverse_lookup" do
it "causes 'peeraddr' to avoid name lookups" do it "causes 'peeraddr' to avoid name lookups" do
@socket.do_not_reverse_lookup = true @socket.do_not_reverse_lookup = true
BasicSocket.do_not_reverse_lookup = true BasicSocket.do_not_reverse_lookup = true
@socket.peeraddr.should == ["AF_INET", SocketSpecs.port, "127.0.0.1", "127.0.0.1"] @socket.peeraddr.should == ["AF_INET", @port, "127.0.0.1", "127.0.0.1"]
end end
it "looks for hostnames when set to false" do it "looks for hostnames when set to false" do

View file

@ -4,7 +4,7 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "BasicSocket#for_fd" do describe "BasicSocket#for_fd" do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.port) @server = TCPServer.new(0)
@s2 = nil @s2 = nil
end end

View file

@ -4,8 +4,9 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::BasicSocket#getpeername" do describe "Socket::BasicSocket#getpeername" do
before :each do before :each do
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@client = TCPSocket.new("127.0.0.1", SocketSpecs.port) @port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @port)
end end
after :each do after :each do
@ -14,7 +15,7 @@ describe "Socket::BasicSocket#getpeername" do
end end
it "returns the sockaddr of the other end of the connection" do it "returns the sockaddr of the other end of the connection" do
server_sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1") server_sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
@client.getpeername.should == server_sockaddr @client.getpeername.should == server_sockaddr
end end

View file

@ -8,16 +8,16 @@ describe "Socket::BasicSocket#getsockname" do
end end
it "returns the sockaddr associacted with the socket" do it "returns the sockaddr associacted with the socket" do
@socket = TCPServer.new("127.0.0.1", SocketSpecs.port) @socket = TCPServer.new("127.0.0.1", 0)
sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname) sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
sockaddr.should == [SocketSpecs.port, "127.0.0.1"] sockaddr.should == [@socket.addr[1], "127.0.0.1"]
end end
it "works on sockets listening in ipaddr_any" do it "works on sockets listening in ipaddr_any" do
@socket = TCPServer.new(SocketSpecs.port) @socket = TCPServer.new(0)
sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname) sockaddr = Socket.unpack_sockaddr_in(@socket.getsockname)
["::", "0.0.0.0", "::ffff:0.0.0.0"].include?(sockaddr[1]).should be_true ["::", "0.0.0.0", "::ffff:0.0.0.0"].include?(sockaddr[1]).should be_true
sockaddr[0].should == SocketSpecs.port sockaddr[0].should == @socket.addr[1]
end end
it "returns empty sockaddr for unbinded sockets" do it "returns empty sockaddr for unbinded sockets" do

View file

@ -5,7 +5,8 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "BasicSocket#recv" do describe "BasicSocket#recv" do
before :each do before :each do
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', 0)
@port = @server.addr[1]
end end
after :each do after :each do
@ -23,7 +24,7 @@ describe "BasicSocket#recv" do
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil t.status.should_not be_nil
socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) socket = TCPSocket.new('127.0.0.1', @port)
socket.send('hello', 0) socket.send('hello', 0)
socket.close socket.close
@ -46,7 +47,7 @@ describe "BasicSocket#recv" do
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil t.status.should_not be_nil
socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) socket = TCPSocket.new('127.0.0.1', @port)
socket.send('helloU', Socket::MSG_OOB) socket.send('helloU', Socket::MSG_OOB)
socket.shutdown(1) socket.shutdown(1)
t.join t.join
@ -67,7 +68,7 @@ describe "BasicSocket#recv" do
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil t.status.should_not be_nil
socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) socket = TCPSocket.new('127.0.0.1', @port)
socket.write("firstline\377secondline\377") socket.write("firstline\377secondline\377")
socket.close socket.close
@ -77,7 +78,7 @@ describe "BasicSocket#recv" do
ruby_version_is "2.3" do ruby_version_is "2.3" do
it "allows an output buffer as third argument" do it "allows an output buffer as third argument" do
socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) socket = TCPSocket.new('127.0.0.1', @port)
socket.write("data") socket.write("data")
client = @server.accept client = @server.accept

View file

@ -3,8 +3,9 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "BasicSocket#send" do describe "BasicSocket#send" do
before :each do before :each do
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', 0)
@socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) @port = @server.addr[1]
@socket = TCPSocket.new('127.0.0.1', @port)
end end
after :each do after :each do
@ -74,7 +75,7 @@ describe "BasicSocket#send" do
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
t.status.should_not be_nil t.status.should_not be_nil
sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1") sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
@socket.send('hello', 0, sockaddr).should == 5 @socket.send('hello', 0, sockaddr).should == 5
@socket.shutdown # indicate, that we are done sending @socket.shutdown # indicate, that we are done sending

View file

@ -23,29 +23,6 @@ module SocketSpecs
Socket.getaddrinfo(host, nil)[0][3] Socket.getaddrinfo(host, nil)[0][3]
end end
def self.find_available_port
begin
s = TCPServer.open(0)
port = s.addr[1]
s.close
port
rescue
43191
end
end
def self.port
@port ||= find_available_port
end
def self.str_port
port.to_s
end
def self.local_port
find_available_port
end
def self.reserved_unused_port def self.reserved_unused_port
# https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
0 0

View file

@ -4,7 +4,7 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::IPSocket#addr" do describe "Socket::IPSocket#addr" do
before :each do before :each do
@do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
@socket = TCPServer.new("127.0.0.1", SocketSpecs.port) @socket = TCPServer.new("127.0.0.1", 0)
end end
after :each do after :each do
@ -17,7 +17,7 @@ describe "Socket::IPSocket#addr" do
BasicSocket.do_not_reverse_lookup = false BasicSocket.do_not_reverse_lookup = false
addrinfo = @socket.addr addrinfo = @socket.addr
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should be_kind_of(Integer)
addrinfo[2].should == SocketSpecs.hostname addrinfo[2].should == SocketSpecs.hostname
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end
@ -27,7 +27,7 @@ describe "Socket::IPSocket#addr" do
BasicSocket.do_not_reverse_lookup = true BasicSocket.do_not_reverse_lookup = true
addrinfo = @socket.addr addrinfo = @socket.addr
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should be_kind_of(Integer)
addrinfo[2].should == "127.0.0.1" addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end
@ -35,7 +35,7 @@ describe "Socket::IPSocket#addr" do
it "returns an address in the array if passed false" do it "returns an address in the array if passed false" do
addrinfo = @socket.addr(false) addrinfo = @socket.addr(false)
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should be_kind_of(Integer)
addrinfo[2].should == "127.0.0.1" addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end

View file

@ -4,8 +4,9 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::IPSocket#peeraddr" do describe "Socket::IPSocket#peeraddr" do
before :each do before :each do
@do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup @do_not_reverse_lookup = BasicSocket.do_not_reverse_lookup
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@client = TCPSocket.new("127.0.0.1", SocketSpecs.port) @port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @port)
end end
after :each do after :each do
@ -23,7 +24,7 @@ describe "Socket::IPSocket#peeraddr" do
BasicSocket.do_not_reverse_lookup = false BasicSocket.do_not_reverse_lookup = false
addrinfo = @client.peeraddr addrinfo = @client.peeraddr
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should == @port
addrinfo[2].should == SocketSpecs.hostname addrinfo[2].should == SocketSpecs.hostname
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end
@ -33,7 +34,7 @@ describe "Socket::IPSocket#peeraddr" do
BasicSocket.do_not_reverse_lookup = true BasicSocket.do_not_reverse_lookup = true
addrinfo = @client.peeraddr addrinfo = @client.peeraddr
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should == @port
addrinfo[2].should == "127.0.0.1" addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end
@ -41,7 +42,7 @@ describe "Socket::IPSocket#peeraddr" do
it "returns an IP instead of hostname if passed false" do it "returns an IP instead of hostname if passed false" do
addrinfo = @client.peeraddr(false) addrinfo = @client.peeraddr(false)
addrinfo[0].should == "AF_INET" addrinfo[0].should == "AF_INET"
addrinfo[1].should == SocketSpecs.port addrinfo[1].should == @port
addrinfo[2].should == "127.0.0.1" addrinfo[2].should == "127.0.0.1"
addrinfo[3].should == "127.0.0.1" addrinfo[3].should == "127.0.0.1"
end end

View file

@ -4,8 +4,9 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::IPSocket#recvfrom" do describe "Socket::IPSocket#recvfrom" do
before :each do before :each do
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@client = TCPSocket.new("127.0.0.1", SocketSpecs.port) @port = @server.addr[1]
@client = TCPSocket.new("127.0.0.1", @port)
end end
after :each do after :each do

View file

@ -1,11 +1,11 @@
describe "partially closable sockets", shared: true do describe "partially closable sockets", shared: true do
specify "if the write end is closed then the other side can read past EOF without blocking" do it "if the write end is closed then the other side can read past EOF without blocking" do
@s1.write("foo") @s1.write("foo")
@s1.close_write @s1.close_write
@s2.read("foo".size + 1).should == "foo" @s2.read("foo".size + 1).should == "foo"
end end
specify "closing the write end ensures that the other side can read until EOF" do it "closing the write end ensures that the other side can read until EOF" do
@s1.write("hello world") @s1.write("hello world")
@s1.close_write @s1.close_write
@s2.read.should == "hello world" @s2.read.should == "hello world"

View file

@ -10,7 +10,7 @@ describe :socket_recv_nonblock, shared: true do
end end
it "raises an exception extending IO::WaitReadable if there's no data available" do it "raises an exception extending IO::WaitReadable if there's no data available" do
@s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")) @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
lambda { lambda {
@s1.recv_nonblock(5) @s1.recv_nonblock(5)
}.should raise_error(IO::WaitReadable) { |e| }.should raise_error(IO::WaitReadable) { |e|
@ -24,7 +24,7 @@ describe :socket_recv_nonblock, shared: true do
end end
it "receives data after it's ready" do it "receives data after it's ready" do
@s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")) @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
@s2.send("aaa", 0, @s1.getsockname) @s2.send("aaa", 0, @s1.getsockname)
IO.select([@s1], nil, nil, 2) IO.select([@s1], nil, nil, 2)
@s1.recv_nonblock(5).should == "aaa" @s1.recv_nonblock(5).should == "aaa"
@ -32,7 +32,7 @@ describe :socket_recv_nonblock, shared: true do
ruby_version_is "2.3" do ruby_version_is "2.3" do
it "allows an output buffer as third argument" do it "allows an output buffer as third argument" do
@s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")) @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
@s2.send("data", 0, @s1.getsockname) @s2.send("data", 0, @s1.getsockname)
IO.select([@s1], nil, nil, 2) IO.select([@s1], nil, nil, 2)
@ -43,7 +43,7 @@ describe :socket_recv_nonblock, shared: true do
end end
it "does not block if there's no data available" do it "does not block if there's no data available" do
@s1.bind(Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1")) @s1.bind(Socket.pack_sockaddr_in(0, "127.0.0.1"))
@s2.send("a", 0, @s1.getsockname) @s2.send("a", 0, @s1.getsockname)
IO.select([@s1], nil, nil, 2) IO.select([@s1], nil, nil, 2)
@s1.recv_nonblock(1).should == "a" @s1.recv_nonblock(1).should == "a"

View file

@ -5,8 +5,8 @@ include Socket::Constants
describe "Socket#bind on SOCK_DGRAM socket" do describe "Socket#bind on SOCK_DGRAM socket" do
before :each do before :each do
@sock = Socket.new(AF_INET, SOCK_DGRAM, 0); @sock = Socket.new(AF_INET, SOCK_DGRAM, 0)
@sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"); @sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
end end
after :each do after :each do
@ -22,30 +22,30 @@ describe "Socket#bind on SOCK_DGRAM socket" do
@sock.bind(@sockaddr).should == 0 @sock.bind(@sockaddr).should == 0
end end
it "raises Errno::EINVAL when binding to an already bound port" do it "raises Errno::EINVAL when already bound" do
@sock.bind(@sockaddr); @sock.bind(@sockaddr)
lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL); lambda { @sock.bind(@sockaddr) }.should raise_error(Errno::EINVAL)
end end
it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1"); sockaddr1 = Socket.pack_sockaddr_in(0, "4.3.2.1")
lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL) lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EADDRNOTAVAIL)
end end
platform_is_not :windows, :cygwin do platform_is_not :windows, :cygwin do
it "raises Errno::EACCES when the current user does not have permission to bind" 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"); sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES) lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
end end
end end
end end
describe "Socket#bind on SOCK_STREAM socket" do describe "Socket#bind on SOCK_STREAM socket" do
before :each do before :each do
@sock = Socket.new(AF_INET, SOCK_STREAM, 0); @sock = Socket.new(AF_INET, SOCK_STREAM, 0)
@sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, true) @sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, true)
@sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1"); @sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
end end
after :each do after :each do
@ -61,21 +61,21 @@ describe "Socket#bind on SOCK_STREAM socket" do
@sock.bind(@sockaddr).should == 0 @sock.bind(@sockaddr).should == 0
end end
it "raises Errno::EINVAL when binding to an already bound port" do it "raises Errno::EINVAL when already bound" do
@sock.bind(@sockaddr); @sock.bind(@sockaddr)
lambda { @sock.bind(@sockaddr); }.should raise_error(Errno::EINVAL); lambda { @sock.bind(@sockaddr) }.should raise_error(Errno::EINVAL)
end end
it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do it "raises Errno::EADDRNOTAVAIL when the specified sockaddr is not available from the local machine" do
sockaddr1 = Socket.pack_sockaddr_in(SocketSpecs.port, "4.3.2.1"); sockaddr1 = Socket.pack_sockaddr_in(0, "4.3.2.1")
lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EADDRNOTAVAIL) lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EADDRNOTAVAIL)
end end
platform_is_not :windows, :cygwin do platform_is_not :windows, :cygwin do
it "raises Errno::EACCES when the current user does not have permission to bind" 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"); sockaddr1 = Socket.pack_sockaddr_in(1, "127.0.0.1")
lambda { @sock.bind(sockaddr1); }.should raise_error(Errno::EACCES) lambda { @sock.bind(sockaddr1) }.should raise_error(Errno::EACCES)
end end
end end
end end

View file

@ -6,7 +6,8 @@ require 'socket'
describe "Socket#connect_nonblock" do describe "Socket#connect_nonblock" do
before :each do before :each do
@hostname = "127.0.0.1" @hostname = "127.0.0.1"
@addr = Socket.sockaddr_in(SocketSpecs.port, @hostname) @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) @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
@thread = nil @thread = nil
end end
@ -17,27 +18,31 @@ describe "Socket#connect_nonblock" do
end end
it "connects the socket to the remote side" do it "connects the socket to the remote side" do
ready = false port = nil
accept = false
@thread = Thread.new do @thread = Thread.new do
server = TCPServer.new(@hostname, SocketSpecs.port) server = TCPServer.new(@hostname, 0)
ready = true port = server.addr[1]
Thread.pass until accept
conn = server.accept conn = server.accept
conn << "hello!" conn << "hello!"
conn.close conn.close
server.close server.close
end end
Thread.pass while (@thread.status and @thread.status != 'sleep') or !ready Thread.pass until port
addr = Socket.sockaddr_in(port, @hostname)
begin begin
@socket.connect_nonblock(@addr) @socket.connect_nonblock(addr)
rescue Errno::EINPROGRESS rescue Errno::EINPROGRESS
end end
accept = true
IO.select nil, [@socket] IO.select nil, [@socket]
begin begin
@socket.connect_nonblock(@addr) @socket.connect_nonblock(addr)
rescue Errno::EISCONN rescue Errno::EISCONN
# Not all OS's use this errno, so we trap and ignore it # Not all OS's use this errno, so we trap and ignore it
end end

View file

@ -4,8 +4,9 @@ require 'socket'
describe "Socket.for_fd" do describe "Socket.for_fd" do
before :each do before :each do
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@client = TCPSocket.open("127.0.0.1", SocketSpecs.port) @port = @server.addr[1]
@client = TCPSocket.open("127.0.0.1", @port)
end end
after :each do after :each do

View file

@ -14,9 +14,9 @@ describe "Socket.getnameinfo" do
end end
it "gets the name information and don't resolve it" do it "gets the name information and don't resolve it" do
sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1' sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV) name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
name_info.should == ['127.0.0.1', "#{SocketSpecs.port}"] name_info.should == ['127.0.0.1', "3333"]
end end
def should_be_valid_dns_name(name) def should_be_valid_dns_name(name)
@ -28,10 +28,10 @@ describe "Socket.getnameinfo" do
end end
it "gets the name information and resolve the host" do it "gets the name information and resolve the host" do
sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1' sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICSERV) name_info = Socket.getnameinfo(sockaddr, Socket::NI_NUMERICSERV)
should_be_valid_dns_name(name_info[0]) should_be_valid_dns_name(name_info[0])
name_info[1].should == SocketSpecs.port.to_s name_info[1].should == 3333.to_s
end end
it "gets the name information and resolves the service" do it "gets the name information and resolves the service" do
@ -44,8 +44,8 @@ describe "Socket.getnameinfo" do
end end
it "gets a 3-element array and doesn't resolve hostname" do it "gets a 3-element array and doesn't resolve hostname" do
name_info = Socket.getnameinfo(["AF_INET", SocketSpecs.port, '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV) name_info = Socket.getnameinfo(["AF_INET", 3333, '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV)
name_info.should == ['127.0.0.1', "#{SocketSpecs.port}"] name_info.should == ['127.0.0.1', "3333"]
end end
it "gets a 3-element array and resolves the service" do it "gets a 3-element array and resolves the service" do
@ -54,8 +54,8 @@ describe "Socket.getnameinfo" do
end end
it "gets a 4-element array and doesn't resolve hostname" do it "gets a 4-element array and doesn't resolve hostname" do
name_info = Socket.getnameinfo(["AF_INET", SocketSpecs.port, 'foo', '127.0.0.1'], Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV) 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', "#{SocketSpecs.port}"] name_info.should == ['127.0.0.1', "3333"]
end end
it "gets a 4-element array and resolves the service" do it "gets a 4-element array and resolves the service" do

View file

@ -14,7 +14,7 @@ describe "Socket#listen" do
end end
it "verifies we can listen for incoming connections" do it "verifies we can listen for incoming connections" do
sockaddr = Socket.pack_sockaddr_in(SocketSpecs.port, "127.0.0.1") sockaddr = Socket.pack_sockaddr_in(0, "127.0.0.1")
@socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true) @socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
@socket.bind(sockaddr) @socket.bind(sockaddr)
@socket.listen(1).should == 0 @socket.listen(1).should == 0

View file

@ -5,13 +5,13 @@ require 'socket'
describe "Socket.unpack_sockaddr_in" do describe "Socket.unpack_sockaddr_in" do
it "decodes the host name and port number of a packed sockaddr_in" do it "decodes the host name and port number of a packed sockaddr_in" do
sockaddr = Socket.sockaddr_in SocketSpecs.port, '127.0.0.1' sockaddr = Socket.sockaddr_in 3333, '127.0.0.1'
Socket.unpack_sockaddr_in(sockaddr).should == [SocketSpecs.port, '127.0.0.1'] Socket.unpack_sockaddr_in(sockaddr).should == [3333, '127.0.0.1']
end end
it "gets the hostname and port number from a passed Addrinfo" do it "gets the hostname and port number from a passed Addrinfo" do
addrinfo = Addrinfo.tcp('127.0.0.1', SocketSpecs.port) addrinfo = Addrinfo.tcp('127.0.0.1', 3333)
Socket.unpack_sockaddr_in(addrinfo).should == [SocketSpecs.port, '127.0.0.1'] Socket.unpack_sockaddr_in(addrinfo).should == [3333, '127.0.0.1']
end end
platform_is_not :windows do platform_is_not :windows do

View file

@ -14,12 +14,12 @@ describe 'Socket.unpack_sockaddr_un' do
end end
it 'raises an ArgumentError when the sin_family is not AF_UNIX' do it 'raises an ArgumentError when the sin_family is not AF_UNIX' do
sockaddr = Socket.sockaddr_in(SocketSpecs.port, '127.0.0.1') sockaddr = Socket.sockaddr_in(0, '127.0.0.1')
lambda { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError) lambda { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError)
end end
it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do
addrinfo = Addrinfo.tcp('127.0.0.1', SocketSpecs.port) addrinfo = Addrinfo.tcp('127.0.0.1', 0)
lambda { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError) lambda { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
end end
end end

View file

@ -3,7 +3,8 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "Socket::TCPServer.accept_nonblock" do describe "Socket::TCPServer.accept_nonblock" do
before :each do before :each do
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@port = @server.addr[1]
end end
after :each do after :each do
@ -16,13 +17,13 @@ describe "Socket::TCPServer.accept_nonblock" do
@server.accept_nonblock @server.accept_nonblock
}.should raise_error(IO::WaitReadable) }.should raise_error(IO::WaitReadable)
c = TCPSocket.new("127.0.0.1", SocketSpecs.port) c = TCPSocket.new("127.0.0.1", @port)
sleep 0.1 sleep 0.1
s = @server.accept_nonblock s = @server.accept_nonblock
port, address = Socket.unpack_sockaddr_in(s.getsockname) port, address = Socket.unpack_sockaddr_in(s.getsockname)
port.should == SocketSpecs.port port.should == @port
address.should == "127.0.0.1" address.should == "127.0.0.1"
s.should be_kind_of(TCPSocket) s.should be_kind_of(TCPSocket)

View file

@ -4,7 +4,8 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "TCPServer#accept" do describe "TCPServer#accept" do
before :each do before :each do
@server = TCPServer.new("127.0.0.1", SocketSpecs.port) @server = TCPServer.new("127.0.0.1", 0)
@port = @server.addr[1]
end end
after :each do after :each do
@ -22,7 +23,7 @@ describe "TCPServer#accept" do
end end
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
socket = TCPSocket.new('127.0.0.1', SocketSpecs.port) socket = TCPSocket.new('127.0.0.1', @port)
socket.write('hello') socket.write('hello')
socket.shutdown(1) # we are done with sending socket.shutdown(1) # we are done with sending
socket.read.should == 'goodbye' socket.read.should == 'goodbye'
@ -38,14 +39,12 @@ describe "TCPServer#accept" do
# kill thread, ensure it dies in a reasonable amount of time # kill thread, ensure it dies in a reasonable amount of time
t.kill t.kill
a = 1 a = 0
while a < 2000 while t.alive? and a < 5000
break unless t.alive? sleep 0.001
Thread.pass
sleep 0.2
a += 1 a += 1
end end
a.should < 2000 a.should < 5000
end end
it "can be interrupted by Thread#raise" do it "can be interrupted by Thread#raise" do

View file

@ -3,7 +3,7 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "TCPServer#gets" do describe "TCPServer#gets" do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port) @server = TCPServer.new(SocketSpecs.hostname, 0)
end end
after :each do after :each do

View file

@ -5,7 +5,7 @@ require 'socket'
describe 'TCPServer#listen' do describe 'TCPServer#listen' do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port) @server = TCPServer.new(SocketSpecs.hostname, 0)
end end
after :each do after :each do

View file

@ -7,7 +7,7 @@ describe "TCPServer.new" do
end end
it "binds to a host and a port" do it "binds to a host and a port" do
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', 0)
addr = @server.addr addr = @server.addr
addr[0].should == 'AF_INET' addr[0].should == 'AF_INET'
addr[1].should be_kind_of(Fixnum) addr[1].should be_kind_of(Fixnum)
@ -18,53 +18,52 @@ describe "TCPServer.new" do
end end
it "binds to localhost and a port with either IPv4 or IPv6" do it "binds to localhost and a port with either IPv4 or IPv6" do
@server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port) @server = TCPServer.new(SocketSpecs.hostname, 0)
addr = @server.addr addr = @server.addr
addr[1].should be_kind_of(Fixnum)
if addr[0] == 'AF_INET' if addr[0] == 'AF_INET'
addr[1].should == SocketSpecs.port
addr[2].should =~ /^#{SocketSpecs.hostname}\b/ addr[2].should =~ /^#{SocketSpecs.hostname}\b/
addr[3].should == '127.0.0.1' addr[3].should == '127.0.0.1'
else else
addr[1].should == SocketSpecs.port
addr[2].should =~ /^#{SocketSpecs.hostnamev6}\b/ addr[2].should =~ /^#{SocketSpecs.hostnamev6}\b/
addr[3].should == '::1' addr[3].should == '::1'
end end
end end
it "binds to INADDR_ANY if the hostname is empty" do it "binds to INADDR_ANY if the hostname is empty" do
@server = TCPServer.new('', SocketSpecs.port) @server = TCPServer.new('', 0)
addr = @server.addr addr = @server.addr
addr[0].should == 'AF_INET' addr[0].should == 'AF_INET'
addr[1].should == SocketSpecs.port addr[1].should be_kind_of(Fixnum)
addr[2].should == '0.0.0.0' addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0' addr[3].should == '0.0.0.0'
end end
it "binds to INADDR_ANY if the hostname is empty and the port is a string" do it "binds to INADDR_ANY if the hostname is empty and the port is a string" do
@server = TCPServer.new('', SocketSpecs.port.to_s) @server = TCPServer.new('', 0)
addr = @server.addr addr = @server.addr
addr[0].should == 'AF_INET' addr[0].should == 'AF_INET'
addr[1].should == SocketSpecs.port addr[1].should be_kind_of(Fixnum)
addr[2].should == '0.0.0.0' addr[2].should == '0.0.0.0'
addr[3].should == '0.0.0.0' addr[3].should == '0.0.0.0'
end end
it "coerces port to string, then determines port from that number or service name" do it "coerces port to string, then determines port from that number or service name" do
t = Object.new lambda { TCPServer.new(SocketSpecs.hostname, Object.new) }.should raise_error(TypeError)
lambda { TCPServer.new(SocketSpecs.hostname, t) }.should raise_error(TypeError)
def t.to_str; SocketSpecs.port.to_s; end port = Object.new
port.should_receive(:to_str).and_return("0")
@server = TCPServer.new(SocketSpecs.hostname, t) @server = TCPServer.new(SocketSpecs.hostname, port)
addr = @server.addr addr = @server.addr
addr[1].should == SocketSpecs.port addr[1].should be_kind_of(Fixnum)
# TODO: This should also accept strings like 'https', but I don't know how to # 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... # pick such a service port that will be able to reliably bind...
end end
it "raises Errno::EADDRNOTAVAIL when the adress is unknown" do it "raises Errno::EADDRNOTAVAIL when the adress is unknown" do
lambda { TCPServer.new("1.2.3.4", 4000) }.should raise_error(Errno::EADDRNOTAVAIL) lambda { TCPServer.new("1.2.3.4", 0) }.should raise_error(Errno::EADDRNOTAVAIL)
end end
# There is no way to make this fail-proof on all machines, because # There is no way to make this fail-proof on all machines, because
@ -73,15 +72,15 @@ describe "TCPServer.new" do
quarantine! do quarantine! do
it "raises a SocketError when the host is unknown" do it "raises a SocketError when the host is unknown" do
lambda { lambda {
TCPServer.new("--notavalidname", 4000) TCPServer.new("--notavalidname", 0)
}.should raise_error(SocketError) }.should raise_error(SocketError)
end end
end end
it "raises Errno::EADDRINUSE when address is already in use" do it "raises Errno::EADDRINUSE when address is already in use" do
@server = TCPServer.new('127.0.0.1', 0)
lambda { lambda {
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', @server.addr[1])
@server = TCPServer.new('127.0.0.1', SocketSpecs.port)
}.should raise_error(Errno::EADDRINUSE) }.should raise_error(Errno::EADDRINUSE)
end end
@ -89,7 +88,7 @@ describe "TCPServer.new" do
# A known bug in AIX. getsockopt(2) does not properly set # A known bug in AIX. getsockopt(2) does not properly set
# the fifth argument for SO_REUSEADDR. # the fifth argument for SO_REUSEADDR.
it "sets SO_REUSEADDR on the resulting server" do it "sets SO_REUSEADDR on the resulting server" do
@server = TCPServer.new('127.0.0.1', SocketSpecs.port) @server = TCPServer.new('127.0.0.1', 0)
@server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00" @server.getsockopt(:SOCKET, :REUSEADDR).data.should_not == "\x00\x00\x00\x00"
@server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0 @server.getsockopt(:SOCKET, :REUSEADDR).int.should_not == 0
end end

View file

@ -1,9 +0,0 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "TCPServer#<<" do
after :each do
@server.close if @server
@socket.close if @socket
end
end

View file

@ -1,9 +0,0 @@
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../../fixtures/classes', __FILE__)
describe "TCPServer#readpartial" do
after :each do
@server.close if @server
@socket.close if @socket
end
end

View file

@ -5,7 +5,8 @@ require 'socket'
describe "TCPServer#sysaccept" do describe "TCPServer#sysaccept" do
before :each do before :each do
@server = TCPServer.new(SocketSpecs.hostname, SocketSpecs.port) @server = TCPServer.new(SocketSpecs.hostname, 0)
@port = @server.addr[1]
end end
after :each do after :each do
@ -18,7 +19,7 @@ describe "TCPServer#sysaccept" do
it 'returns file descriptor of an accepted connection' do it 'returns file descriptor of an accepted connection' do
begin begin
sock = TCPSocket.new(SocketSpecs.hostname, SocketSpecs.port) sock = TCPSocket.new(SocketSpecs.hostname, @port)
fd = @server.sysaccept fd = @server.sysaccept

View file

@ -5,9 +5,8 @@ require File.expand_path('../../shared/partially_closable_sockets', __FILE__)
describe "TCPSocket partial closability" do describe "TCPSocket partial closability" do
before :each do before :each do
port = SocketSpecs.find_available_port @server = TCPServer.new("127.0.0.1", 0)
@server = TCPServer.new("127.0.0.1", port) @s1 = TCPSocket.new("127.0.0.1", @server.addr[1])
@s1 = TCPSocket.new("127.0.0.1", port)
@s2 = @server.accept @s2 = @server.accept
end end

View file

@ -44,8 +44,14 @@ describe :tcpsocket_new, shared: true do
end end
it "connects to a server when passed local_host and local_port arguments" do 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, @socket = TCPSocket.send(@method, @hostname, @server.port,
@hostname, SocketSpecs.local_port) @hostname, available_port)
@socket.should be_an_instance_of(TCPSocket) @socket.should be_an_instance_of(TCPSocket)
end end

View file

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

View file

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

View file

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

View file

@ -3,12 +3,12 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "UDPSocket.send" do describe "UDPSocket.send" do
before :each do before :each do
@ready = false @port = nil
@server_thread = Thread.new do @server_thread = Thread.new do
@server = UDPSocket.open @server = UDPSocket.open
begin begin
@server.bind(nil, SocketSpecs.port) @server.bind(nil, 0)
@ready = true @port = @server.addr[1]
begin begin
@msg = @server.recvfrom_nonblock(64) @msg = @server.recvfrom_nonblock(64)
rescue IO::WaitReadable rescue IO::WaitReadable
@ -19,12 +19,16 @@ describe "UDPSocket.send" do
@server.close if !@server.closed? @server.close if !@server.closed?
end end
end end
Thread.pass while @server_thread.status and !@ready Thread.pass while @server_thread.status and !@port
end
after :each do
@server_thread.join
end end
it "sends data in ad hoc mode" do it "sends data in ad hoc mode" do
@socket = UDPSocket.open @socket = UDPSocket.open
@socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.port) @socket.send("ad hoc", 0, SocketSpecs.hostname, @port)
@socket.close @socket.close
@server_thread.join @server_thread.join
@ -36,7 +40,7 @@ describe "UDPSocket.send" do
it "sends data in ad hoc mode (with port given as a String)" do it "sends data in ad hoc mode (with port given as a String)" do
@socket = UDPSocket.open @socket = UDPSocket.open
@socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.str_port) @socket.send("ad hoc", 0, SocketSpecs.hostname, @port.to_s)
@socket.close @socket.close
@server_thread.join @server_thread.join
@ -48,7 +52,7 @@ describe "UDPSocket.send" do
it "sends data in connection mode" do it "sends data in connection mode" do
@socket = UDPSocket.open @socket = UDPSocket.open
@socket.connect(SocketSpecs.hostname, SocketSpecs.port) @socket.connect(SocketSpecs.hostname, @port)
@socket.send("connection-based", 0) @socket.send("connection-based", 0)
@socket.close @socket.close
@server_thread.join @server_thread.join
@ -63,10 +67,10 @@ describe "UDPSocket.send" do
@socket = UDPSocket.open @socket = UDPSocket.open
begin begin
lambda do lambda do
@socket.send('1' * 100_000, 0, SocketSpecs.hostname, SocketSpecs.str_port) @socket.send('1' * 100_000, 0, SocketSpecs.hostname, @port.to_s)
end.should raise_error(Errno::EMSGSIZE) end.should raise_error(Errno::EMSGSIZE)
ensure ensure
@socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.port) @socket.send("ad hoc", 0, SocketSpecs.hostname, @port)
@socket.close @socket.close
@server_thread.join @server_thread.join
end end

View file

@ -4,11 +4,11 @@ require File.expand_path('../../fixtures/classes', __FILE__)
describe "UDPSocket#write" do describe "UDPSocket#write" do
it "raises EMSGSIZE if msg is too long" do it "raises EMSGSIZE if msg is too long" do
begin begin
host, port = SocketSpecs.hostname, SocketSpecs.port host = SocketSpecs.hostname
s1 = UDPSocket.new s1 = UDPSocket.new
s1.bind(host, port) s1.bind(host, 0)
s2 = UDPSocket.new s2 = UDPSocket.new
s2.connect(host, port) s2.connect(host, s1.addr[1])
lambda do lambda do
s2.write('1' * 100_000) s2.write('1' * 100_000)

View file

@ -5,53 +5,50 @@ platform_is_not :windows do
describe "UNIXServer#accept" do describe "UNIXServer#accept" do
before :each do before :each do
@path = SocketSpecs.socket_path @path = SocketSpecs.socket_path
@server = UNIXServer.open(@path)
end end
after :each do after :each do
@server.close if @server
SocketSpecs.rm_socket @path SocketSpecs.rm_socket @path
end end
it "accepts what is written by the client" do it "accepts what is written by the client" do
server = UNIXServer.open(@path)
client = UNIXSocket.open(@path) client = UNIXSocket.open(@path)
client.send('hello', 0) client.send('hello', 0)
sock = server.accept sock = @server.accept
data, info = sock.recvfrom(5) begin
data, info = sock.recvfrom(5)
data.should == 'hello' data.should == 'hello'
info.should_not be_empty info.should_not be_empty
ensure
server.close sock.close
client.close client.close
sock.close end
end end
it "can be interrupted by Thread#kill" do it "can be interrupted by Thread#kill" do
server = UNIXServer.new(@path)
t = Thread.new { t = Thread.new {
server.accept @server.accept
} }
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
# kill thread, ensure it dies in a reasonable amount of time # kill thread, ensure it dies in a reasonable amount of time
t.kill t.kill
a = 1 a = 0
while a < 2000 while t.alive? and a < 5000
break unless t.alive? sleep 0.001
Thread.pass
sleep 0.2
a += 1 a += 1
end end
a.should < 2000 a.should < 5000
server.close
end end
it "can be interrupted by Thread#raise" do it "can be interrupted by Thread#raise" do
server = UNIXServer.new(@path)
t = Thread.new { t = Thread.new {
server.accept @server.accept
} }
Thread.pass while t.status and t.status != "sleep" Thread.pass while t.status and t.status != "sleep"
@ -59,7 +56,6 @@ platform_is_not :windows do
ex = Exception.new ex = Exception.new
t.raise ex t.raise ex
lambda { t.join }.should raise_error(Exception) lambda { t.join }.should raise_error(Exception)
server.close
end end
end end
end end

View file

@ -1,10 +0,0 @@
#ifndef RUBYSPEC_CAPI_JRUBY_H
#define RUBYSPEC_CAPI_JRUBY_H
/* #undef any HAVE_ defines that JRuby does not have. */
#undef HAVE_RB_DEFINE_HOOKED_VARIABLE
#undef HAVE_RB_DEFINE_VARIABLE
#undef HAVE_RB_EXEC_RECURSIVE
#endif

View file

@ -1,8 +0,0 @@
#ifndef RUBYSPEC_CAPI_RUBINIUS_H
#define RUBYSPEC_CAPI_RUBINIUS_H
/* #undef any HAVE_ defines that Rubinius does not have. */
#undef HAVE_RB_DEFINE_HOOKED_VARIABLE
#undef HAVE_RB_DEFINE_VARIABLE
#endif

View file

@ -595,19 +595,4 @@
/* Util */ /* Util */
#define HAVE_RB_SCAN_ARGS 1 #define HAVE_RB_SCAN_ARGS 1
/* Now, create the differential set. The format of the preprocessor directives
* is significant. The alternative implementations should define RUBY because
* some extensions depend on that. But only one alternative implementation
* macro should be defined at a time. The conditional is structured so that if
* no alternative implementation is defined then MRI is assumed.
*/
#if defined(RUBINIUS)
#include "rubinius.h"
#elif defined(JRUBY)
#include "jruby.h"
#elif defined(TRUFFLERUBY)
#include "truffleruby.h"
#endif
#endif #endif

View file

@ -1,6 +0,0 @@
#ifndef RUBYSPEC_CAPI_TRUFFLERUBY_H
#undef RUBYSPEC_CAPI_TRUFFLERUBY_H
// All features are available
#endif

View file

@ -62,16 +62,18 @@ describe "CApiModule" do
mod = @m.rb_define_module_under(CApiModuleSpecs, "ModuleSpecsModuleUnder2") mod = @m.rb_define_module_under(CApiModuleSpecs, "ModuleSpecsModuleUnder2")
mod.name.should == "CApiModuleSpecs::ModuleSpecsModuleUnder2" mod.name.should == "CApiModuleSpecs::ModuleSpecsModuleUnder2"
end end
end
describe "rb_define_module_under" do
before :each do
compile_extension("module_under_autoload")
end
it "defines a module for an existing Autoload with an extension" do it "defines a module for an existing Autoload with an extension" do
compile_extension("module_under_autoload")
CApiModuleSpecs::ModuleUnderAutoload.name.should == "CApiModuleSpecs::ModuleUnderAutoload" CApiModuleSpecs::ModuleUnderAutoload.name.should == "CApiModuleSpecs::ModuleUnderAutoload"
end end
it "defines a module for an existing Autoload with a ruby object" do it "defines a module for an existing Autoload with a ruby object" do
compile_extension("module_under_autoload")
CApiModuleSpecs::RubyUnderAutoload.name.should == "CApiModuleSpecs::RubyUnderAutoload" CApiModuleSpecs::RubyUnderAutoload.name.should == "CApiModuleSpecs::RubyUnderAutoload"
end end
end end

View file

@ -1,9 +1,11 @@
require File.expand_path('../../../spec_helper', __FILE__) require File.expand_path('../../../spec_helper', __FILE__)
# MRI magic to use built but not installed ruby
$extmk = false $extmk = false
require 'rbconfig' require 'rbconfig'
OBJDIR ||= File.expand_path("../../../ext/#{RUBY_NAME}/#{RUBY_VERSION}", __FILE__) OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__)
mkdir_p(OBJDIR) mkdir_p(OBJDIR)
def extension_path def extension_path
@ -15,130 +17,59 @@ def object_path
end end
def compile_extension(name) def compile_extension(name)
preloadenv = RbConfig::CONFIG["PRELOADENV"] || "LD_PRELOAD" debug = false
preload, ENV[preloadenv] = ENV[preloadenv], nil if preloadenv run_mkmf_in_process = RUBY_ENGINE == 'truffleruby'
path = extension_path
objdir = object_path
# TODO use rakelib/ext_helper.rb?
arch_hdrdir = nil
if RUBY_NAME == 'rbx'
hdrdir = RbConfig::CONFIG["rubyhdrdir"]
elsif RUBY_NAME =~ /^ruby/
hdrdir = RbConfig::CONFIG["rubyhdrdir"]
arch_hdrdir = RbConfig::CONFIG["rubyarchhdrdir"]
elsif RUBY_NAME == 'jruby'
require 'mkmf'
hdrdir = $hdrdir
elsif RUBY_NAME == "maglev"
require 'mkmf'
hdrdir = $hdrdir
elsif RUBY_NAME == 'truffleruby'
return compile_truffleruby_extconf_make(name, path, objdir)
else
raise "Don't know how to build C extensions with #{RUBY_NAME}"
end
ext = "#{name}_spec"
source = File.join(path, "#{ext}.c")
obj = File.join(objdir, "#{ext}.#{RbConfig::CONFIG['OBJEXT']}")
lib = File.join(objdir, "#{ext}.#{RbConfig::CONFIG['DLEXT']}")
ruby_header = File.join(hdrdir, "ruby.h")
rubyspec_header = File.join(path, "rubyspec.h")
return lib if File.exist?(lib) and File.mtime(lib) > File.mtime(source) and
File.mtime(lib) > File.mtime(ruby_header) and
File.mtime(lib) > File.mtime(rubyspec_header) and
true # sentinel
# avoid problems where compilation failed but previous shlib exists
File.delete lib if File.exist? lib
cc = RbConfig::CONFIG["CC"]
cflags = (ENV["CFLAGS"] || RbConfig::CONFIG["CFLAGS"]).dup
cflags += " #{RbConfig::CONFIG["ARCH_FLAG"]}" if RbConfig::CONFIG["ARCH_FLAG"]
cflags += " #{RbConfig::CONFIG["CCDLFLAGS"]}" if RbConfig::CONFIG["CCDLFLAGS"]
cppflags = (ENV["CPPFLAGS"] || RbConfig::CONFIG["CPPFLAGS"]).dup
incflags = "-I#{path}"
incflags << " -I#{arch_hdrdir}" if arch_hdrdir
incflags << " -I#{hdrdir}"
csrcflag = RbConfig::CONFIG["CSRCFLAG"]
coutflag = RbConfig::CONFIG["COUTFLAG"]
compile_cmd = "#{cc} #{incflags} #{cflags} #{cppflags} #{coutflag}#{obj} -c #{csrcflag}#{source}"
output = `#{compile_cmd}`
unless $?.success? and File.exist?(obj)
puts "\nERROR:\n#{compile_cmd}\n#{output}"
puts "incflags=#{incflags}"
puts "cflags=#{cflags}"
puts "cppflags=#{cppflags}"
raise "Unable to compile \"#{source}\""
end
ldshared = RbConfig::CONFIG["LDSHARED"]
ldshared += " #{RbConfig::CONFIG["ARCH_FLAG"]}" if RbConfig::CONFIG["ARCH_FLAG"]
libs = RbConfig::CONFIG["LIBS"]
dldflags = "#{RbConfig::CONFIG["LDFLAGS"]} #{RbConfig::CONFIG["DLDFLAGS"]} #{RbConfig::CONFIG["EXTDLDFLAGS"]}"
dldflags.sub!(/-Wl,-soname,\S+/, '')
if /mswin/ =~ RUBY_PLATFORM
dldflags.sub!("$(LIBPATH)", RbConfig::CONFIG["LIBPATHFLAG"] % path)
libs += RbConfig::CONFIG["LIBRUBY"]
outflag = RbConfig::CONFIG["OUTFLAG"]
link_cmd = "#{ldshared} #{outflag}#{lib} #{obj} #{libs} -link #{dldflags} /export:Init_#{ext}"
else
libpath = "-L#{path}"
dldflags.sub!("$(TARGET_ENTRY)", "Init_#{ext}")
link_cmd = "#{ldshared} #{obj} #{libpath} #{dldflags} #{libs} -o #{lib}"
end
output = `#{link_cmd}`
unless $?.success?
puts "\nERROR:\n#{link_cmd}\n#{output}"
raise "Unable to link \"#{source}\""
end
lib
ensure
ENV[preloadenv] = preload if preloadenv
end
def compile_truffleruby_extconf_make(name, path, objdir)
ext = "#{name}_spec" ext = "#{name}_spec"
file = "#{ext}.c" lib = "#{object_path}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
source = "#{path}/#{ext}.c" ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
lib = "#{objdir}/#{ext}.#{RbConfig::CONFIG['DLEXT']}"
return lib if File.exist?(lib) and
File.mtime(lib) > File.mtime("#{extension_path}/rubyspec.h") and
File.mtime(lib) > File.mtime("#{extension_path}/#{ext}.c") and
File.mtime(lib) > File.mtime(ruby_header) and
true # sentinel
# Copy needed source files to tmpdir # Copy needed source files to tmpdir
tmpdir = tmp("cext_#{name}") tmpdir = tmp("cext_#{name}")
Dir.mkdir tmpdir Dir.mkdir(tmpdir)
begin begin
["rubyspec.h", "truffleruby.h", "#{ext}.c"].each do |file| ["rubyspec.h", "#{ext}.c"].each do |file|
cp "#{path}/#{file}", "#{tmpdir}/#{file}" cp "#{extension_path}/#{file}", "#{tmpdir}/#{file}"
end end
Dir.chdir(tmpdir) do Dir.chdir(tmpdir) do
required = require 'mkmf' if run_mkmf_in_process
# Reinitialize mkmf if already required required = require 'mkmf'
init_mkmf unless required # Reinitialize mkmf if already required
create_makefile(ext, tmpdir) init_mkmf unless required
system "make" create_makefile(ext, tmpdir)
else
copy_exts = RbConfig::CONFIG.values_at('OBJEXT', 'DLEXT') File.write("extconf.rb", "require 'mkmf'\n" +
Dir.glob("*.{#{copy_exts.join(',')}}") do |file| "$ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')\n" +
cp file, "#{objdir}/#{file}" # MRI magic to consider building non-bundled extensions
"$extout = nil\n" +
"create_makefile(#{ext.inspect})\n")
output = ruby_exe("extconf.rb")
raise "extconf failed:\n#{output}" unless $?.success?
$stderr.puts output if debug
end end
make = RbConfig::CONFIG['host_os'].include?("mswin") ? "nmake" : "make"
ENV.delete "MAKEFLAGS" # Fix make warning when invoked with -j in MRI
# Do not capture stderr as we want to show compiler warnings
output = `#{make} V=1`
raise "#{make} failed:\n#{output}" unless $?.success?
$stderr.puts output if debug
cp File.basename(lib), lib
end end
ensure ensure
rm_r tmpdir rm_r tmpdir
end end
File.chmod(0755, lib)
lib lib
end end

View file

@ -501,7 +501,7 @@ describe "C-API String function" do
describe "rb_str_hash" do describe "rb_str_hash" do
it "hashes the string into a number" do it "hashes the string into a number" do
s = "hello" s = "hello"
@s.rb_str_hash(s).should == s.hash @s.rb_str_hash(s).should be_kind_of(Integer)
end end
end end

View file

@ -165,28 +165,30 @@ describe "CApiTimeSpecs" do
usec.should == 500000 usec.should == 500000
end end
it "creates a timeval for a negative Fixnum" do platform_is_not :mingw32 do
sec, usec = @s.rb_time_timeval(-1232141421) it "creates a timeval for a negative Fixnum" do
sec.should be_kind_of(Integer) sec, usec = @s.rb_time_timeval(-1232141421)
sec.should == -1232141421 sec.should be_kind_of(Integer)
usec.should be_kind_of(Integer) sec.should == -1232141421
usec.should == 0 usec.should be_kind_of(Integer)
end usec.should == 0
end
it "creates a timeval for a negative Float" do it "creates a timeval for a negative Float" do
sec, usec = @s.rb_time_timeval(-1.5) sec, usec = @s.rb_time_timeval(-1.5)
sec.should be_kind_of(Integer) sec.should be_kind_of(Integer)
sec.should == -2 sec.should == -2
usec.should be_kind_of(Integer) usec.should be_kind_of(Integer)
usec.should == 500000 usec.should == 500000
end end
it "creates a timeval for a negative Rational" do it "creates a timeval for a negative Rational" do
sec, usec = @s.rb_time_timeval(Rational(-3, 2)) sec, usec = @s.rb_time_timeval(Rational(-3, 2))
sec.should be_kind_of(Integer) sec.should be_kind_of(Integer)
sec.should == -2 sec.should == -2
usec.should be_kind_of(Integer) usec.should be_kind_of(Integer)
usec.should == 500000 usec.should == 500000
end
end end
it "creates a timeval from a Time object" do it "creates a timeval from a Time object" do
@ -222,28 +224,30 @@ describe "CApiTimeSpecs" do
nsec.should == 500000000 nsec.should == 500000000
end end
it "creates a timespec for a negative Fixnum" do platform_is_not :mingw32 do
sec, nsec = @s.rb_time_timespec(-1232141421) it "creates a timespec for a negative Fixnum" do
sec.should be_kind_of(Integer) sec, nsec = @s.rb_time_timespec(-1232141421)
sec.should == -1232141421 sec.should be_kind_of(Integer)
nsec.should be_kind_of(Integer) sec.should == -1232141421
nsec.should == 0 nsec.should be_kind_of(Integer)
end nsec.should == 0
end
it "creates a timespec for a negative Float" do it "creates a timespec for a negative Float" do
sec, nsec = @s.rb_time_timespec(-1.5) sec, nsec = @s.rb_time_timespec(-1.5)
sec.should be_kind_of(Integer) sec.should be_kind_of(Integer)
sec.should == -2 sec.should == -2
nsec.should be_kind_of(Integer) nsec.should be_kind_of(Integer)
nsec.should == 500000000 nsec.should == 500000000
end end
it "creates a timespec for a negative Rational" do it "creates a timespec for a negative Rational" do
sec, nsec = @s.rb_time_timespec(Rational(-3, 2)) sec, nsec = @s.rb_time_timespec(Rational(-3, 2))
sec.should be_kind_of(Integer) sec.should be_kind_of(Integer)
sec.should == -2 sec.should == -2
nsec.should be_kind_of(Integer) nsec.should be_kind_of(Integer)
nsec.should == 500000000 nsec.should == 500000000
end
end end
it "creates a timespec from a Time object" do it "creates a timespec from a Time object" do