Update to ruby/spec@6b04c1d
This commit is contained in:
parent
dbbaf871de
commit
ad636033e2
@ -10,4 +10,21 @@ describe "Binding#dup" do
|
||||
bind.frozen?.should == true
|
||||
bind.dup.frozen?.should == false
|
||||
end
|
||||
|
||||
it "retains original binding variables but the list is distinct" do
|
||||
bind1 = binding
|
||||
eval "a = 1", bind1
|
||||
|
||||
bind2 = bind1.dup
|
||||
eval("a = 2", bind2)
|
||||
eval("a", bind1).should == 2
|
||||
eval("a", bind2).should == 2
|
||||
|
||||
eval("b = 2", bind2)
|
||||
-> { eval("b", bind1) }.should raise_error(NameError)
|
||||
eval("b", bind2).should == 2
|
||||
|
||||
bind1.local_variables.sort.should == [:a, :bind1, :bind2]
|
||||
bind2.local_variables.sort.should == [:a, :b, :bind1, :bind2]
|
||||
end
|
||||
end
|
||||
|
@ -11,6 +11,7 @@ describe "Enumerator#next_values" do
|
||||
yield :e1, :e2, :e3
|
||||
yield nil
|
||||
yield
|
||||
yield [:f1, :f2]
|
||||
end
|
||||
|
||||
@e = o.to_enum
|
||||
@ -48,8 +49,13 @@ describe "Enumerator#next_values" do
|
||||
@e.next_values.should == []
|
||||
end
|
||||
|
||||
it "raises StopIteration if called on a finished enumerator" do
|
||||
it "returns an array of array if yield is called with an array" do
|
||||
7.times { @e.next }
|
||||
@e.next_values.should == [[:f1, :f2]]
|
||||
end
|
||||
|
||||
it "raises StopIteration if called on a finished enumerator" do
|
||||
8.times { @e.next }
|
||||
-> { @e.next_values }.should raise_error(StopIteration)
|
||||
end
|
||||
end
|
||||
|
@ -11,6 +11,7 @@ describe "Enumerator#peek_values" do
|
||||
yield :e1, :e2, :e3
|
||||
yield nil
|
||||
yield
|
||||
yield [:f1, :f2]
|
||||
end
|
||||
|
||||
@e = o.to_enum
|
||||
@ -50,8 +51,13 @@ describe "Enumerator#peek_values" do
|
||||
@e.peek_values.should == []
|
||||
end
|
||||
|
||||
it "raises StopIteration if called on a finished enumerator" do
|
||||
it "returns an array of array if yield is called with an array" do
|
||||
7.times { @e.next }
|
||||
@e.peek_values.should == [[:f1, :f2]]
|
||||
end
|
||||
|
||||
it "raises StopIteration if called on a finished enumerator" do
|
||||
8.times { @e.next }
|
||||
-> { @e.peek_values }.should raise_error(StopIteration)
|
||||
end
|
||||
end
|
||||
|
@ -22,7 +22,7 @@ guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
|
||||
|
||||
it "accepts a length, an offset, and an output buffer" do
|
||||
buffer = +"foo"
|
||||
@file.pread(3, 4, buffer)
|
||||
@file.pread(3, 4, buffer).should.equal?(buffer)
|
||||
buffer.should == "567"
|
||||
end
|
||||
|
||||
@ -38,6 +38,13 @@ guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
|
||||
buffer.should == "12345"
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@file.pread(10, 0, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
it "does not advance the file pointer" do
|
||||
@file.pread(4, 0).should == "1234"
|
||||
@file.read.should == "1234567890"
|
||||
|
@ -376,6 +376,21 @@ describe "IO#read" do
|
||||
buf.should == @contents[0..4]
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@io.read(10, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
# https://bugs.ruby-lang.org/issues/20416
|
||||
it "does not preserve the encoding of the given buffer when max length is not provided" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@io.read(nil, buffer)
|
||||
|
||||
buffer.encoding.should_not == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
it "returns the given buffer" do
|
||||
buf = +""
|
||||
|
||||
|
@ -62,7 +62,7 @@ describe "IO#readpartial" do
|
||||
buffer = +"existing content"
|
||||
@wr.write("hello world")
|
||||
@wr.close
|
||||
@rd.readpartial(11, buffer)
|
||||
@rd.readpartial(11, buffer).should.equal?(buffer)
|
||||
buffer.should == "hello world"
|
||||
end
|
||||
|
||||
@ -106,6 +106,7 @@ describe "IO#readpartial" do
|
||||
@wr.write("abc")
|
||||
@wr.close
|
||||
@rd.readpartial(10, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
end
|
||||
|
@ -97,7 +97,7 @@ describe "IO#sysread on a file" do
|
||||
|
||||
it "discards the existing buffer content upon successful read" do
|
||||
buffer = +"existing content"
|
||||
@file.sysread(11, buffer)
|
||||
@file.sysread(11, buffer).should.equal?(buffer)
|
||||
buffer.should == "01234567890"
|
||||
end
|
||||
|
||||
@ -107,6 +107,13 @@ describe "IO#sysread on a file" do
|
||||
-> { @file.sysread(1, buffer) }.should raise_error(EOFError)
|
||||
buffer.should be_empty
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
string = @file.sysread(10, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
end
|
||||
|
||||
describe "IO#sysread" do
|
||||
|
@ -47,6 +47,34 @@ describe "Module#include" do
|
||||
-> { ModuleSpecs::SubclassSpec.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
|
||||
end
|
||||
|
||||
ruby_version_is ""..."3.2" do
|
||||
it "raises ArgumentError when the argument is a refinement" do
|
||||
refinement = nil
|
||||
|
||||
Module.new do
|
||||
refine String do
|
||||
refinement = self
|
||||
end
|
||||
end
|
||||
|
||||
-> { ModuleSpecs::Basic.include(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed")
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "3.2" do
|
||||
it "raises a TypeError when the argument is a refinement" do
|
||||
refinement = nil
|
||||
|
||||
Module.new do
|
||||
refine String do
|
||||
refinement = self
|
||||
end
|
||||
end
|
||||
|
||||
-> { ModuleSpecs::Basic.include(refinement) }.should raise_error(TypeError, "Cannot include refinement")
|
||||
end
|
||||
end
|
||||
|
||||
it "imports constants to modules and classes" do
|
||||
ModuleSpecs::A.constants.should include(:CONSTANT_A)
|
||||
ModuleSpecs::B.constants.should include(:CONSTANT_A, :CONSTANT_B)
|
||||
|
@ -75,6 +75,26 @@ describe "Module#prepend" do
|
||||
foo.call.should == 'm'
|
||||
end
|
||||
|
||||
it "updates the optimized method when a prepended module is updated" do
|
||||
out = ruby_exe(<<~RUBY)
|
||||
module M; end
|
||||
class Integer
|
||||
prepend M
|
||||
end
|
||||
l = -> { 1 + 2 }
|
||||
p l.call
|
||||
M.module_eval do
|
||||
def +(o)
|
||||
$called = true
|
||||
super(o)
|
||||
end
|
||||
end
|
||||
p l.call
|
||||
p $called
|
||||
RUBY
|
||||
out.should == "3\n3\ntrue\n"
|
||||
end
|
||||
|
||||
it "updates the method when there is a base included method and the prepended module overrides it" do
|
||||
base_module = Module.new do
|
||||
def foo
|
||||
@ -415,6 +435,34 @@ describe "Module#prepend" do
|
||||
-> { ModuleSpecs::SubclassSpec.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
|
||||
end
|
||||
|
||||
ruby_version_is ""..."3.2" do
|
||||
it "raises ArgumentError when the argument is a refinement" do
|
||||
refinement = nil
|
||||
|
||||
Module.new do
|
||||
refine String do
|
||||
refinement = self
|
||||
end
|
||||
end
|
||||
|
||||
-> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed")
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "3.2" do
|
||||
it "raises a TypeError when the argument is a refinement" do
|
||||
refinement = nil
|
||||
|
||||
Module.new do
|
||||
refine String do
|
||||
refinement = self
|
||||
end
|
||||
end
|
||||
|
||||
-> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(TypeError, "Cannot prepend refinement")
|
||||
end
|
||||
end
|
||||
|
||||
it "imports constants" do
|
||||
m1 = Module.new
|
||||
m1::MY_CONSTANT = 1
|
||||
|
28
spec/ruby/core/warning/performance_warning_spec.rb
Normal file
28
spec/ruby/core/warning/performance_warning_spec.rb
Normal file
@ -0,0 +1,28 @@
|
||||
require_relative '../../spec_helper'
|
||||
|
||||
|
||||
describe "Performance warnings" do
|
||||
guard -> { ruby_version_is("3.4") || RUBY_ENGINE == "truffleruby" } do
|
||||
# Optimising Integer, Float or Symbol methods is kind of implementation detail
|
||||
# but multiple implementations do so. So it seems reasonable to have a test case
|
||||
# for at least one such common method.
|
||||
# See https://bugs.ruby-lang.org/issues/20429
|
||||
context "when redefined optimised methods" do
|
||||
it "emits performance warning for redefining Integer#+" do
|
||||
code = <<~CODE
|
||||
Warning[:performance] = true
|
||||
|
||||
class Integer
|
||||
ORIG_METHOD = instance_method(:+)
|
||||
|
||||
def +(...)
|
||||
ORIG_METHOD.bind(self).call(...)
|
||||
end
|
||||
end
|
||||
CODE
|
||||
|
||||
ruby_exe(code, args: "2>&1").should.include?("warning: Redefining 'Integer#+' disables interpreter and JIT optimizations")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -252,6 +252,25 @@ describe "Break inside a while loop" do
|
||||
end
|
||||
end
|
||||
|
||||
describe "The break statement in a method" do
|
||||
it "is invalid and raises a SyntaxError" do
|
||||
-> {
|
||||
eval("def m; break; end")
|
||||
}.should raise_error(SyntaxError)
|
||||
end
|
||||
end
|
||||
|
||||
describe "The break statement in a module literal" do
|
||||
it "is invalid and raises a SyntaxError" do
|
||||
code = <<~RUBY
|
||||
module BreakSpecs:ModuleWithBreak
|
||||
break
|
||||
end
|
||||
RUBY
|
||||
|
||||
-> { eval(code) }.should raise_error(SyntaxError)
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Rewrite all the specs from here to the end of the file in the style
|
||||
# above.
|
||||
|
@ -38,7 +38,7 @@ describe "``" do
|
||||
|
||||
2.times do
|
||||
runner.instance_exec do
|
||||
`test #{:command}`
|
||||
`test #{:command}` # rubocop:disable Lint/LiteralInInterpolation
|
||||
end
|
||||
end
|
||||
|
||||
@ -84,7 +84,7 @@ describe "%x" do
|
||||
|
||||
2.times do
|
||||
runner.instance_exec do
|
||||
%x{test #{:command}}
|
||||
%x{test #{:command}} # rubocop:disable Lint/LiteralInInterpolation
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -86,6 +86,30 @@ describe "Hash literal" do
|
||||
-> { eval("{:a ==> 1}") }.should raise_error(SyntaxError)
|
||||
end
|
||||
|
||||
it "recognizes '!' at the end of the key" do
|
||||
eval("{:a! =>1}").should == {:"a!" => 1}
|
||||
eval("{:a! => 1}").should == {:"a!" => 1}
|
||||
|
||||
eval("{a!:1}").should == {:"a!" => 1}
|
||||
eval("{a!: 1}").should == {:"a!" => 1}
|
||||
end
|
||||
|
||||
it "raises a SyntaxError if there is no space between `!` and `=>`" do
|
||||
-> { eval("{:a!=> 1}") }.should raise_error(SyntaxError)
|
||||
end
|
||||
|
||||
it "recognizes '?' at the end of the key" do
|
||||
eval("{:a? =>1}").should == {:"a?" => 1}
|
||||
eval("{:a? => 1}").should == {:"a?" => 1}
|
||||
|
||||
eval("{a?:1}").should == {:"a?" => 1}
|
||||
eval("{a?: 1}").should == {:"a?" => 1}
|
||||
end
|
||||
|
||||
it "raises a SyntaxError if there is no space between `?` and `=>`" do
|
||||
-> { eval("{:a?=> 1}") }.should raise_error(SyntaxError)
|
||||
end
|
||||
|
||||
it "constructs a new hash with the given elements" do
|
||||
{foo: 123}.should == {foo: 123}
|
||||
h = {rbx: :cool, specs: 'fail_sometimes'}
|
||||
@ -271,6 +295,14 @@ describe "The ** operator" do
|
||||
|
||||
a.new.foo(1).should == {bar: "baz", val: 1}
|
||||
end
|
||||
|
||||
it "raises a SyntaxError when the hash key ends with `!`" do
|
||||
-> { eval("{a!:}") }.should raise_error(SyntaxError, /identifier a! is not valid to get/)
|
||||
end
|
||||
|
||||
it "raises a SyntaxError when the hash key ends with `?`" do
|
||||
-> { eval("{a?:}") }.should raise_error(SyntaxError, /identifier a\? is not valid to get/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -395,4 +395,32 @@ describe "Keyword arguments" do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "in define_method(name, &proc)" do
|
||||
# This tests that a free-standing proc used in define_method and converted to ruby2_keywords adopts that logic.
|
||||
# See jruby/jruby#8119 for a case where aggressive JIT optimization broke later ruby2_keywords changes.
|
||||
it "works with ruby2_keywords" do
|
||||
m = Class.new do
|
||||
def bar(a, foo: nil)
|
||||
[a, foo]
|
||||
end
|
||||
|
||||
# define_method and ruby2_keywords using send to avoid peephole optimizations
|
||||
def self.setup
|
||||
pr = make_proc
|
||||
send :define_method, :foo, &pr
|
||||
send :ruby2_keywords, :foo
|
||||
end
|
||||
|
||||
# create proc in isolated method to force jit compilation on some implementations
|
||||
def self.make_proc
|
||||
proc { |a, *args| bar(a, *args) }
|
||||
end
|
||||
end
|
||||
|
||||
m.setup
|
||||
|
||||
m.new.foo(1, foo:2).should == [1, 2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -22,6 +22,15 @@ describe "Regexps with back-references" do
|
||||
$10.should == "0"
|
||||
end
|
||||
|
||||
it "returns nil for numbered variable with too large index" do
|
||||
-> {
|
||||
eval(<<~CODE).should == nil
|
||||
"a" =~ /(.)/
|
||||
eval('$4294967296')
|
||||
CODE
|
||||
}.should complain(/warning: ('|`)\$4294967296' is too big for a number variable, always nil/)
|
||||
end
|
||||
|
||||
it "will not clobber capture variables across threads" do
|
||||
cap1, cap2, cap3 = nil
|
||||
"foo" =~ /(o+)/
|
||||
|
@ -31,8 +31,11 @@ describe "The retry statement" do
|
||||
results.should == [1, 2, 3, 1, 2, 4, 5, 6, 4, 5]
|
||||
end
|
||||
|
||||
it "raises a SyntaxError when used outside of a begin statement" do
|
||||
it "raises a SyntaxError when used outside of a rescue statement" do
|
||||
-> { eval 'retry' }.should raise_error(SyntaxError)
|
||||
-> { eval 'begin; retry; end' }.should raise_error(SyntaxError)
|
||||
-> { eval 'def m; retry; end' }.should raise_error(SyntaxError)
|
||||
-> { eval 'module RetrySpecs; retry; end' }.should raise_error(SyntaxError)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -206,3 +206,15 @@ describe "Using yield in non-lambda block" do
|
||||
-> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/)
|
||||
end
|
||||
end
|
||||
|
||||
describe "Using yield in a module literal" do
|
||||
it 'raises a SyntaxError' do
|
||||
code = <<~RUBY
|
||||
module YieldSpecs::ModuleWithYield
|
||||
yield
|
||||
end
|
||||
RUBY
|
||||
|
||||
-> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/)
|
||||
end
|
||||
end
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../../spec_helper'
|
||||
require 'time'
|
||||
|
||||
describe "Time#to_date" do
|
@ -1,4 +1,4 @@
|
||||
require_relative '../../spec_helper'
|
||||
require_relative '../../../spec_helper'
|
||||
require 'time'
|
||||
require 'date'
|
||||
date_version = defined?(Date::VERSION) ? Date::VERSION : '3.1.0'
|
@ -52,9 +52,19 @@ describe "Socket::BasicSocket#recv_nonblock" do
|
||||
@s2.send("data", 0, @s1.getsockname)
|
||||
IO.select([@s1], nil, nil, 2)
|
||||
|
||||
buf = +"foo"
|
||||
@s1.recv_nonblock(5, 0, buf)
|
||||
buf.should == "data"
|
||||
buffer = +"foo"
|
||||
@s1.recv_nonblock(5, 0, buffer).should.equal?(buffer)
|
||||
buffer.should == "data"
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
@s1.bind(Socket.pack_sockaddr_in(0, ip_address))
|
||||
@s2.send("data", 0, @s1.getsockname)
|
||||
IO.select([@s1], nil, nil, 2)
|
||||
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@s1.recv_nonblock(5, 0, buffer)
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
it "does not block if there's no data available" do
|
||||
|
@ -100,13 +100,29 @@ describe "BasicSocket#recv" do
|
||||
socket.write("data")
|
||||
|
||||
client = @server.accept
|
||||
buf = +"foo"
|
||||
buffer = +"foo"
|
||||
begin
|
||||
client.recv(4, 0, buf)
|
||||
client.recv(4, 0, buffer).should.equal?(buffer)
|
||||
ensure
|
||||
client.close
|
||||
end
|
||||
buf.should == "data"
|
||||
buffer.should == "data"
|
||||
|
||||
socket.close
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
socket = TCPSocket.new('127.0.0.1', @port)
|
||||
socket.write("data")
|
||||
|
||||
client = @server.accept
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
begin
|
||||
client.recv(4, 0, buffer)
|
||||
ensure
|
||||
client.close
|
||||
end
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
|
||||
socket.close
|
||||
end
|
||||
|
@ -52,6 +52,27 @@ describe 'Socket#recvfrom_nonblock' do
|
||||
end
|
||||
end
|
||||
|
||||
it "allows an output buffer as third argument" do
|
||||
@client.write('hello')
|
||||
|
||||
IO.select([@server])
|
||||
buffer = +''
|
||||
message, = @server.recvfrom_nonblock(5, 0, buffer)
|
||||
|
||||
message.should.equal?(buffer)
|
||||
buffer.should == 'hello'
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
@client.write('hello')
|
||||
|
||||
IO.select([@server])
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@server.recvfrom_nonblock(5, 0, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
describe 'the returned data' do
|
||||
it 'is the same as the sent data' do
|
||||
5.times do
|
||||
|
@ -58,6 +58,15 @@ describe 'UDPSocket#recvfrom_nonblock' do
|
||||
buffer.should == 'h'
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
IO.select([@server])
|
||||
message, = @server.recvfrom_nonblock(1, 0, buffer)
|
||||
|
||||
message.should.equal?(buffer)
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
describe 'the returned Array' do
|
||||
before do
|
||||
IO.select([@server])
|
||||
|
@ -31,6 +31,29 @@ with_feature :unix_socket do
|
||||
sock.close
|
||||
end
|
||||
|
||||
it "allows an output buffer as third argument" do
|
||||
buffer = +''
|
||||
|
||||
@client.send("foobar", 0)
|
||||
sock = @server.accept
|
||||
message, = sock.recvfrom(6, 0, buffer)
|
||||
sock.close
|
||||
|
||||
message.should.equal?(buffer)
|
||||
buffer.should == "foobar"
|
||||
end
|
||||
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
|
||||
@client.send("foobar", 0)
|
||||
sock = @server.accept
|
||||
sock.recvfrom(6, 0, buffer)
|
||||
sock.close
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
|
||||
it "uses different message options" do
|
||||
@client.send("foobar", Socket::MSG_PEEK)
|
||||
sock = @server.accept
|
||||
|
@ -11,10 +11,28 @@ describe :stringio_read, shared: true do
|
||||
end
|
||||
|
||||
it "reads length bytes and writes them to the buffer String" do
|
||||
@io.send(@method, 7, buffer = +"")
|
||||
@io.send(@method, 7, buffer = +"").should.equal?(buffer)
|
||||
buffer.should == "example"
|
||||
end
|
||||
|
||||
ruby_version_is ""..."3.4" do
|
||||
it "does not preserve the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@io.send(@method, 7, buffer)
|
||||
|
||||
buffer.encoding.should_not == Encoding::ISO_8859_1
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "3.4" do
|
||||
it "preserves the encoding of the given buffer" do
|
||||
buffer = ''.encode(Encoding::ISO_8859_1)
|
||||
@io.send(@method, 7, buffer)
|
||||
|
||||
buffer.encoding.should == Encoding::ISO_8859_1
|
||||
end
|
||||
end
|
||||
|
||||
it "tries to convert the passed buffer Object to a String using #to_str" do
|
||||
obj = mock("to_str")
|
||||
obj.should_receive(:to_str).and_return(buffer = +"")
|
||||
|
@ -487,4 +487,16 @@ describe "C-API Class function" do
|
||||
@s.rb_class_real(0).should == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_class_get_superclass" do
|
||||
it "returns parent class for a provided class" do
|
||||
a = Class.new
|
||||
@s.rb_class_get_superclass(Class.new(a)).should == a
|
||||
end
|
||||
|
||||
it "returns false when there is no parent class" do
|
||||
@s.rb_class_get_superclass(BasicObject).should == false
|
||||
@s.rb_class_get_superclass(Module.new).should == false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -79,6 +79,10 @@ static VALUE class_spec_rb_class_real(VALUE self, VALUE object) {
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE class_spec_rb_class_get_superclass(VALUE self, VALUE klass) {
|
||||
return rb_class_get_superclass(klass);
|
||||
}
|
||||
|
||||
static VALUE class_spec_rb_class_superclass(VALUE self, VALUE klass) {
|
||||
return rb_class_superclass(klass);
|
||||
}
|
||||
@ -160,6 +164,7 @@ void Init_class_spec(void) {
|
||||
rb_define_method(cls, "rb_class_new_instance_kw", class_spec_rb_class_new_instance_kw, 2);
|
||||
#endif
|
||||
rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1);
|
||||
rb_define_method(cls, "rb_class_get_superclass", class_spec_rb_class_get_superclass, 1);
|
||||
rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1);
|
||||
rb_define_method(cls, "rb_cvar_defined", class_spec_cvar_defined, 2);
|
||||
rb_define_method(cls, "rb_cvar_get", class_spec_cvar_get, 2);
|
||||
|
@ -16,6 +16,8 @@ VALUE registered_after_rb_global_variable_bignum;
|
||||
VALUE registered_after_rb_global_variable_float;
|
||||
VALUE rb_gc_register_address_outside_init;
|
||||
|
||||
VALUE rb_gc_register_mark_object_not_referenced_float;
|
||||
|
||||
static VALUE registered_tagged_address(VALUE self) {
|
||||
return registered_tagged_value;
|
||||
}
|
||||
@ -90,6 +92,10 @@ static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) {
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE gc_spec_rb_gc_register_mark_object_not_referenced_float(VALUE self) {
|
||||
return rb_gc_register_mark_object_not_referenced_float;
|
||||
}
|
||||
|
||||
void Init_gc_spec(void) {
|
||||
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
|
||||
|
||||
@ -115,6 +121,9 @@ void Init_gc_spec(void) {
|
||||
registered_after_rb_global_variable_float = DBL2NUM(6.28);
|
||||
rb_global_variable(®istered_after_rb_global_variable_float);
|
||||
|
||||
rb_gc_register_mark_object_not_referenced_float = DBL2NUM(1.61);
|
||||
rb_gc_register_mark_object(rb_gc_register_mark_object_not_referenced_float);
|
||||
|
||||
rb_define_method(cls, "registered_tagged_address", registered_tagged_address, 0);
|
||||
rb_define_method(cls, "registered_reference_address", registered_reference_address, 0);
|
||||
rb_define_method(cls, "registered_before_rb_gc_register_address", get_registered_before_rb_gc_register_address, 0);
|
||||
@ -131,6 +140,7 @@ void Init_gc_spec(void) {
|
||||
rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0);
|
||||
rb_define_method(cls, "rb_gc_adjust_memory_usage", gc_spec_rb_gc_adjust_memory_usage, 1);
|
||||
rb_define_method(cls, "rb_gc_register_mark_object", gc_spec_rb_gc_register_mark_object, 1);
|
||||
rb_define_method(cls, "rb_gc_register_mark_object_not_referenced_float", gc_spec_rb_gc_register_mark_object_not_referenced_float, 0);
|
||||
rb_define_method(cls, "rb_gc_latest_gc_info", gc_spec_rb_gc_latest_gc_info, 1);
|
||||
}
|
||||
|
||||
|
@ -390,22 +390,22 @@ static VALUE speced_allocator(VALUE klass) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
static VALUE define_alloc_func(VALUE self, VALUE klass) {
|
||||
static VALUE object_spec_rb_define_alloc_func(VALUE self, VALUE klass) {
|
||||
rb_define_alloc_func(klass, speced_allocator);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE undef_alloc_func(VALUE self, VALUE klass) {
|
||||
static VALUE object_spec_rb_undef_alloc_func(VALUE self, VALUE klass) {
|
||||
rb_undef_alloc_func(klass);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE speced_allocator_p(VALUE self, VALUE klass) {
|
||||
static VALUE object_spec_speced_allocator_p(VALUE self, VALUE klass) {
|
||||
rb_alloc_func_t allocator = rb_get_alloc_func(klass);
|
||||
return (allocator == speced_allocator) ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
static VALUE custom_alloc_func_p(VALUE self, VALUE klass) {
|
||||
static VALUE object_spec_custom_alloc_func_p(VALUE self, VALUE klass) {
|
||||
rb_alloc_func_t allocator = rb_get_alloc_func(klass);
|
||||
return allocator ? Qtrue : Qfalse;
|
||||
}
|
||||
@ -485,10 +485,10 @@ void Init_object_spec(void) {
|
||||
rb_define_method(cls, "rb_ivar_defined", object_spec_rb_ivar_defined, 2);
|
||||
rb_define_method(cls, "rb_copy_generic_ivar", object_spec_rb_copy_generic_ivar, 2);
|
||||
rb_define_method(cls, "rb_free_generic_ivar", object_spec_rb_free_generic_ivar, 1);
|
||||
rb_define_method(cls, "rb_define_alloc_func", define_alloc_func, 1);
|
||||
rb_define_method(cls, "rb_undef_alloc_func", undef_alloc_func, 1);
|
||||
rb_define_method(cls, "speced_allocator?", speced_allocator_p, 1);
|
||||
rb_define_method(cls, "custom_alloc_func?", custom_alloc_func_p, 1);
|
||||
rb_define_method(cls, "rb_define_alloc_func", object_spec_rb_define_alloc_func, 1);
|
||||
rb_define_method(cls, "rb_undef_alloc_func", object_spec_rb_undef_alloc_func, 1);
|
||||
rb_define_method(cls, "speced_allocator?", object_spec_speced_allocator_p, 1);
|
||||
rb_define_method(cls, "custom_alloc_func?", object_spec_custom_alloc_func_p, 1);
|
||||
rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1);
|
||||
rb_define_method(cls, "rb_ivar_foreach", object_spec_rb_ivar_foreach, 1);
|
||||
}
|
||||
|
@ -108,6 +108,10 @@ describe "CApiGCSpecs" do
|
||||
it "can be called with an object" do
|
||||
@f.rb_gc_register_mark_object(Object.new).should be_nil
|
||||
end
|
||||
|
||||
it "keeps the value alive even if the value is not referenced by any Ruby object" do
|
||||
@f.rb_gc_register_mark_object_not_referenced_float.should == 1.61
|
||||
end
|
||||
end
|
||||
|
||||
describe "rb_gc_latest_gc_info" do
|
||||
|
@ -30,6 +30,12 @@ describe :kernel_at_exit, shared: true do
|
||||
result.lines.should.include?("The exception matches: true (message=foo)\n")
|
||||
end
|
||||
|
||||
it "gives access to an exception raised in a previous handler" do
|
||||
code = "#{@method} { print '$!.message = ' + $!.message }; #{@method} { raise 'foo' }"
|
||||
result = ruby_exe(code, args: "2>&1", exit_status: 1)
|
||||
result.lines.should.include?("$!.message = foo")
|
||||
end
|
||||
|
||||
it "both exceptions in a handler and in the main script are printed" do
|
||||
code = "#{@method} { raise 'at_exit_error' }; raise 'main_script_error'"
|
||||
result = ruby_exe(code, args: "2>&1", exit_status: 1)
|
||||
|
Loading…
x
Reference in New Issue
Block a user