Add specs for Mutator::Registry and simplify it

This commit is contained in:
Markus Schirp 2014-11-17 17:05:02 +00:00
parent f3720a6366
commit 9623cd27ab
6 changed files with 83 additions and 65 deletions

View file

@ -1,3 +1,3 @@
---
threshold: 18
total_score: 1126
total_score: 1121

View file

@ -16,7 +16,7 @@ module Mutant
#
def self.each(input, parent = nil, &block)
return to_enum(__method__, input, parent) unless block_given?
Registry.lookup(input).new(input, parent, block)
REGISTRY.lookup(input).new(input, parent, block)
self
end
@ -29,7 +29,7 @@ module Mutant
#
def self.handle(*types)
types.each do |type|
Registry.register(type, self)
REGISTRY.register(type, self)
end
end
private_class_method :handle

View file

@ -1,27 +1,34 @@
module Mutant
class Mutator
# Registry for mutators
module Registry
class Registry
# Initialize object
#
# @return [undefined]
#
# @api private
#
def initialize
@registry = {}
end
# Raised when the type is an invalid type
InvalidTypeError = Class.new(TypeError)
# Raised when the type is a duplicate
DuplicateTypeError = Class.new(ArgumentError)
RegistryError = Class.new(TypeError)
# Register mutator class for AST node class
#
# @param [Symbol] type
# @param [Class] mutator_class
# @param [Class:Mutator] mutator
#
# @api private
#
# @return [self]
#
def self.register(type, mutator_class)
assert_valid_type(type)
assert_unique_type(type)
registry[type] = mutator_class
def register(type, mutator)
fail RegistryError, "Invalid type registration: #{type}" unless AST::Types::ALL.include?(type)
fail RegistryError, "Duplicate type registration: #{type}" if @registry.key?(type)
@registry[type] = mutator
self
end
@ -36,58 +43,16 @@ module Mutant
#
# @api private
#
def self.lookup(node)
def lookup(node)
type = node.type
registry.fetch(type) do
fail ArgumentError, "No mutator to handle: #{type.inspect}"
@registry.fetch(type) do
fail RegistryError, "No mutator to handle: #{type.inspect}"
end
end
# Return registry state
#
# @return [Hash]
#
# @api private
#
def self.registry
@registry ||= {}
end
private_class_method :registry
# Assert the node type is valid
#
# @param [Symbol] type
#
# @return [undefined]
#
# @raise [InvalidTypeError]
# raised when the node type is invalid
#
# @api private
#
def self.assert_valid_type(type)
unless AST::Types::ALL.include?(type) || type.is_a?(Class)
fail InvalidTypeError, "invalid type registration: #{type}"
end
end
private_class_method :assert_valid_type
# Assert the node type is unique and not already registered
#
# @return [undefined]
#
# @raise [DuplicateTypeError]
# raised when the node type is a duplicate
#
# @api private
#
def self.assert_unique_type(type)
if registry.key?(type)
fail DuplicateTypeError, "duplicate type registration: #{type}"
end
end
private_class_method :assert_unique_type
end # Registry
REGISTRY = Registry.new
end # Mutator
end # Mutant

View file

@ -5,8 +5,6 @@ module Mutant
# Mutators that mutates an array of inputs
class Array < self
handle(::Array)
# Element presence mutator
class Presence < Util

View file

@ -5,8 +5,6 @@ module Mutant
# Utility symbol mutator
class Symbol < self
handle(::Symbol)
POSTFIX = '__mutant__'.freeze
private

View file

@ -0,0 +1,57 @@
RSpec.describe Mutant::Mutator::Registry do
describe '#lookup' do
subject { Mutant::Mutator::REGISTRY.lookup(node) }
context 'on registred node' do
let(:node) { s(:true) }
it { should eql(Mutant::Mutator::Node::Literal::Boolean) }
end
context 'on unknown node' do
let(:node) { s(:unknown) }
it 'raises error' do
expect { subject }.to raise_error(described_class::RegistryError, "No mutator to handle: :unknown")
end
end
end
describe '#register' do
let(:object) { described_class.new }
let(:mutator) { double('Mutator') }
subject { object.register(type, mutator) }
context 'when registring an invalid node type' do
let(:type) { :invalid }
it 'raises error' do
expect { subject }.to raise_error(described_class::RegistryError, 'Invalid type registration: invalid')
end
end
context 'when registring a valid node type' do
let(:type) { :true }
it 'allows to lookup mutator' do
subject
expect(object.lookup(s(type))).to be(mutator)
end
it_behaves_like 'a command method'
end
context 'when duplicate the registration of a valid node type' do
let(:type) { :true }
it 'allows to lookup mutator' do
object.register(type, mutator)
expect { subject }.to raise_error(described_class::RegistryError, 'Duplicate type registration: true')
end
it_behaves_like 'a command method'
end
end
end