292 lines
5.8 KiB
Ruby
292 lines
5.8 KiB
Ruby
module Mutant
|
|
class Reporter
|
|
# Reporter that reports in human readable format
|
|
class CLI < self
|
|
include Equalizer.new(:io)
|
|
|
|
# Reporter subject
|
|
#
|
|
# @param [Subject] subject
|
|
#
|
|
# @return [self]
|
|
#
|
|
# @api private
|
|
#
|
|
def subject(subject)
|
|
stats.subject
|
|
puts("Subject: #{subject.identification}")
|
|
end
|
|
|
|
# Return error stream
|
|
#
|
|
# @return [IO]
|
|
#
|
|
# @api private
|
|
#
|
|
def error_stream
|
|
@config.debug? ? io : StringIO.new
|
|
end
|
|
|
|
# Return output stream
|
|
#
|
|
# @return [IO]
|
|
#
|
|
# @api private
|
|
#
|
|
def output_stream
|
|
@config.debug? ? io : StringIO.new
|
|
end
|
|
|
|
# Report mutation
|
|
#
|
|
# @param [Mutation] mutation
|
|
#
|
|
# @return [self]
|
|
#
|
|
# @api private
|
|
#
|
|
def mutation(mutation)
|
|
if @config.debug?
|
|
colorized_diff(mutation)
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
# Report config
|
|
#
|
|
# @param [Mutant::Config] config
|
|
#
|
|
# @return [self]
|
|
#
|
|
# @api private
|
|
#
|
|
def config(config)
|
|
puts 'Mutant configuration:'
|
|
puts "Matcher: #{config.matcher.inspect}"
|
|
puts "Filter: #{config.filter.inspect}"
|
|
puts "Strategy: #{config.strategy.inspect}"
|
|
end
|
|
|
|
# Report noop
|
|
#
|
|
# @param [Killer] killer
|
|
#
|
|
# @return [self]
|
|
#
|
|
# @api private
|
|
#
|
|
def noop(killer)
|
|
color, word =
|
|
if killer.fail?
|
|
[Color::GREEN, 'Alive']
|
|
else
|
|
[Color::RED, 'Killed']
|
|
end
|
|
|
|
print_killer(color, word, killer)
|
|
|
|
unless killer.fail?
|
|
puts(killer.mutation.source)
|
|
stats.noop_fail(killer)
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
# Reporter killer
|
|
#
|
|
# @param [Killer] killer
|
|
#
|
|
# @return [self]
|
|
#
|
|
# @api private
|
|
#
|
|
def killer(killer)
|
|
stats.killer(killer)
|
|
|
|
color, word =
|
|
if killer.fail?
|
|
[Color::RED, 'Alive']
|
|
else
|
|
[Color::GREEN, 'Killed']
|
|
end
|
|
|
|
print_killer(color, word, killer)
|
|
|
|
if killer.fail?
|
|
colorized_diff(killer.mutation)
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
# Report errors
|
|
#
|
|
# @param [Enumerable<Killer>] errors
|
|
#
|
|
# @api private
|
|
#
|
|
# @return [self]
|
|
#
|
|
def errors(errors)
|
|
errors.each do |error|
|
|
failure(error)
|
|
end
|
|
|
|
puts
|
|
puts "subjects: #{stats.subjects}"
|
|
puts "mutations: #{stats.mutations}"
|
|
puts "noop_fails: #{stats.noop_fails}"
|
|
puts "kills: #{stats.kills}"
|
|
puts "alive: #{stats.alive}"
|
|
puts "mtime: %02.2fs" % stats.time
|
|
puts "rtime: %02.2fs" % stats.runtime
|
|
end
|
|
|
|
# Return IO stream
|
|
#
|
|
# @return [IO]
|
|
#
|
|
# @api private
|
|
#
|
|
attr_reader :io
|
|
|
|
# Return stats
|
|
#
|
|
# @return [Stats]
|
|
#
|
|
# @api private
|
|
#
|
|
attr_reader :stats
|
|
|
|
private
|
|
|
|
# Initialize reporter
|
|
#
|
|
# @param [Config] config
|
|
#
|
|
# @return [undefined]
|
|
#
|
|
# @api private
|
|
#
|
|
def initialize(config)
|
|
super
|
|
@io = $stdout
|
|
@stats = Stats.new
|
|
end
|
|
|
|
# Report failure on killer
|
|
#
|
|
# @param [Killer] killer
|
|
#
|
|
# @return [undefined]
|
|
#
|
|
# @api private
|
|
#
|
|
def failure(killer)
|
|
puts(colorize(Color::RED, "!!! Mutant alive: #{killer.identification} !!!"))
|
|
colorized_diff(killer.mutation)
|
|
puts("Took: (%02.2fs)" % killer.runtime)
|
|
end
|
|
|
|
# Test for colored output
|
|
#
|
|
# @return [true]
|
|
# returns true if output is colored
|
|
#
|
|
# @return [false]
|
|
# returns false otherwise
|
|
#
|
|
# @api private
|
|
#
|
|
def color?
|
|
tty?
|
|
end
|
|
|
|
# Colorize message
|
|
#
|
|
# @param [Color] color
|
|
# @param [String] message
|
|
#
|
|
# @api private
|
|
#
|
|
# @return [String]
|
|
# returns colorized string if color is enabled
|
|
# returns unmodified message otherwise
|
|
#
|
|
def colorize(color, message)
|
|
color = Color::NONE unless color?
|
|
color.format(message)
|
|
end
|
|
|
|
# Write string to io
|
|
#
|
|
# @param [String] string
|
|
#
|
|
# @return [undefined]
|
|
#
|
|
# @api private
|
|
#
|
|
def puts(string="\n")
|
|
io.puts(string)
|
|
end
|
|
|
|
# Write colorized diff
|
|
#
|
|
# @param [Mutation] mutation
|
|
#
|
|
# @return [undefined]
|
|
#
|
|
# @api private
|
|
#
|
|
def colorized_diff(mutation)
|
|
if mutation.kind_of?(Mutation::Noop)
|
|
puts mutation.original_source
|
|
return
|
|
end
|
|
|
|
original, current = mutation.original_source, mutation.source
|
|
differ = Differ.new(original, current)
|
|
diff = color? ? differ.colorized_diff : differ.diff
|
|
|
|
# FIXME remove this branch before release
|
|
if diff.empty?
|
|
raise "Unable to create a diff, so ast mutation or to_source has an error!"
|
|
end
|
|
|
|
puts(diff)
|
|
self
|
|
end
|
|
|
|
# Print killer
|
|
#
|
|
# @param [Color] color
|
|
# @param [String] word
|
|
# @param [Killer] killer
|
|
#
|
|
# @return [undefined]
|
|
#
|
|
# @api private
|
|
#
|
|
def print_killer(color, word, killer)
|
|
puts(colorize(color, "#{word}: #{killer.identification} (%02.2fs)" % killer.runtime))
|
|
end
|
|
|
|
# Test for output to tty
|
|
#
|
|
# @return [true]
|
|
# returns true if output is a tty
|
|
#
|
|
# @return [false]
|
|
# returns false otherwise
|
|
#
|
|
# @api private
|
|
#
|
|
def tty?
|
|
@io.respond_to?(:tty?) && @io.tty?
|
|
end
|
|
memoize :tty?
|
|
end
|
|
end
|
|
end
|