Bring back yard coverage to 100%
Also do some minor refactorings
This commit is contained in:
parent
386a2bc2df
commit
93556763dd
17 changed files with 170 additions and 37 deletions
|
@ -235,7 +235,7 @@ module Mutant
|
|||
|
||||
# Add mutation filter
|
||||
#
|
||||
# @param [Class<Mutant::Filter>]
|
||||
# @param [Class<Mutant::Filter>] klass
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
|
@ -283,7 +283,7 @@ module Mutant
|
|||
|
||||
# Set strategy
|
||||
#
|
||||
# @param [Strategy]
|
||||
# @param [Strategy] strategy
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
|
|
|
@ -1,16 +1,44 @@
|
|||
module Mutant
|
||||
class Killer
|
||||
|
||||
# Killer that executes other killer in forked environment
|
||||
class Forked < self
|
||||
|
||||
# Initialize object
|
||||
#
|
||||
# @param [Killer] killer
|
||||
# @param [Strategy] strategy
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def initialize(killer, strategy, mutation)
|
||||
@killer = killer
|
||||
super(strategy, mutation)
|
||||
end
|
||||
|
||||
# Return killer type
|
||||
#
|
||||
# @return [String]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def type
|
||||
@killer.type
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Run killer
|
||||
#
|
||||
# @return [true]
|
||||
# if mutant was killed
|
||||
#
|
||||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def run
|
||||
fork do
|
||||
killer = @killer.new(strategy, mutation)
|
||||
|
@ -22,15 +50,40 @@ module Mutant
|
|||
end
|
||||
end
|
||||
|
||||
# A killer that executes other killer in forked environemnts
|
||||
class Forking < self
|
||||
include Equalizer.new(:killer)
|
||||
|
||||
# Return killer
|
||||
#
|
||||
# @return [Killer]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
attr_reader :killer
|
||||
|
||||
# Initalize killer
|
||||
#
|
||||
# @param [Killer] killer
|
||||
# the killer that will be used
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def initialize(killer)
|
||||
@killer = killer
|
||||
end
|
||||
|
||||
# Return killer instance
|
||||
#
|
||||
# @param [Strategy] strategy
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @return [Killer::Forked]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def new(strategy, mutation)
|
||||
Forked.new(killer, strategy, mutation)
|
||||
end
|
||||
|
|
|
@ -1,15 +1,29 @@
|
|||
module Mutant
|
||||
class Killer
|
||||
# Abstract base class for killer with static result
|
||||
class Static < self
|
||||
|
||||
# Return result
|
||||
#
|
||||
# @return [true]
|
||||
# if mutation was killed
|
||||
#
|
||||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def run
|
||||
self.class::RESULT
|
||||
end
|
||||
|
||||
# Killer that is always successful
|
||||
class Success < self
|
||||
TYPE = 'success'.freeze
|
||||
RESULT = true
|
||||
end
|
||||
|
||||
# Killer that always fails
|
||||
class Fail < self
|
||||
TYPE = 'fail'.freeze
|
||||
RESULT = false
|
||||
|
|
|
@ -43,6 +43,8 @@ module Mutant
|
|||
# @return [nil]
|
||||
# returns nil otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.from_string(input)
|
||||
descendants.each do |descendant|
|
||||
matcher = descendant.parse(input)
|
||||
|
|
|
@ -72,7 +72,7 @@ module Mutant
|
|||
# @return [true]
|
||||
# if method is public
|
||||
#
|
||||
# @retur [false]
|
||||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
|
|
|
@ -98,7 +98,7 @@ module Mutant
|
|||
|
||||
# Yield scope if name matches pattern
|
||||
#
|
||||
# @param [::Module,::Class]
|
||||
# @param [::Module,::Class] scope
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
|
|
|
@ -153,6 +153,8 @@ module Mutant
|
|||
#
|
||||
# @return [Enumerable<Symbol>]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def method_names
|
||||
scope = self.scope
|
||||
return [] unless scope.kind_of?(Module)
|
||||
|
|
|
@ -6,7 +6,7 @@ module Mutant
|
|||
|
||||
# Test for match
|
||||
#
|
||||
# @param [Mutation]
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @return [true]
|
||||
# returns true if mutation matches whitelist
|
||||
|
|
|
@ -12,9 +12,9 @@ module Mutant
|
|||
#
|
||||
# @api private
|
||||
#
|
||||
def self.each(node, &block)
|
||||
return to_enum(__method__, node) unless block_given?
|
||||
Registry.lookup(node.class).new(node, block)
|
||||
def self.each(input, &block)
|
||||
return to_enum(__method__, input) unless block_given?
|
||||
Registry.lookup(input.class).new(input, block)
|
||||
|
||||
self
|
||||
end
|
||||
|
@ -34,10 +34,12 @@ module Mutant
|
|||
|
||||
# Return identity of object (for deduplication)
|
||||
#
|
||||
# @param [Object]
|
||||
# @param [Object] object
|
||||
#
|
||||
# @return [Object]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.identity(object)
|
||||
object
|
||||
end
|
||||
|
@ -105,6 +107,8 @@ module Mutant
|
|||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def allow?(object)
|
||||
true
|
||||
end
|
||||
|
|
|
@ -11,13 +11,28 @@ module Mutant
|
|||
#
|
||||
# @return [String]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def self.identity(node)
|
||||
ToSource.to_source(node)
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
# Return mutated node
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
alias_method :node, :input
|
||||
|
||||
# Return duplicated node
|
||||
#
|
||||
# @return [Rubinius::AST::Node]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
alias_method :dup_node, :dup_input
|
||||
|
||||
# Emit a new AST node
|
||||
|
|
|
@ -16,28 +16,15 @@ module Mutant
|
|||
#
|
||||
def dispatch
|
||||
array = input.array
|
||||
emit_attribute_mutations(:array)
|
||||
end
|
||||
|
||||
# Test if node is new
|
||||
#
|
||||
# FIXME: Remove this hack and make sure empty bodies are not generated
|
||||
#
|
||||
# @param [Rubinius::AST::Node]
|
||||
#
|
||||
# @return [true]
|
||||
# if node is new
|
||||
#
|
||||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
def new?(node)
|
||||
if node.array.empty?
|
||||
node.array << new_nil
|
||||
emit_attribute_mutations(:array) do |mutation|
|
||||
array = mutation.array
|
||||
# Do not generate empty bodies
|
||||
if array.empty?
|
||||
array << new_nil
|
||||
end
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,7 +5,13 @@ module Mutant
|
|||
|
||||
# Run ulitity mutator
|
||||
#
|
||||
# @param [Object]
|
||||
# @param [Object] object
|
||||
#
|
||||
# @return [Enumerator<Object>]
|
||||
# if no block given
|
||||
#
|
||||
# @return [self]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
|
@ -27,6 +33,8 @@ module Mutant
|
|||
# @return [false]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def new?(generated)
|
||||
input != generated
|
||||
end
|
||||
|
|
|
@ -123,7 +123,7 @@ module Mutant
|
|||
|
||||
# Report errors
|
||||
#
|
||||
# @param [Enumerable<Killer>]
|
||||
# @param [Enumerable<Killer>] errors
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
|
@ -164,7 +164,7 @@ module Mutant
|
|||
|
||||
# Initialize reporter
|
||||
#
|
||||
# @param [IO] io
|
||||
# @param [Config] config
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
|
@ -234,8 +234,7 @@ module Mutant
|
|||
|
||||
# Write colorized diff
|
||||
#
|
||||
# @param [String] original
|
||||
# @param [String] current
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
|
|
|
@ -44,30 +44,70 @@ module Mutant
|
|||
#
|
||||
attr_reader :time
|
||||
|
||||
# Initialize object
|
||||
#
|
||||
# @return [undefined]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def initialize
|
||||
@start = Time.now
|
||||
@noop_fails = @subjects = @mutations = @kills = @time = 0
|
||||
end
|
||||
|
||||
# Return runtime in seconds
|
||||
#
|
||||
# @return [Float]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def runtime
|
||||
Time.now - @start
|
||||
end
|
||||
|
||||
# Count subject
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def subject
|
||||
@subjects +=1
|
||||
self
|
||||
end
|
||||
|
||||
# Return number of mutants alive
|
||||
#
|
||||
# @return [Fixnum]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def alive
|
||||
@mutations - @kills
|
||||
end
|
||||
|
||||
# Count noop mutation fail
|
||||
#
|
||||
# @param [Killer] killer
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def noop_fail(killer)
|
||||
@noop_fails += 1
|
||||
@time += killer.runtime
|
||||
self
|
||||
end
|
||||
|
||||
# Count killer
|
||||
#
|
||||
# @param [Killer] killer
|
||||
#
|
||||
# @return [self]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def killer(killer)
|
||||
@mutations +=1
|
||||
@kills +=1 unless killer.fail?
|
||||
|
|
|
@ -44,7 +44,7 @@ module Mutant
|
|||
|
||||
# Kill mutation
|
||||
#
|
||||
# @param [Mutation]
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @return [Killer]
|
||||
#
|
||||
|
|
|
@ -50,6 +50,13 @@ module Mutant
|
|||
|
||||
# Run all specs per mutation
|
||||
class Full < self
|
||||
|
||||
# Return spec files
|
||||
#
|
||||
# @return [Enumerable<String>]
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def spec_files(mutation)
|
||||
Dir['spec/**/*_spec.rb']
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ module Mutant
|
|||
|
||||
# Perform example lookup
|
||||
#
|
||||
# @param [Mutation]
|
||||
# @param [Mutation] mutation
|
||||
#
|
||||
# @return [Enumerable<String>]
|
||||
#
|
||||
|
@ -111,6 +111,8 @@ module Mutant
|
|||
# @return [nil]
|
||||
# otherwise
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
def mapped_name
|
||||
MAPPING[method_name]
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue