free_mutant/lib/mutant/cli.rb

240 lines
5.2 KiB
Ruby
Raw Normal View History

# encoding: utf-8
require 'optparse'
2012-08-28 18:57:39 +02:00
module Mutant
# Comandline parser
class CLI
include Adamantium::Flat, Equalizer.new(:config)
2012-08-28 18:57:39 +02:00
2013-06-13 19:10:34 +02:00
# Error raised when CLI argv is invalid
Error = Class.new(RuntimeError)
EXIT_FAILURE = 1
EXIT_SUCCESS = 0
# Run cli with arguments
#
# @param [Array<String>] arguments
#
# @return [Fixnum]
# the exit status
#
# @api private
#
def self.run(arguments)
config = new(arguments).config
runner = Runner::Config.run(config)
runner.success? ? EXIT_SUCCESS : EXIT_FAILURE
rescue Error => exception
$stderr.puts(exception.message)
EXIT_FAILURE
end
# Initialize objecct
#
# @param [Array<String>]
#
# @return [undefined]
#
# @api private
#
def initialize(arguments = [])
@filters, @matchers = [], []
@debug = @fail_fast = @zombie = false
@cache = Mutant::Cache.new
parse(arguments)
config # trigger lazyness now
end
# Return config
#
# @return [Config]
#
# @api private
#
def config
Config.new(
cache: @cache,
zombie: @zombie,
debug: @debug,
matcher: matcher,
subject_predicate: @subject_predicate.output,
2014-01-18 00:15:42 +01:00
strategy: @strategy || Strategy::Null.new,
fail_fast: @fail_fast,
reporter: reporter
)
end
memoize :config
private
# Return reporter
#
# @return [Mutant::Reporter::CLI]
#
# @api private
#
def reporter
Reporter::CLI.new($stdout)
2012-08-28 18:57:39 +02:00
end
# Return matcher
#
# @return [Mutant::Matcher]
#
# @raise [CLI::Error]
# raises error when matcher is not given
#
# @api private
#
def matcher
if @matchers.empty?
raise(Error, 'No matchers given')
2012-08-28 18:57:39 +02:00
end
Matcher::Chain.build(@matchers)
2012-08-28 18:57:39 +02:00
end
# Add mutation filter
#
2013-09-07 23:12:03 +02:00
# @param [Class<Predicate>] klass
#
# @return [undefined]
#
# @api private
#
2013-09-07 18:57:06 +02:00
def add_filter(klass, *arguments)
@filters << klass.new(*arguments)
2012-08-28 18:57:39 +02:00
end
2013-06-15 16:37:43 +02:00
# Parse the command-line options
#
# @param [Array<String>] arguments
# Command-line options and arguments to be parsed.
#
# @raise [Error]
# An error occurred while parsing the options.
#
2013-06-15 16:37:43 +02:00
# @return [undefined]
#
# @api private
#
def parse(arguments)
2013-07-28 19:58:53 +02:00
opts = OptionParser.new do |builder|
builder.banner = 'usage: mutant STRATEGY [options] MATCHERS ...'
builder.separator('')
2013-07-28 19:58:53 +02:00
add_strategies(builder)
2013-08-04 23:43:57 +02:00
add_environmental_options(builder)
2013-07-28 19:58:53 +02:00
add_options(builder)
end
patterns =
2013-06-21 17:21:04 +02:00
begin
opts.parse!(arguments)
rescue OptionParser::ParseError => error
raise(Error, error.message, error.backtrace)
end
parse_matchers(patterns)
end
# Parse matchers
#
# @param [Enumerable<String>] patterns
#
2013-06-22 03:47:23 +02:00
# @return [undefined]
#
# @api private
#
def parse_matchers(patterns)
patterns.each do |pattern|
2013-09-11 22:06:32 +02:00
matcher = Classifier.run(@cache, pattern)
@matchers << matcher if matcher
end
end
2013-06-14 20:54:02 +02:00
2013-06-21 17:21:04 +02:00
# Add strategies
#
# @param [OptionParser] parser
2013-06-21 17:21:04 +02:00
#
2013-06-22 03:47:23 +02:00
# @return [undefined]
#
2013-06-21 17:21:04 +02:00
# @api private
#
def add_strategies(parser)
parser.separator(EMPTY_STRING)
parser.separator('Strategies:')
2014-01-18 00:15:42 +01:00
builder = Builder::Predicate::Subject.new(@cache, parser)
@subject_predicate = builder
2013-06-21 17:21:04 +02:00
end
2013-08-04 23:03:39 +02:00
# Add environmental options
#
# @param [Object] opts
#
# @return [undefined]
#
# @api private
#
def add_environmental_options(opts)
opts.on('--zombie', 'Run mutant zombified') do
@zombie = true
end.on('-I', '--include DIRECTORY', 'Add DIRECTORY to $LOAD_PATH') do |directory|
2013-08-04 23:03:39 +02:00
$LOAD_PATH << directory
2013-09-15 13:56:26 +02:00
end.on('-r', '--require NAME', 'Require file with NAME') do |name|
require(name)
2013-08-04 23:03:39 +02:00
end
end
2014-01-18 00:15:42 +01:00
# Add runner
#
# @param [String] runner_name
#
# @return [undefined]
#
# @api private
#
def set_strategy(name)
require "mutant/#{name}"
@strategy = Strategy.lookup(name).new
rescue LoadError
$stderr.puts("Cannot load strategy: #{name.inspect}")
raise
end
2013-06-21 17:21:04 +02:00
# Add options
#
2013-08-04 23:03:39 +02:00
# @param [Object] opts
2013-06-21 17:21:04 +02:00
#
2013-06-22 03:47:23 +02:00
# @return [undefined]
#
2013-06-21 17:21:04 +02:00
# @api private
#
def add_options(opts)
opts.separator ''
opts.separator 'Options:'
2014-01-18 00:15:42 +01:00
opts.on('--via STRATEGY', 'Use STRATEGY for killing mutations') do |runner|
set_strategy(runner)
end
opts.on('--version', 'Print mutants version') do |name|
2013-08-04 23:03:39 +02:00
puts("mutant-#{Mutant::VERSION}")
Kernel.exit(0)
2013-08-03 01:41:21 +02:00
end.on('--code FILTER', 'Adds a code filter') do |filter|
2013-09-07 23:12:03 +02:00
add_filter(Predicate::Attribute, :code, filter)
end.on('--fail-fast', 'Fail fast') do
2013-08-04 23:03:39 +02:00
@fail_fast = true
end.on('-d', '--debug', 'Enable debugging output') do
2013-08-04 23:03:39 +02:00
@debug = true
2013-06-21 17:21:04 +02:00
end.on_tail('-h', '--help', 'Show this message') do
2013-08-04 23:03:39 +02:00
puts(opts)
2013-06-21 17:21:04 +02:00
exit
end
end
2013-06-14 20:54:02 +02:00
end # CLI
end # Mutant