diff options
29 files changed, 430 insertions, 129 deletions
diff --git a/spec/rubyspec/.travis.yml b/spec/rubyspec/.travis.yml index 04da12a130..dd72c877f3 100644 --- a/spec/rubyspec/.travis.yml +++ b/spec/rubyspec/.travis.yml @@ -20,6 +20,9 @@ matrix: env: CHECK_LEAKS=true - os: linux rvm: ruby-head + allow_failures: + - os: linux + rvm: ruby-head branches: only: - master diff --git a/spec/rubyspec/core/dir/shared/delete.rb b/spec/rubyspec/core/dir/shared/delete.rb index 72d025bc63..8db17d985f 100644 --- a/spec/rubyspec/core/dir/shared/delete.rb +++ b/spec/rubyspec/core/dir/shared/delete.rb @@ -41,7 +41,7 @@ describe :dir_delete, shared: true do it "raises an Errno::ENOTDIR when trying to remove a non-directory" do file = DirSpecs.mock_rmdir("nonempty/regular") - open(file, "w") {} + touch(file) lambda do Dir.send @method, file end.should raise_error(Errno::ENOTDIR) diff --git a/spec/rubyspec/core/exception/uncaught_throw_error_spec.rb b/spec/rubyspec/core/exception/uncaught_throw_error_spec.rb new file mode 100644 index 0000000000..3ed166af5b --- /dev/null +++ b/spec/rubyspec/core/exception/uncaught_throw_error_spec.rb @@ -0,0 +1,19 @@ +require File.expand_path('../../../spec_helper', __FILE__) + +describe "UncaughtThrowError" do + it "is a subclass of ArgumentError" do + ArgumentError.should be_ancestor_of(UncaughtThrowError) + end +end + +describe "UncaughtThrowError#tag" do + it "returns the object thrown" do + begin + throw :abc + + rescue UncaughtThrowError => e + e.tag.should == :abc + end + end +end + diff --git a/spec/rubyspec/core/io/fixtures/classes.rb b/spec/rubyspec/core/io/fixtures/classes.rb index 5ff6f9aa72..fb431d5023 100644 --- a/spec/rubyspec/core/io/fixtures/classes.rb +++ b/spec/rubyspec/core/io/fixtures/classes.rb @@ -14,7 +14,7 @@ module IOSpecs "\n", "\n", "Aqu\303\255 est\303\241 la l\303\255nea tres.\n", - "Ist hier Linie vier.\n", + "Hier ist Zeile vier.\n", "\n", "Est\303\241 aqui a linha cinco.\n", "Here is line six.\n" ] @@ -31,8 +31,8 @@ module IOSpecs "Aquí está", " la línea", " tres.\n", - "Ist hier L", - "inie vier.", + "Hier ist Z", + "eile vier.", "\n", "\n", "Está aqui", @@ -55,9 +55,10 @@ module IOSpecs "está ", "la ", "línea ", - "tres.\nIst ", - "hier ", - "Linie ", + "tres.\nHier", + " ", + "ist ", + "Zeile ", "vier.\n\nEst", "á ", "aqui ", @@ -71,37 +72,35 @@ module IOSpecs end def self.lines_r_separator - [ "Voici la ligne une.\nQui \303\250 la linea due.\n\n\n" \ - "Aqu\303\255 est\303\241 la l\303\255nea tr", - "es.\nIst hier", - " Linie vier", + [ "Voici la ligne une.\nQui \303\250 la linea due.\n\n\nAqu\303\255 est\303\241 la l\303\255nea tr", + "es.\nHier", + " ist Zeile vier", ".\n\nEst\303\241 aqui a linha cinco.\nHer", "e is line six.\n" ] end def self.lines_empty_separator [ "Voici la ligne une.\nQui \303\250 la linea due.\n\n", - "Aqu\303\255 est\303\241 la l\303\255nea tres.\nIst hier Linie vier.\n\n", + "Aqu\303\255 est\303\241 la l\303\255nea tres.\nHier ist Zeile vier.\n\n", "Est\303\241 aqui a linha cinco.\nHere is line six.\n" ] end def self.lines_space_separator [ "Voici ", "la ", "ligne ", "une.\nQui ", "\303\250 ", "la ", "linea ", "due.\n\n\nAqu\303\255 ", - "est\303\241 ", "la ", "l\303\255nea ", "tres.\nIst ", - "hier ", "Linie ", "vier.\n\nEst\303\241 ", "aqui ", "a ", + "est\303\241 ", "la ", "l\303\255nea ", "tres.\nHier ", + "ist ", "Zeile ", "vier.\n\nEst\303\241 ", "aqui ", "a ", "linha ", "cinco.\nHere ", "is ", "line ", "six.\n" ] end def self.lines_arbitrary_separator [ "Voici la ligne une.\nQui \303\250", - " la linea due.\n\n\nAqu\303\255 est\303\241 la l\303\255nea tres.\n" \ - "Ist hier Linie vier.\n\nEst\303\241 aqui a linha cinco.\nHere is line six.\n" ] + " la linea due.\n\n\nAqu\303\255 est\303\241 la l\303\255nea tres.\nHier ist Zeile vier.\n\nEst\303\241 aqui a linha cinco.\nHere is line six.\n" ] end def self.paragraphs [ "Voici la ligne une.\nQui \303\250 la linea due.\n\n", - "Aqu\303\255 est\303\241 la l\303\255nea tres.\nIst hier Linie vier.\n\n", + "Aqu\303\255 est\303\241 la l\303\255nea tres.\nHier ist Zeile vier.\n\n", "Est\303\241 aqui a linha cinco.\nHere is line six.\n" ] end diff --git a/spec/rubyspec/core/io/fixtures/lines.txt b/spec/rubyspec/core/io/fixtures/lines.txt index a64d8ff6bb..0959997e7b 100644 --- a/spec/rubyspec/core/io/fixtures/lines.txt +++ b/spec/rubyspec/core/io/fixtures/lines.txt @@ -3,7 +3,7 @@ Qui è la linea due. Aquí está la línea tres. -Ist hier Linie vier. +Hier ist Zeile vier. Está aqui a linha cinco. Here is line six. diff --git a/spec/rubyspec/core/kernel/gets_spec.rb b/spec/rubyspec/core/kernel/gets_spec.rb index eb68e093ab..c775b2b7a4 100644 --- a/spec/rubyspec/core/kernel/gets_spec.rb +++ b/spec/rubyspec/core/kernel/gets_spec.rb @@ -5,6 +5,11 @@ describe "Kernel#gets" do it "is a private method" do Kernel.should have_private_instance_method(:gets) end + + it "calls ARGF.gets" do + ARGF.should_receive(:gets).and_return("spec") + gets.should == "spec" + end end describe "Kernel.gets" do diff --git a/spec/rubyspec/core/kernel/system_spec.rb b/spec/rubyspec/core/kernel/system_spec.rb index ccbd43cfde..aee75441a2 100644 --- a/spec/rubyspec/core/kernel/system_spec.rb +++ b/spec/rubyspec/core/kernel/system_spec.rb @@ -42,7 +42,7 @@ describe :kernel_system, shared: true do @shell = ENV['SHELL'] end - before :each do + after :each do ENV['SHELL'] = @shell end @@ -51,7 +51,7 @@ describe :kernel_system, shared: true do end it "ignores SHELL env var and always uses `sh`" do - ENV['SHELL'] = "/bin/zsh" + ENV['SHELL'] = "/bin/fakeshell" lambda { @object.system("echo $0") }.should output_to_fd("sh\n") end end diff --git a/spec/rubyspec/core/kernel/test_spec.rb b/spec/rubyspec/core/kernel/test_spec.rb index 1a6e346616..43e3a963e3 100644 --- a/spec/rubyspec/core/kernel/test_spec.rb +++ b/spec/rubyspec/core/kernel/test_spec.rb @@ -46,7 +46,7 @@ describe "Kernel#test" do context "writable test" do before do @tmp_file = tmp("file.kernel.test") - open(@tmp_file, "w") {} + touch(@tmp_file) end after do diff --git a/spec/rubyspec/language/alias_spec.rb b/spec/rubyspec/language/alias_spec.rb index 626e37a603..e9f0050e17 100644 --- a/spec/rubyspec/language/alias_spec.rb +++ b/spec/rubyspec/language/alias_spec.rb @@ -24,6 +24,62 @@ describe "The alias keyword" do @obj.__value.should == 5 end + it "works with a simple symbol on the left-hand side" do + @meta.class_eval do + alias :a value + end + @obj.a.should == 5 + end + + it "works with a single quoted symbol on the left-hand side" do + @meta.class_eval do + alias :'a' value + end + @obj.a.should == 5 + end + + it "works with a doubule quoted symbol on the left-hand side" do + @meta.class_eval do + alias :"a" value + end + @obj.a.should == 5 + end + + it "works with an interoplated symbol on the left-hand side" do + @meta.class_eval do + alias :"#{'a'}" value + end + @obj.a.should == 5 + end + + it "works with a simple symbol on the right-hand side" do + @meta.class_eval do + alias a :value + end + @obj.a.should == 5 + end + + it "works with a single quoted symbol on the right-hand side" do + @meta.class_eval do + alias a :'value' + end + @obj.a.should == 5 + end + + it "works with a doubule quoted symbol on the right-hand side" do + @meta.class_eval do + alias a :"value" + end + @obj.a.should == 5 + end + + it "works with an interoplated symbol on the right-hand side" do + @meta.class_eval do + alias a :"#{'value'}" + end + @obj.a.should == 5 + end + it "adds the new method to the list of methods" do original_methods = @obj.methods @meta.class_eval do diff --git a/spec/rubyspec/language/undef_spec.rb b/spec/rubyspec/language/undef_spec.rb index 5e15d2a254..5425b78876 100644 --- a/spec/rubyspec/language/undef_spec.rb +++ b/spec/rubyspec/language/undef_spec.rb @@ -1,16 +1,49 @@ require File.expand_path('../../spec_helper', __FILE__) describe "The undef keyword" do - it "undefines a method" do - undef_class = Class.new do - def meth(o); o; end + describe "undefines a method" do + before :each do + @undef_class = Class.new do + def meth(o); o; end + end + @obj = @undef_class.new + @obj.meth(5).should == 5 end - obj = undef_class.new - obj.meth(5).should == 5 - undef_class.class_eval do - undef meth + + it "with an identifier" do + @undef_class.class_eval do + undef meth + end + lambda { @obj.meth(5) }.should raise_error(NoMethodError) + end + + it "with a simple symbol" do + @undef_class.class_eval do + undef :meth + end + lambda { @obj.meth(5) }.should raise_error(NoMethodError) + end + + it "with a single quoted symbol" do + @undef_class.class_eval do + undef :'meth' + end + lambda { @obj.meth(5) }.should raise_error(NoMethodError) + end + + it "with a double quoted symbol" do + @undef_class.class_eval do + undef :"meth" + end + lambda { @obj.meth(5) }.should raise_error(NoMethodError) + end + + it "with a interpolated symbol" do + @undef_class.class_eval do + undef :"#{'meth'}" + end + lambda { @obj.meth(5) }.should raise_error(NoMethodError) end - lambda { obj.meth(5) }.should raise_error(NoMethodError) end it "allows undefining multiple methods at a time" do diff --git a/spec/rubyspec/library/cgi/cookie/to_s_spec.rb b/spec/rubyspec/library/cgi/cookie/to_s_spec.rb index 88aa75c927..806071ba69 100644 --- a/spec/rubyspec/library/cgi/cookie/to_s_spec.rb +++ b/spec/rubyspec/library/cgi/cookie/to_s_spec.rb @@ -23,7 +23,20 @@ describe "CGI::Cookie#to_s" do end it "escapes the self's values" do - cookie = CGI::Cookie.new("test-cookie", " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~") - cookie.to_s.should == "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~; path=" + cookie = CGI::Cookie.new("test-cookie", " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}") + cookie.to_s.should == "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D; path=" end + + ruby_version_is ""..."2.5" do + it "escapes tilde" do + cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=%7E; path=" + end + end + + ruby_version_is "2.5" do + it "does not escape tilde" do + cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path=" + end + end + end diff --git a/spec/rubyspec/library/socket/basicsocket/recv_spec.rb b/spec/rubyspec/library/socket/basicsocket/recv_spec.rb index 9f3227dc65..5ac274f6d8 100644 --- a/spec/rubyspec/library/socket/basicsocket/recv_spec.rb +++ b/spec/rubyspec/library/socket/basicsocket/recv_spec.rb @@ -9,8 +9,7 @@ describe "BasicSocket#recv" do end after :each do - @server.closed?.should be_false - @server.close + @server.close unless @server.closed? ScratchPad.clear end @@ -83,8 +82,11 @@ describe "BasicSocket#recv" do client = @server.accept buf = "foo" - client.recv(4, 0, buf) - client.close + begin + client.recv(4, 0, buf) + ensure + client.close + end buf.should == "data" socket.close diff --git a/spec/rubyspec/library/socket/fixtures/classes.rb b/spec/rubyspec/library/socket/fixtures/classes.rb index b772df5a39..6828f9fad5 100644 --- a/spec/rubyspec/library/socket/fixtures/classes.rb +++ b/spec/rubyspec/library/socket/fixtures/classes.rb @@ -72,26 +72,20 @@ module SocketSpecs # TCPServer echo server accepting one connection class SpecTCPServer - attr_accessor :hostname, :port, :logger + attr_reader :hostname, :port - def initialize(host=nil, port=nil, logger=nil) - @hostname = host || SocketSpecs.hostname - @port = port || SocketSpecs.port - @logger = logger + def initialize + @hostname = SocketSpecs.hostname + @server = TCPServer.new @hostname, 0 + @port = @server.addr[1] - start - end - - def start log "SpecTCPServer starting on #{@hostname}:#{@port}" - @server = TCPServer.new @hostname, @port @thread = Thread.new do socket = @server.accept log "SpecTCPServer accepted connection: #{socket}" service socket end - self end def service(socket) diff --git a/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb b/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb index 565a1795e9..ccf7b1cc51 100644 --- a/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb +++ b/spec/rubyspec/library/socket/ipsocket/recvfrom_spec.rb @@ -17,8 +17,11 @@ describe "Socket::IPSocket#recvfrom" do data = nil t = Thread.new do client = @server.accept - data = client.recvfrom(6) - client.close + begin + data = client.recvfrom(6) + ensure + client.close + end end @client.send('hello', 0) @@ -33,8 +36,11 @@ describe "Socket::IPSocket#recvfrom" do data = nil t = Thread.new do client = @server.accept - data = client.recvfrom(3) - client.close + begin + data = client.recvfrom(3) + ensure + client.close + end end @client.send('hello', 0) diff --git a/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb b/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb index 1d89aa866c..237ff781a3 100644 --- a/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb +++ b/spec/rubyspec/library/socket/tcpsocket/recv_nonblock_spec.rb @@ -16,7 +16,7 @@ describe "TCPSocket#recv_nonblock" do end it "returns a String read from the socket" do - @socket = TCPSocket.new @hostname, SocketSpecs.port + @socket = TCPSocket.new @hostname, @server.port @socket.write "TCPSocket#recv_nonblock" # Wait for the server to echo. This spec is testing the return @@ -29,7 +29,7 @@ describe "TCPSocket#recv_nonblock" do ruby_version_is '2.3' do it 'returns :wait_readable in exceptionless mode' do - @socket = TCPSocket.new @hostname, SocketSpecs.port + @socket = TCPSocket.new @hostname, @server.port @socket.recv_nonblock(50, exception: false).should == :wait_readable end end diff --git a/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb b/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb index 8eacc1275d..8a0cb443b5 100644 --- a/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb +++ b/spec/rubyspec/library/socket/tcpsocket/setsockopt_spec.rb @@ -5,10 +5,7 @@ describe "TCPSocket#setsockopt" do before :each do @server = SocketSpecs::SpecTCPServer.new @hostname = @server.hostname - end - - before :each do - @sock = TCPSocket.new @hostname, SocketSpecs.port + @sock = TCPSocket.new @hostname, @server.port end after :each do diff --git a/spec/rubyspec/library/socket/tcpsocket/shared/new.rb b/spec/rubyspec/library/socket/tcpsocket/shared/new.rb index d172456923..14b6e4373b 100644 --- a/spec/rubyspec/library/socket/tcpsocket/shared/new.rb +++ b/spec/rubyspec/library/socket/tcpsocket/shared/new.rb @@ -29,28 +29,28 @@ describe :tcpsocket_new, shared: true do end it "silently ignores 'nil' as the third parameter" do - @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port, nil) + @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, SocketSpecs.port) + @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, SocketSpecs.port, @hostname) + @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 - @socket = TCPSocket.send(@method, @hostname, SocketSpecs.port, + @socket = TCPSocket.send(@method, @hostname, @server.port, @hostname, SocketSpecs.local_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, SocketSpecs.port) + @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 diff --git a/spec/rubyspec/library/socket/udpsocket/send_spec.rb b/spec/rubyspec/library/socket/udpsocket/send_spec.rb index ad0e6a7f2f..feff020dd7 100644 --- a/spec/rubyspec/library/socket/udpsocket/send_spec.rb +++ b/spec/rubyspec/library/socket/udpsocket/send_spec.rb @@ -6,22 +6,25 @@ describe "UDPSocket.send" do @ready = false @server_thread = Thread.new do @server = UDPSocket.open - @server.bind(nil, SocketSpecs.port) - @ready = true begin - @msg = @server.recvfrom_nonblock(64) - rescue IO::WaitReadable - IO.select([@server]) - retry + @server.bind(nil, SocketSpecs.port) + @ready = true + begin + @msg = @server.recvfrom_nonblock(64) + rescue IO::WaitReadable + IO.select([@server]) + retry + end + ensure + @server.close if !@server.closed? end - @server.close end Thread.pass while @server_thread.status and !@ready end it "sends data in ad hoc mode" do @socket = UDPSocket.open - @socket.send("ad hoc", 0, SocketSpecs.hostname,SocketSpecs.port) + @socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.port) @socket.close @server_thread.join @@ -33,7 +36,7 @@ describe "UDPSocket.send" do it "sends data in ad hoc mode (with port given as a String)" do @socket = UDPSocket.open - @socket.send("ad hoc", 0, SocketSpecs.hostname,SocketSpecs.str_port) + @socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.str_port) @socket.close @server_thread.join @@ -45,7 +48,7 @@ describe "UDPSocket.send" do it "sends data in connection mode" do @socket = UDPSocket.open - @socket.connect(SocketSpecs.hostname,SocketSpecs.port) + @socket.connect(SocketSpecs.hostname, SocketSpecs.port) @socket.send("connection-based", 0) @socket.close @server_thread.join @@ -55,4 +58,17 @@ describe "UDPSocket.send" do @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, SocketSpecs.str_port) + end.should raise_error(Errno::EMSGSIZE) + ensure + @socket.send("ad hoc", 0, SocketSpecs.hostname, SocketSpecs.port) + @socket.close + @server_thread.join + end + end end diff --git a/spec/rubyspec/library/socket/udpsocket/write_spec.rb b/spec/rubyspec/library/socket/udpsocket/write_spec.rb new file mode 100644 index 0000000000..97985ff7ae --- /dev/null +++ b/spec/rubyspec/library/socket/udpsocket/write_spec.rb @@ -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, port = SocketSpecs.hostname, SocketSpecs.port + s1 = UDPSocket.new + s1.bind(host, port) + s2 = UDPSocket.new + s2.connect(host, port) + + 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 diff --git a/spec/rubyspec/library/yaml/dump_spec.rb b/spec/rubyspec/library/yaml/dump_spec.rb index 10b29ced2b..c3613521e0 100644 --- a/spec/rubyspec/library/yaml/dump_spec.rb +++ b/spec/rubyspec/library/yaml/dump_spec.rb @@ -42,6 +42,10 @@ describe "YAML.dump" do it "dumps a File without any state" do file = File.new(__FILE__) - YAML.dump(file).should match_yaml("--- !ruby/object:File {}\n") + begin + YAML.dump(file).should match_yaml("--- !ruby/object:File {}\n") + ensure + file.close + end end end diff --git a/spec/rubyspec/library/zlib/crc_table_spec.rb b/spec/rubyspec/library/zlib/crc_table_spec.rb index de40232d38..22aaa32233 100644 --- a/spec/rubyspec/library/zlib/crc_table_spec.rb +++ b/spec/rubyspec/library/zlib/crc_table_spec.rb @@ -4,8 +4,72 @@ require "zlib" describe "Zlib.crc_table" do it "returns the same value as zlib's get_crc_table()" do - Zlib.crc_table.should == - [0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035, 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049, 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639, 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317, 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443, 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665, 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303, 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565, 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059, 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297, 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223, 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405, 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995, 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649, 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015, 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989, 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523, 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377, 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879, 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637, 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859, 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161, 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815, 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221, 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371, 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881, 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567, 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701, 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035, 2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897, 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431, 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117] + Zlib.crc_table.should == [ + 0, 1996959894, 3993919788, 2567524794, + 124634137, 1886057615, 3915621685, 2657392035, + 249268274, 2044508324, 3772115230, 2547177864, + 162941995, 2125561021, 3887607047, 2428444049, + 498536548, 1789927666, 4089016648, 2227061214, + 450548861, 1843258603, 4107580753, 2211677639, + 325883990, 1684777152, 4251122042, 2321926636, + 335633487, 1661365465, 4195302755, 2366115317, + 997073096, 1281953886, 3579855332, 2724688242, + 1006888145, 1258607687, 3524101629, 2768942443, + 901097722, 1119000684, 3686517206, 2898065728, + 853044451, 1172266101, 3705015759, 2882616665, + 651767980, 1373503546, 3369554304, 3218104598, + 565507253, 1454621731, 3485111705, 3099436303, + 671266974, 1594198024, 3322730930, 2970347812, + 795835527, 1483230225, 3244367275, 3060149565, + 1994146192, 31158534, 2563907772, 4023717930, + 1907459465, 112637215, 2680153253, 3904427059, + 2013776290, 251722036, 2517215374, 3775830040, + 2137656763, 141376813, 2439277719, 3865271297, + 1802195444, 476864866, 2238001368, 4066508878, + 1812370925, 453092731, 2181625025, 4111451223, + 1706088902, 314042704, 2344532202, 4240017532, + 1658658271, 366619977, 2362670323, 4224994405, + 1303535960, 984961486, 2747007092, 3569037538, + 1256170817, 1037604311, 2765210733, 3554079995, + 1131014506, 879679996, 2909243462, 3663771856, + 1141124467, 855842277, 2852801631, 3708648649, + 1342533948, 654459306, 3188396048, 3373015174, + 1466479909, 544179635, 3110523913, 3462522015, + 1591671054, 702138776, 2966460450, 3352799412, + 1504918807, 783551873, 3082640443, 3233442989, + 3988292384, 2596254646, 62317068, 1957810842, + 3939845945, 2647816111, 81470997, 1943803523, + 3814918930, 2489596804, 225274430, 2053790376, + 3826175755, 2466906013, 167816743, 2097651377, + 4027552580, 2265490386, 503444072, 1762050814, + 4150417245, 2154129355, 426522225, 1852507879, + 4275313526, 2312317920, 282753626, 1742555852, + 4189708143, 2394877945, 397917763, 1622183637, + 3604390888, 2714866558, 953729732, 1340076626, + 3518719985, 2797360999, 1068828381, 1219638859, + 3624741850, 2936675148, 906185462, 1090812512, + 3747672003, 2825379669, 829329135, 1181335161, + 3412177804, 3160834842, 628085408, 1382605366, + 3423369109, 3138078467, 570562233, 1426400815, + 3317316542, 2998733608, 733239954, 1555261956, + 3268935591, 3050360625, 752459403, 1541320221, + 2607071920, 3965973030, 1969922972, 40735498, + 2617837225, 3943577151, 1913087877, 83908371, + 2512341634, 3803740692, 2075208622, 213261112, + 2463272603, 3855990285, 2094854071, 198958881, + 2262029012, 4057260610, 1759359992, 534414190, + 2176718541, 4139329115, 1873836001, 414664567, + 2282248934, 4279200368, 1711684554, 285281116, + 2405801727, 4167216745, 1634467795, 376229701, + 2685067896, 3608007406, 1308918612, 956543938, + 2808555105, 3495958263, 1231636301, 1047427035, + 2932959818, 3654703836, 1088359270, 936918000, + 2847714899, 3736837829, 1202900863, 817233897, + 3183342108, 3401237130, 1404277552, 615818150, + 3134207493, 3453421203, 1423857449, 601450431, + 3009837614, 3294710456, 1567103746, 711928724, + 3020668471, 3272380065, 1510334235, 755167117, + ] end end diff --git a/spec/rubyspec/optional/capi/false_spec.rb b/spec/rubyspec/optional/capi/boolean_spec.rb index 8c0d94cf70..49303662e7 100644 --- a/spec/rubyspec/optional/capi/false_spec.rb +++ b/spec/rubyspec/optional/capi/boolean_spec.rb @@ -2,11 +2,23 @@ require File.expand_path('../spec_helper', __FILE__) load_extension("boolean") -describe "CApiFalseSpecs" do +describe "CApiBooleanSpecs" do before :each do @b = CApiBooleanSpecs.new end + describe "a true value from Ruby" do + it "is truthy in C" do + @b.is_true(true).should == 1 + end + end + + describe "a true value from Qtrue" do + it "is truthy in C" do + @b.is_true(@b.q_true).should == 1 + end + end + describe "a false value from Ruby" do it "is falsey in C" do @b.is_true(false).should == 2 diff --git a/spec/rubyspec/optional/capi/ext/io_spec.c b/spec/rubyspec/optional/capi/ext/io_spec.c index 491ceed9cb..751cb33fd8 100644 --- a/spec/rubyspec/optional/capi/ext/io_spec.c +++ b/spec/rubyspec/optional/capi/ext/io_spec.c @@ -2,7 +2,7 @@ #include "rubyspec.h" #include "ruby/io.h" #include <fcntl.h> -#if HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include <unistd.h> #endif @@ -145,13 +145,13 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) { wait_bool ret; if (set_non_blocking(fd) == -1) - rb_sys_fail(0); + rb_sys_fail("set_non_blocking failed"); if(RTEST(read_p)) { - rb_ivar_set(self, rb_intern("@write_data"), Qtrue); if(read(fd, buf, RB_IO_WAIT_READABLE_BUF) != -1) { return Qnil; } + rb_ivar_set(self, rb_intern("@write_data"), Qtrue); } ret = rb_io_wait_readable(fd); diff --git a/spec/rubyspec/optional/capi/ext/kernel_spec.c b/spec/rubyspec/optional/capi/ext/kernel_spec.c index d855b5689f..f126bd0a4a 100644 --- a/spec/rubyspec/optional/capi/ext/kernel_spec.c +++ b/spec/rubyspec/optional/capi/ext/kernel_spec.c @@ -183,6 +183,18 @@ VALUE kernel_spec_rb_rescue2(int argc, VALUE *args, VALUE self) { } #endif +#ifdef HAVE_RB_PROTECT +static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) { + int status = 0; + VALUE res = rb_protect(rb_yield, obj, &status); + rb_ary_store(ary, 0, INT2NUM(23)); + if (status) { + rb_jump_tag(status); + } + return res; +} +#endif + #ifdef HAVE_RB_SYS_FAIL VALUE kernel_spec_rb_sys_fail(VALUE self, VALUE msg) { errno = 1; @@ -217,6 +229,21 @@ VALUE kernel_spec_rb_warn(VALUE self, VALUE msg) { static VALUE kernel_spec_rb_yield(VALUE self, VALUE obj) { return rb_yield(obj); } + +static int kernel_cb(const void *a, const void *b) { + rb_yield(Qtrue); + return 0; +} + +static VALUE kernel_indirected(int (*compar)(const void *, const void *)) { + int bob[] = { 1, 1, 2, 3, 5, 8, 13 }; + qsort(bob, 7, sizeof(int), compar); + return Qfalse; +} + +static VALUE kernel_spec_rb_yield_indirected(VALUE self, VALUE obj) { + return kernel_indirected(kernel_cb); +} #endif #ifdef HAVE_RB_YIELD_SPLAT @@ -338,6 +365,10 @@ void Init_kernel_spec(void) { rb_define_method(cls, "rb_rescue2", kernel_spec_rb_rescue2, -1); #endif +#ifdef HAVE_RB_PROTECT + rb_define_method(cls, "rb_protect_yield", kernel_spec_rb_protect_yield, 2); +#endif + #ifdef HAVE_RB_CATCH rb_define_method(cls, "rb_catch", kernel_spec_rb_catch, 2); #endif @@ -360,6 +391,7 @@ void Init_kernel_spec(void) { #ifdef HAVE_RB_YIELD rb_define_method(cls, "rb_yield", kernel_spec_rb_yield, 1); + rb_define_method(cls, "rb_yield_indirected", kernel_spec_rb_yield_indirected, 1); #endif #ifdef HAVE_RB_YIELD_VALUES diff --git a/spec/rubyspec/optional/capi/ext/rubyspec.h b/spec/rubyspec/optional/capi/ext/rubyspec.h index f20bdde37c..aa0f4def19 100644 --- a/spec/rubyspec/optional/capi/ext/rubyspec.h +++ b/spec/rubyspec/optional/capi/ext/rubyspec.h @@ -366,6 +366,7 @@ #define HAVE_RB_YIELD_VALUES 1 #define HAVE_RB_FUNCALL3 1 #define HAVE_RB_FUNCALL_WITH_BLOCK 1 +#define HAVE_RB_PROTECT 1 /* GC */ #define HAVE_RB_GC_REGISTER_ADDRESS 1 diff --git a/spec/rubyspec/optional/capi/io_spec.rb b/spec/rubyspec/optional/capi/io_spec.rb index a0bcc9ef15..bc75ad4307 100644 --- a/spec/rubyspec/optional/capi/io_spec.rb +++ b/spec/rubyspec/optional/capi/io_spec.rb @@ -259,18 +259,18 @@ describe "C-API IO function" do it "raises and IOError if passed a closed stream" do @r_io.close - lambda { @o.rb_io_wait_readable(@r_io, false) }.should raise_error(IOError) + lambda { + @o.rb_io_wait_readable(@r_io, false) + }.should raise_error(IOError) end it "blocks until the io is readable and returns true" do @o.instance_variable_set :@write_data, false thr = Thread.new do - sleep 0.1 until @o.instance_variable_get(:@write_data) + Thread.pass until @o.instance_variable_get(:@write_data) @w_io.write "rb_io_wait_readable" end - Thread.pass until thr.alive? - @o.rb_io_wait_readable(@r_io, true).should be_true @o.instance_variable_get(:@read_data).should == "rb_io_wait_re" @@ -284,7 +284,7 @@ describe "C-API IO function" do start = false thr = Thread.new do start = true - sleep 0.5 + sleep 0.05 @w_io.write "rb_io_wait_readable" end diff --git a/spec/rubyspec/optional/capi/kernel_spec.rb b/spec/rubyspec/optional/capi/kernel_spec.rb index 4d721b4b56..5747fe169f 100644 --- a/spec/rubyspec/optional/capi/kernel_spec.rb +++ b/spec/rubyspec/optional/capi/kernel_spec.rb @@ -184,6 +184,18 @@ describe "C-API Kernel function" do it "raises LocalJumpError when no block is given" do lambda { @s.rb_yield(1) }.should raise_error(LocalJumpError) end + + it "rb_yield to a block that breaks does not raise an error" do + @s.rb_yield(1) { break }.should == nil + end + + it "rb_yield to a block that breaks with a value returns the value" do + @s.rb_yield(1) { break 73 }.should == 73 + end + + it "rb_yield through a callback to a block that breaks with a value returns the value" do + @s.rb_yield_indirected(1) { break 73 }.should == 73 + end end describe "rb_yield_values" do @@ -218,6 +230,36 @@ describe "C-API Kernel function" do end end + describe "rb_protect" do + it "will run a function with an argument" do + proof = [] # Hold proof of work performed after the yield. + res = @s.rb_protect_yield(7, proof) { |x| x + 1 } + res.should == 8 + proof[0].should == 23 + end + + it "will allow cleanup code to run after break" do + proof = [] # Hold proof of work performed after the yield. + @s.rb_protect_yield(7, proof) { |x| break } + proof[0].should == 23 + end + + it "will allow cleanup code to run after break with value" do + proof = [] # Hold proof of work performed after the yield. + res = @s.rb_protect_yield(7, proof) { |x| break x + 1 } + res.should == 8 + proof[0].should == 23 + end + + it "will allow cleanup code to run after a raise" do + proof = [] # Hold proof of work performed after the yield. + lambda do + @s.rb_protect_yield(7, proof) { |x| raise NameError} + end.should raise_error(NameError) + proof[0].should == 23 + end +end + describe "rb_rescue" do before :each do @proc = lambda { |x| x } diff --git a/spec/rubyspec/optional/capi/spec_helper.rb b/spec/rubyspec/optional/capi/spec_helper.rb index f8314029c9..2a0c515306 100644 --- a/spec/rubyspec/optional/capi/spec_helper.rb +++ b/spec/rubyspec/optional/capi/spec_helper.rb @@ -2,8 +2,6 @@ require File.expand_path('../../../spec_helper', __FILE__) $extmk = false require 'rbconfig' -require 'fileutils' -require 'tmpdir' OBJDIR ||= File.expand_path("../../../ext/#{RUBY_NAME}/#{RUBY_VERSION}", __FILE__) mkdir_p(OBJDIR) @@ -83,15 +81,13 @@ def compile_extension(name) ldshared = RbConfig::CONFIG["LDSHARED"] ldshared += " #{RbConfig::CONFIG["ARCH_FLAG"]}" if RbConfig::CONFIG["ARCH_FLAG"] - libs = RbConfig::CONFIG["LIBRUBYARG_SHARED"] - libs += " " if libs - libs += RbConfig::CONFIG["LIBS"] + libs = RbConfig::CONFIG["LIBS"] dldflags = "#{RbConfig::CONFIG["LDFLAGS"]} #{RbConfig::CONFIG["DLDFLAGS"]} #{RbConfig::CONFIG["EXTDLDFLAGS"]}" dldflags.sub!(/-Wl,-soname,\S+/, '') - dldflags.sub!(/\$\(DEFFILE\)/, '') 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}" @@ -114,29 +110,36 @@ ensure end def compile_truffleruby_extconf_make(name, path, objdir) - ext = "#{name}_spec" - file = "#{ext}.c" - source = "#{path}/#{file}" - lib_target = "#{objdir}/#{ext}.#{RbConfig::CONFIG['DLEXT']}" - temp_dir = Dir.mktmpdir + ext = "#{name}_spec" + file = "#{ext}.c" + source = "#{path}/#{ext}.c" + lib = "#{objdir}/#{ext}.#{RbConfig::CONFIG['DLEXT']}" + + # Copy needed source files to tmpdir + tmpdir = tmp("cext_#{name}") + Dir.mkdir tmpdir begin - copy = "#{temp_dir}/#{file}" - FileUtils.cp "#{path}/rubyspec.h", temp_dir - FileUtils.cp "#{path}/truffleruby.h", temp_dir - FileUtils.cp source, copy - extconf_src = "require 'mkmf'\n" + - "create_makefile('#{ext}', '#{temp_dir}')" - File.write("#{temp_dir}/extconf.rb", extconf_src) - Dir.chdir(temp_dir) do - system "#{RbConfig.ruby} extconf.rb" - system "make" # run make in temp dir - FileUtils.cp "#{ext}.su", lib_target # copy to .su file to library dir - FileUtils.cp "#{ext}.bc", objdir # copy to .bc file to library dir + ["rubyspec.h", "truffleruby.h", "#{ext}.c"].each do |file| + cp "#{path}/#{file}", "#{tmpdir}/#{file}" + end + + Dir.chdir(tmpdir) do + required = require 'mkmf' + # Reinitialize mkmf if already required + init_mkmf unless required + create_makefile(ext, tmpdir) + system "make" + + copy_exts = RbConfig::CONFIG.values_at('OBJEXT', 'DLEXT') + Dir.glob("*.{#{copy_exts.join(',')}}") do |file| + cp file, "#{objdir}/#{file}" + end end ensure - FileUtils.remove_entry temp_dir + rm_r tmpdir end - lib_target + + lib end def load_extension(name) diff --git a/spec/rubyspec/optional/capi/true_spec.rb b/spec/rubyspec/optional/capi/true_spec.rb deleted file mode 100644 index fcb57567ec..0000000000 --- a/spec/rubyspec/optional/capi/true_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require File.expand_path('../spec_helper', __FILE__) - -load_extension("boolean") - -describe "CApiTrueSpecs" do - before :each do - @b = CApiBooleanSpecs.new - end - - describe "a true value from Ruby" do - it "is truthy in C" do - @b.is_true(true).should == 1 - end - end - - describe "a true value from Qtrue" do - it "is truthy in C" do - @b.is_true(@b.q_true).should == 1 - end - end -end |