Fix zombifier require to return loaded flag
* Ruby 2.3 uses Kernel#require to expand autoloads, and autload constant propagation only is done on #require returning true. * The zombifier used to return incorrect falsy/truthy values. * This would never have happened on a static language
This commit is contained in:
parent
d292dc8028
commit
7e670bafaa
4 changed files with 29 additions and 25 deletions
|
@ -1,3 +1,3 @@
|
||||||
---
|
---
|
||||||
threshold: 18
|
threshold: 18
|
||||||
total_score: 1171
|
total_score: 1167
|
||||||
|
|
|
@ -57,13 +57,15 @@ module Mutant
|
||||||
#
|
#
|
||||||
# @param [#to_s] logical_name
|
# @param [#to_s] logical_name
|
||||||
#
|
#
|
||||||
# @return [undefined]
|
# @return [Bool]
|
||||||
|
# true if successful and false if feature already loaded
|
||||||
def require(logical_name)
|
def require(logical_name)
|
||||||
logical_name = logical_name.to_s
|
logical_name = logical_name.to_s
|
||||||
@original.call(logical_name)
|
loaded = @original.call(logical_name)
|
||||||
return unless include?(logical_name)
|
return loaded unless include?(logical_name)
|
||||||
@zombified << logical_name
|
@zombified << logical_name
|
||||||
zombify(find(logical_name))
|
zombify(find(logical_name))
|
||||||
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Find file by logical path
|
# Find file by logical path
|
||||||
|
|
|
@ -3,7 +3,7 @@ module MutantSpec
|
||||||
# require semantics Zombifier relies on in a way we can avoid having to
|
# require semantics Zombifier relies on in a way we can avoid having to
|
||||||
# mock around everywhere to test every detail.
|
# mock around everywhere to test every detail.
|
||||||
class RubyVM
|
class RubyVM
|
||||||
include Concord.new(:expected_events)
|
include Concord::Public.new(:expected_events)
|
||||||
|
|
||||||
# An event being observed by the VM handlers
|
# An event being observed by the VM handlers
|
||||||
class EventObservation
|
class EventObservation
|
||||||
|
@ -14,7 +14,8 @@ module MutantSpec
|
||||||
class EventExpectation
|
class EventExpectation
|
||||||
include AbstractType, Anima.new(
|
include AbstractType, Anima.new(
|
||||||
:expected_payload,
|
:expected_payload,
|
||||||
:trigger_requires
|
:trigger_requires,
|
||||||
|
:return_value
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULTS = IceNine.deep_freeze(trigger_requires: [])
|
DEFAULTS = IceNine.deep_freeze(trigger_requires: [])
|
||||||
|
@ -29,12 +30,12 @@ module MutantSpec
|
||||||
end
|
end
|
||||||
|
|
||||||
trigger_requires.each(&vm.method(:require))
|
trigger_requires.each(&vm.method(:require))
|
||||||
|
|
||||||
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
abstract_method :advance_vm
|
|
||||||
|
|
||||||
def match?(observation)
|
def match?(observation)
|
||||||
observation.type.eql?(self.class) && observation.payload.eql?(expected_payload)
|
observation.type.eql?(self.class) && observation.payload.eql?(expected_payload)
|
||||||
end
|
end
|
||||||
|
@ -51,7 +52,6 @@ module MutantSpec
|
||||||
# A fake implementation of Kernel#require
|
# A fake implementation of Kernel#require
|
||||||
def require(logical_name)
|
def require(logical_name)
|
||||||
handle_event(EventObservation.new(EventExpectation::Require, logical_name: logical_name))
|
handle_event(EventObservation.new(EventExpectation::Require, logical_name: logical_name))
|
||||||
self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# A fake implementation of Kernel#eval
|
# A fake implementation of Kernel#eval
|
||||||
|
@ -64,7 +64,6 @@ module MutantSpec
|
||||||
source_location: location
|
source_location: location
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Test if VM events where fully processed
|
# Test if VM events where fully processed
|
||||||
|
@ -77,7 +76,7 @@ module MutantSpec
|
||||||
def handle_event(observation)
|
def handle_event(observation)
|
||||||
fail "Unexpected event: #{observation.type} / #{observation.payload}" if expected_events.empty?
|
fail "Unexpected event: #{observation.type} / #{observation.payload}" if expected_events.empty?
|
||||||
|
|
||||||
expected_events.slice!(0).handle(self, observation)
|
expected_events.slice!(0).handle(self, observation).return_value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end # MutantSpec
|
end # MutantSpec
|
||||||
|
|
|
@ -5,7 +5,10 @@ RSpec.describe Mutant::Zombifier do
|
||||||
let(:require_highjack) do
|
let(:require_highjack) do
|
||||||
lambda do |block|
|
lambda do |block|
|
||||||
original = ruby_vm.method(:require)
|
original = ruby_vm.method(:require)
|
||||||
allow(ruby_vm).to receive(:require, &block)
|
allow(ruby_vm).to receive(:require) do |argument|
|
||||||
|
return_value = ruby_vm.expected_events.first.return_value
|
||||||
|
expect(block.call(argument)).to be(return_value)
|
||||||
|
end
|
||||||
original
|
original
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -28,7 +31,8 @@ RSpec.describe Mutant::Zombifier do
|
||||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
logical_name: 'project'
|
logical_name: 'project'
|
||||||
}
|
},
|
||||||
|
return_value: true
|
||||||
),
|
),
|
||||||
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
|
@ -36,18 +40,21 @@ RSpec.describe Mutant::Zombifier do
|
||||||
source: "module Zombie\n module Project\n end\nend",
|
source: "module Zombie\n module Project\n end\nend",
|
||||||
source_location: 'a/project.rb'
|
source_location: 'a/project.rb'
|
||||||
},
|
},
|
||||||
trigger_requires: %w[foo bar]
|
trigger_requires: %w[foo bar],
|
||||||
|
return_value: nil
|
||||||
),
|
),
|
||||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
logical_name: 'foo'
|
logical_name: 'foo'
|
||||||
},
|
},
|
||||||
trigger_requires: %w[bar]
|
trigger_requires: %w[bar],
|
||||||
|
return_value: true
|
||||||
),
|
),
|
||||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
logical_name: 'bar'
|
logical_name: 'bar'
|
||||||
}
|
},
|
||||||
|
return_value: true
|
||||||
),
|
),
|
||||||
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
|
@ -55,23 +62,19 @@ RSpec.describe Mutant::Zombifier do
|
||||||
source: "module Zombie\n module Bar\n end\nend",
|
source: "module Zombie\n module Bar\n end\nend",
|
||||||
source_location: 'b/bar.rb'
|
source_location: 'b/bar.rb'
|
||||||
},
|
},
|
||||||
trigger_requires: %w[]
|
trigger_requires: %w[],
|
||||||
|
return_value: nil
|
||||||
),
|
),
|
||||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||||
expected_payload: {
|
expected_payload: {
|
||||||
logical_name: 'bar'
|
logical_name: 'bar'
|
||||||
}
|
},
|
||||||
|
return_value: false
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:require_effects) do
|
|
||||||
{
|
|
||||||
'project' => { requires: [] }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:file_entries) do
|
let(:file_entries) do
|
||||||
{
|
{
|
||||||
'a/project.rb' => { file: true, contents: 'module Project; end' },
|
'a/project.rb' => { file: true, contents: 'module Project; end' },
|
||||||
|
@ -100,7 +103,7 @@ RSpec.describe Mutant::Zombifier do
|
||||||
expect(apply).to be(described_class)
|
expect(apply).to be(described_class)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'consumes walks the VM through expected steps' do
|
it 'walks the VM through expected steps' do
|
||||||
expect { apply }.to change(ruby_vm, :done?).from(false).to(true)
|
expect { apply }.to change(ruby_vm, :done?).from(false).to(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue