summaryrefslogtreecommitdiff
path: root/spec/ruby
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2020-11-13 13:17:24 +0100
committerBenoit Daloze <eregontp@gmail.com>2020-11-13 13:17:24 +0100
commit6d05967468ea58ba481259718f07b3cb5a386945 (patch)
treee21976cdae28f91bcac002dc463a099ca64d111d /spec/ruby
parentacbe7aa19705905e7ad1952395e98e8bfe583a97 (diff)
Update to ruby/spec@b0b7f53
Diffstat (limited to 'spec/ruby')
-rw-r--r--spec/ruby/.rubocop.yml3
-rw-r--r--spec/ruby/.rubocop_todo.yml6
-rw-r--r--spec/ruby/core/array/flatten_spec.rb2
-rw-r--r--spec/ruby/core/exception/errno_spec.rb8
-rw-r--r--spec/ruby/core/exception/system_exit_spec.rb17
-rw-r--r--spec/ruby/core/fiber/fixtures/classes.rb12
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb76
-rw-r--r--spec/ruby/core/file/extname_spec.rb10
-rw-r--r--spec/ruby/core/integer/shared/comparison_coerce.rb22
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb57
-rw-r--r--spec/ruby/core/kernel/respond_to_spec.rb3
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb220
-rw-r--r--spec/ruby/core/module/constants_spec.rb10
-rw-r--r--spec/ruby/core/module/fixtures/autoload_location.rb3
-rw-r--r--spec/ruby/core/process/exec_spec.rb8
-rw-r--r--spec/ruby/core/process/spawn_spec.rb16
-rw-r--r--spec/ruby/core/range/minmax_spec.rb170
-rw-r--r--spec/ruby/core/string/chomp_spec.rb8
-rw-r--r--spec/ruby/core/thread/list_spec.rb4
-rw-r--r--spec/ruby/fixtures/constants.rb18
-rw-r--r--spec/ruby/language/predefined_spec.rb22
-rw-r--r--spec/ruby/library/socket/socket/listen_spec.rb14
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb12
-rw-r--r--spec/ruby/optional/capi/module_spec.rb6
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb2
-rw-r--r--spec/ruby/shared/enumerator/enum_for.rb7
-rw-r--r--spec/ruby/shared/kernel/raise.rb45
27 files changed, 704 insertions, 77 deletions
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index 5db9256572..a26b525b1c 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -113,6 +113,9 @@ Lint/Debugger:
Exclude:
- 'core/binding/fixtures/irb.rb'
+Lint/Loop:
+ Enabled: false
+
Style/Lambda:
Enabled: true
EnforcedStyle: literal
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index 7a5f9f74c5..a469213841 100644
--- a/spec/ruby/.rubocop_todo.yml
+++ b/spec/ruby/.rubocop_todo.yml
@@ -76,12 +76,6 @@ Lint/LiteralInInterpolation:
- 'language/undef_spec.rb'
- 'library/net/ftp/connect_spec.rb'
-# Offense count: 16
-Lint/Loop:
- Exclude:
- - 'language/until_spec.rb'
- - 'language/while_spec.rb'
-
# Offense count: 8
# Cop supports --auto-correct.
Lint/MultipleComparison:
diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb
index b2aa015764..2f9fb8a3ec 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -90,7 +90,7 @@ describe "Array#flatten" do
ArraySpecs::MyArray[].flatten.should be_an_instance_of(Array)
ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(Array)
ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(Array)
- ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == Array[1, 2, 3, 4]
+ ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4]
[ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
end
end
diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb
index 78b3eafc2a..095a926e09 100644
--- a/spec/ruby/core/exception/errno_spec.rb
+++ b/spec/ruby/core/exception/errno_spec.rb
@@ -47,4 +47,12 @@ describe "Errno::ENOTSUP" do
it "is defined" do
Errno.should have_constant(:ENOTSUP)
end
+
+ it "is the same class as Errno::EOPNOTSUPP if they represent the same errno value" do
+ if Errno::ENOTSUP::Errno == Errno::EOPNOTSUPP::Errno
+ Errno::ENOTSUP.should == Errno::EOPNOTSUPP
+ else
+ Errno::ENOTSUP.should_not == Errno::EOPNOTSUPP
+ end
+ end
end
diff --git a/spec/ruby/core/exception/system_exit_spec.rb b/spec/ruby/core/exception/system_exit_spec.rb
new file mode 100644
index 0000000000..5c6116576b
--- /dev/null
+++ b/spec/ruby/core/exception/system_exit_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+describe "SystemExit" do
+ it "sets the exit status and exits silently when raised" do
+ code = 'raise SystemExit.new(7)'
+ result = ruby_exe(code, args: "2>&1")
+ result.should == ""
+ $?.exitstatus.should == 7
+ end
+
+ it "sets the exit status and exits silently when raised when subclassed" do
+ code = 'class CustomExit < SystemExit; end; raise CustomExit.new(8)'
+ result = ruby_exe(code, args: "2>&1")
+ result.should == ""
+ $?.exitstatus.should == 8
+ end
+end
diff --git a/spec/ruby/core/fiber/fixtures/classes.rb b/spec/ruby/core/fiber/fixtures/classes.rb
new file mode 100644
index 0000000000..c00facd6e1
--- /dev/null
+++ b/spec/ruby/core/fiber/fixtures/classes.rb
@@ -0,0 +1,12 @@
+module FiberSpecs
+
+ class NewFiberToRaise
+ def self.raise(*args)
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ fiber.raise(*args)
+ end
+ end
+
+ class CustomError < StandardError; end
+end
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
new file mode 100644
index 0000000000..fd1cc911b5
--- /dev/null
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -0,0 +1,76 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative '../../shared/kernel/raise'
+
+ruby_version_is "2.7" do
+ describe "Fiber#raise" do
+ it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise
+ end
+
+ describe "Fiber#raise" do
+ it 'raises RuntimeError by default' do
+ -> { FiberSpecs::NewFiberToRaise.raise }.should raise_error(RuntimeError)
+ end
+
+ it "raises FiberError if Fiber is not born" do
+ fiber = Fiber.new { true }
+ -> { fiber.raise }.should raise_error(FiberError, "cannot raise exception on unborn fiber")
+ end
+
+ it "raises FiberError if Fiber is dead" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.raise }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ end
+
+ it 'accepts error class' do
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should raise_error(FiberSpecs::CustomError)
+ end
+
+ it 'accepts error message' do
+ -> { FiberSpecs::NewFiberToRaise.raise "error message" }.should raise_error(RuntimeError, "error message")
+ end
+
+ it 'does not accept array of backtrace information only' do
+ -> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should raise_error(TypeError)
+ end
+
+ it 'does not accept integer' do
+ -> { FiberSpecs::NewFiberToRaise.raise 100 }.should raise_error(TypeError)
+ end
+
+ it 'accepts error class with error message' do
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error')
+ end
+
+ it 'accepts error class with with error message and backtrace information' do
+ -> {
+ FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
+ }.should raise_error(FiberSpecs::CustomError) { |e|
+ e.message.should == 'test error'
+ e.backtrace.should == ['foo', 'boo']
+ }
+ end
+
+ it 'does not accept only error message and backtrace information' do
+ -> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should raise_error(TypeError)
+ end
+
+ it "raises a FiberError if invoked from a different Thread" do
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ Thread.new do
+ -> {
+ fiber.raise
+ }.should raise_error(FiberError, "fiber called across threads")
+ end.join
+ end
+
+ it "kills Fiber" do
+ fiber = Fiber.new { Fiber.yield :first; :second }
+ fiber.resume
+ -> { fiber.raise }.should raise_error
+ -> { fiber.resume }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ end
+ end
+end
diff --git a/spec/ruby/core/file/extname_spec.rb b/spec/ruby/core/file/extname_spec.rb
index e9b53bc24d..e182ed44f2 100644
--- a/spec/ruby/core/file/extname_spec.rb
+++ b/spec/ruby/core/file/extname_spec.rb
@@ -12,6 +12,16 @@ describe "File.extname" do
File.extname(".app.conf").should == ".conf"
end
+ it "returns unfrozen strings" do
+ File.extname("foo.rb").frozen?.should == false
+ File.extname("/foo/bar.rb").frozen?.should == false
+ File.extname("/foo.rb/bar.c").frozen?.should == false
+ File.extname("bar").frozen?.should == false
+ File.extname(".bashrc").frozen?.should == false
+ File.extname("/foo.bar/baz").frozen?.should == false
+ File.extname(".app.conf").frozen?.should == false
+ end
+
it "returns the extension for edge cases" do
File.extname("").should == ""
File.extname(".").should == ""
diff --git a/spec/ruby/core/integer/shared/comparison_coerce.rb b/spec/ruby/core/integer/shared/comparison_coerce.rb
index 50437f77f5..af52f5e99b 100644
--- a/spec/ruby/core/integer/shared/comparison_coerce.rb
+++ b/spec/ruby/core/integer/shared/comparison_coerce.rb
@@ -1,27 +1,5 @@
require_relative '../fixtures/classes'
-describe :integer_comparison_coerce_rescue, shared: true do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError)
-
- # e.g. 1 > b
- -> {
- -> { 1.send(@method, b) }.should raise_error(ArgumentError, /comparison of Integer with MockObject failed/)
- }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. 1 > b
- -> { 1.send(@method, b) }.should raise_error(exception)
- end
- end
-end
-
describe :integer_comparison_coerce_not_rescue, shared: true do
it "does not rescue exception raised in other#coerce" do
b = mock("numeric with failed #coerce")
diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
new file mode 100644
index 0000000000..b8e4eedcb9
--- /dev/null
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -0,0 +1,57 @@
+require_relative '../../spec_helper'
+
+describe "IO#set_encoding_by_bom" do
+ before :each do
+ @name = tmp('io_set_encoding_by_bom.txt')
+ touch(@name)
+ @io = new_io(@name, 'rb')
+ end
+
+ after :each do
+ @io.close unless @io.closed?
+ rm_r @name
+ end
+
+ ruby_version_is "2.7" do
+ it "returns the result encoding if found BOM UTF-8 sequence" do
+ File.binwrite(@name, "\u{FEFF}abc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ end
+
+ it "returns the result encoding if found BOM UTF_16LE sequence" do
+ File.binwrite(@name, "\xFF\xFEabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ end
+
+ it "returns the result encoding if found BOM UTF_16BE sequence" do
+ File.binwrite(@name, "\xFE\xFFabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ end
+
+ it "returns nil if found BOM sequence not provided" do
+ File.write(@name, "abc")
+
+ @io.set_encoding_by_bom.should == nil
+ end
+
+ it 'returns exception if io not in binary mode' do
+ not_binary_io = new_io(@name, 'r')
+
+ -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode')
+ ensure
+ not_binary_io.close
+ end
+
+ it 'returns exception if encoding already set' do
+ @io.set_encoding("utf-8")
+
+ -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
+ end
+ end
+end
diff --git a/spec/ruby/core/kernel/respond_to_spec.rb b/spec/ruby/core/kernel/respond_to_spec.rb
index e7efc9f275..5b3ea3f651 100644
--- a/spec/ruby/core/kernel/respond_to_spec.rb
+++ b/spec/ruby/core/kernel/respond_to_spec.rb
@@ -25,7 +25,7 @@ describe "Kernel#respond_to?" do
end
it "throws a type error if argument can't be coerced into a Symbol" do
- -> { @a.respond_to?(Object.new) }.should raise_error(TypeError)
+ -> { @a.respond_to?(Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
it "returns false if obj responds to the given protected method" do
@@ -69,5 +69,4 @@ describe "Kernel#respond_to?" do
KernelSpecs::Foo.new.respond_to?(:bar).should == true
KernelSpecs::Foo.new.respond_to?(:invalid_and_silly_method_name).should == false
end
-
end
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
new file mode 100644
index 0000000000..9e1f2c1c49
--- /dev/null
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -0,0 +1,220 @@
+require_relative '../../spec_helper'
+require_relative '../../fixtures/constants'
+
+describe "Module#const_source_location" do
+ before do
+ @constants_fixture_path = File.expand_path('../../fixtures/constants.rb', __dir__)
+ end
+
+ ruby_version_is "2.7" do
+ describe "with dynamically assigned constants" do
+ it "searches a path in the immediate class or module first" do
+ ConstantSpecs::ClassA::CSL_CONST301 = :const301_1
+ ConstantSpecs::ClassA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ModuleA::CSL_CONST301 = :const301_2
+ ConstantSpecs::ModuleA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ParentA::CSL_CONST301 = :const301_3
+ ConstantSpecs::ParentA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ContainerA::ChildA::CSL_CONST301 = :const301_5
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in a module included in the immediate class before the superclass" do
+ ConstantSpecs::ParentB::CSL_CONST302 = :const302_1
+ ConstantSpecs::ModuleF::CSL_CONST302 = :const302_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST302).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in the superclass before a module included in the superclass" do
+ ConstantSpecs::ModuleE::CSL_CONST303 = :const303_1
+ ConstantSpecs::ParentB::CSL_CONST303 = :const303_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST303).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in a module included in the superclass" do
+ ConstantSpecs::ModuleA::CSL_CONST304 = :const304_1
+ ConstantSpecs::ModuleE::CSL_CONST304 = :const304_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST304).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in the superclass chain" do
+ ConstantSpecs::ModuleA::CSL_CONST305 = :const305
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST305).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "returns path to a toplevel constant when the receiver is a Class" do
+ Object::CSL_CONST306 = :const306
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST306).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "returns path to a toplevel constant when the receiver is a Module" do
+ Object::CSL_CONST308 = :const308
+ ConstantSpecs.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 1]
+ ConstantSpecs::ModuleA.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 2]
+ end
+
+ it "returns path to the updated value of a constant" do
+ ConstantSpecs::ClassB::CSL_CONST309 = :const309_1
+ ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 1]
+
+ -> {
+ ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
+ }.should complain(/already initialized constant/)
+ ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
+ end
+ end
+
+ describe "with statically assigned constants" do
+ it "searches location path the immediate class or module first" do
+ ConstantSpecs::ClassA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE]
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST10_LINE]
+ ConstantSpecs::ParentA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST10_LINE]
+ ConstantSpecs::ContainerA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::CS_CONST10_LINE]
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::ChildA::CS_CONST10_LINE]
+ end
+
+ it "searches location path a module included in the immediate class before the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST15).should == [@constants_fixture_path, ConstantSpecs::ModuleC::CS_CONST15_LINE]
+ end
+
+ it "searches location path the superclass before a module included in the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST11).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST11_LINE]
+ end
+
+ it "searches location path a module included in the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST12).should == [@constants_fixture_path, ConstantSpecs::ModuleB::CS_CONST12_LINE]
+ end
+
+ it "searches location path the superclass chain" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST13).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST13_LINE]
+ end
+
+ it "returns location path a toplevel constant when the receiver is a Class" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "returns location path a toplevel constant when the receiver is a Module" do
+ ConstantSpecs.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+ end
+
+ it "return empty path if constant defined in C code" do
+ Object.const_source_location(:String).should == []
+ end
+
+ it "accepts a String or Symbol name" do
+ Object.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "returns nil if no constant is defined in the search path" do
+ ConstantSpecs.const_source_location(:CS_CONSTX).should == nil
+ end
+
+ it "raises a NameError if the name does not start with a capital letter" do
+ -> { ConstantSpecs.const_source_location "name" }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if the name starts with a non-alphabetic character" do
+ -> { ConstantSpecs.const_source_location "__CONSTX__" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "@CS_CONST1" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "!CS_CONST1" }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if the name contains non-alphabetic characters except '_'" do
+ Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ -> { ConstantSpecs.const_source_location "CS_CONST1=" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "CS_CONST1?" }.should raise_error(NameError)
+ end
+
+ it "calls #to_str to convert the given name to a String" do
+ name = mock("ClassA")
+ name.should_receive(:to_str).and_return("ClassA")
+ ConstantSpecs.const_source_location(name).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CLASS_A_LINE]
+ end
+
+ it "raises a TypeError if conversion to a String by calling #to_str fails" do
+ name = mock('123')
+ -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+
+ name.should_receive(:to_str).and_return(123)
+ -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+ end
+
+ it "does not search the singleton class of a Class or Module" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST14).should == nil
+ ConstantSpecs.const_source_location(:CS_CONST14).should == nil
+ end
+
+ it "does not search the containing scope" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST20).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST20_LINE]
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST5) == nil
+ end
+
+ it "returns nil if the constant is defined in the receiver's superclass and the inherit flag is false" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, false).should == nil
+ end
+
+ it "searches into the receiver superclasses if the inherit flag is true" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, true).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST4_LINE]
+ end
+
+ it "returns nil when the receiver is a Module, the constant is defined at toplevel and the inherit flag is false" do
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST1, false).should == nil
+ end
+
+ it "returns nil when the receiver is a Class, the constant is defined at toplevel and the inherit flag is false" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1, false).should == nil
+ end
+
+ it "accepts a toplevel scope qualifier" do
+ ConstantSpecs.const_source_location("::CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "accepts a scoped constant name" do
+ ConstantSpecs.const_source_location("ClassA::CS_CONST10").should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE]
+ end
+
+ it "raises a NameError if the name includes two successive scope separators" do
+ -> { ConstantSpecs.const_source_location("ClassA::::CS_CONST10") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if only '::' is passed" do
+ -> { ConstantSpecs.const_source_location("::") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if a Symbol has a toplevel scope qualifier" do
+ -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if a Symbol is a scoped constant name" do
+ -> { ConstantSpecs.const_source_location(:'ClassA::CS_CONST10') }.should raise_error(NameError)
+ end
+
+ it "does search private constants path" do
+ ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
+ end
+
+ context 'autoload' do
+ before :all do
+ ConstantSpecs.autoload :CSL_CONST1, "#{__dir__}/notexisting.rb"
+ @line = __LINE__ - 1
+ end
+
+ it 'returns the autoload location while not resolved' do
+ ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line]
+ end
+
+ it 'returns where the constant was resolved when resolved' do
+ file = fixture(__FILE__, 'autoload_location.rb')
+ ConstantSpecs.autoload :CONST_LOCATION, file
+ line = ConstantSpecs::CONST_LOCATION
+ ConstantSpecs.const_source_location('CONST_LOCATION').should == [file, line]
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/module/constants_spec.rb b/spec/ruby/core/module/constants_spec.rb
index 4538e828dd..beb25c6eaa 100644
--- a/spec/ruby/core/module/constants_spec.rb
+++ b/spec/ruby/core/module/constants_spec.rb
@@ -43,31 +43,31 @@ end
describe "Module#constants" do
it "returns an array of Symbol names of all constants defined in the module and all included modules" do
ConstantSpecs::ContainerA.constants.sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "returns all constants including inherited when passed true" do
ConstantSpecs::ContainerA.constants(true).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "returns all constants including inherited when passed some object" do
ConstantSpecs::ContainerA.constants(Object.new).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "doesn't returns inherited constants when passed false" do
ConstantSpecs::ContainerA.constants(false).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA
]
end
it "doesn't returns inherited constants when passed nil" do
ConstantSpecs::ContainerA.constants(nil).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA
]
end
diff --git a/spec/ruby/core/module/fixtures/autoload_location.rb b/spec/ruby/core/module/fixtures/autoload_location.rb
new file mode 100644
index 0000000000..318851b2df
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_location.rb
@@ -0,0 +1,3 @@
+module ConstantSpecs
+ CONST_LOCATION = __LINE__
+end
diff --git a/spec/ruby/core/process/exec_spec.rb b/spec/ruby/core/process/exec_spec.rb
index 0a2c2f77e7..deb8913b6b 100644
--- a/spec/ruby/core/process/exec_spec.rb
+++ b/spec/ruby/core/process/exec_spec.rb
@@ -193,9 +193,11 @@ describe "Process.exec" do
map_fd_fixture = fixture __FILE__, "map_fd.rb"
cmd = <<-EOC
f = File.open(#{@name.inspect}, "w+")
- child_fd = f.fileno + 1
- File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
- Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ File.open(#{__FILE__.inspect}, "r") do |io|
+ child_fd = io.fileno
+ File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
+ Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ end
EOC
ruby_exe(cmd, escape: true)
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index a068e05571..40509471ef 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -706,13 +706,15 @@ describe "Process.spawn" do
end
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
- child_fd = find_unused_fd
- args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
- pid = Process.spawn(*args, { child_fd => @io })
- Process.waitpid pid
- @io.rewind
-
- @io.read.should == "writing to fd: #{child_fd}"
+ File.open(__FILE__, "r") do |f|
+ child_fd = f.fileno
+ args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
+ pid = Process.spawn(*args, { child_fd => @io })
+ Process.waitpid pid
+ @io.rewind
+
+ @io.read.should == "writing to fd: #{child_fd}"
+ end
end
end
end
diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb
new file mode 100644
index 0000000000..c3973af13f
--- /dev/null
+++ b/spec/ruby/core/range/minmax_spec.rb
@@ -0,0 +1,170 @@
+require_relative '../../spec_helper'
+
+# These specs use Range.new instead of the literal notation so they parse fine on Ruby < 2.6
+describe 'Range#minmax' do
+ before(:each) do
+ @x = mock('x')
+ @y = mock('y')
+
+ @x.should_receive(:<=>).with(@y).any_number_of_times.and_return(-1) # x < y
+ @x.should_receive(:<=>).with(@x).any_number_of_times.and_return(0) # x == x
+ @y.should_receive(:<=>).with(@x).any_number_of_times.and_return(1) # y > x
+ @y.should_receive(:<=>).with(@y).any_number_of_times.and_return(0) # y == y
+ end
+
+ describe 'on an inclusive range' do
+ ruby_version_is '2.6'...'2.7' do
+ it 'should try to iterate endlessly on an endless range' do
+ @x.should_receive(:succ).once.and_return(@y)
+ range = Range.new(@x, nil)
+
+ -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should raise RangeError on an endless range without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ range = Range.new(@x, nil)
+
+ -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ end
+
+ it 'raises RangeError or ArgumentError on a beginless range' do
+ range = Range.new(nil, @x)
+
+ -> { range.minmax }.should raise_error(StandardError) { |e|
+ if RangeError === e
+ # error from #min
+ -> { raise e }.should raise_error(RangeError, 'cannot get the minimum of beginless range')
+ else
+ # error from #max
+ -> { raise e }.should raise_error(ArgumentError, 'comparison of NilClass with MockObject failed')
+ end
+ }
+ end
+ end
+
+ it 'should return begining of range if beginning and end are equal without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x..@x).minmax.should == [@x, @x]
+ end
+
+ it 'should return nil pair if beginning is greater than end without iterating the range' do
+ @y.should_not_receive(:succ)
+
+ (@y..@x).minmax.should == [nil, nil]
+ end
+
+ ruby_version_is ''...'2.7' do
+ it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x..@y).minmax.should == [@x, @y]
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a non-numeric range without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x..@y).minmax.should == [@x, @y]
+ end
+ end
+
+ it 'should return the minimum and maximum values for a numeric range' do
+ (1..3).minmax.should == [1, 3]
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a numeric range without iterating the range' do
+ # We cannot set expectations on integers,
+ # so we "prevent" iteration by picking a value that would iterate until the spec times out.
+ range_end = Float::INFINITY
+
+ (1..range_end).minmax.should == [1, range_end]
+ end
+ end
+
+ it 'should return the minimum and maximum values according to the provided block by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x..@y).minmax { |x, y| - (x <=> y) }.should == [@y, @x]
+ end
+ end
+
+ describe 'on an exclusive range' do
+ ruby_version_is '2.6'...'2.7' do
+ # Endless ranges introduced in 2.6
+ it 'should try to iterate endlessly on an endless range' do
+ @x.should_receive(:succ).once.and_return(@y)
+ range = Range.new(@x, nil, true)
+
+ -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should raise RangeError on an endless range' do
+ @x.should_not_receive(:succ)
+ range = Range.new(@x, nil, true)
+
+ -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ end
+
+ it 'should raise RangeError on a beginless range' do
+ range = Range.new(nil, @x, true)
+
+ -> { range.minmax }.should raise_error(RangeError,
+ /cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/)
+ end
+ end
+
+ ruby_bug "#17014", "2.7.0"..."2.8" do
+ it 'should return nil pair if beginning and end are equal without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x...@x).minmax.should == [nil, nil]
+ end
+
+ it 'should return nil pair if beginning is greater than end without iterating the range' do
+ @y.should_not_receive(:succ)
+
+ (@y...@x).minmax.should == [nil, nil]
+ end
+
+ it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x...@y).minmax.should == [@x, @x]
+ end
+ end
+
+ it 'should return the minimum and maximum values for a numeric range' do
+ (1...3).minmax.should == [1, 2]
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a numeric range without iterating the range' do
+ # We cannot set expectations on integers,
+ # so we "prevent" iteration by picking a value that would iterate until the spec times out.
+ range_end = bignum_value
+
+ (1...range_end).minmax.should == [1, range_end - 1]
+ end
+
+ it 'raises TypeError if the end value is not an integer' do
+ range = (0...Float::INFINITY)
+ -> { range.minmax }.should raise_error(TypeError, 'cannot exclude non Integer end value')
+ end
+ end
+
+ it 'should return the minimum and maximum values according to the provided block by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x...@y).minmax { |x, y| - (x <=> y) }.should == [@x, @x]
+ end
+ end
+end
diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb
index b3f64d7118..7a1118d534 100644
--- a/spec/ruby/core/string/chomp_spec.rb
+++ b/spec/ruby/core/string/chomp_spec.rb
@@ -55,6 +55,10 @@ describe "String#chomp" do
$/ = "cdef"
"abcdef".chomp.should == "ab"
end
+
+ it "removes one trailing newline for string with invalid encoding" do
+ "\xa0\xa1\n".chomp.should == "\xa0\xa1"
+ end
end
describe "when passed nil" do
@@ -108,6 +112,10 @@ describe "String#chomp" do
it "returns an empty String when self is empty" do
"".chomp("").should == ""
end
+
+ it "removes one trailing newline for string with invalid encoding" do
+ "\xa0\xa1\n".chomp("").should == "\xa0\xa1"
+ end
end
describe "when passed '\\n'" do
diff --git a/spec/ruby/core/thread/list_spec.rb b/spec/ruby/core/thread/list_spec.rb
index a0bf831856..3c6f70c13e 100644
--- a/spec/ruby/core/thread/list_spec.rb
+++ b/spec/ruby/core/thread/list_spec.rb
@@ -43,11 +43,11 @@ describe "Thread.list" do
end
end
- while spawner.alive?
+ begin
Thread.list.each { |th|
th.should be_kind_of(Thread)
}
- end
+ end while spawner.alive?
threads = spawner.value
threads.each(&:join)
diff --git a/spec/ruby/fixtures/constants.rb b/spec/ruby/fixtures/constants.rb
index e5b20596ef..37271ddcc8 100644
--- a/spec/ruby/fixtures/constants.rb
+++ b/spec/ruby/fixtures/constants.rb
@@ -1,7 +1,7 @@
# Contains all static code examples of all constants behavior in language and
# library specs. The specs include language/constants_spec.rb and the specs
-# for Module#const_defined?, Module#const_get, Module#const_set,
-# Module#remove_const, Module#const_missing and Module#constants.
+# for Module#const_defined?, Module#const_get, Module#const_set, Module#remove_const,
+# Module#const_source_location, Module#const_missing and Module#constants.
#
# Rather than defining a class structure for each example, a canonical set of
# classes is used along with numerous constants, in most cases, a unique
@@ -28,14 +28,17 @@
# for completeness. No other constant of this name should be defined in the
# specs.
CS_CONST1 = :const1 # only defined here
+CS_CONST1_LINE = __LINE__ - 1
module ConstantSpecs
# Included at toplevel
module ModuleA
CS_CONST10 = :const10_1
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST12 = :const12_2
CS_CONST13 = :const13
+ CS_CONST13_LINE = __LINE__ - 1
CS_CONST21 = :const21_2
end
@@ -44,12 +47,14 @@ module ConstantSpecs
CS_CONST10 = :const10_9
CS_CONST11 = :const11_2
CS_CONST12 = :const12_1
+ CS_CONST12_LINE = __LINE__ - 1
end
# Included in ChildA
module ModuleC
CS_CONST10 = :const10_4
CS_CONST15 = :const15_1
+ CS_CONST15_LINE = __LINE__ - 1
end
# Included in ChildA metaclass
@@ -75,7 +80,9 @@ module ConstantSpecs
# are run.
class ClassA
+ CS_CLASS_A_LINE = __LINE__ - 1
CS_CONST10 = :const10_10
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST16 = :const16
CS_CONST17 = :const17_2
CS_CONST22 = :const22_1
@@ -97,10 +104,14 @@ module ConstantSpecs
include ModuleB
CS_CONST4 = :const4
+ CS_CONST4_LINE = __LINE__ - 1
CS_CONST10 = :const10_5
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST11 = :const11_1
+ CS_CONST11_LINE = __LINE__ - 1
CS_CONST15 = :const15_2
CS_CONST20 = :const20_2
+ CS_CONST20_LINE = __LINE__ - 1
CS_CONST21 = :const21_1
CS_CONST22 = :const22_2
@@ -118,6 +129,7 @@ module ConstantSpecs
CS_CONST5 = :const5
CS_CONST10 = :const10_2
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST23 = :const23
class ChildA < ParentA
@@ -135,6 +147,7 @@ module ConstantSpecs
CS_CONST6 = :const6
CS_CONST10 = :const10_3
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST19 = :const19_2
def self.const10; CS_CONST10; end
@@ -282,6 +295,7 @@ module ConstantSpecs
end
CS_PRIVATE = :cs_private
+ CS_PRIVATE_LINE = __LINE__ - 1
private_constant :CS_PRIVATE
end
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index 764c96e838..65fcb1e2ac 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -1254,3 +1254,25 @@ describe "The predefined global constant" do
end
end
end
+
+ruby_version_is "2.7" do
+ describe "$LOAD_PATH.resolve_feature_path" do
+ it "returns what will be loaded without actual loading, .rb file" do
+ extension, path = $LOAD_PATH.resolve_feature_path('set')
+ extension.should == :rb
+ path.should.end_with?('/set.rb')
+ end
+
+ it "returns what will be loaded without actual loading, .so file" do
+ require 'rbconfig'
+
+ extension, path = $LOAD_PATH.resolve_feature_path('etc')
+ extension.should == :so
+ path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
+ end
+
+ it "raises LoadError if feature cannot be found" do
+ -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/listen_spec.rb b/spec/ruby/library/socket/socket/listen_spec.rb
index 6598e254d7..4d2aedab19 100644
--- a/spec/ruby/library/socket/socket/listen_spec.rb
+++ b/spec/ruby/library/socket/socket/listen_spec.rb
@@ -34,16 +34,10 @@ describe 'Socket#listen' do
@server.close
end
- platform_is_not :android do
- it 'raises Errno::EOPNOTSUPP' do
- -> { @server.listen(1) }.should raise_error(Errno::EOPNOTSUPP)
- end
- end
-
- platform_is :android do
- it 'raises Errno::EOPNOTSUPP or Errno::EACCES' do
- -> { @server.listen(1) }.should raise_error(-> exc { Errno::EACCES === exc || Errno::EOPNOTSUPP === exc })
- end
+ it 'raises Errno::EOPNOTSUPP or Errno::EACCES' do
+ -> { @server.listen(1) }.should raise_error { |e|
+ [Errno::EOPNOTSUPP, Errno::EACCES].should.include?(e.class)
+ }
end
end
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 44cf311895..7539e0c01c 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -396,12 +396,20 @@ describe "C-API Kernel function" do
proc = -> x { x }
arg_error_proc = -> *_ { raise ArgumentError, '' }
run_error_proc = -> *_ { raise RuntimeError, '' }
- type_error_proc = -> *_ { raise TypeError, '' }
+ type_error_proc = -> *_ { raise Exception, 'custom error' }
@s.rb_rescue2(arg_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc
@s.rb_rescue2(run_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc
-> {
@s.rb_rescue2(type_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError)
- }.should raise_error(TypeError)
+ }.should raise_error(Exception, 'custom error')
+ end
+
+ ruby_bug "#17305", ""..."2.7" do
+ it "raises TypeError if one of the passed exceptions is not a Module" do
+ -> {
+ @s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
+ }.should raise_error(TypeError, /class or module required/)
+ end
end
end
diff --git a/spec/ruby/optional/capi/module_spec.rb b/spec/ruby/optional/capi/module_spec.rb
index f5ce7ed8de..fde86d2223 100644
--- a/spec/ruby/optional/capi/module_spec.rb
+++ b/spec/ruby/optional/capi/module_spec.rb
@@ -135,7 +135,7 @@ describe "CApiModule" do
end
it "returns a constant defined at toplevel" do
- @m.rb_const_get(CApiModuleSpecs::A, :Fixnum).should == Fixnum
+ @m.rb_const_get(CApiModuleSpecs::A, :Integer).should == Integer
end
it "returns a constant defined in a superclass" do
@@ -176,8 +176,8 @@ describe "CApiModule" do
end
it "calls #const_missing if the constant is not defined in the class or ancestors" do
- CApiModuleSpecs::M.should_receive(:const_missing).with(:Fixnum)
- @m.rb_const_get_from(CApiModuleSpecs::M, :Fixnum)
+ CApiModuleSpecs::M.should_receive(:const_missing).with(:Integer)
+ @m.rb_const_get_from(CApiModuleSpecs::M, :Integer)
end
it "resolves autoload constants" do
diff --git a/spec/ruby/optional/capi/struct_spec.rb b/spec/ruby/optional/capi/struct_spec.rb
index c071203673..0e9e366908 100644
--- a/spec/ruby/optional/capi/struct_spec.rb
+++ b/spec/ruby/optional/capi/struct_spec.rb
@@ -62,7 +62,7 @@ describe "C-API Struct function" do
end
describe "C-API Struct function" do
- before :each do
+ before :all do
@s = CApiStructSpecs.new
@struct = @s.rb_struct_define_under(CApiStructSpecs, "CAPIStructUnder", "a", "b", "c")
end
diff --git a/spec/ruby/shared/enumerator/enum_for.rb b/spec/ruby/shared/enumerator/enum_for.rb
index 9030ffbd7d..a67a76c461 100644
--- a/spec/ruby/shared/enumerator/enum_for.rb
+++ b/spec/ruby/shared/enumerator/enum_for.rb
@@ -12,6 +12,13 @@ describe :enum_for, shared: true do
enum.map { |v| v }.should == [1,2].each { |v| v }
end
+ it "sets regexp matches in the caller" do
+ "wawa".send(@method, :scan, /./).map {|o| $& }.should == ["w", "a", "w", "a"]
+ a = []
+ "wawa".send(@method, :scan, /./).each {|o| a << $& }
+ a.should == ["w", "a", "w", "a"]
+ end
+
it "exposes multi-arg yields as an array" do
o = Object.new
def o.each
diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb
index 7d9954e29a..f00a6ef294 100644
--- a/spec/ruby/shared/kernel/raise.rb
+++ b/spec/ruby/shared/kernel/raise.rb
@@ -50,20 +50,43 @@ describe :kernel_raise, shared: true do
end
it "re-raises a previously rescued exception without overwriting the backtrace" do
- begin
- initial_raise_line = __LINE__; @object.raise 'raised'
- rescue => raised
- begin
- raise_again_line = __LINE__; @object.raise raised
- rescue => raised_again
- # This spec is written using #backtrace and matching the line number
- # from the string, as backtrace_locations is a more advanced
- # method that is not always supported by implementations.
+ # This spec is written using #backtrace and matching the line number
+ # from the string, as backtrace_locations is a more advanced
+ # method that is not always supported by implementations.
+ #
+ initial_raise_line = nil
+ raise_again_line = nil
+ raised_again = nil
- raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
- raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
+ if defined?(FiberSpecs::NewFiberToRaise) and @object == FiberSpecs::NewFiberToRaise
+ fiber = Fiber.new do
+ begin
+ initial_raise_line = __LINE__; Fiber.yield
+ rescue => raised
+ begin
+ raise_again_line = __LINE__; Fiber.yield raised
+ rescue => raised_again
+ raised_again
+ end
+ end
+ end
+ fiber.resume
+ raised = fiber.raise 'raised'
+ raised_again = fiber.raise raised
+ else
+ begin
+ initial_raise_line = __LINE__; @object.raise 'raised'
+ rescue => raised
+ begin
+ raise_again_line = __LINE__; @object.raise raised
+ rescue => raised_again
+ raised_again
+ end
end
end
+
+ raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
+ raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
end
it "allows Exception, message, and backtrace parameters" do