Guard against the generation of equal mutants
* Move Mutant::Mutator::Generator in a dedicated file * Mutant::Mutator::Generator#append only forwards mutated node when it does not equal original nodes sexpession. This does not catch equivalent mutations, but mutations that exactly reproduce the same AST. This way a check for not generating the same asts can be centralized.
This commit is contained in:
parent
993f08d975
commit
ef9172bca4
5 changed files with 76 additions and 13 deletions
3
TODO
3
TODO
|
@ -17,3 +17,6 @@
|
|||
It can be used to make sure each literal value is touched.
|
||||
* Replace nil or add "do not touch me object" to literal mutations.
|
||||
* Add remaining literals
|
||||
* Mutate options for Regexp literals
|
||||
* Move Mutant.random_* into Mutant::Random namespace.
|
||||
* Use inheritable alias once (virtus,veritas,mapper,session, ...) support gem is born.
|
||||
|
|
|
@ -82,6 +82,7 @@ module Mutant
|
|||
end
|
||||
|
||||
require 'mutant/mutator'
|
||||
require 'mutant/mutator/generator'
|
||||
require 'mutant/mutator/true_literal'
|
||||
require 'mutant/mutator/false_literal'
|
||||
require 'mutant/mutator/symbol_literal'
|
||||
|
@ -93,6 +94,8 @@ require 'mutant/mutator/empty_array'
|
|||
require 'mutant/mutator/hash_literal'
|
||||
require 'mutant/mutator/range'
|
||||
require 'mutant/mutator/range_exclude'
|
||||
require 'mutant/mutator/regex_literal'
|
||||
require 'mutant/mutator/dynamic_string'
|
||||
require 'mutant/mutator/block'
|
||||
require 'mutant/loader'
|
||||
require 'mutant/context'
|
||||
|
|
|
@ -31,25 +31,13 @@ module Mutant
|
|||
const_get(unqualified_name)
|
||||
end
|
||||
|
||||
class Generator
|
||||
def initialize(block)
|
||||
@block = block
|
||||
end
|
||||
|
||||
def append(node)
|
||||
@block.call(node)
|
||||
end
|
||||
|
||||
alias :<< :append
|
||||
end
|
||||
|
||||
# Enumerate mutated asts
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def each(&block)
|
||||
return to_enum unless block_given?
|
||||
mutants(Generator.new(block))
|
||||
mutants(Generator.new(@node,block))
|
||||
self
|
||||
end
|
||||
|
||||
|
|
25
lib/mutant/mutator/generator.rb
Normal file
25
lib/mutant/mutator/generator.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
class Generator
|
||||
def initialize(node,block)
|
||||
@sexp,@block = node.to_sexp,block
|
||||
end
|
||||
|
||||
def append(node)
|
||||
p same_node?(node)
|
||||
unless same_node?(node)
|
||||
@block.call(node)
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: Use interhitable alias once in support gem.
|
||||
alias :<< :append
|
||||
|
||||
private
|
||||
|
||||
def same_node?(node)
|
||||
@sexp == node.to_sexp
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
44
spec/unit/mutant/mutator/generator/append_spec.rb
Normal file
44
spec/unit/mutant/mutator/generator/append_spec.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator::Generator,'#append' do
|
||||
subject { object.append(node) }
|
||||
|
||||
class Block
|
||||
attr_reader :arguments
|
||||
|
||||
def called?
|
||||
defined?(@arguments)
|
||||
end
|
||||
|
||||
def call(*arguments)
|
||||
@arguments = arguments
|
||||
end
|
||||
end
|
||||
|
||||
let(:object) { described_class.new(wrapped_node,block) }
|
||||
let(:block) { Block.new }
|
||||
let(:wrapped_node) { '"foo"'.to_ast }
|
||||
|
||||
context 'with node that is not equal to wrapped node' do
|
||||
let(:node) { '"bar"'.to_ast }
|
||||
|
||||
it 'should call block' do
|
||||
subject
|
||||
block.should be_called
|
||||
end
|
||||
|
||||
it 'should call block with node' do
|
||||
subject
|
||||
block.arguments.should eql([node])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with node that is equal to wrapped node' do
|
||||
let(:node) { '"foo"'.to_ast }
|
||||
|
||||
it 'should call block' do
|
||||
subject
|
||||
block.should_not be_called
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue