зеркало из https://github.com/github/ruby.git
Update to ruby/spec@4f59d86
This commit is contained in:
Родитель
342fbae83c
Коммит
148961adcd
|
@ -18,3 +18,25 @@ end
|
|||
describe "The -W command line option with 2" do
|
||||
it_behaves_like :command_line_verbose, "-W2"
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
describe "The -W command line option with :no-deprecated" do
|
||||
it "suppresses deprecation warnings" do
|
||||
result = ruby_exe('$; = ""', options: '-w', args: '2>&1')
|
||||
result.should =~ /is deprecated/
|
||||
|
||||
result = ruby_exe('$; = ""', options: '-w -W:no-deprecated', args: '2>&1')
|
||||
result.should == ""
|
||||
end
|
||||
end
|
||||
|
||||
describe "The -W command line option with :no-experimental" do
|
||||
it "suppresses experimental warnings" do
|
||||
result = ruby_exe('0 in a', args: '2>&1')
|
||||
result.should =~ /is experimental/
|
||||
|
||||
result = ruby_exe('0 in a', options: '-W:no-experimental', args: '2>&1')
|
||||
result.should == ""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,11 +37,13 @@ describe "The --enable and --disable flags" do
|
|||
ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false"
|
||||
end
|
||||
|
||||
it "can be used with all for enable" do
|
||||
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
|
||||
env = {'RUBYOPT' => '-w'}
|
||||
# Use a single variant here because it can be quite slow as it might enable jit, etc
|
||||
ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
|
||||
platform_is_not :darwin do # frequently hangs for >60s on GitHub Actions macos-latest
|
||||
it "can be used with all for enable" do
|
||||
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
|
||||
env = {'RUBYOPT' => '-w'}
|
||||
# Use a single variant here because it can be quite slow as it might enable jit, etc
|
||||
ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
|
||||
end
|
||||
end
|
||||
|
||||
it "can be used with all for disable" do
|
||||
|
|
|
@ -59,6 +59,26 @@ describe "Processing RUBYOPT" do
|
|||
ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it "suppresses deprecation warnings for '-W:no-deprecated'" do
|
||||
ENV["RUBYOPT"] = '-W:no-deprecated'
|
||||
result = ruby_exe('$; = ""', args: '2>&1')
|
||||
result.should == ""
|
||||
end
|
||||
|
||||
it "suppresses experimental warnings for '-W:no-experimental'" do
|
||||
ENV["RUBYOPT"] = '-W:no-experimental'
|
||||
result = ruby_exe('0 in a', args: '2>&1')
|
||||
result.should == ""
|
||||
end
|
||||
|
||||
it "suppresses deprecation and experimental warnings for '-W:no-deprecated -W:no-experimental'" do
|
||||
ENV["RUBYOPT"] = '-W:no-deprecated -W:no-experimental'
|
||||
result = ruby_exe('($; = "") in a', args: '2>&1')
|
||||
result.should == ""
|
||||
end
|
||||
end
|
||||
|
||||
it "requires the file for '-r'" do
|
||||
f = fixture __FILE__, "rubyopt"
|
||||
ENV["RUBYOPT"] = "-r#{f}"
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative '../../shared/enumerable/minmax'
|
||||
|
||||
describe "Array#minmax" do
|
||||
before :each do
|
||||
@enum = [6, 4, 5, 10, 8]
|
||||
@empty_enum = []
|
||||
@incomparable_enum = [BasicObject.new, BasicObject.new]
|
||||
@incompatible_enum = [11, "22"]
|
||||
@strs = ["333", "2", "60", "55555", "1010", "111"]
|
||||
end
|
||||
|
||||
it_behaves_like :enumerable_minmax, :minmax
|
||||
end
|
|
@ -96,11 +96,12 @@ describe "Class.new" do
|
|||
|
||||
it "raises a TypeError when given a non-Class" do
|
||||
error_msg = /superclass must be a Class/
|
||||
-> { Class.new("") }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(1) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new("") }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(1) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
|
||||
-> { Class.new(BasicObject.new) }.should raise_error(TypeError, error_msg)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ describe "Encoding.list" do
|
|||
end
|
||||
|
||||
it "returns each encoding only once" do
|
||||
orig = Encoding.list.map {|e| e.name}
|
||||
orig = Encoding.list.map { |e| e.name }
|
||||
orig.should == orig.uniq
|
||||
end
|
||||
|
||||
|
@ -33,7 +33,17 @@ describe "Encoding.list" do
|
|||
end
|
||||
|
||||
it "includes dummy encodings" do
|
||||
Encoding.list.select {|e| e.dummy?}.should_not == []
|
||||
Encoding.list.select { |e| e.dummy? }.should_not == []
|
||||
end
|
||||
|
||||
it 'includes UTF-8 encoding' do
|
||||
Encoding.list.should.include?(Encoding::UTF_8)
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it 'includes CESU-8 encoding' do
|
||||
Encoding.list.should.include?(Encoding::CESU_8)
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Find example that illustrates this
|
||||
|
|
|
@ -1,41 +1,17 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative 'fixtures/classes'
|
||||
require_relative '../../shared/enumerable/minmax'
|
||||
|
||||
describe "Enumerable#minmax" do
|
||||
before :each do
|
||||
@enum = EnumerableSpecs::Numerous.new(6, 4, 5, 10, 8)
|
||||
|
||||
@empty_enum = EnumerableSpecs::Empty.new
|
||||
@incomparable_enum = EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new)
|
||||
@incompatible_enum = EnumerableSpecs::Numerous.new(11,"22")
|
||||
@strs = EnumerableSpecs::Numerous.new("333", "2", "60", "55555", "1010", "111")
|
||||
end
|
||||
|
||||
it "min should return the minimum element" do
|
||||
@enum.minmax.should == [4, 10]
|
||||
@strs.minmax.should == ["1010", "60" ]
|
||||
end
|
||||
|
||||
it "returns [nil, nil] for an empty Enumerable" do
|
||||
EnumerableSpecs::Empty.new.minmax.should == [nil, nil]
|
||||
end
|
||||
|
||||
it "raises an ArgumentError when elements are incomparable" do
|
||||
-> do
|
||||
EnumerableSpecs::Numerous.new(11,"22").minmax
|
||||
end.should raise_error(ArgumentError)
|
||||
-> do
|
||||
EnumerableSpecs::Numerous.new(11,12,22,33).minmax{|a, b| nil}
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it "raises a NoMethodError for elements without #<=>" do
|
||||
-> do
|
||||
EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new).minmax
|
||||
end.should raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
it "returns the minimum when using a block rule" do
|
||||
@enum.minmax {|a,b| b <=> a }.should == [10, 4]
|
||||
@strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"]
|
||||
end
|
||||
it_behaves_like :enumerable_minmax, :minmax
|
||||
|
||||
it "gathers whole arrays as elements when each yields multiple" do
|
||||
multi = EnumerableSpecs::YieldsMulti.new
|
||||
|
|
|
@ -9,15 +9,23 @@ describe :env_key, shared: true do
|
|||
|
||||
it "returns the index associated with the passed value" do
|
||||
ENV["foo"] = "bar"
|
||||
ENV.send(@method, "bar").should == "foo"
|
||||
suppress_warning {
|
||||
ENV.send(@method, "bar").should == "foo"
|
||||
}
|
||||
end
|
||||
|
||||
it "returns nil if the passed value is not found" do
|
||||
ENV.delete("foo")
|
||||
ENV.send(@method, "foo").should be_nil
|
||||
suppress_warning {
|
||||
ENV.send(@method, "foo").should be_nil
|
||||
}
|
||||
end
|
||||
|
||||
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
|
||||
-> { ENV.send(@method, Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
-> {
|
||||
suppress_warning {
|
||||
ENV.send(@method, Object.new)
|
||||
}
|
||||
}.should raise_error(TypeError, "no implicit conversion of Object into String")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,23 @@ describe :file_path, shared: true do
|
|||
@file.send(@method).should be_an_instance_of(String)
|
||||
end
|
||||
|
||||
it "returns a different String on every call" do
|
||||
@file = File.new @path
|
||||
path1 = @file.send(@method)
|
||||
path2 = @file.send(@method)
|
||||
path1.should == path2
|
||||
path1.should_not.equal?(path2)
|
||||
end
|
||||
|
||||
it "returns a mutable String" do
|
||||
@file = File.new @path.dup.freeze
|
||||
path = @file.send(@method)
|
||||
path.should == @path
|
||||
path.should_not.frozen?
|
||||
path << "test"
|
||||
@file.send(@method).should == @path
|
||||
end
|
||||
|
||||
it "calls to_str on argument and returns exact value" do
|
||||
path = mock('path')
|
||||
path.should_receive(:to_str).and_return(@path)
|
||||
|
|
|
@ -117,4 +117,18 @@ describe "Hash#[]" do
|
|||
key = HashSpecs::KeyWithPrivateHash.new
|
||||
{ key => 42 }[key].should == 42
|
||||
end
|
||||
|
||||
it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
|
||||
code = <<-EOC
|
||||
load '#{fixture __FILE__, "name.rb"}'
|
||||
hash = { true => 42, false => 42, 1 => 42, 2.0 => 42, "hello" => 42, :ok => 42 }
|
||||
[true, false, 1, 2.0, "hello", :ok].each do |value|
|
||||
raise "incorrect value" unless hash[value] == 42
|
||||
end
|
||||
puts "Ok."
|
||||
EOC
|
||||
result = ruby_exe(code, args: "2>&1")
|
||||
result.should == "Ok.\n"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
class TrueClass
|
||||
def hash
|
||||
raise "TrueClass#hash should not be called"
|
||||
end
|
||||
end
|
||||
class FalseClass
|
||||
def hash
|
||||
raise "FalseClass#hash should not be called"
|
||||
end
|
||||
end
|
||||
class Integer
|
||||
def hash
|
||||
raise "Integer#hash should not be called"
|
||||
end
|
||||
end
|
||||
class Float
|
||||
def hash
|
||||
raise "Float#hash should not be called"
|
||||
end
|
||||
end
|
||||
class String
|
||||
def hash
|
||||
raise "String#hash should not be called"
|
||||
end
|
||||
end
|
||||
class Symbol
|
||||
def hash
|
||||
raise "Symbol#hash should not be called"
|
||||
end
|
||||
end
|
|
@ -95,4 +95,21 @@ describe :hash_store, shared: true do
|
|||
hash.each { hash.send(@method, 1, :foo) }
|
||||
hash.should == {1 => :foo, 3 => 4, 5 => 6}
|
||||
end
|
||||
|
||||
it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
|
||||
code = <<-EOC
|
||||
load '#{fixture __FILE__, "name.rb"}'
|
||||
hash = {}
|
||||
[true, false, 1, 2.0, "hello", :ok].each do |value|
|
||||
hash[value] = 42
|
||||
raise "incorrect value" unless hash[value] == 42
|
||||
hash[value] = 43
|
||||
raise "incorrect value" unless hash[value] == 43
|
||||
end
|
||||
puts "OK"
|
||||
puts hash.size
|
||||
EOC
|
||||
result = ruby_exe(code, args: "2>&1")
|
||||
result.should == "OK\n6\n"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -240,4 +240,17 @@ describe "Integer#chr with an encoding argument" do
|
|||
-> { integer.chr(encoding_name) }.should raise_error(RangeError)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it 'returns a String encoding self interpreted as a codepoint in the CESU-8 encoding' do
|
||||
# see more details here https://en.wikipedia.org/wiki/CESU-8
|
||||
# code points from U+0000 to U+FFFF is encoded in the same way as in UTF-8
|
||||
0x0045.chr(Encoding::CESU_8).bytes.should == 0x0045.chr(Encoding::UTF_8).bytes
|
||||
|
||||
# code points in range from U+10000 to U+10FFFF is CESU-8 data containing a 6-byte surrogate pair,
|
||||
# which decodes to a 4-byte UTF-8 string
|
||||
0x10400.chr(Encoding::CESU_8).bytes.should != 0x10400.chr(Encoding::UTF_8).bytes
|
||||
0x10400.chr(Encoding::CESU_8).bytes.to_a.should == [0xED, 0xA0, 0x81, 0xED, 0xB0, 0x80]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -160,6 +160,14 @@ describe :kernel_require_basic, shared: true do
|
|||
ScratchPad.recorded.should == [:loaded]
|
||||
end
|
||||
|
||||
it "accepts an Object with #to_path in $LOAD_PATH" do
|
||||
obj = mock("to_path")
|
||||
obj.should_receive(:to_path).at_least(:once).and_return(CODE_LOADING_DIR)
|
||||
$LOAD_PATH << obj
|
||||
@object.send(@method, "load_fixture.rb").should be_true
|
||||
ScratchPad.recorded.should == [:loaded]
|
||||
end
|
||||
|
||||
it "does not require file twice after $LOAD_PATH change" do
|
||||
$LOAD_PATH << CODE_LOADING_DIR
|
||||
@object.require("load_fixture.rb").should be_true
|
||||
|
|
|
@ -44,4 +44,19 @@ describe "Kernel#taint" do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = Object.new
|
||||
o.taint
|
||||
o.should_not.tainted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
obj = mock("tainted")
|
||||
obj.taint
|
||||
}.should complain(/Object#taint is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,4 +11,21 @@ describe "Kernel#tainted?" do
|
|||
p.should.tainted?
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = mock('o')
|
||||
p = mock('p')
|
||||
p.taint
|
||||
o.should_not.tainted?
|
||||
p.should_not.tainted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
o = mock('o')
|
||||
o.tainted?
|
||||
}.should complain(/Object#tainted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,4 +24,20 @@ describe "Kernel#trust" do
|
|||
o.trust.should equal(o)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = Object.new.untrust
|
||||
o.should_not.untrusted?
|
||||
o.trust
|
||||
o.should_not.untrusted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
o = Object.new.untrust
|
||||
o.trust
|
||||
}.should complain(/Object#trust is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,4 +24,20 @@ describe "Kernel#untaint" do
|
|||
o.untaint.should equal(o)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = Object.new.taint
|
||||
o.should_not.tainted?
|
||||
o.untaint
|
||||
o.should_not.tainted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
o = Object.new.taint
|
||||
o.untaint
|
||||
}.should complain(/Object#untaint is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,4 +24,19 @@ describe "Kernel#untrust" do
|
|||
o.untrust.should equal(o)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = Object.new
|
||||
o.untrust
|
||||
o.should_not.untrusted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
o = Object.new
|
||||
o.untrust
|
||||
}.should complain(/Object#untrust is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -27,4 +27,20 @@ describe "Kernel#untrusted?" do
|
|||
-> { d.untrust }.should_not raise_error(RuntimeError)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "is a no-op" do
|
||||
o = mock('o')
|
||||
o.should_not.untrusted?
|
||||
o.untrust
|
||||
o.should_not.untrusted?
|
||||
end
|
||||
|
||||
it "warns in verbose mode" do
|
||||
-> {
|
||||
o = mock('o')
|
||||
o.untrusted?
|
||||
}.should complain(/Object#untrusted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -197,4 +197,35 @@ describe "Kernel#warn" do
|
|||
-> { warn(**h) }.should_not complain(verbose: true)
|
||||
-> { warn('foo', **h) }.should complain("foo\n")
|
||||
end
|
||||
|
||||
it "does not call Warning.warn if self is the Warning module" do
|
||||
# RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
|
||||
code = <<-RUBY
|
||||
def Warning.warn(*args, **kwargs)
|
||||
raise 'should not be called'
|
||||
end
|
||||
Kernel.instance_method(:warn).bind(Warning).call('Kernel#warn spec edge case')
|
||||
RUBY
|
||||
out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
|
||||
out.should == "Kernel#warn spec edge case\n"
|
||||
$?.should.success?
|
||||
end
|
||||
|
||||
it "avoids recursion if Warning#warn is redefined and calls super" do
|
||||
# This works because of the spec above, which is the workaround for it.
|
||||
# Note that redefining Warning#warn is a mistake which would naturally end in infinite recursion,
|
||||
# Warning.extend Module.new { def warn } should be used instead.
|
||||
# RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
|
||||
code = <<-RUBY
|
||||
module Warning
|
||||
def warn(*args, **kwargs)
|
||||
super
|
||||
end
|
||||
end
|
||||
warn "avoid infinite recursion"
|
||||
RUBY
|
||||
out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
|
||||
out.should == "avoid infinite recursion\n"
|
||||
$?.should.success?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,6 +50,8 @@ module MethodSpecs
|
|||
def one_req(a); end
|
||||
def two_req(a, b); end
|
||||
|
||||
def one_req_named(a:); end
|
||||
|
||||
def zero_with_block(&blk); end
|
||||
def one_req_with_block(a, &blk); end
|
||||
def two_req_with_block(a, b, &blk); end
|
||||
|
@ -59,6 +61,8 @@ module MethodSpecs
|
|||
def one_req_two_opt(a, b=nil, c=nil); end
|
||||
def two_req_one_opt(a, b, c=nil); end
|
||||
|
||||
def one_opt_named(a: nil); end
|
||||
|
||||
def one_opt_with_block(a=nil, &blk); end
|
||||
def one_req_one_opt_with_block(a, b=nil, &blk); end
|
||||
def one_req_two_opt_with_block(a, b=nil, c=nil, &blk); end
|
||||
|
@ -71,6 +75,8 @@ module MethodSpecs
|
|||
def two_req_one_opt_with_splat(a, b, c=nil, *d); end
|
||||
def one_req_two_opt_with_splat(a, b=nil, c=nil, *d); end
|
||||
|
||||
def zero_with_double_splat(**a); end
|
||||
|
||||
def zero_with_splat_and_block(*a, &blk); end
|
||||
def one_req_with_splat_and_block(a, *b, &blk); end
|
||||
def two_req_with_splat_and_block(a, b, *c, &blk); end
|
||||
|
|
|
@ -4,7 +4,7 @@ require_relative '../fixtures/classes'
|
|||
describe :method_to_s, shared: true do
|
||||
before :each do
|
||||
@m = MethodSpecs::MySub.new.method :bar
|
||||
@string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX')
|
||||
@string = @m.send(@method)
|
||||
end
|
||||
|
||||
it "returns a String" do
|
||||
|
@ -24,6 +24,21 @@ describe :method_to_s, shared: true do
|
|||
@string.should =~ /\#bar/
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it "returns a String containing method arguments" do
|
||||
obj = MethodSpecs::Methods.new
|
||||
obj.method(:zero).send(@method).should.include?("()")
|
||||
obj.method(:one_req).send(@method).should.include?("(a)")
|
||||
obj.method(:one_req_named).send(@method).should.include?("(a:)")
|
||||
obj.method(:zero_with_block).send(@method).should.include?("(&blk)")
|
||||
obj.method(:one_opt).send(@method).should.include?("(a=...)")
|
||||
obj.method(:one_opt_named).send(@method).should.include?("(a: ...)")
|
||||
obj.method(:zero_with_splat).send(@method).should.include?("(*a)")
|
||||
obj.method(:zero_with_double_splat).send(@method).should.include?("(**a)")
|
||||
obj.method(:one_req_one_opt_with_splat_and_block).send(@method).should.include?("(a, b=..., *c, &blk)")
|
||||
end
|
||||
end
|
||||
|
||||
it "returns a String containing the Module the method is defined in" do
|
||||
@string.should =~ /MethodSpecs::MyMod/
|
||||
end
|
||||
|
@ -32,13 +47,21 @@ describe :method_to_s, shared: true do
|
|||
@string.should =~ /MethodSpecs::MySub/
|
||||
end
|
||||
|
||||
it "returns a String including all details" do
|
||||
@string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
|
||||
end
|
||||
|
||||
it "does not show the defining module if it is the same as the receiver class" do
|
||||
MethodSpecs::A.new.method(:baz).send(@method).should.start_with? "#<Method: MethodSpecs::A#baz"
|
||||
end
|
||||
|
||||
ruby_version_is '3.0' do
|
||||
it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do
|
||||
obj = MethodSpecs::MySub.new
|
||||
obj.singleton_class
|
||||
@m = obj.method(:bar)
|
||||
@string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX')
|
||||
@string.should =~ /\A#<Method: MethodSpecs::MySub\(MethodSpecs::MyMod\)#bar\(\) /
|
||||
@string = @m.send(@method)
|
||||
@string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -46,7 +69,7 @@ describe :method_to_s, shared: true do
|
|||
obj = MethodSpecs::MySub.new
|
||||
def obj.bar; end
|
||||
@m = obj.method(:bar)
|
||||
@string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX')
|
||||
@string.should =~ /\A#<Method: #<MethodSpecs::MySub:0xXXXXXX>\.bar/
|
||||
@string = @m.send(@method).sub(/0x\h+/, '0xXXXXXX')
|
||||
@string.should.start_with? "#<Method: #<MethodSpecs::MySub:0xXXXXXX>.bar"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -86,6 +86,24 @@ describe "Method#source_location" do
|
|||
method.source_location[1].should == line
|
||||
end
|
||||
|
||||
it "works for core methods where it returns nil or <internal:" do
|
||||
loc = method(:__id__).source_location
|
||||
if loc == nil
|
||||
loc.should == nil
|
||||
else
|
||||
loc[0].should.start_with?('<internal:')
|
||||
loc[1].should be_kind_of(Integer)
|
||||
end
|
||||
|
||||
loc = method(:tap).source_location
|
||||
if loc == nil
|
||||
loc.should == nil
|
||||
else
|
||||
loc[0].should.start_with?('<internal:')
|
||||
loc[1].should be_kind_of(Integer)
|
||||
end
|
||||
end
|
||||
|
||||
describe "for a Method generated by respond_to_missing?" do
|
||||
it "returns nil" do
|
||||
m = MethodSpecs::Methods.new
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require_relative '../../spec_helper'
|
||||
require_relative '../../fixtures/code_loading'
|
||||
require_relative 'fixtures/classes'
|
||||
require 'thread'
|
||||
|
||||
|
@ -33,14 +34,7 @@ end
|
|||
describe "Module#autoload" do
|
||||
before :all do
|
||||
@non_existent = fixture __FILE__, "no_autoload.rb"
|
||||
|
||||
# Require RubyGems eagerly, to ensure #require is already the RubyGems
|
||||
# version, before starting #autoload specs which snapshot #require, and
|
||||
# could end up redefining #require as the original core Kernel#require.
|
||||
begin
|
||||
require "rubygems"
|
||||
rescue LoadError
|
||||
end
|
||||
CodeLoadingSpecs.preload_rubygems
|
||||
end
|
||||
|
||||
before :each do
|
||||
|
|
|
@ -25,4 +25,9 @@ describe "Range#===" do
|
|||
(range === RangeSpecs::WithoutSucc.new(2)).should == true
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it_behaves_like :range_cover_and_include, :===
|
||||
it_behaves_like :range_cover, :===
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,4 +6,5 @@ require_relative 'shared/cover'
|
|||
describe "Range#cover?" do
|
||||
it_behaves_like :range_cover_and_include, :cover?
|
||||
it_behaves_like :range_cover, :cover?
|
||||
it_behaves_like :range_cover_subrange, :cover?
|
||||
end
|
||||
|
|
|
@ -90,7 +90,9 @@ describe :range_cover, shared: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe :range_cover_subrange, shared: true do
|
||||
ruby_version_is "2.6" do
|
||||
context "range argument" do
|
||||
it "accepts range argument" do
|
||||
|
|
|
@ -36,6 +36,19 @@ describe 'Thread::Backtrace::Location#absolute_path' do
|
|||
end
|
||||
end
|
||||
|
||||
context "when used in a core method" do
|
||||
it "returns nil" do
|
||||
location = nil
|
||||
tap { location = caller_locations(1, 1)[0] }
|
||||
location.label.should == "tap"
|
||||
if location.path.start_with?("<internal:")
|
||||
location.absolute_path.should == nil
|
||||
else
|
||||
location.absolute_path.should == File.realpath(__FILE__)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "canonicalization" do
|
||||
platform_is_not :windows do
|
||||
before :each do
|
||||
|
|
|
@ -22,4 +22,13 @@ describe :unboundmethod_to_s, shared: true do
|
|||
@from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/
|
||||
@from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
|
||||
end
|
||||
|
||||
it "returns a String including all details" do
|
||||
@from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
|
||||
@from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
|
||||
end
|
||||
|
||||
it "does not show the defining module if it is the same as the origin" do
|
||||
UnboundMethodSpecs::A.instance_method(:baz).send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::A#baz"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
ruby_version_is '2.7.2' do
|
||||
describe "Warning.[]" do
|
||||
it "returns default values for categories :deprecated and :experimental" do
|
||||
ruby_exe('p Warning[:deprecated]').chomp.should == "false"
|
||||
ruby_exe('p Warning[:experimental]').chomp.should == "true"
|
||||
end
|
||||
|
||||
it "raises for unknown category" do
|
||||
-> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require_relative '../../spec_helper'
|
||||
|
||||
ruby_version_is '2.7' do
|
||||
describe "Warning.[]=" do
|
||||
it "emits and suppresses warnings for :deprecated" do
|
||||
ruby_exe('Warning[:deprecated] = true; $; = ""', args: "2>&1").should =~ /is deprecated/
|
||||
ruby_exe('Warning[:deprecated] = false; $; = ""', args: "2>&1").should == ""
|
||||
end
|
||||
|
||||
it "emits and suppresses warnings for :experimental" do
|
||||
ruby_exe('Warning[:experimental] = true; eval("0 in a")', args: "2>&1").should =~ /is experimental/
|
||||
ruby_exe('Warning[:experimental] = false; eval("0 in a")', args: "2>&1").should == ""
|
||||
end
|
||||
|
||||
it "raises for unknown category" do
|
||||
-> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,7 +12,22 @@ module CodeLoadingSpecs
|
|||
end
|
||||
end
|
||||
|
||||
def self.preload_rubygems
|
||||
# Require RubyGems eagerly, to ensure #require is already the RubyGems
|
||||
# version and RubyGems is only loaded once, before starting #require/#autoload specs
|
||||
# which snapshot $LOADED_FEATURES and could cause RubyGems to load twice.
|
||||
# #require specs also snapshot #require, and could end up redefining #require as the original core Kernel#require.
|
||||
@rubygems ||= begin
|
||||
require "rubygems"
|
||||
true
|
||||
rescue LoadError
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def self.spec_setup
|
||||
preload_rubygems
|
||||
|
||||
@saved_loaded_features = $LOADED_FEATURES.clone
|
||||
@saved_load_path = $LOAD_PATH.clone
|
||||
ScratchPad.record []
|
||||
|
|
|
@ -424,4 +424,13 @@ describe "The 'case'-construct with no target expression" do
|
|||
:called
|
||||
end.should == :called
|
||||
end
|
||||
|
||||
# Homogeneous cases are often optimized to avoid === using a jump table, and should be tested separately.
|
||||
# See https://github.com/jruby/jruby/issues/6440
|
||||
it "handles homogeneous cases" do
|
||||
case
|
||||
when 1; 'foo'
|
||||
when 2; 'bar'
|
||||
end.should == 'foo'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -285,6 +285,16 @@ describe "A class definition extending an object (sclass)" do
|
|||
}.should raise_error(TypeError)
|
||||
end
|
||||
|
||||
it "raises a TypeError when trying to extend non-Class" do
|
||||
error_msg = /superclass must be a Class/
|
||||
-> { class TestClass < ""; end }.should raise_error(TypeError, error_msg)
|
||||
-> { class TestClass < 1; end }.should raise_error(TypeError, error_msg)
|
||||
-> { class TestClass < :symbol; end }.should raise_error(TypeError, error_msg)
|
||||
-> { class TestClass < mock('o'); end }.should raise_error(TypeError, error_msg)
|
||||
-> { class TestClass < Module.new; end }.should raise_error(TypeError, error_msg)
|
||||
-> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg)
|
||||
end
|
||||
|
||||
ruby_version_is ""..."3.0" do
|
||||
it "allows accessing the block of the original scope" do
|
||||
suppress_warning do
|
||||
|
|
|
@ -455,6 +455,52 @@ module SuperSpecs
|
|||
end
|
||||
end
|
||||
|
||||
module ZSuperWithRestAndPost
|
||||
class A
|
||||
def m(*args, a, b)
|
||||
args
|
||||
end
|
||||
|
||||
def m_modified(*args, a, b)
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
class B < A
|
||||
def m(*args, a, b)
|
||||
super
|
||||
end
|
||||
|
||||
def m_modified(*args, a, b)
|
||||
args[1] = 14
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ZSuperWithRestOthersAndPost
|
||||
class A
|
||||
def m(a, *args, b)
|
||||
args
|
||||
end
|
||||
|
||||
def m_modified(a, *args, b)
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
class B < A
|
||||
def m(a, *args, b)
|
||||
super
|
||||
end
|
||||
|
||||
def m_modified(a, *args, b)
|
||||
args[1] = 14
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module ZSuperWithRestReassigned
|
||||
class A
|
||||
def a(*args)
|
||||
|
|
|
@ -59,6 +59,22 @@ HERE
|
|||
s.encoding.should == Encoding::US_ASCII
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
it 'raises SyntaxError if quoted HEREDOC identifier is ending not on same line' do
|
||||
-> {
|
||||
eval %{<<"HERE\n"\nraises syntax error\nHERE}
|
||||
}.should raise_error(SyntaxError)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is ""..."2.7" do
|
||||
it 'prints a warning if quoted HEREDOC identifier is ending not on same line' do
|
||||
-> {
|
||||
eval %{<<"HERE\n"\nit warns\nHERE}
|
||||
}.should complain(/here document identifier ends with a newline/)
|
||||
end
|
||||
end
|
||||
|
||||
it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do
|
||||
require_relative 'fixtures/squiggly_heredoc'
|
||||
SquigglyHeredocSpecs.message.should == "character density, n.:\n The number of very weird people in the office.\n"
|
||||
|
|
|
@ -596,10 +596,21 @@ describe "A method" do
|
|||
m(a: 1, b: 2).should == { a: 1, b: 2 }
|
||||
m(*[]).should == {}
|
||||
m(**{}).should == {}
|
||||
m(**{a: 1, b: 2}, **{a: 4, c: 7}).should == { a: 4, b: 2, c: 7 }
|
||||
suppress_warning {
|
||||
eval "m(**{a: 1, b: 2}, **{a: 4, c: 7})"
|
||||
}.should == { a: 4, b: 2, c: 7 }
|
||||
-> { m(2) }.should raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
evaluate <<-ruby do
|
||||
def m(**k); k end;
|
||||
ruby
|
||||
|
||||
m("a" => 1).should == { "a" => 1 }
|
||||
end
|
||||
end
|
||||
|
||||
evaluate <<-ruby do
|
||||
def m(&b) b end
|
||||
ruby
|
||||
|
@ -1626,6 +1637,20 @@ describe "A method" do
|
|||
result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l]
|
||||
end
|
||||
|
||||
ruby_version_is "2.7" do
|
||||
evaluate <<-ruby do
|
||||
def m(a, **nil); a end;
|
||||
ruby
|
||||
|
||||
m({a: 1}).should == {a: 1}
|
||||
m({"a" => 1}).should == {"a" => 1}
|
||||
|
||||
-> { m(a: 1) }.should raise_error(ArgumentError)
|
||||
-> { m(**{a: 1}) }.should raise_error(ArgumentError)
|
||||
-> { m("a" => 1) }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is ''...'3.0' do
|
||||
evaluate <<-ruby do
|
||||
def m(a, b = nil, c = nil, d, e: nil, **f)
|
||||
|
@ -1665,6 +1690,32 @@ describe "A method" do
|
|||
end
|
||||
end
|
||||
|
||||
ruby_version_is '2.7' do
|
||||
context 'when passing an empty keyword splat to a method that does not accept keywords' do
|
||||
evaluate <<-ruby do
|
||||
def m(*a); a; end
|
||||
ruby
|
||||
|
||||
h = {}
|
||||
m(**h).should == []
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is '2.7'...'3.0' do
|
||||
context 'when passing an empty keyword splat to a method that does not accept keywords' do
|
||||
evaluate <<-ruby do
|
||||
def m(a); a; end
|
||||
ruby
|
||||
h = {}
|
||||
|
||||
-> do
|
||||
m(**h).should == {}
|
||||
end.should complain(/warning: Passing the keyword argument as the last hash parameter is deprecated/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is ''...'3.0' do
|
||||
context "assigns keyword arguments from a passed Hash without modifying it" do
|
||||
evaluate <<-ruby do
|
||||
|
@ -1683,6 +1734,18 @@ describe "A method" do
|
|||
end
|
||||
|
||||
ruby_version_is '3.0' do
|
||||
context 'when passing an empty keyword splat to a method that does not accept keywords' do
|
||||
evaluate <<-ruby do
|
||||
def m(a); a; end
|
||||
ruby
|
||||
h = {}
|
||||
|
||||
-> do
|
||||
m(**h).should == {}
|
||||
end.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
context "raises ArgumentError if passing hash as keyword arguments" do
|
||||
evaluate <<-ruby do
|
||||
def m(a: nil); a; end
|
||||
|
|
|
@ -933,6 +933,14 @@ describe "Global variable $-d" do
|
|||
end
|
||||
|
||||
describe "Global variable $VERBOSE" do
|
||||
before :each do
|
||||
@verbose = $VERBOSE
|
||||
end
|
||||
|
||||
after :each do
|
||||
$VERBOSE = @verbose
|
||||
end
|
||||
|
||||
it "converts truthy values to true" do
|
||||
[true, 1, 0, [], ""].each do |true_value|
|
||||
$VERBOSE = true_value
|
||||
|
|
|
@ -135,4 +135,18 @@ describe "The $SAFE variable" do
|
|||
}.call
|
||||
end
|
||||
end
|
||||
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it "warn when access" do
|
||||
-> {
|
||||
$SAFE
|
||||
}.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/)
|
||||
end
|
||||
|
||||
it "warn when set" do
|
||||
-> {
|
||||
$SAFE = 1
|
||||
}.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -157,6 +157,23 @@ describe "A constant on a singleton class" do
|
|||
end
|
||||
end
|
||||
|
||||
describe "Defining yield in singleton class" do
|
||||
ruby_version_is "2.7"..."3.0" do
|
||||
it 'emits a deprecation warning' do
|
||||
code = <<~RUBY
|
||||
def m
|
||||
class << Object.new
|
||||
yield
|
||||
end
|
||||
end
|
||||
m { :ok }
|
||||
RUBY
|
||||
|
||||
-> { eval(code) }.should complain(/warning: `yield' in class syntax will not be supported from Ruby 3.0/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Defining instance methods on a singleton class" do
|
||||
before :each do
|
||||
@k = ClassSpecs::K.new
|
||||
|
|
|
@ -293,6 +293,21 @@ describe "The super keyword" do
|
|||
|
||||
it "without explicit arguments passes arguments and rest arguments" do
|
||||
SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2, 3, 4, 5).should == [3, 4, 5]
|
||||
SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2).should == []
|
||||
end
|
||||
|
||||
it "without explicit arguments passes arguments, rest arguments, and post arguments" do
|
||||
SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2, 3, 4, 5).should == [1, 2, 3]
|
||||
SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2, 3, 4, 5).should == [2, 3, 4]
|
||||
SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2).should == []
|
||||
SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2).should == []
|
||||
end
|
||||
|
||||
it "without explicit arguments passes arguments, rest arguments including modifications, and post arguments" do
|
||||
SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [1, 14, 3]
|
||||
SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [2, 14, 4]
|
||||
SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2).should == [nil, 14]
|
||||
SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2).should == [nil, 14]
|
||||
end
|
||||
|
||||
it "without explicit arguments passes arguments and rest arguments including any modifications" do
|
||||
|
|
|
@ -796,3 +796,32 @@ describe 'Local variable shadowing' do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Allowed characters' do
|
||||
ruby_version_is "2.6" do
|
||||
# new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770
|
||||
it 'does not allow non-ASCII upcased characters at the beginning' do
|
||||
-> do
|
||||
eval <<-CODE
|
||||
def test
|
||||
ἍBB = 1
|
||||
end
|
||||
CODE
|
||||
end.should raise_error(SyntaxError, /dynamic constant assignment/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'allows non-ASCII lowercased characters at the beginning' do
|
||||
result = nil
|
||||
|
||||
eval <<-CODE
|
||||
def test
|
||||
μ = 1
|
||||
end
|
||||
|
||||
result = test
|
||||
CODE
|
||||
|
||||
result.should == 1
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,9 +37,12 @@ describe "YAML.dump" do
|
|||
it "dumps an OpenStruct" do
|
||||
require "ostruct"
|
||||
os = OpenStruct.new("age" => 20, "name" => "John")
|
||||
os2 = YAML.load(YAML.dump(os))
|
||||
os2.age.should == 20
|
||||
os2.name.should == "John"
|
||||
yaml_dump = YAML.dump(os)
|
||||
|
||||
[
|
||||
"--- !ruby/object:OpenStruct\nage: 20\nname: John\n",
|
||||
"--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n",
|
||||
].should.include?(yaml_dump)
|
||||
end
|
||||
|
||||
it "dumps a File without any state" do
|
||||
|
|
|
@ -73,6 +73,14 @@ static void* blocking_gvl_func_for_udf_io(void *data) {
|
|||
}
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
static VALUE thread_spec_rb_thread_call_without_gvl_native_function(VALUE self) {
|
||||
pid_t ret = (pid_t) (long) rb_thread_call_without_gvl((void *(*)(void *)) getpid, 0, RUBY_UBF_IO, 0);
|
||||
return LONG2FIX(ret);
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/* Returns true if the thread is interrupted. */
|
||||
static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) {
|
||||
int fds[2];
|
||||
|
@ -134,6 +142,7 @@ void Init_thread_spec(void) {
|
|||
VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject);
|
||||
rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0);
|
||||
rb_define_method(cls, "rb_thread_call_without_gvl", thread_spec_rb_thread_call_without_gvl, 0);
|
||||
rb_define_method(cls, "rb_thread_call_without_gvl_native_function", thread_spec_rb_thread_call_without_gvl_native_function, 0);
|
||||
rb_define_method(cls, "rb_thread_call_without_gvl_with_ubf_io", thread_spec_rb_thread_call_without_gvl_with_ubf_io, 0);
|
||||
rb_define_method(cls, "rb_thread_current", thread_spec_rb_thread_current, 0);
|
||||
rb_define_method(cls, "rb_thread_local_aref", thread_spec_rb_thread_local_aref, 2);
|
||||
|
|
|
@ -121,6 +121,10 @@ describe "C-API Thread function" do
|
|||
thr.value.should be_true
|
||||
end
|
||||
|
||||
it "runs a native function with the global lock unlocked" do
|
||||
@t.rb_thread_call_without_gvl_native_function.should == Process.pid
|
||||
end
|
||||
|
||||
guard -> { platform_is :mingw and ruby_version_is ""..."2.7" } do
|
||||
it "runs a C function with the global lock unlocked and unlocks IO with the generic RUBY_UBF_IO" do
|
||||
thr = Thread.new do
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
describe :enumerable_minmax, shared: true do
|
||||
it "min should return the minimum element" do
|
||||
@enum.minmax.should == [4, 10]
|
||||
@strs.minmax.should == ["1010", "60"]
|
||||
end
|
||||
|
||||
it "returns the minimum when using a block rule" do
|
||||
@enum.minmax {|a,b| b <=> a }.should == [10, 4]
|
||||
@strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"]
|
||||
end
|
||||
|
||||
it "returns [nil, nil] for an empty Enumerable" do
|
||||
@empty_enum.minmax.should == [nil, nil]
|
||||
end
|
||||
|
||||
it "raises a NoMethodError for elements without #<=>" do
|
||||
-> { @incomparable_enum.minmax }.should raise_error(NoMethodError)
|
||||
end
|
||||
|
||||
it "raises an ArgumentError when elements are incompatible" do
|
||||
-> { @incompatible_enum.minmax }.should raise_error(ArgumentError)
|
||||
-> { @enum.minmax{ |a, b| nil } }.should raise_error(ArgumentError)
|
||||
end
|
||||
end
|
Загрузка…
Ссылка в новой задаче