1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67361 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
eregon 2019-03-28 14:22:29 +00:00
parent 0f64776745
commit a28aa80c73
53 changed files with 932 additions and 106 deletions

View file

@ -16,17 +16,28 @@ end
describe "Module#autoload" do
before :all do
@non_existent = fixture __FILE__, "no_autoload.rb"
# Require RubyGems eagerly, to ensure #require is already the RubyGems
# version, before starting #autoload specs which snapshot #require, and
# could end up redefining #require as the original core Kernel#require.
begin
require "rubygems"
rescue LoadError
end
end
before :each do
@loaded_features = $".dup
@frozen_module = Module.new.freeze
ScratchPad.clear
@remove = []
end
after :each do
$".replace @loaded_features
@remove.each { |const|
ModuleSpecs::Autoload.send :remove_const, const
}
end
it "registers a file to load the first time the named constant is accessed" do
@ -39,16 +50,29 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.should have_constant(:B)
end
it "can be overridden with a second autoload on the same constant" do
ModuleSpecs::Autoload.autoload :Overridden, @non_existent
@remove << :Overridden
ModuleSpecs::Autoload.autoload?(:Overridden).should == @non_existent
path = fixture(__FILE__, "autoload_overridden.rb")
ModuleSpecs::Autoload.autoload :Overridden, path
ModuleSpecs::Autoload.autoload?(:Overridden).should == path
ModuleSpecs::Autoload::Overridden.should == :overridden
end
it "loads the registered constant when it is accessed" do
ModuleSpecs::Autoload.should_not have_constant(:X)
ModuleSpecs::Autoload.autoload :X, fixture(__FILE__, "autoload_x.rb")
@remove << :X
ModuleSpecs::Autoload::X.should == :x
ModuleSpecs::Autoload.send(:remove_const, :X)
end
it "loads the registered constant into a dynamically created class" do
cls = Class.new { autoload :C, fixture(__FILE__, "autoload_c.rb") }
ModuleSpecs::Autoload::DynClass = cls
@remove << :DynClass
ScratchPad.recorded.should be_nil
ModuleSpecs::Autoload::DynClass::C.new.loaded.should == :dynclass_c
@ -58,6 +82,7 @@ describe "Module#autoload" do
it "loads the registered constant into a dynamically created module" do
mod = Module.new { autoload :D, fixture(__FILE__, "autoload_d.rb") }
ModuleSpecs::Autoload::DynModule = mod
@remove << :DynModule
ScratchPad.recorded.should be_nil
ModuleSpecs::Autoload::DynModule::D.new.loaded.should == :dynmodule_d
@ -95,6 +120,7 @@ describe "Module#autoload" do
it "does not load the file when the constant is already set" do
ModuleSpecs::Autoload.autoload :I, fixture(__FILE__, "autoload_i.rb")
@remove << :I
ModuleSpecs::Autoload.const_set :I, 3
ModuleSpecs::Autoload::I.should == 3
ScratchPad.recorded.should be_nil
@ -116,6 +142,7 @@ describe "Module#autoload" do
it "does not load the file if the file is manually required" do
filename = fixture(__FILE__, "autoload_k.rb")
ModuleSpecs::Autoload.autoload :KHash, filename
@remove << :KHash
require filename
ScratchPad.recorded.should == :loaded
@ -135,8 +162,8 @@ describe "Module#autoload" do
ScratchPad.clear
ModuleSpecs::Autoload.autoload :S, filename
@remove << :S
ModuleSpecs::Autoload.autoload?(:S).should be_nil
ModuleSpecs::Autoload.send(:remove_const, :S)
end
it "retains the autoload even if the request to require fails" do
@ -182,11 +209,10 @@ describe "Module#autoload" do
module ModuleSpecs::Autoload
autoload :GoodParent, fixture(__FILE__, "autoload_nested.rb")
end
@remove << :GoodParent
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
@ -199,11 +225,12 @@ describe "Module#autoload" do
end
end
describe "the autoload is removed when the same file is required directly without autoload" do
describe "the autoload is triggered when the same file is required directly" do
before :each do
module ModuleSpecs::Autoload
autoload :RequiredDirectly, fixture(__FILE__, "autoload_required_directly.rb")
end
@remove << :RequiredDirectly
@path = fixture(__FILE__, "autoload_required_directly.rb")
@check = -> {
[
@ -214,10 +241,6 @@ describe "Module#autoload" do
ScratchPad.record @check
end
after :each do
ModuleSpecs::Autoload.send(:remove_const, :RequiredDirectly)
end
it "with a full path" do
@check.call.should == ["constant", @path]
require @path
@ -242,7 +265,7 @@ describe "Module#autoload" do
nested_require = -> {
result = nil
ScratchPad.record -> {
result = [@check.call, Thread.new { @check.call }.value]
result = @check.call
}
require nested
result
@ -251,24 +274,41 @@ describe "Module#autoload" do
@check.call.should == ["constant", @path]
require @path
cur, other = ScratchPad.recorded
cur.should == [nil, nil]
other.should == [nil, nil]
ScratchPad.recorded.should == [nil, nil]
@check.call.should == ["constant", nil]
end
end
describe "after the autoload is triggered by require" do
before :each do
@path = tmp("autoload.rb")
end
after :each do
rm_r @path
end
it "the mapping feature to autoload is removed, and a new autoload with the same path is considered" do
ModuleSpecs::Autoload.autoload :RequireMapping1, @path
touch(@path) { |f| f.puts "ModuleSpecs::Autoload::RequireMapping1 = 1" }
ModuleSpecs::Autoload::RequireMapping1.should == 1
$LOADED_FEATURES.delete(@path)
ModuleSpecs::Autoload.autoload :RequireMapping2, @path[0...-3]
@remove << :RequireMapping2
touch(@path) { |f| f.puts "ModuleSpecs::Autoload::RequireMapping2 = 2" }
ModuleSpecs::Autoload::RequireMapping2.should == 2
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
@remove << :DuringAutoload
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
@ -419,6 +459,7 @@ describe "Module#autoload" do
X = get_value
end
end
@remove << :U
ModuleSpecs::Autoload::U::V::X.should == :autoload_uvx
end
@ -474,6 +515,7 @@ describe "Module#autoload" do
end
it "and fails when finding the undefined autoload constant in the the current scope when declared in current and defined in parent" do
@remove << :DeclaredInCurrentDefinedInParent
module ModuleSpecs::Autoload
ScratchPad.record -> {
DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
@ -494,6 +536,7 @@ describe "Module#autoload" do
end
it "in the included modules" do
@remove << :DefinedInIncludedModule
module ModuleSpecs::Autoload
ScratchPad.record -> {
module DefinedInIncludedModule
@ -507,6 +550,7 @@ describe "Module#autoload" do
end
it "in the included modules of the superclass" do
@remove << :DefinedInSuperclassIncludedModule
module ModuleSpecs::Autoload
class LookupAfterAutoloadSuper
end
@ -528,6 +572,7 @@ describe "Module#autoload" do
end
it "in the prepended modules" do
@remove << :DefinedInPrependedModule
module ModuleSpecs::Autoload
ScratchPad.record -> {
module DefinedInPrependedModule
@ -567,10 +612,10 @@ describe "Module#autoload" do
end
end
end
@remove << :W
ModuleSpecs::Autoload::W::Y.should be_kind_of(Class)
ScratchPad.recorded.should == :loaded
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
@ -611,6 +656,7 @@ describe "Module#autoload" do
it "shares the autoload request across dup'ed copies of modules" do
require fixture(__FILE__, "autoload_s.rb")
@remove << :S
filename = fixture(__FILE__, "autoload_t.rb")
mod1 = Module.new { autoload :T, filename }
lambda {
@ -651,8 +697,9 @@ describe "Module#autoload" do
describe "on a frozen module" do
it "raises a #{frozen_error_class} before setting the name" do
lambda { @frozen_module.autoload :Foo, @non_existent }.should raise_error(frozen_error_class)
@frozen_module.should_not have_constant(:Foo)
frozen_module = Module.new.freeze
lambda { frozen_module.autoload :Foo, @non_existent }.should raise_error(frozen_error_class)
frozen_module.should_not have_constant(:Foo)
end
end
@ -675,6 +722,7 @@ describe "Module#autoload" do
describe "(concurrently)" do
it "blocks a second thread while a first is doing the autoload" do
ModuleSpecs::Autoload.autoload :Concur, fixture(__FILE__, "autoload_concur.rb")
@remove << :Concur
start = false
@ -717,8 +765,6 @@ describe "Module#autoload" do
t2_val.should == t1_val
t2_exc.should be_nil
ModuleSpecs::Autoload.send(:remove_const, :Concur)
end
# https://bugs.ruby-lang.org/issues/10892