1
0
Fork 0

Do not mutate to invalid AST on reqarg promotion

Closes 
This commit is contained in:
Markus Schirp 2014-06-06 23:05:27 +00:00
parent 83f6a22a16
commit d21f4ae5fb
6 changed files with 70 additions and 17 deletions

View file

@ -56,6 +56,7 @@ NestedIterators:
- Mutant::CLI#parse
- Mutant::Mutator::Util::Array::Element#dispatch
- Mutant::Mutator::Node::Resbody#mutate_captures
- Mutant::Mutator::Node::Arguments#emit_argument_mutations
- Mutant::Reporter::CLI::Report::Config#generic_stats
- Mutant::RequireHighjack#infect
- Mutant::RequireHighjack#desinfect

View file

@ -119,7 +119,7 @@ module Mutant
# @api private
#
def mutate_child(index, mutator = Mutator, &block)
block ||= lambda { |_node| true }
block ||= ->(_node) { true }
child = children.at(index)
mutator.each(child, self) do |mutation|
if block.call(mutation)
@ -166,7 +166,7 @@ module Mutant
# @api private
#
def emit_type(*children)
emit(new_self(*children))
emit(Parser::AST::Node.new(node.type, children))
end
# Emit singleton literals
@ -200,16 +200,6 @@ module Mutant
emit(N_NIL) unless asgn_left?
end
# Return new self typed child
#
# @return [Parser::AST::Node]
#
# @api private
#
def new_self(*children)
Parser::AST::Node.new(node.type, children)
end
# Emit values
#
# @param [Array<Object>] values

View file

@ -27,8 +27,7 @@ module Mutant
emit_right_mutations
end
end # OrAsgn
end # AndAsgn
end # Node
end # Mutator
end # Mutant

View file

@ -17,10 +17,55 @@ module Mutant
# @api private
#
def dispatch
emit_children_mutations
emit_argument_presence
emit_argument_mutations
emit_mlhs_expansion
end
# Emit argument presence mutation
#
# @return [undefined]
#
# @api private
#
def emit_argument_presence
emit_type
Mutator::Util::Array::Presence.each(children, self) do |children|
emit_type(*children)
end
end
# Emit argument mutations
#
# @return [undefined]
#
# @api private
#
def emit_argument_mutations
children.each_with_index do |child, index|
Mutator.each(child) do |mutant|
unless invalid_argument_replacement?(mutant, index)
emit_child_update(index, mutant)
end
end
end
end
# Test if child mutation is allowed
#
# @param [Parser::AST::Node]
#
# @return [Boolean]
#
# @api private
#
def invalid_argument_replacement?(mutant, index)
original = children.fetch(index)
original.type.equal?(:optarg) &&
mutant.type.equal?(:arg) &&
children[0...index].any? { |node| node.type.equal?(:optarg) }
end
# Emit mlhs expansions
#
# @return [undefined]
@ -44,7 +89,7 @@ module Mutant
#
def mlhs_childs_with_index
children.each_with_index.select do |child, _index|
child.type == :mlhs
child.type.equal?(:mlhs)
end
end

View file

@ -28,4 +28,3 @@ module Mutant
end # Node
end # Mutator
end # Mutant

View file

@ -69,6 +69,25 @@ Mutant::Meta::Example.add do
mutation 'def foo; end'
end
Mutant::Meta::Example.add do
source 'def foo(a = 0, b = 0); end'
mutation 'def foo(a = 0, b__mutant__ = 0); end'
mutation 'def foo(a__mutant__ = 0, b = 0); end'
mutation 'def foo(a = 0, b = 1); end'
mutation 'def foo(a = 0, b = -1); end'
mutation 'def foo(a = 0, b = self); end'
mutation 'def foo(a = 0, b = nil); end'
mutation 'def foo(a = -1, b = 0); end'
mutation 'def foo(a = self, b = 0); end'
mutation 'def foo(a = nil, b = 0); end'
mutation 'def foo(a = 1, b = 0); end'
mutation 'def foo(a = 0); end'
mutation 'def foo(b = 0); end'
mutation 'def foo(a, b = 0); end'
mutation 'def foo; end'
mutation 'def foo(a = 0, b = 0); raise; end'
end
Mutant::Meta::Example.add do
source 'def foo(a = true); end'