1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
This commit is contained in:
Benoit Daloze 2021-10-20 21:41:46 +02:00
parent 207a5a5bc1
commit a6c6eef04a
44 changed files with 1141 additions and 250 deletions

View file

@ -0,0 +1,48 @@
require_relative '../spec_helper'
ruby_version_is "3.0" do
describe "The --backtrace-limit command line option" do
it "limits top-level backtraces to a given number of entries" do
file = fixture(__FILE__ , "backtrace.rb")
out = ruby_exe(file, options: "--backtrace-limit=2", args: "top 2>&1", exit_status: 1)
out = out.gsub(__dir__, '')
out.should == <<-MSG
top
/fixtures/backtrace.rb:2:in `a': unhandled exception
\tfrom /fixtures/backtrace.rb:6:in `b'
\tfrom /fixtures/backtrace.rb:10:in `c'
\t ... 2 levels...
MSG
end
it "affects Exception#full_message" do
file = fixture(__FILE__ , "backtrace.rb")
out = ruby_exe(file, options: "--backtrace-limit=2", args: "full_message 2>&1")
out = out.gsub(__dir__, '')
out.should == <<-MSG
full_message
/fixtures/backtrace.rb:2:in `a': unhandled exception
\tfrom /fixtures/backtrace.rb:6:in `b'
\tfrom /fixtures/backtrace.rb:10:in `c'
\t ... 2 levels...
MSG
end
it "does not affect Exception#backtrace" do
file = fixture(__FILE__ , "backtrace.rb")
out = ruby_exe(file, options: "--backtrace-limit=2", args: "backtrace 2>&1")
out = out.gsub(__dir__, '')
out.should == <<-MSG
backtrace
/fixtures/backtrace.rb:2:in `a'
/fixtures/backtrace.rb:6:in `b'
/fixtures/backtrace.rb:10:in `c'
/fixtures/backtrace.rb:14:in `d'
/fixtures/backtrace.rb:29:in `<main>'
MSG
end
end
end

View file

@ -0,0 +1,35 @@
def a
raise
end
def b
a
end
def c
b
end
def d
c
end
arg = ARGV.first
$stderr.puts arg
case arg
when 'full_message'
begin
d
rescue => exc
puts exc.full_message
end
when 'backtrace'
begin
d
rescue => exc
puts exc.backtrace
end
else
d
end

View file

@ -517,8 +517,9 @@ describe :array_slice, shared: true do
end
it "raises a RangeError if passed a range with a bound that is too large" do
-> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
-> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
array = [1, 2, 3, 4, 5, 6]
-> { array.send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
-> { array.send(@method, 0..bignum_value) }.should raise_error(RangeError)
end
it "can accept endless ranges" do
@ -533,6 +534,218 @@ describe :array_slice, shared: true do
a.send(@method, eval("(-9...)")).should == nil
end
ruby_version_is "3.0" do
describe "can be sliced with Enumerator::ArithmeticSequence" do
before :each do
@array = [0, 1, 2, 3, 4, 5]
end
it "has endless range and positive steps" do
@array.send(@method, eval("(0..).step(1)")).should == [0, 1, 2, 3, 4, 5]
@array.send(@method, eval("(0..).step(2)")).should == [0, 2, 4]
@array.send(@method, eval("(0..).step(10)")).should == [0]
@array.send(@method, eval("(2..).step(1)")).should == [2, 3, 4, 5]
@array.send(@method, eval("(2..).step(2)")).should == [2, 4]
@array.send(@method, eval("(2..).step(10)")).should == [2]
@array.send(@method, eval("(-3..).step(1)")).should == [3, 4, 5]
@array.send(@method, eval("(-3..).step(2)")).should == [3, 5]
@array.send(@method, eval("(-3..).step(10)")).should == [3]
end
it "has beginless range and positive steps" do
# end with zero index
@array.send(@method, eval("(..0).step(1)")).should == [0]
@array.send(@method, eval("(...0).step(1)")).should == []
@array.send(@method, eval("(..0).step(2)")).should == [0]
@array.send(@method, eval("(...0).step(2)")).should == []
@array.send(@method, eval("(..0).step(10)")).should == [0]
@array.send(@method, eval("(...0).step(10)")).should == []
# end with positive index
@array.send(@method, eval("(..3).step(1)")).should == [0, 1, 2, 3]
@array.send(@method, eval("(...3).step(1)")).should == [0, 1, 2]
@array.send(@method, eval("(..3).step(2)")).should == [0, 2]
@array.send(@method, eval("(...3).step(2)")).should == [0, 2]
@array.send(@method, eval("(..3).step(10)")).should == [0]
@array.send(@method, eval("(...3).step(10)")).should == [0]
# end with negative index
@array.send(@method, eval("(..-2).step(1)")).should == [0, 1, 2, 3, 4,]
@array.send(@method, eval("(...-2).step(1)")).should == [0, 1, 2, 3]
@array.send(@method, eval("(..-2).step(2)")).should == [0, 2, 4]
@array.send(@method, eval("(...-2).step(2)")).should == [0, 2]
@array.send(@method, eval("(..-2).step(10)")).should == [0]
@array.send(@method, eval("(...-2).step(10)")).should == [0]
end
it "has endless range and negative steps" do
@array.send(@method, eval("(0..).step(-1)")).should == [0]
@array.send(@method, eval("(0..).step(-2)")).should == [0]
@array.send(@method, eval("(0..).step(-10)")).should == [0]
@array.send(@method, eval("(2..).step(-1)")).should == [2, 1, 0]
@array.send(@method, eval("(2..).step(-2)")).should == [2, 0]
@array.send(@method, eval("(-3..).step(-1)")).should == [3, 2, 1, 0]
@array.send(@method, eval("(-3..).step(-2)")).should == [3, 1]
end
it "has closed range and positive steps" do
# start and end with 0
@array.send(@method, eval("(0..0).step(1)")).should == [0]
@array.send(@method, eval("(0...0).step(1)")).should == []
@array.send(@method, eval("(0..0).step(2)")).should == [0]
@array.send(@method, eval("(0...0).step(2)")).should == []
@array.send(@method, eval("(0..0).step(10)")).should == [0]
@array.send(@method, eval("(0...0).step(10)")).should == []
# start and end with positive index
@array.send(@method, eval("(1..3).step(1)")).should == [1, 2, 3]
@array.send(@method, eval("(1...3).step(1)")).should == [1, 2]
@array.send(@method, eval("(1..3).step(2)")).should == [1, 3]
@array.send(@method, eval("(1...3).step(2)")).should == [1]
@array.send(@method, eval("(1..3).step(10)")).should == [1]
@array.send(@method, eval("(1...3).step(10)")).should == [1]
# start with positive index, end with negative index
@array.send(@method, eval("(1..-2).step(1)")).should == [1, 2, 3, 4]
@array.send(@method, eval("(1...-2).step(1)")).should == [1, 2, 3]
@array.send(@method, eval("(1..-2).step(2)")).should == [1, 3]
@array.send(@method, eval("(1...-2).step(2)")).should == [1, 3]
@array.send(@method, eval("(1..-2).step(10)")).should == [1]
@array.send(@method, eval("(1...-2).step(10)")).should == [1]
# start with negative index, end with positive index
@array.send(@method, eval("(-4..4).step(1)")).should == [2, 3, 4]
@array.send(@method, eval("(-4...4).step(1)")).should == [2, 3]
@array.send(@method, eval("(-4..4).step(2)")).should == [2, 4]
@array.send(@method, eval("(-4...4).step(2)")).should == [2]
@array.send(@method, eval("(-4..4).step(10)")).should == [2]
@array.send(@method, eval("(-4...4).step(10)")).should == [2]
# start with negative index, end with negative index
@array.send(@method, eval("(-4..-2).step(1)")).should == [2, 3, 4]
@array.send(@method, eval("(-4...-2).step(1)")).should == [2, 3]
@array.send(@method, eval("(-4..-2).step(2)")).should == [2, 4]
@array.send(@method, eval("(-4...-2).step(2)")).should == [2]
@array.send(@method, eval("(-4..-2).step(10)")).should == [2]
@array.send(@method, eval("(-4...-2).step(10)")).should == [2]
end
it "has closed range and negative steps" do
# start and end with 0
@array.send(@method, eval("(0..0).step(-1)")).should == [0]
@array.send(@method, eval("(0...0).step(-1)")).should == []
@array.send(@method, eval("(0..0).step(-2)")).should == [0]
@array.send(@method, eval("(0...0).step(-2)")).should == []
@array.send(@method, eval("(0..0).step(-10)")).should == [0]
@array.send(@method, eval("(0...0).step(-10)")).should == []
# start and end with positive index
@array.send(@method, eval("(1..3).step(-1)")).should == []
@array.send(@method, eval("(1...3).step(-1)")).should == []
@array.send(@method, eval("(1..3).step(-2)")).should == []
@array.send(@method, eval("(1...3).step(-2)")).should == []
@array.send(@method, eval("(1..3).step(-10)")).should == []
@array.send(@method, eval("(1...3).step(-10)")).should == []
# start with positive index, end with negative index
@array.send(@method, eval("(1..-2).step(-1)")).should == []
@array.send(@method, eval("(1...-2).step(-1)")).should == []
@array.send(@method, eval("(1..-2).step(-2)")).should == []
@array.send(@method, eval("(1...-2).step(-2)")).should == []
@array.send(@method, eval("(1..-2).step(-10)")).should == []
@array.send(@method, eval("(1...-2).step(-10)")).should == []
# start with negative index, end with positive index
@array.send(@method, eval("(-4..4).step(-1)")).should == []
@array.send(@method, eval("(-4...4).step(-1)")).should == []
@array.send(@method, eval("(-4..4).step(-2)")).should == []
@array.send(@method, eval("(-4...4).step(-2)")).should == []
@array.send(@method, eval("(-4..4).step(-10)")).should == []
@array.send(@method, eval("(-4...4).step(-10)")).should == []
# start with negative index, end with negative index
@array.send(@method, eval("(-4..-2).step(-1)")).should == []
@array.send(@method, eval("(-4...-2).step(-1)")).should == []
@array.send(@method, eval("(-4..-2).step(-2)")).should == []
@array.send(@method, eval("(-4...-2).step(-2)")).should == []
@array.send(@method, eval("(-4..-2).step(-10)")).should == []
@array.send(@method, eval("(-4...-2).step(-10)")).should == []
end
it "has inverted closed range and positive steps" do
# start and end with positive index
@array.send(@method, eval("(3..1).step(1)")).should == []
@array.send(@method, eval("(3...1).step(1)")).should == []
@array.send(@method, eval("(3..1).step(2)")).should == []
@array.send(@method, eval("(3...1).step(2)")).should == []
@array.send(@method, eval("(3..1).step(10)")).should == []
@array.send(@method, eval("(3...1).step(10)")).should == []
# start with negative index, end with positive index
@array.send(@method, eval("(-2..1).step(1)")).should == []
@array.send(@method, eval("(-2...1).step(1)")).should == []
@array.send(@method, eval("(-2..1).step(2)")).should == []
@array.send(@method, eval("(-2...1).step(2)")).should == []
@array.send(@method, eval("(-2..1).step(10)")).should == []
@array.send(@method, eval("(-2...1).step(10)")).should == []
# start with positive index, end with negative index
@array.send(@method, eval("(4..-4).step(1)")).should == []
@array.send(@method, eval("(4...-4).step(1)")).should == []
@array.send(@method, eval("(4..-4).step(2)")).should == []
@array.send(@method, eval("(4...-4).step(2)")).should == []
@array.send(@method, eval("(4..-4).step(10)")).should == []
@array.send(@method, eval("(4...-4).step(10)")).should == []
# start with negative index, end with negative index
@array.send(@method, eval("(-2..-4).step(1)")).should == []
@array.send(@method, eval("(-2...-4).step(1)")).should == []
@array.send(@method, eval("(-2..-4).step(2)")).should == []
@array.send(@method, eval("(-2...-4).step(2)")).should == []
@array.send(@method, eval("(-2..-4).step(10)")).should == []
@array.send(@method, eval("(-2...-4).step(10)")).should == []
end
end
end
ruby_version_is "2.7" do
it "can accept beginless ranges" do
a = [0, 1, 2, 3, 4, 5]

View file

@ -93,16 +93,28 @@ describe "Binding#eval" do
it "inherits __FILE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
suppress_warning {bind.eval("__FILE__")}.should == obj.get_file_of_binding
suppress_warning { bind.eval("__FILE__") }.should == obj.get_file_of_binding
end
it "inherits __LINE__ from the enclosing scope" do
obj = BindingSpecs::Demo.new(1)
bind, line = obj.get_binding_and_line
suppress_warning { bind.eval("__LINE__") }.should == line
end
end
ruby_version_is "3.0" do
it "Uses (eval) as __FILE__ if single argument given" do
it "uses (eval) as __FILE__ if single argument given" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
bind.eval("__FILE__").should == '(eval)'
end
it "uses 1 as __LINE__" do
obj = BindingSpecs::Demo.new(1)
bind = obj.get_binding
suppress_warning { bind.eval("__LINE__") }.should == 1
end
end
it "uses the __FILE__ that is passed in" do

View file

@ -38,6 +38,23 @@ describe :dir_glob, shared: true do
end
end
ruby_version_is "3.0" do
it "result is sorted by default" do
result = Dir.send(@method, '*')
result.should == result.sort
end
it "result is sorted with sort: true" do
result = Dir.send(@method, '*', sort: true)
result.should == result.sort
end
it "sort: false returns same files" do
result = Dir.send(@method,'*', sort: false)
result.sort.should == Dir.send(@method, '*').sort
end
end
it "matches non-dotfiles with '*'" do
expected = %w[
brace

View file

@ -1,30 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
describe "ENV.shift" do
it "returns a pair and deletes it" do
ENV.should_not.empty?
orig = ENV.to_hash
begin
pair = ENV.shift
ENV.has_key?(pair.first).should == false
ensure
ENV.replace orig
end
ENV.has_key?(pair.first).should == true
end
it "returns nil if ENV.empty?" do
orig = ENV.to_hash
begin
ENV.clear
ENV.shift.should == nil
ensure
ENV.replace orig
end
end
end
describe "ENV.shift" do
before :each do
@orig = ENV.to_hash
@ -32,6 +8,7 @@ describe "ENV.shift" do
@internal = Encoding.default_internal
Encoding.default_external = Encoding::BINARY
ENV.replace({"FOO"=>"BAR"})
end
after :each do
@ -40,6 +17,18 @@ describe "ENV.shift" do
ENV.replace @orig
end
it "returns a pair and deletes it" do
ENV.should.has_key?("FOO")
pair = ENV.shift
pair.should == ["FOO", "BAR"]
ENV.should_not.has_key?("FOO")
end
it "returns nil if ENV.empty?" do
ENV.clear
ENV.shift.should == nil
end
it "uses the locale encoding if Encoding.default_internal is nil" do
Encoding.default_internal = nil
@ -52,9 +41,7 @@ describe "ENV.shift" do
Encoding.default_internal = Encoding::IBM437
pair = ENV.shift
pair.first.encode(Encoding::IBM437) rescue next
pair.first.encoding.should equal(Encoding::IBM437)
pair.last.encode(Encoding::IBM437) rescue next
pair.last.encoding.should equal(Encoding::IBM437)
end
end

View file

@ -70,11 +70,13 @@ describe "File.utime" do
end
end
it "may set nanosecond precision" do
t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
File.utime(t, t, @file1)
File.atime(@file1).nsec.should.between?(0, 123500000)
File.mtime(@file1).nsec.should.between?(0, 123500000)
platform_is_not :windows do
it "sets nanosecond precision" do
t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789r)
File.utime(t, t, @file1)
File.atime(@file1).nsec.should == 123456789
File.mtime(@file1).nsec.should == 123456789
end
end
platform_is :linux do

View file

@ -90,4 +90,19 @@ describe "Float#<=>" do
end
(infinity_value <=> obj).should == 1
end
it "returns 0 for -0.0 and 0.0" do
(-0.0 <=> 0.0).should == 0
(0.0 <=> -0.0).should == 0
end
it "returns 0 for -0.0 and 0" do
(-0.0 <=> 0).should == 0
(0 <=> -0.0).should == 0
end
it "returns 0 for 0.0 and 0" do
(0.0 <=> 0).should == 0
(0 <=> 0.0).should == 0
end
end

View file

@ -42,6 +42,20 @@ describe "Hash#transform_keys" do
r.keys.should == [:xfoo]
r.class.should == Hash
end
ruby_version_is "3.0" do
it "allows a hash argument" do
@hash.transform_keys({ a: :A, b: :B, c: :C }).should == { A: 1, B: 2, C: 3 }
end
it "allows a partial transformation of keys when using a hash argument" do
@hash.transform_keys({ a: :A, c: :C }).should == { A: 1, b: 2, C: 3 }
end
it "allows a combination of hash and block argument" do
@hash.transform_keys({ a: :A }, &:to_s).should == { A: 1, 'b' => 2, 'c' => 3 }
end
end
end
describe "Hash#transform_keys!" do
@ -98,6 +112,13 @@ describe "Hash#transform_keys!" do
end
end
ruby_version_is "3.0" do
it "allows a hash argument" do
@hash.transform_keys!({ a: :A, b: :B, c: :C, d: :D })
@hash.should == { A: 1, B: 2, C: 3, D: 4 }
end
end
describe "on frozen instance" do
before :each do
@hash.freeze
@ -112,6 +133,12 @@ describe "Hash#transform_keys!" do
@hash.should == @initial_pairs
end
ruby_version_is "3.0" do
it "raises a FrozenError on hash argument" do
->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError)
end
end
context "when no block is given" do
it "does not raise an exception" do
@hash.transform_keys!.should be_an_instance_of(Enumerator)

View file

@ -0,0 +1,21 @@
require_relative '../../spec_helper'
describe "Integer#zero?" do
it "returns true if self is 0" do
0.should.zero?
1.should_not.zero?
-1.should_not.zero?
end
ruby_version_is "3.0" do
it "Integer#zero? overrides Numeric#zero?" do
42.method(:zero?).owner.should == Integer
end
end
ruby_version_is ""..."3.0" do
it "Integer#zero? uses Numeric#zero?" do
42.method(:zero?).owner.should == Numeric
end
end
end

View file

@ -28,27 +28,88 @@ describe "Kernel#clone" do
clone.class.should equal klass
end
it "copies frozen state from the original" do
o2 = @obj.clone
@obj.freeze
o3 = @obj.clone
o2.should_not.frozen?
o3.should.frozen?
end
ruby_version_is '3.0' do
it 'takes an freeze: true option to frozen copy' do
@obj.clone(freeze: true).should.frozen?
describe "with no arguments" do
it "copies frozen state from the original" do
o2 = @obj.clone
@obj.freeze
@obj.clone(freeze: true).should.frozen?
o3 = @obj.clone
o2.should_not.frozen?
o3.should.frozen?
end
it 'copies frozen?' do
o = ''.freeze.clone
o.frozen?.should be_true
end
end
it 'takes an freeze: false option to not return frozen copy' do
@obj.clone(freeze: false).should_not.frozen?
@obj.freeze
@obj.clone(freeze: false).should_not.frozen?
describe "with freeze: true" do
it 'makes a frozen copy if the original is frozen' do
@obj.freeze
@obj.clone(freeze: true).should.frozen?
end
ruby_version_is ''...'3.0' do
it 'does not freeze the copy even if the original is not frozen' do
@obj.clone(freeze: true).should_not.frozen?
end
it "calls #initialize_clone with no kwargs" do
obj = KernelSpecs::CloneFreeze.new
obj.clone(freeze: true)
ScratchPad.recorded.should == [obj, {}]
end
end
ruby_version_is '3.0' do
it 'freezes the copy even if the original was not frozen' do
@obj.clone(freeze: true).should.frozen?
end
it "calls #initialize_clone with kwargs freeze: true" do
obj = KernelSpecs::CloneFreeze.new
obj.clone(freeze: true)
ScratchPad.recorded.should == [obj, { freeze: true }]
end
it "calls #initialize_clone with kwargs freeze: true even if #initialize_clone only takes a single argument" do
obj = KernelSpecs::Clone.new
-> { obj.clone(freeze: true) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
end
describe "with freeze: false" do
it 'does not freeze the copy if the original is frozen' do
@obj.freeze
@obj.clone(freeze: false).should_not.frozen?
end
it 'does not freeze the copy if the original is not frozen' do
@obj.clone(freeze: false).should_not.frozen?
end
ruby_version_is ''...'3.0' do
it "calls #initialize_clone with no kwargs" do
obj = KernelSpecs::CloneFreeze.new
obj.clone(freeze: false)
ScratchPad.recorded.should == [obj, {}]
end
end
ruby_version_is '3.0' do
it "calls #initialize_clone with kwargs freeze: false" do
obj = KernelSpecs::CloneFreeze.new
obj.clone(freeze: false)
ScratchPad.recorded.should == [obj, { freeze: false }]
end
it "calls #initialize_clone with kwargs freeze: false even if #initialize_clone only takes a single argument" do
obj = KernelSpecs::Clone.new
-> { obj.clone(freeze: false) }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
end
end
it "copies instance variables" do
@ -114,11 +175,6 @@ describe "Kernel#clone" do
cloned.bar.should == ['a']
end
it 'copies frozen?' do
o = ''.freeze.clone
o.frozen?.should be_true
end
ruby_version_is ''...'2.7' do
it 'copies tainted?' do
o = ''.taint.clone

View file

@ -168,6 +168,12 @@ describe "Kernel#eval" do
suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__
suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success'
end
it 'uses the given binding file and line for __FILE__ and __LINE__' do
suppress_warning {
eval("[__FILE__, __LINE__]", binding).should == [__FILE__, __LINE__]
}
end
end
ruby_version_is "3.0" do
@ -180,6 +186,10 @@ describe "Kernel#eval" do
eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
end
it 'uses (eval) for __FILE__ and 1 for __LINE__ with a binding argument' do
eval("[__FILE__, __LINE__]", binding).should == ["(eval)", 1]
end
end
# Found via Rubinius bug github:#149

View file

@ -288,7 +288,13 @@ module KernelSpecs
class Clone
def initialize_clone(other)
ScratchPad.record other.object_id
ScratchPad.record other
end
end
class CloneFreeze
def initialize_clone(other, **kwargs)
ScratchPad.record([other, kwargs])
end
end

View file

@ -441,42 +441,21 @@ describe "Module#autoload" do
ScratchPad.recorded.should == [:raise, :raise]
end
ruby_version_is "3.1" do
it "removes the constant from Module#constants if the loaded file does not define it" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :O, path
it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :O, path
ModuleSpecs::Autoload.const_defined?(:O).should == true
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == path
ModuleSpecs::Autoload.const_defined?(:O).should == true
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == path
-> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
-> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
ModuleSpecs::Autoload.const_defined?(:O).should == false
ModuleSpecs::Autoload.should_not have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == nil
-> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
end
end
ruby_version_is ""..."3.1" do
it "does not remove the constant from Module#constants if the loaded file does not define it, but leaves it as 'undefined'" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
ModuleSpecs::Autoload.autoload :O, path
ModuleSpecs::Autoload.const_defined?(:O).should == true
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == path
-> { ModuleSpecs::Autoload::O }.should raise_error(NameError)
ModuleSpecs::Autoload.const_defined?(:O).should == false
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.autoload?(:O).should == nil
-> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
end
ModuleSpecs::Autoload.should have_constant(:O)
ModuleSpecs::Autoload.const_defined?(:O).should == false
ModuleSpecs::Autoload.autoload?(:O).should == nil
-> { ModuleSpecs::Autoload.const_get(:O) }.should raise_error(NameError)
end
it "does not try to load the file again if the loaded file did not define the constant" do
@ -575,54 +554,31 @@ describe "Module#autoload" do
# Basically, the parent autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInParentDefinedInCurrent).should == nil
const_defined?(:DeclaredInParentDefinedInCurrent).should == false
self.should have_constant(:DeclaredInParentDefinedInCurrent)
-> { DeclaredInParentDefinedInCurrent }.should raise_error(NameError)
ModuleSpecs::Autoload::LexicalScope.send(:remove_const, :DeclaredInParentDefinedInCurrent)
end
end
ruby_version_is "3.1" do
it "looks up in parent scope after failed autoload" do
@remove << :DeclaredInCurrentDefinedInParent
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
}
it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do
@remove << :DeclaredInCurrentDefinedInParent
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
}
class LexicalScope
autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
-> { DeclaredInCurrentDefinedInParent }.should_not raise_error(NameError)
# Basically, the autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
const_defined?(:DeclaredInCurrentDefinedInParent).should == false
-> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
end
DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
class LexicalScope
autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
-> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
# Basically, the autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
const_defined?(:DeclaredInCurrentDefinedInParent).should == false
self.should have_constant(:DeclaredInCurrentDefinedInParent)
-> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
end
end
end
ruby_version_is ""..."3.1" do
it "and fails when finding the undefined autoload constant in the current scope when declared in current and defined in parent" do
@remove << :DeclaredInCurrentDefinedInParent
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
}
class LexicalScope
autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
-> { DeclaredInCurrentDefinedInParent }.should raise_error(NameError)
# Basically, the autoload constant remains in a "undefined" state
self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
const_defined?(:DeclaredInCurrentDefinedInParent).should == false
self.should have_constant(:DeclaredInCurrentDefinedInParent)
-> { const_get(:DeclaredInCurrentDefinedInParent) }.should raise_error(NameError)
end
DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
end

View file

@ -101,7 +101,7 @@ describe "Module#const_set" do
mod.const_get(:Foo).should == 1
end
it "does not warn after a failed autoload" do
it "does not warn if the previous value was undefined" do
path = fixture(__FILE__, "autoload_o.rb")
ScratchPad.record []
mod = Module.new
@ -109,6 +109,7 @@ describe "Module#const_set" do
mod.autoload :Foo, path
-> { mod::Foo }.should raise_error(NameError)
mod.should have_constant(:Foo)
mod.const_defined?(:Foo).should == false
mod.autoload?(:Foo).should == nil

View file

@ -74,6 +74,12 @@ describe "Module#constants" do
it "returns only public constants" do
ModuleSpecs::PrivConstModule.constants.should == [:PUBLIC_CONSTANT]
end
it "returns only constants starting with an uppercase letter" do
# e.g. fatal, IO::generic_readable and IO::generic_writable should not be returned by Module#constants
Object.constants.each { |c| c[0].should == c[0].upcase }
IO.constants.each { |c| c[0].should == c[0].upcase }
end
end
describe "Module#constants" do

View file

@ -84,9 +84,27 @@ describe "Range#each" do
enum.to_a.should == [1, 2, 3]
end
it "raises a TypeError if the first element is a Time object" do
t = Time.now
-> { (t..t+1).each { |i| i } }.should raise_error(TypeError)
ruby_version_is "3.1" do
it "supports Time objects that respond to #succ" do
t = Time.utc(1970)
def t.succ; self + 1 end
t_succ = t.succ
def t_succ.succ; self + 1; end
(t..t_succ).to_a.should == [Time.utc(1970), Time.utc(1970, nil, nil, nil, nil, 1)]
(t...t_succ).to_a.should == [Time.utc(1970)]
end
end
ruby_version_is ""..."3.1" do
it "raises a TypeError if the first element is a Time object even if it responds to #succ" do
t = Time.utc(1970)
def t.succ; self + 1 end
t_succ = t.succ
def t_succ.succ; self + 1; end
-> { (t..t_succ).each { |i| i } }.should raise_error(TypeError)
end
end
it "passes each Symbol element by using #succ" do

View file

@ -225,4 +225,43 @@ describe "The ** operator" do
h.should == { two: 2 }
end
end
ruby_version_is "3.1" do
describe "hash with omitted value" do
it "accepts short notation 'key' for 'key: value' syntax" do
a, b, c = 1, 2, 3
h = eval('{a:}')
{a: 1}.should == h
h = eval('{a:, b:, c:}')
{a: 1, b: 2, c: 3}.should == h
end
it "ignores hanging comma on short notation" do
a, b, c = 1, 2, 3
h = eval('{a:, b:, c:,}')
{a: 1, b: 2, c: 3}.should == h
end
it "accepts mixed syntax" do
a, e = 1, 5
h = eval('{a:, b: 2, "c" => 3, :d => 4, e:}')
eval('{a: 1, :b => 2, "c" => 3, "d": 4, e: 5}').should == h
end
it "works with methods and local vars" do
a = Class.new
a.class_eval(<<-RUBY)
def bar
"baz"
end
def foo(val)
{bar:, val:}
end
RUBY
a.new.foo(1).should == {bar: "baz", val: 1}
end
end
end
end

View file

@ -1861,15 +1861,158 @@ describe "An array-dereference method ([])" do
end
end
ruby_version_is '3.0' do
ruby_version_is "3.0" do
describe "An endless method definition" do
evaluate <<-ruby do
def m(a) = a
ruby
context "without arguments" do
evaluate <<-ruby do
def m() = 42
ruby
a = b = m 1
a.should == 1
b.should == 1
m.should == 42
end
end
context "with arguments" do
evaluate <<-ruby do
def m(a, b) = a + b
ruby
m(1, 4).should == 5
end
end
context "with multiline body" do
evaluate <<-ruby do
def m(n) =
if n > 2
m(n - 2) + m(n - 1)
else
1
end
ruby
m(6).should == 8
end
end
context "with args forwarding" do
evaluate <<-ruby do
def mm(word, num:)
word * num
end
def m(...) = mm(...) + mm(...)
ruby
m("meow", num: 2).should == "meow" * 4
end
end
end
describe "Keyword arguments are now separated from positional arguments" do
context "when the method has only positional parameters" do
it "treats incoming keyword arguments as positional for compatibility" do
def foo(a, b, c, hsh)
hsh[:key]
end
foo(1, 2, 3, key: 42).should == 42
end
end
context "when the method takes a ** parameter" do
it "captures the passed literal keyword arguments" do
def foo(a, b, c, **hsh)
hsh[:key]
end
foo(1, 2, 3, key: 42).should == 42
end
it "captures the passed ** keyword arguments" do
def foo(a, b, c, **hsh)
hsh[:key]
end
h = { key: 42 }
foo(1, 2, 3, **h).should == 42
end
it "does not convert a positional Hash to keyword arguments" do
def foo(a, b, c, **hsh)
hsh[:key]
end
-> {
foo(1, 2, 3, { key: 42 })
}.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)')
end
end
context "when the method takes a key: parameter" do
context "when it's called with a positional Hash and no **" do
it "raises ArgumentError" do
def foo(a, b, c, key: 1)
key
end
-> {
foo(1, 2, 3, { key: 42 })
}.should raise_error(ArgumentError, 'wrong number of arguments (given 4, expected 3)')
end
end
context "when it's called with **" do
it "captures the passed keyword arguments" do
def foo(a, b, c, key: 1)
key
end
h = { key: 42 }
foo(1, 2, 3, **h).should == 42
end
end
end
end
end
ruby_version_is "3.1" do
describe "kwarg with omitted value in a method call" do
context "accepts short notation 'kwarg' in method call" do
evaluate <<-ruby do
def call(*args, **kwargs) = [args, kwargs]
ruby
a, b, c = 1, 2, 3
arr, h = eval('call a:')
h.should == {a: 1}
arr.should == []
arr, h = eval('call(a:, b:, c:)')
h.should == {a: 1, b: 2, c: 3}
arr.should == []
arr, h = eval('call(a:, b: 10, c:)')
h.should == {a: 1, b: 10, c: 3}
arr.should == []
end
end
context "with methods and local variables" do
evaluate <<-ruby do
def call(*args, **kwargs) = [args, kwargs]
def bar
"baz"
end
def foo(val)
call bar:, val:
end
ruby
foo(1).should == [[], {bar: "baz", val: 1}]
end
end
end
end

View file

@ -18,6 +18,63 @@ ruby_version_is "2.7" do
RUBY
end
end
describe "find pattern" do
it "captures preceding elements to the pattern" do
eval(<<~RUBY).should == [0, 1]
case [0, 1, 2, 3]
in [*pre, 2, 3]
pre
else
false
end
RUBY
end
it "captures following elements to the pattern" do
eval(<<~RUBY).should == [2, 3]
case [0, 1, 2, 3]
in [0, 1, *post]
post
else
false
end
RUBY
end
it "captures both preceding and following elements to the pattern" do
eval(<<~RUBY).should == [[0, 1], [3, 4]]
case [0, 1, 2, 3, 4]
in [*pre, 2, *post]
[pre, post]
else
false
end
RUBY
end
it "can capture the entirety of the pattern" do
eval(<<~RUBY).should == [0, 1, 2, 3, 4]
case [0, 1, 2, 3, 4]
in [*everything]
everything
else
false
end
RUBY
end
it "will match an empty Array-like structure" do
eval(<<~RUBY).should == []
case []
in [*everything]
everything
else
false
end
RUBY
end
end
end
it "extends case expression with case/in construction" do
@ -41,25 +98,49 @@ ruby_version_is "2.7" do
end
describe "warning" do
ruby_version_is ""..."3.1" do
before :each do
ruby_version_is ""..."3.0" do
@src = 'case [0, 1]; in [a, b]; end'
end
before :each do
@experimental, Warning[:experimental] = Warning[:experimental], true
end
ruby_version_is "3.0" do
after :each do
Warning[:experimental] = @experimental
end
context 'when regular form' do
before :each do
@src = 'case [0, 1]; in [a, b]; end'
end
ruby_version_is ""..."3.0" do
it "warns about pattern matching is experimental feature" do
-> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
end
end
ruby_version_is "3.0" do
it "does not warn about pattern matching is experimental feature" do
-> { eval @src }.should_not complain
end
end
end
context 'when one-line form' do
ruby_version_is '3.0' do
before :each do
@src = '[0, 1] => [a, b]'
end
@experimental, Warning[:experimental] = Warning[:experimental], true
end
ruby_version_is ""..."3.1" do
it "warns about pattern matching is experimental feature" do
-> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
end
end
after :each do
Warning[:experimental] = @experimental
end
it "warns about pattern matching is experimental feature" do
-> { eval @src }.should complain(/pattern matching is experimental, and the behavior may change in future versions of Ruby!/i)
ruby_version_is "3.1" do
it "does not warn about pattern matching is experimental feature" do
-> { eval @src }.should_not complain
end
end
end
end
end
@ -444,6 +525,28 @@ ruby_version_is "2.7" do
end
RUBY
end
it "can be used as a nested pattern" do
eval(<<~RUBY).should == true
case [[1], ["2"]]
in [[0] | nil, _]
false
in [[1], [1]]
false
in [[1], [2 | "2"]]
true
end
RUBY
eval(<<~RUBY).should == true
case [1, 2]
in [0, _] | {a: 0}
false
in {a: 1, b: 2} | [1, 2]
true
end
RUBY
end
end
describe "AS pattern" do
@ -705,6 +808,28 @@ ruby_version_is "2.7" do
end
RUBY
end
it "can be used as a nested pattern" do
eval(<<~RUBY).should == true
case [[1], ["2"]]
in [[0] | nil, _]
false
in [[1], [1]]
false
in [[1], [2 | "2"]]
true
end
RUBY
eval(<<~RUBY).should == true
case [1, 2]
in [0, _] | {a: 0}
false
in {a: 1, b: 2} | [1, 2]
true
end
RUBY
end
end
describe "Hash pattern" do
@ -1060,6 +1185,30 @@ ruby_version_is "2.7" do
end
RUBY
end
it "can be used as a nested pattern" do
eval(<<~RUBY).should == true
case {a: {a: 1, b: 1}, b: {a: 1, b: 2}}
in {a: {a: 0}}
false
in {a: {a: 1}, b: {b: 1}}
false
in {a: {a: 1}, b: {b: 2}}
true
end
RUBY
eval(<<~RUBY).should == true
case [{a: 1, b: [1]}, {a: 1, c: ["2"]}]
in [{a:, c:},]
false
in [{a: 1, b:}, {a: 1, c: [Integer]}]
false
in [_, {a: 1, c: [String]}]
true
end
RUBY
end
end
describe "refinements" do

View file

@ -217,4 +217,30 @@ describe "A Proc" do
lambda { @l.call(obj) }.should raise_error(TypeError)
end
end
describe "taking |*a, **kw| arguments" do
before :each do
@p = proc { |*a, **kw| [a, kw] }
end
ruby_version_is ""..."2.7" do
it 'autosplats keyword arguments' do
@p.call([1, {a: 1}]).should == [[1], {a: 1}]
end
end
ruby_version_is "2.7"..."3.0" do
it 'autosplats keyword arguments and warns' do
-> {
@p.call([1, {a: 1}]).should == [[1], {a: 1}]
}.should complain(/warning: Using the last argument as keyword parameters is deprecated; maybe \*\* should be added to the call/)
end
end
ruby_version_is "3.0" do
it 'does not autosplat keyword arguments' do
@p.call([1, {a: 1}]).should == [[[1, {a: 1}]], {}]
end
end
end
end

View file

@ -15,6 +15,12 @@ describe "Literal Ranges" do
(1...).should == Range.new(1, nil, true)
end
ruby_version_is "3.0" do
it "is frozen" do
(42..).should.frozen?
end
end
ruby_version_is "2.7" do
it "creates beginless ranges" do
eval("(..1)").should == Range.new(nil, 1)

View file

@ -157,23 +157,6 @@ 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

View file

@ -183,5 +183,33 @@ describe "The yield call" do
it "uses captured block of a block used in define_method" do
@y.deep(2).should == 4
end
end
describe "Using yield in a singleton class literal" 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
ruby_version_is "3.0" do
it 'raises a SyntaxError' do
code = <<~RUBY
class << Object.new
yield
end
RUBY
-> { eval(code) }.should raise_error(SyntaxError, /Invalid yield/)
end
end
end

View file

@ -77,34 +77,17 @@ describe "IPAddr#new" do
a.family.should == Socket::AF_INET6
end
ruby_version_is ""..."3.1" do
it "raises on incorrect IPAddr strings" do
[
["fe80::1%fxp0"],
["::1/255.255.255.0"],
[IPAddr.new("::1").to_i],
["::ffff:192.168.1.2/120", Socket::AF_INET],
["[192.168.1.2]/120"],
].each { |args|
->{
IPAddr.new(*args)
}.should raise_error(ArgumentError)
}
end
end
ruby_version_is "3.1" do
it "raises on incorrect IPAddr strings" do
[
["::1/255.255.255.0"],
[IPAddr.new("::1").to_i],
["::ffff:192.168.1.2/120", Socket::AF_INET],
["[192.168.1.2]/120"],
].each { |args|
->{
IPAddr.new(*args)
}.should raise_error(ArgumentError)
}
end
it "raises on incorrect IPAddr strings" do
[
["fe80::1%fxp0"],
["::1/255.255.255.0"],
[IPAddr.new("::1").to_i],
["::ffff:192.168.1.2/120", Socket::AF_INET],
["[192.168.1.2]/120"],
].each { |args|
->{
IPAddr.new(*args)
}.should raise_error(ArgumentError)
}
end
end

View file

@ -0,0 +1,29 @@
require_relative '../../spec_helper'
require 'set'
ruby_version_is "3.0" do
describe "Set#<=>" do
it "returns 0 if the sets are equal" do
(Set[] <=> Set[]).should == 0
(Set[:a, :b, :c] <=> Set[:a, :b, :c]).should == 0
end
it "returns -1 if the set is a proper subset of the other set" do
(Set[] <=> Set[1]).should == -1
(Set[1, 2] <=> Set[1, 2, 3]).should == -1
end
it "returns +1 if the set is a proper superset of other set" do
(Set[1] <=> Set[]).should == +1
(Set[1, 2, 3] <=> Set[1, 2]).should == +1
end
it "returns nil if the set has unique elements" do
(Set[1, 2, 3] <=> Set[:a, :b, :c]).should be_nil
end
it "returns nil when the argument is not set-like" do
(Set[] <=> false).should be_nil
end
end
end

View file

@ -0,0 +1,18 @@
require_relative '../../spec_helper'
require 'set'
describe "Set#initialize_clone" do
ruby_version_is "3.0" do
# See https://bugs.ruby-lang.org/issues/14266
it "does not freeze the new Set when called from clone(freeze: false)" do
set1 = Set[1, 2]
set1.freeze
set2 = set1.clone(freeze: false)
set1.frozen?.should == true
set2.frozen?.should == false
set2.add 3
set1.should == Set[1, 2]
set2.should == Set[1, 2, 3]
end
end
end

View file

@ -0,0 +1,31 @@
require_relative '../../spec_helper'
require 'set'
ruby_version_is "3.0" do
describe "Set#join" do
it "returns an empty string if the Set is empty" do
Set[].join.should == ''
end
it "returns a new string formed by joining elements after conversion" do
set = Set[:a, :b, :c]
set.join.should == "abc"
end
it "does not separate elements when the passed separator is nil" do
set = Set[:a, :b, :c]
set.join(nil).should == "abc"
end
it "returns a string formed by concatenating each element separated by the separator" do
set = Set[:a, :b, :c]
set.join(' | ').should == "a | b | c"
end
it "calls #to_a to convert the Set in to an Array" do
set = Set[:a, :b, :c]
set.should_receive(:to_a).and_return([:a, :b, :c])
set.join.should == "abc"
end
end
end

View file

@ -0,0 +1,22 @@
require_relative '../../../spec_helper'
require 'set'
ruby_version_is "3.0" do
describe "SortedSet" do
it "raises error including message that it has been extracted from the set stdlib" do
-> {
SortedSet
}.should raise_error(RuntimeError) { |e|
e.message.should.include?("The `SortedSet` class has been extracted from the `set` library")
}
end
end
end
ruby_version_is ""..."3.0" do
describe "SortedSet" do
it "is part of the set stdlib" do
SortedSet.superclass.should == Set
end
end
end

View file

@ -1,5 +1,10 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/new'
describe 'TCPSocket#initialize' do
it_behaves_like :tcpsocket_new, :new
end
describe 'TCPSocket#initialize' do
SocketSpecs.each_ip_protocol do |family, ip_address|

View file

@ -1,5 +0,0 @@
require_relative 'shared/new'
describe "TCPSocket.new" do
it_behaves_like :tcpsocket_new, :new
end

View file

@ -14,6 +14,14 @@ describe :tcpsocket_new, shared: true do
}
end
ruby_version_is "3.0" do
it 'raises Errno::ETIMEDOUT with :connect_timeout when no server is listening on the given address' do
-> {
TCPSocket.send(@method, "192.0.2.1", 80, connect_timeout: 0)
}.should raise_error(Errno::ETIMEDOUT)
end
end
describe "with a running server" do
before :each do
@server = SocketSpecs::SpecTCPServer.new
@ -75,5 +83,12 @@ describe :tcpsocket_new, shared: true do
@socket.addr[1].should be_kind_of(Integer)
@socket.addr[2].should =~ /^#{@hostname}/
end
ruby_version_is "3.0" do
it "connects to a server when passed connect_timeout argument" do
@socket = TCPSocket.send(@method, @hostname, @server.port, connect_timeout: 1)
@socket.should be_an_instance_of(TCPSocket)
end
end
end
end

View file

@ -30,7 +30,7 @@ describe "StringIO#ungetbyte" do
io.string.should == 'Shis is a simple string.'
end
it "ungets the bytes of a string if given a string as an argument" do
it "ungets the bytes of a string if given a string as an arugment" do
str = "\u01a9"
io = StringIO.new(str)
b = io.getbyte

View file

@ -1,7 +1,6 @@
require_relative '../spec_helper'
describe "String#gsub" do
it "resists CVE-2010-1330 by raising an exception on invalid UTF-8 bytes" do
# This original vulnerability talked about KCODE, which is no longer
# used. Instead we are forcing encodings here. But I think the idea is the
@ -17,5 +16,4 @@ describe "String#gsub" do
str.gsub(/</, "&lt;")
}.should raise_error(ArgumentError, /invalid byte sequence in UTF-8/)
end
end

View file

@ -3,17 +3,13 @@ require_relative '../spec_helper'
require 'json'
describe "String#to_f" do
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
"1.#{'1'*1000000}".to_f.should be_close(1.1111111111111112, TOLERANCE)
end
end
describe "JSON.parse" do
it "resists CVE-2013-4164 by converting very long Strings to a Float" do
JSON.parse("[1.#{'1'*1000000}]").first.should be_close(1.1111111111111112, TOLERANCE)
end
end

View file

@ -1,6 +1,5 @@
require_relative '../spec_helper'
ruby_version_is ''...'3.0' do
require 'rexml/document'

View file

@ -1,7 +1,6 @@
require_relative '../spec_helper'
describe "Array#pack" do
ruby_version_is ''...'2.7' do
it "resists CVE-2018-16396 by tainting output based on input" do
"aAZBbHhuMmPp".each_char do |f|
@ -9,11 +8,9 @@ describe "Array#pack" do
end
end
end
end
describe "String#unpack" do
ruby_version_is ''...'2.7' do
it "resists CVE-2018-16396 by tainting output based on input" do
"aAZBbHhuMm".each_char do |f|
@ -21,5 +18,4 @@ describe "String#unpack" do
end
end
end
end

View file

@ -1,12 +1,10 @@
require_relative '../spec_helper'
describe "String#unpack" do
it "resists CVE-2018-8778 by raising an exception when a position indicator is larger than a native integer" do
pos = (1 << PlatformGuard::POINTER_SIZE) - 99
-> {
"0123456789".unpack("@#{pos}C10")
}.should raise_error(RangeError, /pack length too big/)
end
end

View file

@ -1,36 +1,38 @@
require_relative '../spec_helper'
require 'optparse'
platform_is_not :darwin do # frequent timeout/hang on macOS
require 'optparse'
require 'rubygems'
require 'rubygems/gemcutter_utilities'
require 'rubygems'
require 'rubygems/gemcutter_utilities'
describe "CVE-2019-8323 is resisted by" do
describe "sanitising the body" do
it "for success codes" do
cutter = Class.new {
include Gem::GemcutterUtilities
}.new
response = Net::HTTPSuccess.new(nil, nil, nil)
def response.body
"\e]2;nyan\a"
describe "CVE-2019-8323 is resisted by" do
describe "sanitising the body" do
it "for success codes" do
cutter = Class.new {
include Gem::GemcutterUtilities
}.new
response = Net::HTTPSuccess.new(nil, nil, nil)
def response.body
"\e]2;nyan\a"
end
cutter.should_receive(:say).with(".]2;nyan.")
cutter.with_response response
end
cutter.should_receive(:say).with(".]2;nyan.")
cutter.with_response response
end
it "for error codes" do
cutter = Class.new {
include Gem::GemcutterUtilities
}.new
def cutter.terminate_interaction(n)
it "for error codes" do
cutter = Class.new {
include Gem::GemcutterUtilities
}.new
def cutter.terminate_interaction(n)
end
response = Net::HTTPNotFound.new(nil, nil, nil)
def response.body
"\e]2;nyan\a"
end
cutter.should_receive(:say).with(".]2;nyan.")
cutter.with_response response
end
response = Net::HTTPNotFound.new(nil, nil, nil)
def response.body
"\e]2;nyan\a"
end
cutter.should_receive(:say).with(".]2;nyan.")
cutter.with_response response
end
end
end

View file

@ -1,9 +1,9 @@
require_relative '../spec_helper'
require 'rubygems'
require 'rubygems/command_manager'
platform_is_not :darwin do # frequent timeout/hang on macOS
require 'rubygems'
require 'rubygems/command_manager'
describe "CVE-2019-8325 is resisted by" do
describe "sanitising error message components" do
it "for the 'while executing' message" do