Metric driven code refactoring
Break some classes, rename stuff etc.
This commit is contained in:
parent
cca235d6e2
commit
eb6ea9a74f
27 changed files with 291 additions and 229 deletions
|
@ -1,3 +1,3 @@
|
||||||
---
|
---
|
||||||
threshold: 25 # Todo bring down to ~20
|
threshold: 25 # Todo bring down to ~20
|
||||||
total_score: 972
|
total_score: 914
|
||||||
|
|
|
@ -10,13 +10,14 @@ UncommunicativeParameterName:
|
||||||
LargeClass:
|
LargeClass:
|
||||||
max_methods: 10
|
max_methods: 10
|
||||||
exclude:
|
exclude:
|
||||||
#- "Mutant::Matcher::Method" # 13 methods
|
|
||||||
- "Mutant::Reporter::CLI" # 16 methods TODO Reduce!
|
- "Mutant::Reporter::CLI" # 16 methods TODO Reduce!
|
||||||
|
- "Mutant::Reporter::Stats" # 6 ivars TODO Reduce!
|
||||||
- "Mutant::CLI" # 19 methods and 7 ivars, TODO Reduce!
|
- "Mutant::CLI" # 19 methods and 7 ivars, TODO Reduce!
|
||||||
enabled: true
|
enabled: true
|
||||||
max_instance_variables: 3
|
max_instance_variables: 3
|
||||||
UncommunicativeMethodName:
|
UncommunicativeMethodName:
|
||||||
accept: []
|
accept:
|
||||||
|
- sha1
|
||||||
exclude: []
|
exclude: []
|
||||||
enabled: true
|
enabled: true
|
||||||
reject:
|
reject:
|
||||||
|
@ -26,7 +27,9 @@ UncommunicativeMethodName:
|
||||||
LongParameterList:
|
LongParameterList:
|
||||||
max_params: 2
|
max_params: 2
|
||||||
exclude:
|
exclude:
|
||||||
|
- "Mutant::Mutator::Node#new_send_with_arguments" # 3 params
|
||||||
- "Mutant::Context::Constant#initialize" # 3 params
|
- "Mutant::Context::Constant#initialize" # 3 params
|
||||||
|
- "Mutant::Subject#initialize" # 3 params
|
||||||
enabled: true
|
enabled: true
|
||||||
overrides: {}
|
overrides: {}
|
||||||
FeatureEnvy:
|
FeatureEnvy:
|
||||||
|
@ -43,6 +46,7 @@ IrresponsibleModule:
|
||||||
enabled: true
|
enabled: true
|
||||||
UncommunicativeModuleName:
|
UncommunicativeModuleName:
|
||||||
accept:
|
accept:
|
||||||
|
- Mutant::Mutator::Node::Iter19
|
||||||
- Mutant::Strategy::Rspec::DM2
|
- Mutant::Strategy::Rspec::DM2
|
||||||
exclude: []
|
exclude: []
|
||||||
enabled: true
|
enabled: true
|
||||||
|
@ -53,6 +57,8 @@ NestedIterators:
|
||||||
ignore_iterators: []
|
ignore_iterators: []
|
||||||
exclude:
|
exclude:
|
||||||
- Mutant#self.define_singleton_subclass
|
- Mutant#self.define_singleton_subclass
|
||||||
|
- Mutant::Mutator::Util::Array::Element#dispatch
|
||||||
|
- Mutant::Mutator::Node::ReceiverCase#emit_when_branch_mutation
|
||||||
enabled: true
|
enabled: true
|
||||||
max_allowed_nesting: 1
|
max_allowed_nesting: 1
|
||||||
LongMethod:
|
LongMethod:
|
||||||
|
@ -61,7 +67,8 @@ LongMethod:
|
||||||
enabled: true
|
enabled: true
|
||||||
Duplication:
|
Duplication:
|
||||||
allow_calls: []
|
allow_calls: []
|
||||||
exclude: []
|
exclude:
|
||||||
|
- Mutant::Mutator::Node::Literal::Hash#emit_element_presence
|
||||||
enabled: true
|
enabled: true
|
||||||
max_calls: 1
|
max_calls: 1
|
||||||
UtilityFunction:
|
UtilityFunction:
|
||||||
|
|
|
@ -63,6 +63,9 @@ require 'mutant/mutator/node/block'
|
||||||
require 'mutant/mutator/node/while'
|
require 'mutant/mutator/node/while'
|
||||||
require 'mutant/mutator/node/super'
|
require 'mutant/mutator/node/super'
|
||||||
require 'mutant/mutator/node/send'
|
require 'mutant/mutator/node/send'
|
||||||
|
require 'mutant/mutator/node/send/with_arguments'
|
||||||
|
require 'mutant/mutator/node/send/binary_operator_method'
|
||||||
|
require 'mutant/mutator/node/when'
|
||||||
require 'mutant/mutator/node/assignment'
|
require 'mutant/mutator/node/assignment'
|
||||||
require 'mutant/mutator/node/define'
|
require 'mutant/mutator/node/define'
|
||||||
require 'mutant/mutator/node/formal_arguments_19'
|
require 'mutant/mutator/node/formal_arguments_19'
|
||||||
|
@ -75,7 +78,7 @@ require 'mutant/mutator/node/pattern_variable'
|
||||||
require 'mutant/mutator/node/default_arguments'
|
require 'mutant/mutator/node/default_arguments'
|
||||||
require 'mutant/mutator/node/return'
|
require 'mutant/mutator/node/return'
|
||||||
require 'mutant/mutator/node/iter_19'
|
require 'mutant/mutator/node/iter_19'
|
||||||
require 'mutant/mutator/node/if_statement'
|
require 'mutant/mutator/node/if'
|
||||||
require 'mutant/mutator/node/receiver_case'
|
require 'mutant/mutator/node/receiver_case'
|
||||||
require 'mutant/loader'
|
require 'mutant/loader'
|
||||||
require 'mutant/context'
|
require 'mutant/context'
|
||||||
|
|
|
@ -17,15 +17,14 @@ module Mutant
|
||||||
# Initialize and insert mutation into vm
|
# Initialize and insert mutation into vm
|
||||||
#
|
#
|
||||||
# @param [Rubinius::AST::Script] root
|
# @param [Rubinius::AST::Script] root
|
||||||
# @param [String] file
|
# @param [Subject] subject
|
||||||
# @param [Fixnum] line
|
|
||||||
#
|
#
|
||||||
# @return [undefined]
|
# @return [undefined]
|
||||||
#
|
#
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def initialize(root, file, line)
|
def initialize(root, subject)
|
||||||
@root, @file, @line = root, file, line
|
@root, @subject = root, subject
|
||||||
run
|
run
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def run
|
def run
|
||||||
eval(source, TOPLEVEL_BINDING, @file, @line)
|
Kernel.eval(source, TOPLEVEL_BINDING, @subject.source_path, @subject.source_line)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return source
|
# Return source
|
||||||
|
|
|
@ -37,7 +37,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def insert
|
def insert
|
||||||
Loader::Eval.run(root, subject.source_path, subject.source_line)
|
Loader::Eval.run(root, subject)
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,9 +110,10 @@ module Mutant
|
||||||
@subject, @node = subject, node
|
@subject, @node = subject, node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Noop mutation
|
||||||
class Noop < self
|
class Noop < self
|
||||||
|
|
||||||
# Initialihe object
|
# Initialize object
|
||||||
#
|
#
|
||||||
# @param [Subject] subject
|
# @param [Subject] subject
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Mutation
|
class Mutation
|
||||||
class Filter
|
class Filter
|
||||||
|
|
||||||
|
# Whiltelist filter
|
||||||
class Whitelist < self
|
class Whitelist < self
|
||||||
include Adamantium::Flat, Equalizer.new(:whitelist)
|
include Adamantium::Flat, Equalizer.new(:whitelist)
|
||||||
|
|
||||||
|
|
|
@ -118,22 +118,31 @@ module Mutant
|
||||||
emit(new_nil)
|
emit(new_nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return new Rubiinius::AST::SendWithArguments node
|
||||||
|
#
|
||||||
|
# @param [Rubnius::AST::Node] receiver
|
||||||
|
# @param [Symbol] name
|
||||||
|
# @param [Object] arguments
|
||||||
|
#
|
||||||
|
# @return [Rubinius::AST::SendWithArguments]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def new_send_with_arguments(receiver, name, arguments)
|
||||||
|
new(Rubinius::AST::SendWithArguments, receiver, name, arguments)
|
||||||
|
end
|
||||||
|
|
||||||
# Return AST representing send
|
# Return AST representing send
|
||||||
#
|
#
|
||||||
# @param [Rubinius::AST::Node] receiver
|
# @param [Rubinius::AST::Node] receiver
|
||||||
# @param [Symbol] name
|
# @param [Symbol] name
|
||||||
# @param [Rubinius::AST::Node] arguments
|
|
||||||
#
|
#
|
||||||
# @return [Rubnius::AST::SendWithArguments]
|
# @return [Rubnius::AST::Send]
|
||||||
#
|
#
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def new_send(receiver, name, arguments=nil)
|
def new_send(receiver, name)
|
||||||
if arguments
|
new(Rubinius::AST::Send, receiver, name)
|
||||||
new(Rubinius::AST::SendWithArguments, receiver, name, arguments)
|
|
||||||
else
|
|
||||||
new(Rubinius::AST::Send, receiver, name)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return duplicated (unfrozen) node each call
|
# Return duplicated (unfrozen) node each call
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
|
|
||||||
|
# Abstract base class for assignment mutators
|
||||||
class Assignment < self
|
class Assignment < self
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Abstract base class for variable assignments
|
||||||
class Variable < self
|
class Variable < self
|
||||||
|
|
||||||
# Emit mutants
|
# Emit mutants
|
||||||
|
@ -20,28 +23,31 @@ module Mutant
|
||||||
emit_attribute_mutations(:value)
|
emit_attribute_mutations(:value)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mutator for local variable assignments
|
||||||
class Local < self
|
class Local < self
|
||||||
PREFIX = ''.freeze
|
PREFIX = ''.freeze
|
||||||
handle(Rubinius::AST::LocalVariableAssignment)
|
handle(Rubinius::AST::LocalVariableAssignment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mutator for instance variable assignments
|
||||||
class Instance < self
|
class Instance < self
|
||||||
PREFIX = '@'.freeze
|
PREFIX = '@'.freeze
|
||||||
handle(Rubinius::AST::InstanceVariableAssignment)
|
handle(Rubinius::AST::InstanceVariableAssignment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mutator for class variable assignments
|
||||||
class Class < self
|
class Class < self
|
||||||
PREFIX = '@@'.freeze
|
PREFIX = '@@'.freeze
|
||||||
handle(Rubinius::AST::ClassVariableAssignment)
|
handle(Rubinius::AST::ClassVariableAssignment)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mutator for global variable assignments
|
||||||
class Global < self
|
class Global < self
|
||||||
PREFIX = '$'.freeze
|
PREFIX = '$'.freeze
|
||||||
handle(Rubinius::AST::GlobalVariableAssignment)
|
handle(Rubinius::AST::GlobalVariableAssignment)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
# Mutator for Rubinius::AST::If nodes
|
# Mutator for Rubinius::AST::If nodes
|
||||||
class IfStatement < self
|
class If < self
|
||||||
|
|
||||||
handle(Rubinius::AST::If)
|
handle(Rubinius::AST::If)
|
||||||
|
|
||||||
|
@ -16,13 +16,29 @@ module Mutant
|
||||||
#
|
#
|
||||||
def dispatch
|
def dispatch
|
||||||
emit_attribute_mutations(:condition)
|
emit_attribute_mutations(:condition)
|
||||||
emit_attribute_mutations(:body) if node.body.class != Rubinius::AST::NilLiteral
|
emit_attribute_mutations(:body) unless nil_literal?(:body)
|
||||||
emit_attribute_mutations(:else) if node.else.class != Rubinius::AST::NilLiteral
|
emit_attribute_mutations(:else) unless nil_literal?(:else)
|
||||||
emit_inverted_condition
|
emit_inverted_condition
|
||||||
emit_deleted_if_branch
|
emit_deleted_if_branch
|
||||||
emit_deleted_else_branch
|
emit_deleted_else_branch
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Test if attribute is non nil literal
|
||||||
|
#
|
||||||
|
# @param [Symbol] name
|
||||||
|
#
|
||||||
|
# @return [true]
|
||||||
|
# if attribute value a nil literal
|
||||||
|
#
|
||||||
|
# @return [false]
|
||||||
|
# otherwise
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def nil_literal?(name)
|
||||||
|
node.public_send(name).kind_of?(Rubinius::AST::NilLiteral)
|
||||||
|
end
|
||||||
|
|
||||||
# Emit inverted condition
|
# Emit inverted condition
|
||||||
#
|
#
|
||||||
# Especially the same like swap branches but more universal as it also
|
# Especially the same like swap branches but more universal as it also
|
||||||
|
@ -53,9 +69,8 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def emit_deleted_if_branch
|
def emit_deleted_if_branch
|
||||||
body = else_branch
|
body = else_branch || return
|
||||||
return unless body
|
emit_self(condition, body, nil)
|
||||||
emit_self(condition, else_branch, nil)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return if_branch of node
|
# Return if_branch of node
|
|
@ -40,7 +40,8 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def nan
|
def nan
|
||||||
new_send(new_float(0), :/, new_float(0))
|
zero_float = new_float(0)
|
||||||
|
new_send_with_arguments(zero_float, :/, zero_float)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return AST representing negative infinity
|
# Return AST representing negative infinity
|
||||||
|
@ -60,7 +61,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def infinity
|
def infinity
|
||||||
new_send(new_float(1), :/, new_float(0))
|
new_send_with_arguments(new_float(1), :/, new_float(0))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -59,7 +59,8 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def values
|
def values
|
||||||
[[], [new_nil, new_nil] + dup_array]
|
nil_node = new_nil
|
||||||
|
[[], [nil_node, nil_node] + dup_array]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit element presence mutations
|
# Emit element presence mutations
|
||||||
|
|
|
@ -27,7 +27,8 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def inverse
|
def inverse
|
||||||
new(inverse_class,node.start, node.finish)
|
node = self.node
|
||||||
|
new(inverse_class, node.start, node.finish)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit range specific mutants
|
# Emit range specific mutants
|
||||||
|
|
|
@ -1,24 +1,6 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
# Mutator for Rubinius::AST::When nodes
|
|
||||||
class When < self
|
|
||||||
|
|
||||||
handle(Rubinius::AST::When)
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Emit mutations
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def dispatch
|
|
||||||
emit_attribute_mutations(:body)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
# Mutator for Rubinius::AST::ReceiverCase nodes
|
# Mutator for Rubinius::AST::ReceiverCase nodes
|
||||||
class ReceiverCase < self
|
class ReceiverCase < self
|
||||||
|
@ -57,7 +39,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def emit_when_branch_mutations
|
def emit_when_branch_mutations
|
||||||
when_branches.each_with_index do |branch,index|
|
when_branches.each_with_index do |branch, index|
|
||||||
Mutator.each(branch) do |mutant|
|
Mutator.each(branch) do |mutant|
|
||||||
branches = dup_when_branches
|
branches = dup_when_branches
|
||||||
branches[index]=mutant
|
branches[index]=mutant
|
||||||
|
|
|
@ -1,17 +1,18 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
# Class for mutations where messages are send to objects
|
|
||||||
|
# Namespace for send mutators
|
||||||
class Send < self
|
class Send < self
|
||||||
|
|
||||||
handle(Rubinius::AST::Send)
|
handle(Rubinius::AST::Send)
|
||||||
|
|
||||||
# Test if node corresponds to "self.class"
|
# Test if node name is a keyword
|
||||||
#
|
#
|
||||||
# @param [Rubinius::AST::Node] node
|
# @param [Rubinius::AST::Node] node
|
||||||
#
|
#
|
||||||
# @return [true]
|
# @return [true]
|
||||||
# if node equals to self.class
|
# if node name equals a ruby keyword
|
||||||
#
|
#
|
||||||
# @return [false]
|
# @return [false]
|
||||||
# otherwise
|
# otherwise
|
||||||
|
@ -19,9 +20,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def self.keyword_name?(node)
|
def self.keyword_name?(node)
|
||||||
node.kind_of?(Rubinius::AST::Send) &&
|
Mutant::KEYWORDS.include?(node.name)
|
||||||
Mutant::KEYWORDS.include?(node.name) &&
|
|
||||||
node.receiver.kind_of?(Rubinius::AST::Self)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -59,9 +58,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def emit_block_mutations
|
def emit_block_mutations
|
||||||
if node.block
|
emit_attribute_mutations(:block) if node.block
|
||||||
emit_attribute_mutations(:block)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit receiver mutations
|
# Emit receiver mutations
|
||||||
|
@ -71,11 +68,7 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def emit_receiver_mutations
|
def emit_receiver_mutations
|
||||||
util = self.class
|
emit_attribute_mutations(:receiver)
|
||||||
|
|
||||||
unless to_self? or util.keyword_name?(receiver)
|
|
||||||
emit_attribute_mutations(:receiver)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Emit block absence mutation
|
# Emit block absence mutation
|
||||||
|
@ -150,119 +143,14 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def emit_implicit_self_receiver
|
def emit_implicit_self_receiver
|
||||||
return unless to_self?
|
if to_self? and self.class.keyword_name?(node)
|
||||||
return if self.class.keyword_name?(node)
|
return
|
||||||
|
end
|
||||||
|
|
||||||
mutant = dup_node
|
mutant = dup_node
|
||||||
mutant.privately = true
|
mutant.privately = true
|
||||||
# TODO: Fix rubinius to allow this as an attr_accessor
|
|
||||||
mutant.instance_variable_set(:@vcall_style, true)
|
|
||||||
emit(mutant)
|
emit(mutant)
|
||||||
end
|
end
|
||||||
|
|
||||||
class SendWithArguments < self
|
|
||||||
|
|
||||||
handle(Rubinius::AST::SendWithArguments)
|
|
||||||
|
|
||||||
class BinaryOperatorMethod < Node
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Emit mutations
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def dispatch
|
|
||||||
emit_left_mutations
|
|
||||||
emit_right_mutations
|
|
||||||
end
|
|
||||||
|
|
||||||
# Emit left mutations
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def emit_left_mutations
|
|
||||||
emit_attribute_mutations(:receiver)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Emit right mutations
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def emit_right_mutations
|
|
||||||
right = node.arguments.array.first
|
|
||||||
Mutator.each(right).each do |mutated|
|
|
||||||
dup = dup_node
|
|
||||||
dup.arguments.array[0] = mutated
|
|
||||||
emit(dup)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
# Emit mutations
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def dispatch
|
|
||||||
super
|
|
||||||
emit_call_remove_mutation
|
|
||||||
emit_argument_mutations
|
|
||||||
end
|
|
||||||
|
|
||||||
# Test if message is a binary operator
|
|
||||||
#
|
|
||||||
# @return [true]
|
|
||||||
# if message is a binary operator
|
|
||||||
#
|
|
||||||
# @return [false]
|
|
||||||
# otherwise
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def binary_operator?
|
|
||||||
Mutant::BINARY_METHOD_OPERATORS.include?(node.name)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Emit argument mutations
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def emit_argument_mutations
|
|
||||||
if binary_operator?
|
|
||||||
run(BinaryOperatorMethod)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
emit_attribute_mutations(:arguments)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Emit transfomr call mutation
|
|
||||||
#
|
|
||||||
# @return [undefined]
|
|
||||||
#
|
|
||||||
# @api private
|
|
||||||
#
|
|
||||||
def emit_call_remove_mutation
|
|
||||||
array = node.arguments.array
|
|
||||||
return unless array.length == 1
|
|
||||||
emit(array.first)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
51
lib/mutant/mutator/node/send/binary_operator_method.rb
Normal file
51
lib/mutant/mutator/node/send/binary_operator_method.rb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
module Mutant
|
||||||
|
class Mutator
|
||||||
|
class Node
|
||||||
|
class Send
|
||||||
|
|
||||||
|
# Mutator for sends that correspond to a binary operator
|
||||||
|
class BinaryOperatorMethod < Node
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Emit mutations
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def dispatch
|
||||||
|
emit_left_mutations
|
||||||
|
emit_right_mutations
|
||||||
|
end
|
||||||
|
|
||||||
|
# Emit left mutations
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def emit_left_mutations
|
||||||
|
emit_attribute_mutations(:receiver)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Emit right mutations
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def emit_right_mutations
|
||||||
|
right = node.arguments.array.first
|
||||||
|
Mutator.each(right).each do |mutated|
|
||||||
|
dup = dup_node
|
||||||
|
dup.arguments.array[0] = mutated
|
||||||
|
emit(dup)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
72
lib/mutant/mutator/node/send/with_arguments.rb
Normal file
72
lib/mutant/mutator/node/send/with_arguments.rb
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
module Mutant
|
||||||
|
class Mutator
|
||||||
|
class Node
|
||||||
|
class Send
|
||||||
|
|
||||||
|
# Mutator for send with arguments
|
||||||
|
class WithArguments < self
|
||||||
|
|
||||||
|
handle(Rubinius::AST::SendWithArguments)
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Emit mutations
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def dispatch
|
||||||
|
super
|
||||||
|
emit_call_remove_mutation
|
||||||
|
emit_argument_mutations
|
||||||
|
end
|
||||||
|
|
||||||
|
# Test if message is a binary operator
|
||||||
|
#
|
||||||
|
# @return [true]
|
||||||
|
# if message is a binary operator
|
||||||
|
#
|
||||||
|
# @return [false]
|
||||||
|
# otherwise
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def binary_operator?
|
||||||
|
Mutant::BINARY_METHOD_OPERATORS.include?(node.name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Emit argument mutations
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def emit_argument_mutations
|
||||||
|
if binary_operator?
|
||||||
|
run(BinaryOperatorMethod)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
emit_attribute_mutations(:arguments)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Emit transfomr call mutation
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def emit_call_remove_mutation
|
||||||
|
array = node.arguments.array
|
||||||
|
return unless array.length == 1
|
||||||
|
emit(array.first)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,6 +2,7 @@ module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
|
|
||||||
|
# Mutator for super without parantheses
|
||||||
class ZSuper < self
|
class ZSuper < self
|
||||||
|
|
||||||
handle(Rubinius::AST::ZSuper)
|
handle(Rubinius::AST::ZSuper)
|
||||||
|
@ -18,6 +19,7 @@ module Mutant
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Mutator for super with parantheses
|
||||||
class Super < self
|
class Super < self
|
||||||
handle(Rubinius::AST::Super)
|
handle(Rubinius::AST::Super)
|
||||||
|
|
||||||
|
|
25
lib/mutant/mutator/node/when.rb
Normal file
25
lib/mutant/mutator/node/when.rb
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
module Mutant
|
||||||
|
class Mutator
|
||||||
|
class Node
|
||||||
|
|
||||||
|
# Mutator for Rubinius::AST::When nodes
|
||||||
|
class When < self
|
||||||
|
|
||||||
|
handle(Rubinius::AST::When)
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Emit mutations
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def dispatch
|
||||||
|
emit_attribute_mutations(:body)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,8 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Mutator
|
class Mutator
|
||||||
class Node
|
class Node
|
||||||
|
|
||||||
|
# Mutator for while expressions
|
||||||
class While < self
|
class While < self
|
||||||
|
|
||||||
handle(Rubinius::AST::While)
|
handle(Rubinius::AST::While)
|
||||||
|
|
|
@ -7,6 +7,7 @@ module Mutant
|
||||||
|
|
||||||
handle(::Array)
|
handle(::Array)
|
||||||
|
|
||||||
|
# Element presence mutator
|
||||||
class Presence < Util
|
class Presence < Util
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -27,6 +28,7 @@ module Mutant
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Array element mutator
|
||||||
class Element < Util
|
class Element < Util
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -40,7 +42,6 @@ module Mutant
|
||||||
def dispatch
|
def dispatch
|
||||||
input.each_with_index do |element, index|
|
input.each_with_index do |element, index|
|
||||||
dup = dup_input
|
dup = dup_input
|
||||||
|
|
||||||
Mutator.each(element).each do |mutation|
|
Mutator.each(element).each do |mutation|
|
||||||
dup[index]=mutation
|
dup[index]=mutation
|
||||||
emit(dup)
|
emit(dup)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
class Reporter
|
class Reporter
|
||||||
|
|
||||||
|
# Null reporter
|
||||||
class Null < self
|
class Null < self
|
||||||
|
|
||||||
# Report subject
|
# Report subject
|
||||||
|
|
|
@ -47,11 +47,10 @@ module Mutant
|
||||||
def initialize(config)
|
def initialize(config)
|
||||||
@config, @errors = config, []
|
@config, @errors = config, []
|
||||||
|
|
||||||
reporter.config(config)
|
util_reporter = reporter
|
||||||
|
util_reporter.config(config)
|
||||||
run
|
run
|
||||||
|
util_reporter.errors(@errors)
|
||||||
reporter.errors(@errors)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return reporter
|
# Return reporter
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
module Mutant
|
module Mutant
|
||||||
|
|
||||||
|
# Abstract base class for killing strategies
|
||||||
class Strategy
|
class Strategy
|
||||||
include AbstractType, Adamantium::Flat, Equalizer.new
|
include AbstractType, Adamantium::Flat, Equalizer.new
|
||||||
|
|
||||||
|
|
|
@ -116,10 +116,12 @@ module Mutant
|
||||||
# @api private
|
# @api private
|
||||||
#
|
#
|
||||||
def glob_expression
|
def glob_expression
|
||||||
|
base = base_path
|
||||||
|
|
||||||
if mutation.subject.matcher.public?
|
if mutation.subject.matcher.public?
|
||||||
"#{base_path}/#{spec_file}"
|
"#{base}/#{spec_file}"
|
||||||
else
|
else
|
||||||
"#{base_path}/*_spec.rb"
|
"#{base}/*_spec.rb"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,39 @@ module Zombie
|
||||||
end
|
end
|
||||||
private_class_method :root
|
private_class_method :root
|
||||||
|
|
||||||
|
class DummySubject
|
||||||
|
|
||||||
|
# Return line
|
||||||
|
#
|
||||||
|
# @return [Fixnum]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
attr_reader :source_line
|
||||||
|
|
||||||
|
# Return path
|
||||||
|
#
|
||||||
|
# @return [String]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
attr_reader :source_path
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Initialize object
|
||||||
|
#
|
||||||
|
# @param [String] path
|
||||||
|
# @param [Fixnum] line
|
||||||
|
#
|
||||||
|
# @return [undefined]
|
||||||
|
#
|
||||||
|
# @api private
|
||||||
|
#
|
||||||
|
def initialize(path, line)
|
||||||
|
@source_path, @source_line = path, line
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Replace Mutant with Zombie namespace
|
# Replace Mutant with Zombie namespace
|
||||||
#
|
#
|
||||||
|
@ -51,7 +84,7 @@ module Zombie
|
||||||
node.body = Rubinius::AST::ModuleScope.new(scope.line, node.name, scope.body)
|
node.body = Rubinius::AST::ModuleScope.new(scope.line, node.name, scope.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
::Mutant::Loader::Eval.run(root, path, 1)
|
::Mutant::Loader::Eval.run(root, DummySubject.new(path, 1))
|
||||||
end
|
end
|
||||||
private_class_method :zombify
|
private_class_method :zombify
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,14 @@ require 'spec_helper'
|
||||||
|
|
||||||
describe Mutant::Loader::Eval, '.run' do
|
describe Mutant::Loader::Eval, '.run' do
|
||||||
|
|
||||||
subject { object.run(node, file, line) }
|
subject { object.run(node, mutation_subject) }
|
||||||
|
|
||||||
let(:object) { described_class }
|
let(:object) { described_class }
|
||||||
let(:file) { 'test.rb' }
|
let(:mutation_subject) { mock('Subject', :source_path => path, :source_line => line) }
|
||||||
let(:line) { 1 }
|
let(:path) { 'test.rb' }
|
||||||
|
let(:line) { 1 }
|
||||||
|
|
||||||
let(:source) do
|
let(:source) do
|
||||||
# This test case will blow up when not executed
|
|
||||||
# under toplevel binding.
|
|
||||||
<<-RUBY
|
<<-RUBY
|
||||||
class SomeNamespace
|
class SomeNamespace
|
||||||
class Bar
|
class Bar
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
describe Mutant::Loader::Rubinius, '.run' do
|
|
||||||
before do
|
|
||||||
pending
|
|
||||||
end
|
|
||||||
|
|
||||||
subject { object.run(node) }
|
|
||||||
|
|
||||||
let(:object) { described_class }
|
|
||||||
|
|
||||||
after do
|
|
||||||
Object.send(:remove_const, :SomeNamespace)
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:source) do
|
|
||||||
# This test case will blow up when not executed
|
|
||||||
# under toplevel binding.
|
|
||||||
<<-RUBY
|
|
||||||
class SomeNamespace
|
|
||||||
class Bar
|
|
||||||
end
|
|
||||||
|
|
||||||
class SomeOther
|
|
||||||
class Foo < Bar
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
RUBY
|
|
||||||
end
|
|
||||||
|
|
||||||
let(:node) do
|
|
||||||
Rubinius::AST::Script.new(source.to_ast).tap do |source|
|
|
||||||
source.file = "/some/source"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'should load nodes into vm' do
|
|
||||||
subject
|
|
||||||
SomeNamespace::SomeOther::Foo
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Add table
Reference in a new issue