free_mutant/spec/support/ruby_vm.rb
Markus Schirp 7e670bafaa 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
2016-01-24 21:08:56 +00:00

82 lines
2.1 KiB
Ruby

module MutantSpec
# Not a real VM, just kidding. It connects the require / eval triggers
# require semantics Zombifier relies on in a way we can avoid having to
# mock around everywhere to test every detail.
class RubyVM
include Concord::Public.new(:expected_events)
# An event being observed by the VM handlers
class EventObservation
include Concord::Public.new(:type, :payload)
end
# An event being expected, can advance the VM
class EventExpectation
include AbstractType, Anima.new(
:expected_payload,
:trigger_requires,
:return_value
)
DEFAULTS = IceNine.deep_freeze(trigger_requires: [])
def initialize(attributes)
super(DEFAULTS.merge(attributes))
end
def handle(vm, observation)
unless match?(observation)
fail "Unexpected event observation: #{observation.inspect}, expected #{inspect}"
end
trigger_requires.each(&vm.method(:require))
self
end
private
def match?(observation)
observation.type.eql?(self.class) && observation.payload.eql?(expected_payload)
end
# Expectation and advance on require calls
class Require < self
end
# Expectation and advance on eval calls
class Eval < self
end
end
# A fake implementation of Kernel#require
def require(logical_name)
handle_event(EventObservation.new(EventExpectation::Require, logical_name: logical_name))
end
# A fake implementation of Kernel#eval
def eval(source, binding, location)
handle_event(
EventObservation.new(
EventExpectation::Eval,
binding: binding,
source: source,
source_location: location
)
)
end
# Test if VM events where fully processed
def done?
expected_events.empty?
end
private
def handle_event(observation)
fail "Unexpected event: #{observation.type} / #{observation.payload}" if expected_events.empty?
expected_events.slice!(0).handle(self, observation).return_value
end
end
end # MutantSpec