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 2022-03-03 14:43:14 +01:00
parent 1dc6bed0ca
commit 3b21818db1
16 changed files with 213 additions and 72 deletions

View file

@ -73,6 +73,7 @@ EvalBindingProcA
Exception2MessageMapper
ExceptionForMatrix
Fcntl
Fiddle
FileStat
FileUtils
Find

View file

@ -3,9 +3,10 @@ require_relative 'fixtures/classes'
require_relative 'shared/enumeratorize'
require_relative '../enumerable/shared/enumeratorized'
# Modifying a collection while the contents are being iterated
# gives undefined behavior. See
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/23633
# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
# CRuby simply reads the array storage and checks the size for every iteration;
# like `i = 0; while i < size; yield self[i]; end`
describe "Array#each" do
it "yields each element to the block" do
@ -15,6 +16,34 @@ describe "Array#each" do
a.should == [1, 2, 3]
end
it "yields each element to the block even if the array is changed during iteration" do
a = [1, 2, 3, 4, 5]
iterated = []
a.each { |x| iterated << x; a << x+5 if x.even? }
iterated.should == [1, 2, 3, 4, 5, 7, 9]
end
it "yields only elements that are still in the array" do
a = [0, 1, 2, 3, 4]
iterated = []
a.each { |x| iterated << x; a.pop if x.even? }
iterated.should == [0, 1, 2]
end
it "yields elements based on an internal index" do
a = [0, 1, 2, 3, 4]
iterated = []
a.each { |x| iterated << x; a.shift if x.even? }
iterated.should == [0, 2, 4]
end
it "yields the same element multiple times if inserting while iterating" do
a = [1, 2]
iterated = []
a.each { |x| iterated << x; a.unshift(0) if a.size == 2 }
iterated.should == [1, 1, 2]
end
it "yields each element to a block that takes multiple arguments" do
a = [[1, 2], :a, [3, 4]]
b = []

View file

@ -101,12 +101,30 @@ module DirSpecs
@mock_dir_files
end
def self.mock_dir_links
unless @mock_dir_links
@mock_dir_links = []
platform_is_not :windows do
@mock_dir_links += [
['special/ln', 'subdir_one']
]
end
end
@mock_dir_links
end
def self.create_mock_dirs
mock_dir_files.each do |name|
file = File.join mock_dir, name
mkdir_p File.dirname(file)
touch file
end
mock_dir_links.each do |link, target|
full_link = File.join mock_dir, link
full_target = File.join mock_dir, target
File.symlink full_target, full_link
end
end
def self.delete_mock_dirs

View file

@ -222,5 +222,30 @@ describe "Dir.glob" do
Dir.rmdir('no_permission')
end
end
it "will follow symlinks when processing a `*/` pattern." do
expected = ['special/ln/nondotfile']
Dir.glob('special/*/nondotfile').should == expected
end
it "will not follow symlinks when recursively traversing directories" do
expected = %w[
deeply/nondotfile
nondotfile
subdir_one/nondotfile
subdir_two/nondotfile
]
Dir.glob('**/nondotfile').sort.should == expected
end
it "will follow symlinks when testing directory after recursive directory in pattern" do
expected = %w[
deeply/nondotfile
special/ln/nondotfile
subdir_one/nondotfile
subdir_two/nondotfile
]
Dir.glob('**/*/nondotfile').sort.should == expected
end
end
end

View file

@ -54,16 +54,16 @@ describe "Dir#read" do
old_external_encoding = Encoding::default_external
Encoding.default_internal = Encoding::UTF_8
Encoding.default_external = Encoding::SHIFT_JIS
dir = Dir.open(File.join(DirSpecs.mock_dir, 'special'))
shift_jis_entries = []
begin
Dir.open(File.join(DirSpecs.mock_dir, 'special')) do |d|
-> {
while entry = dir.read
while entry = d.read
shift_jis_entries << entry
end
}.should_not raise_error
end
ensure
dir.close
Encoding.default_internal = old_internal_encoding
Encoding.default_external = old_external_encoding
end

View file

@ -48,4 +48,13 @@ describe "Interrupt" do
RUBY
out.should == "Interrupt: #{Signal.list["INT"]}\n"
end
platform_is_not :windows do
it "shows the backtrace and has a signaled exit status" do
err = IO.popen([*ruby_exe, '-e', 'Process.kill :INT, Process.pid; sleep'], err: [:child, :out], &:read)
$?.termsig.should == Signal.list.fetch('INT')
err.should.include? ': Interrupt'
err.should.include? "from -e:1:in `<main>'"
end
end
end

View file

@ -44,6 +44,12 @@ describe "IO#close" do
@io.close.should be_nil
end
it "does not call the #flush method but flushes the stream internally" do
@io.should_not_receive(:flush)
@io.close
@io.should.closed?
end
it 'raises an IOError with a clear message' do
matching_exception = nil

View file

@ -1,7 +1,51 @@
require_relative '../../shared/rational/minus'
require_relative '../../spec_helper'
require_relative '../../shared/rational/arithmetic_exception_in_coerce'
describe "Rational#-" do
it_behaves_like :rational_minus, :-
it_behaves_like :rational_arithmetic_exception_in_coerce, :-
it "calls #coerce on the passed argument with self" do
rational = Rational(3, 4)
obj = mock("Object")
obj.should_receive(:coerce).with(rational).and_return([1, 2])
rational - obj
end
it "calls #- on the coerced Rational with the coerced Object" do
rational = Rational(3, 4)
coerced_rational = mock("Coerced Rational")
coerced_rational.should_receive(:-).and_return(:result)
coerced_obj = mock("Coerced Object")
obj = mock("Object")
obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
(rational - obj).should == :result
end
end
describe "Rational#- passed a Rational" do
it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - Rational(0, 1)).should eql(Rational(3, 4))
(Rational(3, 4) - Rational(1, 4)).should eql(Rational(1, 2))
(Rational(3, 4) - Rational(2, 1)).should eql(Rational(-5, 4))
end
end
describe "Rational#- passed a Float" do
it "returns the result of subtracting other from self as a Float" do
(Rational(3, 4) - 0.2).should eql(0.55)
(Rational(3, 4) - 2.5).should eql(-1.75)
end
end
describe "Rational#- passed an Integer" do
it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - 1).should eql(Rational(-1, 4))
(Rational(3, 4) - 2).should eql(Rational(-5, 4))
end
end

View file

@ -53,6 +53,15 @@ describe :string_to_sym, shared: true do
sym.to_s.should == binary_string
end
it "ignores exising symbols with different encoding" do
source = "fée"
iso_symbol = source.force_encoding(Encoding::ISO_8859_1).send(@method)
iso_symbol.encoding.should == Encoding::ISO_8859_1
binary_symbol = source.force_encoding(Encoding::BINARY).send(@method)
binary_symbol.encoding.should == Encoding::BINARY
end
it "raises an EncodingError for UTF-8 String containing invalid bytes" do
invalid_utf8 = "\xC3"
invalid_utf8.should_not.valid_encoding?

View file

@ -60,6 +60,27 @@ describe "Thread#report_on_exception=" do
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception specs")
end
it "prints the backtrace even if the thread was killed just after Thread#raise" do
t = nil
ready = false
-> {
t = Thread.new {
Thread.current.report_on_exception = true
ready = true
sleep
}
Thread.pass until ready and t.stop?
t.raise RuntimeError, "Thread#report_on_exception before kill spec"
t.kill
Thread.pass while t.alive?
}.should output("", /Thread.+terminated with exception.+Thread#report_on_exception before kill spec/m)
-> {
t.join
}.should raise_error(RuntimeError, "Thread#report_on_exception before kill spec")
end
end
describe "when set to false" do

View file

@ -12,18 +12,10 @@ describe "The __FILE__ pseudo-variable" do
end
end
describe "The __FILE__ pseudo-variable" do
it_behaves_like :language___FILE__, :require, CodeLoadingSpecs::Method.new
end
describe "The __FILE__ pseudo-variable" do
describe "The __FILE__ pseudo-variable with require" do
it_behaves_like :language___FILE__, :require, Kernel
end
describe "The __FILE__ pseudo-variable" do
it_behaves_like :language___FILE__, :load, CodeLoadingSpecs::Method.new
end
describe "The __FILE__ pseudo-variable" do
describe "The __FILE__ pseudo-variable with load" do
it_behaves_like :language___FILE__, :load, Kernel
end

View file

@ -835,6 +835,8 @@ describe "Execution variable $:" do
it "can be changed via <<" do
$: << "foo"
$:.should include("foo")
ensure
$:.delete("foo")
end
it "is read-only" do
@ -850,6 +852,14 @@ describe "Execution variable $:" do
$-I = []
}.should raise_error(NameError)
end
it "default $LOAD_PATH entries until sitelibdir included have @gem_prelude_index set" do
$:.should.include?(RbConfig::CONFIG['sitelibdir'])
idx = $:.index(RbConfig::CONFIG['sitelibdir'])
$:[idx..-1].all? { |p| p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
$:[0...idx].all? { |p| !p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
end
end
describe "Global variable $\"" do

View file

@ -118,11 +118,14 @@ static VALUE so_rb_obj_call_init(VALUE self, VALUE object,
return Qnil;
}
static VALUE so_rb_obj_class(VALUE self, VALUE obj) {
return rb_obj_class(obj);
}
static VALUE so_rbobjclassname(VALUE self, VALUE obj) {
return rb_str_new2(rb_obj_classname(obj));
}
static VALUE object_spec_rb_obj_freeze(VALUE self, VALUE obj) {
return rb_obj_freeze(obj);
}
@ -442,6 +445,7 @@ void Init_object_spec(void) {
rb_define_method(cls, "rb_obj_alloc", so_rb_obj_alloc, 1);
rb_define_method(cls, "rb_obj_dup", so_rb_obj_dup, 1);
rb_define_method(cls, "rb_obj_call_init", so_rb_obj_call_init, 3);
rb_define_method(cls, "rb_obj_class", so_rb_obj_class, 1);
rb_define_method(cls, "rb_obj_classname", so_rbobjclassname, 1);
rb_define_method(cls, "rb_obj_freeze", object_spec_rb_obj_freeze, 1);
rb_define_method(cls, "rb_obj_frozen_p", object_spec_rb_obj_frozen_p, 1);

View file

@ -480,12 +480,31 @@ describe "CApiObject" do
end
end
describe "rb_obj_class" do
it "returns the class of an object" do
@o.rb_obj_class(nil).should == NilClass
@o.rb_obj_class(0).should == Integer
@o.rb_obj_class(0.1).should == Float
@o.rb_obj_class(ObjectTest.new).should == ObjectTest
end
it "does not return the singleton class if it exists" do
o = ObjectTest.new
o.singleton_class
@o.rb_obj_class(o).should equal ObjectTest
end
end
describe "rb_obj_classname" do
it "returns the class name of an object" do
@o.rb_obj_classname(nil).should == 'NilClass'
@o.rb_obj_classname(0).should == 'Integer'
@o.rb_obj_classname(0.1).should == 'Float'
@o.rb_obj_classname(ObjectTest.new).should == 'ObjectTest'
o = ObjectTest.new
o.singleton_class
@o.rb_obj_classname(o).should == 'ObjectTest'
end
end

View file

@ -611,7 +611,9 @@ describe "C-API String function" do
filename = fixture(__FILE__, "read.txt")
str = ""
capacities = @s.RSTRING_PTR_read(str, filename)
capacities.should == [30, 53]
capacities[0].should >= 30
capacities[1].should >= 53
capacities[0].should < capacities[1]
str.should == "fixture file contents to test read() with RSTRING_PTR"
end
end

View file

@ -1,48 +0,0 @@
require_relative '../../spec_helper'
describe :rational_minus_rat, shared: true do
it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - Rational(0, 1)).should eql(Rational(3, 4))
(Rational(3, 4) - Rational(1, 4)).should eql(Rational(1, 2))
(Rational(3, 4) - Rational(2, 1)).should eql(Rational(-5, 4))
end
end
describe :rational_minus_int, shared: true do
it "returns the result of subtracting other from self as a Rational" do
(Rational(3, 4) - 1).should eql(Rational(-1, 4))
(Rational(3, 4) - 2).should eql(Rational(-5, 4))
end
end
describe :rational_minus_float, shared: true do
it "returns the result of subtracting other from self as a Float" do
(Rational(3, 4) - 0.2).should eql(0.55)
(Rational(3, 4) - 2.5).should eql(-1.75)
end
end
describe :rational_minus, shared: true do
it "calls #coerce on the passed argument with self" do
rational = Rational(3, 4)
obj = mock("Object")
obj.should_receive(:coerce).with(rational).and_return([1, 2])
rational - obj
end
it "calls #- on the coerced Rational with the coerced Object" do
rational = Rational(3, 4)
coerced_rational = mock("Coerced Rational")
coerced_rational.should_receive(:-).and_return(:result)
coerced_obj = mock("Coerced Object")
obj = mock("Object")
obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
(rational - obj).should == :result
end
end