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
|
||||
total_score: 1171
|
||||
total_score: 1167
|
||||
|
|
|
@ -57,13 +57,15 @@ module Mutant
|
|||
#
|
||||
# @param [#to_s] logical_name
|
||||
#
|
||||
# @return [undefined]
|
||||
# @return [Bool]
|
||||
# true if successful and false if feature already loaded
|
||||
def require(logical_name)
|
||||
logical_name = logical_name.to_s
|
||||
@original.call(logical_name)
|
||||
return unless include?(logical_name)
|
||||
loaded = @original.call(logical_name)
|
||||
return loaded unless include?(logical_name)
|
||||
@zombified << logical_name
|
||||
zombify(find(logical_name))
|
||||
true
|
||||
end
|
||||
|
||||
# Find file by logical path
|
||||
|
|
|
@ -3,7 +3,7 @@ module MutantSpec
|
|||
# require semantics Zombifier relies on in a way we can avoid having to
|
||||
# mock around everywhere to test every detail.
|
||||
class RubyVM
|
||||
include Concord.new(:expected_events)
|
||||
include Concord::Public.new(:expected_events)
|
||||
|
||||
# An event being observed by the VM handlers
|
||||
class EventObservation
|
||||
|
@ -14,7 +14,8 @@ module MutantSpec
|
|||
class EventExpectation
|
||||
include AbstractType, Anima.new(
|
||||
:expected_payload,
|
||||
:trigger_requires
|
||||
:trigger_requires,
|
||||
:return_value
|
||||
)
|
||||
|
||||
DEFAULTS = IceNine.deep_freeze(trigger_requires: [])
|
||||
|
@ -29,12 +30,12 @@ module MutantSpec
|
|||
end
|
||||
|
||||
trigger_requires.each(&vm.method(:require))
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
abstract_method :advance_vm
|
||||
|
||||
def match?(observation)
|
||||
observation.type.eql?(self.class) && observation.payload.eql?(expected_payload)
|
||||
end
|
||||
|
@ -51,7 +52,6 @@ module MutantSpec
|
|||
# A fake implementation of Kernel#require
|
||||
def require(logical_name)
|
||||
handle_event(EventObservation.new(EventExpectation::Require, logical_name: logical_name))
|
||||
self
|
||||
end
|
||||
|
||||
# A fake implementation of Kernel#eval
|
||||
|
@ -64,7 +64,6 @@ module MutantSpec
|
|||
source_location: location
|
||||
)
|
||||
)
|
||||
self
|
||||
end
|
||||
|
||||
# Test if VM events where fully processed
|
||||
|
@ -77,7 +76,7 @@ module MutantSpec
|
|||
def handle_event(observation)
|
||||
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 # MutantSpec
|
||||
|
|
|
@ -5,7 +5,10 @@ RSpec.describe Mutant::Zombifier do
|
|||
let(:require_highjack) do
|
||||
lambda do |block|
|
||||
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
|
||||
end
|
||||
end
|
||||
|
@ -28,7 +31,8 @@ RSpec.describe Mutant::Zombifier do
|
|||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||
expected_payload: {
|
||||
logical_name: 'project'
|
||||
}
|
||||
},
|
||||
return_value: true
|
||||
),
|
||||
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
||||
expected_payload: {
|
||||
|
@ -36,18 +40,21 @@ RSpec.describe Mutant::Zombifier do
|
|||
source: "module Zombie\n module Project\n end\nend",
|
||||
source_location: 'a/project.rb'
|
||||
},
|
||||
trigger_requires: %w[foo bar]
|
||||
trigger_requires: %w[foo bar],
|
||||
return_value: nil
|
||||
),
|
||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||
expected_payload: {
|
||||
logical_name: 'foo'
|
||||
},
|
||||
trigger_requires: %w[bar]
|
||||
trigger_requires: %w[bar],
|
||||
return_value: true
|
||||
),
|
||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||
expected_payload: {
|
||||
logical_name: 'bar'
|
||||
}
|
||||
},
|
||||
return_value: true
|
||||
),
|
||||
MutantSpec::RubyVM::EventExpectation::Eval.new(
|
||||
expected_payload: {
|
||||
|
@ -55,23 +62,19 @@ RSpec.describe Mutant::Zombifier do
|
|||
source: "module Zombie\n module Bar\n end\nend",
|
||||
source_location: 'b/bar.rb'
|
||||
},
|
||||
trigger_requires: %w[]
|
||||
trigger_requires: %w[],
|
||||
return_value: nil
|
||||
),
|
||||
MutantSpec::RubyVM::EventExpectation::Require.new(
|
||||
expected_payload: {
|
||||
logical_name: 'bar'
|
||||
}
|
||||
},
|
||||
return_value: false
|
||||
)
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
let(:require_effects) do
|
||||
{
|
||||
'project' => { requires: [] }
|
||||
}
|
||||
end
|
||||
|
||||
let(:file_entries) do
|
||||
{
|
||||
'a/project.rb' => { file: true, contents: 'module Project; end' },
|
||||
|
@ -100,7 +103,7 @@ RSpec.describe Mutant::Zombifier do
|
|||
expect(apply).to be(described_class)
|
||||
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)
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue