aboutsummaryrefslogtreecommitdiffstats
path: root/spec/ruby/core
diff options
context:
space:
mode:
authoreregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-03 16:19:40 +0000
committereregon <eregon@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-03 16:19:40 +0000
commitb53cf149ad8d7c46572e4567ca949b4f82ebb22c (patch)
treeee5032bcb38573dade8ba2c46acbcc0d5f3ddfe3 /spec/ruby/core
parentaeeaadaad08038217440c1e9e7c5ca126d7dc633 (diff)
downloadruby-b53cf149ad8d7c46572e4567ca949b4f82ebb22c.tar.gz
Update to ruby/spec@9be7c7e
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64180 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'spec/ruby/core')
-rw-r--r--spec/ruby/core/array/reject_spec.rb25
-rw-r--r--spec/ruby/core/binding/eval_spec.rb60
-rw-r--r--spec/ruby/core/binding/fixtures/classes.rb12
-rw-r--r--spec/ruby/core/binding/location_spec.rb46
-rw-r--r--spec/ruby/core/enumerable/sort_by_spec.rb7
-rw-r--r--spec/ruby/core/io/read_spec.rb4
-rw-r--r--spec/ruby/core/io/shared/write.rb4
-rw-r--r--spec/ruby/core/kernel/__dir___spec.rb7
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb11
-rw-r--r--spec/ruby/core/kernel/fixtures/autoload_c.rb5
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb40
-rw-r--r--spec/ruby/core/kernel/require_spec.rb2
-rw-r--r--spec/ruby/core/kernel/shared/require.rb76
-rw-r--r--spec/ruby/core/module/autoload_spec.rb307
-rw-r--r--spec/ruby/core/module/const_get_spec.rb21
-rw-r--r--spec/ruby/core/module/fixtures/autoload_callback.rb2
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_autoload.rb7
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_require.rb4
-rw-r--r--spec/ruby/core/module/fixtures/autoload_exception.rb3
-rw-r--r--spec/ruby/core/module/fixtures/autoload_nested.rb8
-rw-r--r--spec/ruby/core/module/fixtures/autoload_o.rb1
-rw-r--r--spec/ruby/core/module/fixtures/autoload_raise.rb2
-rw-r--r--spec/ruby/core/module/fixtures/autoload_scope.rb8
-rw-r--r--spec/ruby/core/module/fixtures/constants_autoload.rb6
-rw-r--r--spec/ruby/core/module/fixtures/constants_autoload_a.rb2
-rw-r--r--spec/ruby/core/module/fixtures/constants_autoload_b.rb2
-rw-r--r--spec/ruby/core/module/fixtures/constants_autoload_c.rb3
-rw-r--r--spec/ruby/core/module/fixtures/constants_autoload_d.rb4
-rw-r--r--spec/ruby/core/module/initialize_copy_spec.rb8
-rw-r--r--spec/ruby/core/signal/fixtures/trap_all.rb8
-rw-r--r--spec/ruby/core/signal/trap_spec.rb43
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb20
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb38
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/absolute_path.rb4
-rw-r--r--spec/ruby/core/time/localtime_spec.rb2
35 files changed, 709 insertions, 93 deletions
diff --git a/spec/ruby/core/array/reject_spec.rb b/spec/ruby/core/array/reject_spec.rb
index 77835ef5cd..e6e5e851b6 100644
--- a/spec/ruby/core/array/reject_spec.rb
+++ b/spec/ruby/core/array/reject_spec.rb
@@ -111,6 +111,31 @@ describe "Array#reject!" do
lambda { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(frozen_error_class)
end
+ it "does not truncate the array is the block raises an exception" do
+ a = [1, 2, 3]
+ begin
+ a.reject! { raise StandardError, 'Oops' }
+ rescue
+ end
+
+ a.should == [1, 2, 3]
+ end
+
+ ruby_version_is "2.4" do
+ it "only removes elements for which the block returns true, keeping the element which raised an error." do
+ a = [1, 2, 3, 4]
+ begin
+ a.reject! do |x|
+ return true if x == 2
+ raise raise StandardError, 'Oops' if x == 3
+ end
+ rescue
+ end
+
+ a.should == [1, 3, 4]
+ end
+ end
+
it_behaves_like :enumeratorize, :reject!
it_behaves_like :enumeratorized_with_origin_size, :reject!, [1,2,3]
it_behaves_like :delete_if, :reject!
diff --git a/spec/ruby/core/binding/eval_spec.rb b/spec/ruby/core/binding/eval_spec.rb
index 9a397757e9..c0264192b8 100644
--- a/spec/ruby/core/binding/eval_spec.rb
+++ b/spec/ruby/core/binding/eval_spec.rb
@@ -23,6 +23,54 @@ describe "Binding#eval" do
bind2.local_variables.should == []
end
+ it "inherits __LINE__ from the enclosing scope" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == obj.get_line_of_binding
+ end
+
+ it "preserves __LINE__ across multiple calls to eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == obj.get_line_of_binding
+ bind.eval("__LINE__").should == obj.get_line_of_binding
+ end
+
+ it "increments __LINE__ on each line of a multiline eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("#foo\n__LINE__").should == obj.get_line_of_binding + 1
+ end
+
+ it "inherits __LINE__ from the enclosing scope even if the Binding is created with #send" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, line = obj.get_binding_with_send_and_line
+ bind.eval("__LINE__").should == line
+ end
+
+ it "starts with a __LINE__ of 1 if a filename is passed" do
+ bind = BindingSpecs::Demo.new(1).get_binding
+ bind.eval("__LINE__", "(test)").should == 1
+ bind.eval("#foo\n__LINE__", "(test)").should == 2
+ end
+
+ it "starts with a __LINE__ from the third argument if passed" do
+ bind = BindingSpecs::Demo.new(1).get_binding
+ bind.eval("__LINE__", "(test)", 88).should == 88
+ bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
+ end
+
+ it "inherits __FILE__ from the enclosing scope" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__FILE__").should == obj.get_file_of_binding
+ end
+
+ it "uses the __FILE__ that is passed in" do
+ bind = BindingSpecs::Demo.new(1).get_binding
+ bind.eval("__FILE__", "(test)").should == "(test)"
+ end
+
describe "with a file given" do
it "does not store the filename permanently" do
obj = BindingSpecs::Demo.new(1)
@@ -33,5 +81,15 @@ describe "Binding#eval" do
end
end
- it "needs to be reviewed for spec completeness"
+ it "with __method__ returns the method where the Binding was created" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, meth = obj.get_binding_and_method
+ bind.eval("__method__").should == meth
+ end
+
+ it "with __method__ returns the method where the Binding was created, ignoring #send" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, meth = obj.get_binding_with_send_and_method
+ bind.eval("__method__").should == meth
+ end
end
diff --git a/spec/ruby/core/binding/fixtures/classes.rb b/spec/ruby/core/binding/fixtures/classes.rb
index 05ca2479ba..43e32cacf6 100644
--- a/spec/ruby/core/binding/fixtures/classes.rb
+++ b/spec/ruby/core/binding/fixtures/classes.rb
@@ -25,6 +25,18 @@ module BindingSpecs
__FILE__
end
+ def get_binding_with_send_and_line
+ [send(:binding), __LINE__]
+ end
+
+ def get_binding_and_method
+ [binding, :get_binding_and_method]
+ end
+
+ def get_binding_with_send_and_method
+ [send(:binding), :get_binding_with_send_and_method]
+ end
+
def get_empty_binding
binding
end
diff --git a/spec/ruby/core/binding/location_spec.rb b/spec/ruby/core/binding/location_spec.rb
deleted file mode 100644
index 2ae0c5e9f1..0000000000
--- a/spec/ruby/core/binding/location_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-
-describe "Binding#eval" do
- it "inherits __LINE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__LINE__").should == obj.get_line_of_binding
- end
-
- it "preserves __LINE__ across multiple calls to eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__LINE__").should == obj.get_line_of_binding
- bind.eval("__LINE__").should == obj.get_line_of_binding
- end
-
- it "increments __LINE__ on each line of a multiline eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("#foo\n__LINE__").should == obj.get_line_of_binding + 1
- end
-
- it "starts with a __LINE__ of 1 if a filename is passed" do
- bind = BindingSpecs::Demo.new(1).get_binding
- bind.eval("__LINE__", "(test)").should == 1
- bind.eval("#foo\n__LINE__", "(test)").should == 2
- end
-
- it "starts with a __LINE__ from the third argument if passed" do
- bind = BindingSpecs::Demo.new(1).get_binding
- bind.eval("__LINE__", "(test)", 88).should == 88
- bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
- end
-
- it "inherits __FILE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- bind.eval("__FILE__").should == obj.get_file_of_binding
- end
-
- it "uses the __FILE__ that is passed in" do
- bind = BindingSpecs::Demo.new(1).get_binding
- bind.eval("__FILE__", "(test)").should == "(test)"
- end
-end
diff --git a/spec/ruby/core/enumerable/sort_by_spec.rb b/spec/ruby/core/enumerable/sort_by_spec.rb
index 46e1135412..8fdd923fb4 100644
--- a/spec/ruby/core/enumerable/sort_by_spec.rb
+++ b/spec/ruby/core/enumerable/sort_by_spec.rb
@@ -32,5 +32,12 @@ describe "Enumerable#sort_by" do
b.sort_by{ |x| -x }.should == [3, 2, 1]
end
+ it "calls #each to iterate over the elements to be sorted" do
+ b = EnumerableSpecs::Numerous.new( 1, 2, 3 )
+ b.should_receive(:each).once.and_yield(1).and_yield(2).and_yield(3)
+ b.should_not_receive :map
+ b.sort_by { |x| -x }.should == [3, 2, 1]
+ end
+
it_behaves_like :enumerable_enumeratorized_with_origin_size, :sort_by
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index dffa79f10e..3bb581f430 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -27,6 +27,10 @@ describe "IO.read" do
IO.read(@fname, {}).should == @contents
end
+ it "accepts a length, and empty options Hash" do
+ IO.read(@fname, 3, {}).should == @contents[0, 3]
+ end
+
it "accepts a length, offset, and empty options Hash" do
IO.read(@fname, 3, 0, {}).should == @contents[0, 3]
end
diff --git a/spec/ruby/core/io/shared/write.rb b/spec/ruby/core/io/shared/write.rb
index bca96da81c..140eeb04ab 100644
--- a/spec/ruby/core/io/shared/write.rb
+++ b/spec/ruby/core/io/shared/write.rb
@@ -85,9 +85,9 @@ describe :io_write, shared: true do
@r.read.should == "foo"
end
- it "raises Errno::EPIPE if the read end is closed" do
+ it "raises Errno::EPIPE if the read end is closed and does not die from SIGPIPE" do
@r.close
- -> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, "Broken pipe")
+ -> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, /Broken pipe/)
end
end
end
diff --git a/spec/ruby/core/kernel/__dir___spec.rb b/spec/ruby/core/kernel/__dir___spec.rb
index 25df92a15d..3c34277277 100644
--- a/spec/ruby/core/kernel/__dir___spec.rb
+++ b/spec/ruby/core/kernel/__dir___spec.rb
@@ -5,6 +5,13 @@ describe "Kernel#__dir__" do
__dir__.should == File.realpath(File.dirname(__FILE__))
end
+ context "when used in eval with a given filename" do
+ it "returns File.dirname(filename)" do
+ eval("__dir__", nil, "foo.rb").should == "."
+ eval("__dir__", nil, "foo/bar.rb").should == "foo"
+ end
+ end
+
context "when used in eval with top level binding" do
it "returns the real name of the directory containing the currently-executing file" do
eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))
diff --git a/spec/ruby/core/kernel/autoload_spec.rb b/spec/ruby/core/kernel/autoload_spec.rb
index c2573ffac6..5fa8fa92b3 100644
--- a/spec/ruby/core/kernel/autoload_spec.rb
+++ b/spec/ruby/core/kernel/autoload_spec.rb
@@ -7,7 +7,7 @@ require_relative 'fixtures/classes'
autoload :KSAutoloadA, "autoload_a.rb"
autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
-autoload :KSAutoloadC, fixture(__FILE__, "autoload_c.rb")
+autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
def check_autoload(const)
autoload? const
@@ -42,10 +42,11 @@ describe "Kernel#autoload" do
KSAutoloadB.loaded.should == :ksautoload_b
end
- it "does not call Kernel.require or Kernel.load to load the file" do
- Kernel.should_not_receive(:require)
- Kernel.should_not_receive(:load)
- KSAutoloadC.loaded.should == :ksautoload_c
+ it "calls main.require(path) to load the file" do
+ main = TOPLEVEL_BINDING.eval("self")
+ main.should_receive(:require).with("main_autoload_not_exist.rb")
+ # The constant won't be defined since require is mocked to do nothing
+ -> { KSAutoloadCallsRequire }.should raise_error(NameError)
end
it "can autoload in instance_eval" do
diff --git a/spec/ruby/core/kernel/fixtures/autoload_c.rb b/spec/ruby/core/kernel/fixtures/autoload_c.rb
deleted file mode 100644
index 4569b23669..0000000000
--- a/spec/ruby/core/kernel/fixtures/autoload_c.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module KSAutoloadC
- def self.loaded
- :ksautoload_c
- end
-end
diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb
index 4a2ef87357..a16e7164e6 100644
--- a/spec/ruby/core/kernel/require_relative_spec.rb
+++ b/spec/ruby/core/kernel/require_relative_spec.rb
@@ -199,6 +199,46 @@ describe "Kernel#require_relative with a relative path" do
$LOADED_FEATURES.should include(@abs_path)
end
+ platform_is_not :windows do
+ describe "with symlinks" do
+ before :each do
+ @symlink_to_code_dir = tmp("codesymlink")
+ File.symlink(CODE_LOADING_DIR, @symlink_to_code_dir)
+ @symlink_basename = File.basename(@symlink_to_code_dir)
+ @requiring_file = tmp("requiring")
+ end
+
+ after :each do
+ rm_r @symlink_to_code_dir, @requiring_file
+ end
+
+ it "does not canonicalize the path and stores a path with symlinks" do
+ symlink_path = "#{@symlink_basename}/load_fixture.rb"
+ absolute_path = "#{tmp("")}#{symlink_path}"
+ canonical_path = "#{CODE_LOADING_DIR}/load_fixture.rb"
+ touch(@requiring_file) { |f|
+ f.puts "require_relative #{symlink_path.inspect}"
+ }
+ load(@requiring_file)
+ ScratchPad.recorded.should == [:loaded]
+
+ features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
+ features.should include(absolute_path)
+ features.should_not include(canonical_path)
+ end
+
+ it "stores the same path that __FILE__ returns in the required file" do
+ symlink_path = "#{@symlink_basename}/load_fixture_and__FILE__.rb"
+ touch(@requiring_file) { |f|
+ f.puts "require_relative #{symlink_path.inspect}"
+ }
+ load(@requiring_file)
+ loaded_feature = $LOADED_FEATURES.last
+ ScratchPad.recorded.should == [loaded_feature]
+ end
+ end
+ end
+
it "does not store the path if the load fails" do
saved_loaded_features = $LOADED_FEATURES.dup
lambda { require_relative("#{@dir}/raise_fixture.rb") }.should raise_error(RuntimeError)
diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb
index 362acf8003..dc3da4b7e6 100644
--- a/spec/ruby/core/kernel/require_spec.rb
+++ b/spec/ruby/core/kernel/require_spec.rb
@@ -17,7 +17,6 @@ describe "Kernel#require" do
end
it_behaves_like :kernel_require_basic, :require, CodeLoadingSpecs::Method.new
-
it_behaves_like :kernel_require, :require, CodeLoadingSpecs::Method.new
end
@@ -31,6 +30,5 @@ describe "Kernel.require" do
end
it_behaves_like :kernel_require_basic, :require, Kernel
-
it_behaves_like :kernel_require, :require, Kernel
end
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 5e3f98f813..a81a68088a 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -305,6 +305,80 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES.should include(@path)
end
+ platform_is_not :windows do
+ describe "with symlinks" do
+ before :each do
+ @symlink_to_code_dir = tmp("codesymlink")
+ File.symlink(CODE_LOADING_DIR, @symlink_to_code_dir)
+
+ $LOAD_PATH.delete(CODE_LOADING_DIR)
+ $LOAD_PATH.unshift(@symlink_to_code_dir)
+ end
+
+ after :each do
+ rm_r @symlink_to_code_dir
+ end
+
+ it "does not canonicalize the path and stores a path with symlinks" do
+ symlink_path = "#{@symlink_to_code_dir}/load_fixture.rb"
+ canonical_path = "#{CODE_LOADING_DIR}/load_fixture.rb"
+ @object.require(symlink_path).should be_true
+ ScratchPad.recorded.should == [:loaded]
+
+ features = $LOADED_FEATURES.select { |path| path.end_with?('load_fixture.rb') }
+ features.should include(symlink_path)
+ features.should_not include(canonical_path)
+ end
+
+ it "stores the same path that __FILE__ returns in the required file" do
+ symlink_path = "#{@symlink_to_code_dir}/load_fixture_and__FILE__.rb"
+ @object.require(symlink_path).should be_true
+ loaded_feature = $LOADED_FEATURES.last
+ ScratchPad.recorded.should == [loaded_feature]
+ end
+ end
+
+ describe "with symlinks in the required feature and $LOAD_PATH" do
+ before :each do
+ @dir = tmp("realdir")
+ mkdir_p @dir
+ @file = "#{@dir}/realfile.rb"
+ touch(@file) { |f| f.puts 'ScratchPad << __FILE__' }
+
+ @symlink_to_dir = tmp("symdir").freeze
+ File.symlink(@dir, @symlink_to_dir)
+ @symlink_to_file = "#{@dir}/symfile.rb"
+ File.symlink("realfile.rb", @symlink_to_file)
+ end
+
+ after :each do
+ rm_r @dir, @symlink_to_dir
+ end
+
+ ruby_version_is ""..."2.4.4" do
+ it "canonicalizes neither the entry in $LOAD_PATH nor the filename passed to #require" do
+ $LOAD_PATH.unshift(@symlink_to_dir)
+ @object.require("symfile").should be_true
+ loaded_feature = "#{@symlink_to_dir}/symfile.rb"
+ ScratchPad.recorded.should == [loaded_feature]
+ $".last.should == loaded_feature
+ $LOAD_PATH[0].should == @symlink_to_dir
+ end
+ end
+
+ ruby_version_is "2.4.4" do
+ it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do
+ $LOAD_PATH.unshift(@symlink_to_dir)
+ @object.require("symfile").should be_true
+ loaded_feature = "#{@dir}/symfile.rb"
+ ScratchPad.recorded.should == [loaded_feature]
+ $".last.should == loaded_feature
+ $LOAD_PATH[0].should == @symlink_to_dir
+ end
+ end
+ end
+ end
+
it "does not store the path if the load fails" do
$LOAD_PATH << CODE_LOADING_DIR
saved_loaded_features = $LOADED_FEATURES.dup
@@ -417,7 +491,7 @@ describe :kernel_require, shared: true do
$LOADED_FEATURES.should include(@path)
end
- it "canonicalizes non-unique absolute paths" do
+ it "expands absolute paths containing .." do
path = File.join CODE_LOADING_DIR, "..", "code", "load_fixture.rb"
@object.require(path).should be_true
$LOADED_FEATURES.should include(@path)
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index f355a5968d..89c061ff47 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -105,6 +105,14 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::J.should == :autoload_j
end
+ it "calls main.require(path) to load the file" do
+ ModuleSpecs::Autoload.autoload :ModuleAutoloadCallsRequire, "module_autoload_not_exist.rb"
+ main = TOPLEVEL_BINDING.eval("self")
+ main.should_receive(:require).with("module_autoload_not_exist.rb")
+ # The constant won't be defined since require is mocked to do nothing
+ -> { ModuleSpecs::Autoload::ModuleAutoloadCallsRequire }.should raise_error(NameError)
+ end
+
it "does not load the file if the file is manually required" do
filename = fixture(__FILE__, "autoload_k.rb")
ModuleSpecs::Autoload.autoload :KHash, filename
@@ -158,28 +166,169 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.use_ex1.should == :good
end
- it "does not load the file when referring to the constant in defined?" do
- module ModuleSpecs::Autoload::Q
- autoload :R, fixture(__FILE__, "autoload.rb")
- defined?(R).should == "constant"
+ describe "interacting with defined?" do
+ it "does not load the file when referring to the constant in defined?" do
+ module ModuleSpecs::Autoload::Dog
+ autoload :R, fixture(__FILE__, "autoload_exception.rb")
+ end
+
+ defined?(ModuleSpecs::Autoload::Dog::R).should == "constant"
+ ScratchPad.recorded.should be_nil
+
+ ModuleSpecs::Autoload::Dog.should have_constant(:R)
+ end
+
+ it "loads an autoloaded parent when referencing a nested constant" do
+ module ModuleSpecs::Autoload
+ autoload :GoodParent, fixture(__FILE__, "autoload_nested.rb")
+ end
+
+ defined?(ModuleSpecs::Autoload::GoodParent::Nested).should == 'constant'
+ ScratchPad.recorded.should == :loaded
+
+ ModuleSpecs::Autoload.send(:remove_const, :GoodParent)
+ end
+
+ it "returns nil when it fails to load an autoloaded parent when referencing a nested constant" do
+ module ModuleSpecs::Autoload
+ autoload :BadParent, fixture(__FILE__, "autoload_exception.rb")
+ end
+
+ defined?(ModuleSpecs::Autoload::BadParent::Nested).should be_nil
+ ScratchPad.recorded.should == :exception
+ end
+ end
+
+ describe "during the autoload before the constant is assigned" do
+ before :each do
+ @path = fixture(__FILE__, "autoload_during_autoload.rb")
+ ModuleSpecs::Autoload.autoload :DuringAutoload, @path
+ raise unless ModuleSpecs::Autoload.autoload?(:DuringAutoload) == @path
+ end
+
+ after :each do
+ ModuleSpecs::Autoload.send(:remove_const, :DuringAutoload)
+ end
+
+ def check_before_during_thread_after(&check)
+ before = check.call
+ to_autoload_thread, from_autoload_thread = Queue.new, Queue.new
+ ScratchPad.record -> {
+ from_autoload_thread.push check.call
+ to_autoload_thread.pop
+ }
+ t = Thread.new {
+ in_loading_thread = from_autoload_thread.pop
+ in_other_thread = check.call
+ to_autoload_thread.push :done
+ [in_loading_thread, in_other_thread]
+ }
+ in_loading_thread, in_other_thread = nil
+ begin
+ ModuleSpecs::Autoload::DuringAutoload
+ ensure
+ in_loading_thread, in_other_thread = t.value
+ end
+ after = check.call
+ [before, in_loading_thread, in_other_thread, after]
+ end
+
+ it "returns nil in autoload thread and 'constant' otherwise for defined?" do
+ results = check_before_during_thread_after {
+ defined?(ModuleSpecs::Autoload::DuringAutoload)
+ }
+ results.should == ['constant', nil, 'constant', 'constant']
+ end
+
+ it "keeps the constant in Module#constants" do
+ results = check_before_during_thread_after {
+ ModuleSpecs::Autoload.constants(false).include?(:DuringAutoload)
+ }
+ results.should == [true, true, true, true]
+ end
+
+ it "returns false in autoload thread and true otherwise for Module#const_defined?" do
+ results = check_before_during_thread_after {
+ ModuleSpecs::Autoload.const_defined?(:DuringAutoload, false)
+ }
+ results.should == [true, false, true, true]
+ end
+
+ it "returns nil in autoload thread and returns the path in other threads for Module#autoload?" do
+ results = check_before_during_thread_after {
+ ModuleSpecs::Autoload.autoload?(:DuringAutoload)
+ }
+ results.should == [@path, nil, @path, nil]
end
- ModuleSpecs::Autoload::Q.should have_constant(:R)
end
- it "does not remove the constant from the constant table if load fails" do
+ it "does not remove the constant from Module#constants if load fails and keeps it as an autoload" do
ModuleSpecs::Autoload.autoload :Fail, @non_existent
+
+ ModuleSpecs::Autoload.const_defined?(:Fail).should == true
ModuleSpecs::Autoload.should have_constant(:Fail)
+ ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
lambda { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
+
ModuleSpecs::Autoload.should have_constant(:Fail)
+ ModuleSpecs::Autoload.const_defined?(:Fail).should == true
+ ModuleSpecs::Autoload.autoload?(:Fail).should == @non_existent
+
+ lambda { ModuleSpecs::Autoload::Fail }.should raise_error(LoadError)
end
- it "does not remove the constant from the constant table if the loaded files does not define it" do
- ModuleSpecs::Autoload.autoload :O, fixture(__FILE__, "autoload_o.rb")
+ it "does not remove the constant from Module#constants if load raises a RuntimeError and keeps it as an autoload" do
+ path = fixture(__FILE__, "autoload_raise.rb")
+ ScratchPad.record []
+ ModuleSpecs::Autoload.autoload :Raise, path
+
+ ModuleSpecs::Autoload.const_defined?(:Raise).should == true
+ ModuleSpecs::Autoload.should have_constant(:Raise)
+ ModuleSpecs::Autoload.autoload?(:Raise).should == path
+
+ lambda { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
+ ScratchPad.recorded.should == [:raise]
+
+ ModuleSpecs::Autoload.should have_constant(:Raise)
+ ModuleSpecs::Autoload.const_defined?(:Raise).should == true
+ ModuleSpecs::Autoload.autoload?(:Raise).should == path
+
+ lambda { ModuleSpecs::Autoload::Raise }.should raise_error(RuntimeError)
+ ScratchPad.recorded.should == [:raise, :raise]
+ end
+
+ 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
lambda { ModuleSpecs::Autoload::O }.should raise_error(NameError)
+
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
+ path = fixture(__FILE__, "autoload_o.rb")
+ ScratchPad.record []
+ ModuleSpecs::Autoload.autoload :NotDefinedByFile, path
+
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ ScratchPad.recorded.should == [:loaded]
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ ScratchPad.recorded.should == [:loaded]
+
+ Thread.new {
+ -> { ModuleSpecs::Autoload::NotDefinedByFile }.should raise_error(NameError)
+ }.join
+ ScratchPad.recorded.should == [:loaded]
end
it "returns 'constant' on referring the constant with defined?()" do
@@ -216,7 +365,6 @@ describe "Module#autoload" do
end
it "loads the file that defines subclass XX::YY < YY and YY is a top level constant" do
-
module ModuleSpecs::Autoload::XX
autoload :YY, fixture(__FILE__, "autoload_subclass.rb")
end
@@ -224,30 +372,130 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::XX::YY.superclass.should == YY
end
+ describe "after autoloading searches for the constant like the original lookup" do
+ it "in lexical scopes if both declared and defined in parent" do
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ DeclaredAndDefinedInParent = :declared_and_defined_in_parent
+ }
+ autoload :DeclaredAndDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ class LexicalScope
+ DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
- it "looks up the constant in the scope where it is referred" do
- module ModuleSpecs
- module Autoload
- autoload :QQ, fixture(__FILE__, "autoload_scope.rb")
- class PP
- QQ.new.should be_kind_of(ModuleSpecs::Autoload::PP::QQ)
+ # The constant is really in Autoload, not Autoload::LexicalScope
+ self.should_not have_constant(:DeclaredAndDefinedInParent)
+ -> { const_get(:DeclaredAndDefinedInParent) }.should raise_error(NameError)
end
+ DeclaredAndDefinedInParent.should == :declared_and_defined_in_parent
end
end
- end
- it "looks up the constant when in a meta class scope" do
- module ModuleSpecs
- module Autoload
- autoload :R, fixture(__FILE__, "autoload_r.rb")
+ it "in lexical scopes if declared in parent and defined in current" do
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ class LexicalScope
+ DeclaredInParentDefinedInCurrent = :declared_in_parent_defined_in_current
+ end
+ }
+ autoload :DeclaredInParentDefinedInCurrent, fixture(__FILE__, "autoload_callback.rb")
+
+ class LexicalScope
+ DeclaredInParentDefinedInCurrent.should == :declared_in_parent_defined_in_current
+ LexicalScope::DeclaredInParentDefinedInCurrent.should == :declared_in_parent_defined_in_current
+ end
+
+ # 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
+
+ it "and fails when finding the undefined autoload constant in the the current scope when declared in current and defined in parent" do
+ 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
+ end
+
+ it "in the included modules" do
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ module DefinedInIncludedModule
+ Incl = :defined_in_included_module
+ end
+ include DefinedInIncludedModule
+ }
+ autoload :Incl, fixture(__FILE__, "autoload_callback.rb")
+ Incl.should == :defined_in_included_module
+ end
+ end
+
+ it "in the included modules of the superclass" do
+ module ModuleSpecs::Autoload
+ class LookupAfterAutoloadSuper
+ end
+ class LookupAfterAutoloadChild < LookupAfterAutoloadSuper
+ end
+
+ ScratchPad.record -> {
+ module DefinedInSuperclassIncludedModule
+ InclS = :defined_in_superclass_included_module
+ end
+ LookupAfterAutoloadSuper.include DefinedInSuperclassIncludedModule
+ }
+
+ class LookupAfterAutoloadChild
+ autoload :InclS, fixture(__FILE__, "autoload_callback.rb")
+ InclS.should == :defined_in_superclass_included_module
+ end
+ end
+ end
+
+ it "in the prepended modules" do
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ module DefinedInPrependedModule
+ Prep = :defined_in_prepended_module
+ end
+ include DefinedInPrependedModule
+ }
+ autoload :Prep, fixture(__FILE__, "autoload_callback.rb")
+ Prep.should == :defined_in_prepended_module
+ end
+ end
+
+ it "in a meta class scope" do
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ class MetaScope
+ end
+ }
+ autoload :MetaScope, fixture(__FILE__, "autoload_callback.rb")
class << self
def r
- R.new
+ MetaScope.new
end
end
end
+ ModuleSpecs::Autoload.r.should be_kind_of(ModuleSpecs::Autoload::MetaScope)
end
- ModuleSpecs::Autoload.r.should be_kind_of(ModuleSpecs::Autoload::R)
end
# [ruby-core:19127] [ruby-core:29941]
@@ -266,6 +514,21 @@ describe "Module#autoload" do
ModuleSpecs::Autoload::W.send(:remove_const, :Y)
end
+ it "does not call #require a second time and does not warn if already loading the same feature with #require" do
+ main = TOPLEVEL_BINDING.eval("self")
+ main.should_not_receive(:require)
+
+ module ModuleSpecs::Autoload
+ autoload :AutoloadDuringRequire, fixture(__FILE__, "autoload_during_require.rb")
+ end
+
+ -> {
+ $VERBOSE = true
+ Kernel.require fixture(__FILE__, "autoload_during_require.rb")
+ }.should_not complain
+ ModuleSpecs::Autoload::AutoloadDuringRequire.should be_kind_of(Class)
+ end
+
it "calls #to_path on non-string filenames" do
p = mock('path')
p.should_receive(:to_path).and_return @non_existent
diff --git a/spec/ruby/core/module/const_get_spec.rb b/spec/ruby/core/module/const_get_spec.rb
index 74fe94aaed..461b303d6d 100644
--- a/spec/ruby/core/module/const_get_spec.rb
+++ b/spec/ruby/core/module/const_get_spec.rb
@@ -1,5 +1,6 @@
require_relative '../../spec_helper'
require_relative '../../fixtures/constants'
+require_relative 'fixtures/constants_autoload'
describe "Module#const_get" do
it "accepts a String or Symbol name" do
@@ -95,6 +96,10 @@ describe "Module#const_get" do
ConstantSpecs.const_get("ClassA::CS_CONST10").should == :const10_10
end
+ it "raises a NameError if the name includes two successive scope separators" do
+ lambda { ConstantSpecs.const_get("ClassA::::CS_CONST10") }.should raise_error(NameError)
+ end
+
it "raises a NameError if only '::' is passed" do
lambda { ConstantSpecs.const_get("::") }.should raise_error(NameError)
end
@@ -111,6 +116,22 @@ describe "Module#const_get" do
ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
end
+ it 'does autoload a constant' do
+ Object.const_get('CSAutoloadA').name.should == 'CSAutoloadA'
+ end
+
+ it 'does autoload a constant with a toplevel scope qualifier' do
+ Object.const_get('::CSAutoloadB').name.should == 'CSAutoloadB'
+ end
+
+ it 'does autoload a module and resolve a constant within' do
+ Object.const_get('CSAutoloadC::CONST').should == 7
+ end
+
+ it 'does autoload a non-toplevel module' do
+ Object.const_get('CSAutoloadD::InnerModule').name.should == 'CSAutoloadD::InnerModule'
+ end
+
describe "with statically assigned constants" do
it "searches the immediate class or module first" do
ConstantSpecs::ClassA.const_get(:CS_CONST10).should == :const10_10
diff --git a/spec/ruby/core/module/fixtures/autoload_callback.rb b/spec/ruby/core/module/fixtures/autoload_callback.rb
new file mode 100644
index 0000000000..51d53eb580
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_callback.rb
@@ -0,0 +1,2 @@
+block = ScratchPad.recorded
+block.call
diff --git a/spec/ruby/core/module/fixtures/autoload_during_autoload.rb b/spec/ruby/core/module/fixtures/autoload_during_autoload.rb
new file mode 100644
index 0000000000..5202bd8b23
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_during_autoload.rb
@@ -0,0 +1,7 @@
+block = ScratchPad.recorded
+ScratchPad.record(block.call)
+
+module ModuleSpecs::Autoload
+ class DuringAutoload
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_during_require.rb b/spec/ruby/core/module/fixtures/autoload_during_require.rb
new file mode 100644
index 0000000000..6fd81592e3
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_during_require.rb
@@ -0,0 +1,4 @@
+module ModuleSpecs::Autoload
+ class AutoloadDuringRequire
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_exception.rb b/spec/ruby/core/module/fixtures/autoload_exception.rb
new file mode 100644
index 0000000000..09acf9f537
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_exception.rb
@@ -0,0 +1,3 @@
+ScratchPad.record(:exception)
+
+raise 'intentional error to test failure conditions during autoloading'
diff --git a/spec/ruby/core/module/fixtures/autoload_nested.rb b/spec/ruby/core/module/fixtures/autoload_nested.rb
new file mode 100644
index 0000000000..073cec0dce
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_nested.rb
@@ -0,0 +1,8 @@
+module ModuleSpecs::Autoload
+ module GoodParent
+ class Nested
+ end
+ end
+end
+
+ScratchPad.record(:loaded)
diff --git a/spec/ruby/core/module/fixtures/autoload_o.rb b/spec/ruby/core/module/fixtures/autoload_o.rb
index 6d54ddaf12..7d88f969b2 100644
--- a/spec/ruby/core/module/fixtures/autoload_o.rb
+++ b/spec/ruby/core/module/fixtures/autoload_o.rb
@@ -1 +1,2 @@
# does not define ModuleSpecs::Autoload::O
+ScratchPad << :loaded
diff --git a/spec/ruby/core/module/fixtures/autoload_raise.rb b/spec/ruby/core/module/fixtures/autoload_raise.rb
new file mode 100644
index 0000000000..f6051e3ba2
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_raise.rb
@@ -0,0 +1,2 @@
+ScratchPad << :raise
+raise "exception during autoload"
diff --git a/spec/ruby/core/module/fixtures/autoload_scope.rb b/spec/ruby/core/module/fixtures/autoload_scope.rb
deleted file mode 100644
index 04193687b5..0000000000
--- a/spec/ruby/core/module/fixtures/autoload_scope.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-module ModuleSpecs
- module Autoload
- class PP
- class QQ
- end
- end
- end
-end
diff --git a/spec/ruby/core/module/fixtures/constants_autoload.rb b/spec/ruby/core/module/fixtures/constants_autoload.rb
new file mode 100644
index 0000000000..8e9aa8de0c
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/constants_autoload.rb
@@ -0,0 +1,6 @@
+autoload :CSAutoloadA, fixture(__FILE__, 'constants_autoload_a.rb')
+autoload :CSAutoloadB, fixture(__FILE__, 'constants_autoload_b.rb')
+autoload :CSAutoloadC, fixture(__FILE__, 'constants_autoload_c.rb')
+module CSAutoloadD
+ autoload :InnerModule, fixture(__FILE__, 'constants_autoload_d.rb')
+end
diff --git a/spec/ruby/core/module/fixtures/constants_autoload_a.rb b/spec/ruby/core/module/fixtures/constants_autoload_a.rb
new file mode 100644
index 0000000000..48d3b63681
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/constants_autoload_a.rb
@@ -0,0 +1,2 @@
+module CSAutoloadA
+end
diff --git a/spec/ruby/core/module/fixtures/constants_autoload_b.rb b/spec/ruby/core/module/fixtures/constants_autoload_b.rb
new file mode 100644
index 0000000000..29cd742d03
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/constants_autoload_b.rb
@@ -0,0 +1,2 @@
+module CSAutoloadB
+end
diff --git a/spec/ruby/core/module/fixtures/constants_autoload_c.rb b/spec/ruby/core/module/fixtures/constants_autoload_c.rb
new file mode 100644
index 0000000000..9d6a6bf4d7
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/constants_autoload_c.rb
@@ -0,0 +1,3 @@
+module CSAutoloadC
+ CONST = 7
+end
diff --git a/spec/ruby/core/module/fixtures/constants_autoload_d.rb b/spec/ruby/core/module/fixtures/constants_autoload_d.rb
new file mode 100644
index 0000000000..52d550bab0
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/constants_autoload_d.rb
@@ -0,0 +1,4 @@
+module CSAutoloadD
+ module InnerModule
+ end
+end
diff --git a/spec/ruby/core/module/initialize_copy_spec.rb b/spec/ruby/core/module/initialize_copy_spec.rb
index 412f1c511b..7ae48f85a9 100644
--- a/spec/ruby/core/module/initialize_copy_spec.rb
+++ b/spec/ruby/core/module/initialize_copy_spec.rb
@@ -7,4 +7,12 @@ describe "Module#initialize_copy" do
end
mod.dup.methods(false).should == [:hello]
end
+
+ # jruby/jruby#5245, https://bugs.ruby-lang.org/issues/3461
+ it "should produce a duped module with inspectable class methods" do
+ mod = Module.new
+ def mod.hello
+ end
+ mod.dup.method(:hello).inspect.should =~ /Module.*hello/
+ end
end
diff --git a/spec/ruby/core/signal/fixtures/trap_all.rb b/spec/ruby/core/signal/fixtures/trap_all.rb
new file mode 100644
index 0000000000..b2e85df247
--- /dev/null
+++ b/spec/ruby/core/signal/fixtures/trap_all.rb
@@ -0,0 +1,8 @@
+reserved_signals = ARGV
+
+(Signal.list.keys - reserved_signals).each do |signal|
+ Signal.trap(signal, -> {})
+ Signal.trap(signal, "DEFAULT")
+end
+
+puts "OK"
diff --git a/spec/ruby/core/signal/trap_spec.rb b/spec/ruby/core/signal/trap_spec.rb
index d621b6ae6d..66101ee5a0 100644
--- a/spec/ruby/core/signal/trap_spec.rb
+++ b/spec/ruby/core/signal/trap_spec.rb
@@ -115,6 +115,49 @@ platform_is_not :windows do
end
describe "Signal.trap" do
+ cannot_be_trapped = %w[KILL STOP] # See man 2 signal
+ reserved_signals = %w[VTALRM]
+
+ if PlatformGuard.implementation?(:ruby)
+ reserved_signals += %w[SEGV ILL FPE BUS]
+ end
+
+ if PlatformGuard.implementation?(:truffleruby)
+ if !TruffleRuby.native?
+ reserved_signals += %w[SEGV ILL FPE USR1 QUIT]
+ end
+ end
+
+ if PlatformGuard.implementation?(:jruby)
+ reserved_signals += %w[SEGV ILL FPE BUS USR1 QUIT]
+ end
+
+ cannot_be_trapped.each do |signal|
+ it "raises ArgumentError or Errno::EINVAL for SIG#{signal}" do
+ -> {
+ trap(signal, -> {})
+ }.should raise_error(StandardError) { |e|
+ [ArgumentError, Errno::EINVAL].should include(e.class)
+ e.message.should =~ /Invalid argument|Signal already used by VM or OS/
+ }
+ end
+ end
+
+ reserved_signals.each do |signal|
+ it "raises ArgumentError for reserved signal SIG#{signal}" do
+ -> {
+ trap(signal, -> {})
+ }.should raise_error(ArgumentError, /can't trap reserved signal|Signal already used by VM or OS/)
+ end
+ end
+
+ it "allows to register a handler for all known signals, except reserved signals" do
+ excluded = cannot_be_trapped + reserved_signals
+ out = ruby_exe(fixture(__FILE__, "trap_all.rb"), args: [*excluded, "2>&1"])
+ out.should == "OK\n"
+ $?.exitstatus.should == 0
+ end
+
it "returns SYSTEM_DEFAULT if passed DEFAULT and no handler was ever set" do
Signal.trap("PROF", "DEFAULT").should == "SYSTEM_DEFAULT"
end
diff --git a/spec/ruby/core/string/force_encoding_spec.rb b/spec/ruby/core/string/force_encoding_spec.rb
index c317c84c1f..06e04b8d95 100644
--- a/spec/ruby/core/string/force_encoding_spec.rb
+++ b/spec/ruby/core/string/force_encoding_spec.rb
@@ -6,6 +6,26 @@ with_feature :encoding do
"abc".force_encoding('shift_jis').encoding.should == Encoding::Shift_JIS
end
+ describe "with a special encoding name" do
+ before :each do
+ @original_encoding = Encoding.default_internal
+ end
+
+ after :each do
+ Encoding.default_internal = @original_encoding
+ end
+
+ it "accepts valid special encoding names" do
+ Encoding.default_internal = "US-ASCII"
+ "abc".force_encoding("internal").encoding.should == Encoding::US_ASCII
+ end
+
+ it "defaults to ASCII-8BIT if special encoding name is not set" do
+ Encoding.default_internal = nil
+ "abc".force_encoding("internal").encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+
it "accepts an Encoding instance" do
"abc".force_encoding(Encoding::SHIFT_JIS).encoding.should == Encoding::Shift_JIS
end
diff --git a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
index aeae6b77c6..5bd97442d9 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -9,4 +9,42 @@ describe 'Thread::Backtrace::Location#absolute_path' do
it 'returns the absolute path of the call frame' do
@frame.absolute_path.should == File.realpath(__FILE__)
end
+
+ context "when used in eval with a given filename" do
+ it "returns filename" do
+ code = "caller_locations(0)[0].absolute_path"
+ eval(code, nil, "foo.rb").should == "foo.rb"
+ eval(code, nil, "foo/bar.rb").should == "foo/bar.rb"
+ end
+ end
+
+ platform_is_not :windows do
+ before :each do
+ @file = fixture(__FILE__, "absolute_path.rb")
+ @symlink = tmp("symlink.rb")
+ File.symlink(@file, @symlink)
+ ScratchPad.record []
+ end
+
+ after :each do
+ rm_r @symlink
+ end
+
+ it "returns a canonical path without symlinks, even when __FILE__ does not" do
+ realpath = File.realpath(@symlink)
+ realpath.should_not == @symlink
+
+ load @symlink
+ ScratchPad.recorded.should == [@symlink, realpath]
+ end
+
+ it "returns a canonical path without symlinks, even when __FILE__ is removed" do
+ realpath = File.realpath(@symlink)
+ realpath.should_not == @symlink
+
+ ScratchPad << -> { rm_r(@symlink) }
+ load @symlink
+ ScratchPad.recorded.should == [@symlink, realpath]
+ end
+ end
end
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path.rb b/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path.rb
new file mode 100644
index 0000000000..875e97ffac
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path.rb
@@ -0,0 +1,4 @@
+action = ScratchPad.recorded.pop
+ScratchPad << __FILE__
+action.call if action
+ScratchPad << caller_locations(0)[0].absolute_path
diff --git a/spec/ruby/core/time/localtime_spec.rb b/spec/ruby/core/time/localtime_spec.rb
index 5592150ca2..7942653c78 100644
--- a/spec/ruby/core/time/localtime_spec.rb
+++ b/spec/ruby/core/time/localtime_spec.rb
@@ -93,7 +93,7 @@ describe "Time#localtime" do
it "does nothing if already in a local time zone" do
time = with_timezone("America/New_York") do
- break Time.new(2005, 2, 27, 22, 50, 0)
+ Time.new(2005, 2, 27, 22, 50, 0)
end
zone = time.zone