Add initial support for mutating case statements
This commit is contained in:
parent
00136ab9df
commit
a25f99c97a
4 changed files with 187 additions and 0 deletions
1
TODO
1
TODO
|
@ -22,3 +22,4 @@
|
|||
* Mutations on Rubinius::AST::Self?
|
||||
* Support the numerous Rubinius::AST::SendWithArguments mutations.
|
||||
* Fix rubinius to allow setting @vcall_style variable in Rubinius::AST::Send nodes.
|
||||
* Add mutations on the conditiosn of case statements. (Rubinius::AST::When)
|
||||
|
|
|
@ -56,6 +56,7 @@ require 'mutant/mutator/noop'
|
|||
require 'mutant/mutator/call'
|
||||
require 'mutant/mutator/call'
|
||||
require 'mutant/mutator/if_statement'
|
||||
require 'mutant/mutator/receiver_case'
|
||||
require 'mutant/loader'
|
||||
require 'mutant/context'
|
||||
require 'mutant/context/constant'
|
||||
|
|
160
lib/mutant/mutator/receiver_case.rb
Normal file
160
lib/mutant/mutator/receiver_case.rb
Normal file
|
@ -0,0 +1,160 @@
|
|||
module Mutant
|
||||
class Mutator
|
||||
# Mutator for Rubinius::AST::When nodes
|
||||
class When < Mutator
|
||||
|
||||
handle(Rubinius::AST::When)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dispatch
|
||||
emit_body_mutations
|
||||
end
|
||||
|
||||
# Emit body mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def emit_body_mutations
|
||||
Mutator.each(node.body) do |mutation|
|
||||
node = dup_node
|
||||
node.body = mutation
|
||||
emit_unsafe(node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Mutator for Rubinius::AST::ReceiverCase nodes
|
||||
class ReceiverCase < Mutator
|
||||
|
||||
handle(Rubinius::AST::ReceiverCase)
|
||||
|
||||
private
|
||||
|
||||
# Emit mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dispatch
|
||||
emit_receiver_mutations
|
||||
emit_when_branch_presence_mutations
|
||||
emit_else_branch_presence_mutation
|
||||
emit_when_branch_mutations
|
||||
end
|
||||
|
||||
# Emit receiver mutation
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def emit_receiver_mutations
|
||||
Mutator.each(receiver) do |mutant|
|
||||
emit_self(mutant,when_branches,else_branch)
|
||||
end
|
||||
end
|
||||
|
||||
# Emit else branch presence mutation
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def emit_else_branch_presence_mutation
|
||||
emit_self(receiver,when_branches,nil)
|
||||
end
|
||||
|
||||
# Emit when branch body mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def emit_when_branch_mutations
|
||||
when_branches.each_with_index do |branch,index|
|
||||
Mutator.each(branch) do |mutant|
|
||||
branches = dup_when_branches
|
||||
branches[index]=mutant
|
||||
emit_self(receiver,branches,else_branch)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Emit when branch presence mutations
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def emit_when_branch_presence_mutations
|
||||
return if one?
|
||||
when_branches.each_index do |index|
|
||||
dup_branches = dup_when_branches
|
||||
dup_branches.delete_at(index)
|
||||
emit_self(receiver,dup_branches,else_branch)
|
||||
end
|
||||
end
|
||||
|
||||
# Check for case there is only one when branch
|
||||
#
|
||||
# @return [true]
|
||||
# returns true when there is only one when branch
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def one?
|
||||
when_branches.size == 1
|
||||
end
|
||||
|
||||
# Return duplicatedd when branches
|
||||
#
|
||||
# @return [Array]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def dup_when_branches
|
||||
when_branches.dup
|
||||
end
|
||||
|
||||
# Return when branches
|
||||
#
|
||||
# @return [Array]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def when_branches
|
||||
node.whens
|
||||
end
|
||||
|
||||
# Return receiver
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def receiver
|
||||
node.receiver
|
||||
end
|
||||
|
||||
# Return else branch
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def else_branch
|
||||
node.else
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,6 +5,31 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Mutant::Mutator, '.each' do
|
||||
context 'case statements' do
|
||||
let(:source) { 'case self.condition; when true; true; when false; false; else raise; end' }
|
||||
|
||||
let(:mutations) do
|
||||
mutations = []
|
||||
|
||||
# Delete each when once
|
||||
mutations << 'case self.condition; when true; true; else raise; end'
|
||||
mutations << 'case self.condition; when false; false; else raise; end'
|
||||
|
||||
# Mutate receiver
|
||||
mutations << 'case condition; when true; true; when false; false; else raise; end'
|
||||
|
||||
# Remove else branch
|
||||
mutations << 'case self.condition; when true; true; when false; false; end'
|
||||
|
||||
# Mutate when branch bodies
|
||||
mutations << 'case self.condition; when true; nil; when false; false; else raise; end'
|
||||
mutations << 'case self.condition; when true; false; when false; false; else raise; end'
|
||||
mutations << 'case self.condition; when true; true; when false; nil; else raise; end'
|
||||
mutations << 'case self.condition; when true; true; when false; true; else raise; end'
|
||||
end
|
||||
|
||||
it_should_behave_like 'a mutator'
|
||||
end
|
||||
pending 'interpolated string literal (DynamicString)' do
|
||||
let(:source) { '"foo#{1}bar"' }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue