mutant 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -11
- data/.rspec +0 -1
- data/.travis.yml +14 -3
- data/Changelog.md +3 -0
- data/Gemfile +5 -1
- data/Gemfile.devtools +49 -0
- data/Guardfile +18 -0
- data/README.md +67 -0
- data/Rakefile +4 -1
- data/TODO +13 -0
- data/bin/mutant +14 -0
- data/bin/zombie +14 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/roodi.yml +26 -0
- data/config/site.reek +93 -0
- data/config/yardstick.yml +2 -0
- data/lib/inflector.rb +7 -0
- data/lib/inflector/defaults.rb +62 -0
- data/lib/inflector/inflections.rb +209 -0
- data/lib/inflector/methods.rb +149 -0
- data/lib/inflector/version.rb +3 -0
- data/lib/mutant.rb +96 -21
- data/lib/mutant/cli.rb +309 -0
- data/lib/mutant/color.rb +61 -0
- data/lib/mutant/context.rb +36 -0
- data/lib/mutant/context/scope.rb +138 -0
- data/lib/mutant/differ.rb +100 -0
- data/lib/mutant/helper.rb +38 -0
- data/lib/mutant/killer.rb +136 -0
- data/lib/mutant/killer/forking.rb +41 -0
- data/lib/mutant/killer/rspec.rb +49 -0
- data/lib/mutant/killer/static.rb +19 -0
- data/lib/mutant/loader.rb +129 -0
- data/lib/mutant/matcher.rb +55 -0
- data/lib/mutant/matcher/chain.rb +66 -0
- data/lib/mutant/matcher/method.rb +173 -0
- data/lib/mutant/matcher/method/classifier.rb +126 -0
- data/lib/mutant/matcher/method/instance.rb +67 -0
- data/lib/mutant/matcher/method/singleton.rb +141 -0
- data/lib/mutant/matcher/object_space.rb +114 -0
- data/lib/mutant/matcher/scope_methods.rb +127 -0
- data/lib/mutant/mutation.rb +101 -12
- data/lib/mutant/mutation/filter.rb +75 -0
- data/lib/mutant/mutation/filter/code.rb +68 -0
- data/lib/mutant/mutation/filter/regexp.rb +39 -0
- data/lib/mutant/mutation/filter/whitelist.rb +47 -0
- data/lib/mutant/mutator.rb +134 -30
- data/lib/mutant/mutator/node.rb +163 -0
- data/lib/mutant/mutator/node/arguments.rb +24 -0
- data/lib/mutant/mutator/node/block.rb +24 -0
- data/lib/mutant/mutator/node/define.rb +24 -0
- data/lib/mutant/mutator/node/if_statement.rb +93 -0
- data/lib/mutant/mutator/node/literal.rb +54 -0
- data/lib/mutant/mutator/node/literal/array.rb +28 -0
- data/lib/mutant/mutator/node/literal/boolean.rb +49 -0
- data/lib/mutant/mutator/node/literal/dynamic.rb +24 -0
- data/lib/mutant/mutator/node/literal/empty_array.rb +26 -0
- data/lib/mutant/mutator/node/literal/fixnum.rb +37 -0
- data/lib/mutant/mutator/node/literal/float.rb +48 -0
- data/lib/mutant/mutator/node/literal/hash.rb +89 -0
- data/lib/mutant/mutator/node/literal/nil.rb +25 -0
- data/lib/mutant/mutator/node/literal/range.rb +94 -0
- data/lib/mutant/mutator/node/literal/regex.rb +43 -0
- data/lib/mutant/mutator/node/literal/string.rb +26 -0
- data/lib/mutant/mutator/node/literal/symbol.rb +26 -0
- data/lib/mutant/mutator/node/noop.rb +55 -0
- data/lib/mutant/mutator/node/receiver_case.rb +140 -0
- data/lib/mutant/mutator/node/return.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +112 -0
- data/lib/mutant/mutator/registry.rb +48 -0
- data/lib/mutant/mutator/util.rb +87 -0
- data/lib/mutant/random.rb +24 -27
- data/lib/mutant/reporter.rb +48 -30
- data/lib/mutant/reporter/cli.rb +221 -0
- data/lib/mutant/reporter/null.rb +42 -0
- data/lib/mutant/reporter/stats.rb +64 -0
- data/lib/mutant/runner.rb +112 -0
- data/lib/mutant/strategy.rb +42 -0
- data/lib/mutant/strategy/rspec.rb +59 -0
- data/lib/mutant/strategy/rspec/example_lookup.rb +122 -0
- data/lib/mutant/subject.rb +115 -0
- data/lib/mutant/support/method_object.rb +31 -0
- data/locator.rb +87 -0
- data/mutant.gemspec +21 -21
- data/spec/integration/mutant/differ_spec.rb +15 -0
- data/spec/integration/mutant/loader_spec.rb +21 -0
- data/spec/integration/mutant/method_matching_spec.rb +269 -0
- data/spec/integration/mutant/rspec_killer_spec.rb +24 -0
- data/spec/integration/mutant/runner_spec.rb +26 -0
- data/spec/integration/mutant/zombie_spec.rb +8 -0
- data/spec/rcov.opts +7 -0
- data/spec/shared/command_method_behavior.rb +7 -0
- data/spec/shared/each_method_behaviour.rb +15 -0
- data/spec/shared/hash_method_behavior.rb +17 -0
- data/spec/shared/idempotent_method_behavior.rb +7 -0
- data/spec/shared/invertible_method_behaviour.rb +9 -0
- data/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/spec/shared/method_match_behavior.rb +39 -0
- data/spec/shared/mutator_behavior.rb +46 -0
- data/spec/spec_helper.rb +11 -14
- data/spec/support/compress_helper.rb +10 -0
- data/spec/support/rspec.rb +22 -0
- data/spec/support/test_app.rb +5 -0
- data/spec/support/zombie.rb +141 -0
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +87 -0
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +38 -0
- data/spec/unit/mutant/context/root_spec.rb +11 -0
- data/spec/unit/mutant/context/scope/class_methods/build_spec.rb +29 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +22 -0
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +27 -0
- data/spec/unit/mutant/killer/fail_ques_spec.rb +39 -0
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +32 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +33 -0
- data/spec/unit/mutant/loader/rubinius/class_methods/run_spec.rb +42 -0
- data/spec/unit/mutant/matcher/chain/each_spec.rb +37 -0
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +12 -0
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +49 -0
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +12 -0
- data/spec/unit/mutant/matcher/each_spec.rb +14 -0
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +21 -0
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +34 -0
- data/spec/unit/mutant/matcher/method/method_spec.rb +11 -0
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +24 -0
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +31 -0
- data/spec/unit/mutant/mutator/each_spec.rb +25 -0
- data/spec/unit/mutant/mutator/emit_new_spec.rb +51 -0
- data/spec/unit/mutant/mutator/emit_spec.rb +52 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +36 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +47 -0
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/array_spec.rb +30 -0
- data/spec/unit/mutant/mutator/node/literal/boolean/mutation_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/empty_array_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/float_spec.rb +25 -0
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +34 -0
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +13 -0
- data/spec/unit/mutant/mutator/node/literal/range_spec.rb +35 -0
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +23 -0
- data/spec/unit/mutant/mutator/node/literal/string_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/literal/symbol_spec.rb +17 -0
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +27 -0
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +21 -0
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +78 -0
- data/spec/unit/mutant/mutator/self_spec.rb +7 -0
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +13 -0
- data/spec/unit/mutant/subject/context_spec.rb +14 -0
- data/spec/unit/mutant/subject/each_spec.rb +35 -0
- data/spec/unit/mutant/subject/node_spec.rb +13 -0
- data/tasks/metrics/ci.rake +7 -0
- data/tasks/metrics/flay.rake +41 -0
- data/tasks/metrics/flog.rake +43 -0
- data/tasks/metrics/heckle.rake +216 -0
- data/tasks/metrics/metric_fu.rake +31 -0
- data/tasks/metrics/reek.rake +15 -0
- data/tasks/metrics/roodi.rake +15 -0
- data/tasks/metrics/yardstick.rake +23 -0
- data/tasks/spec.rake +45 -0
- data/tasks/yard.rake +9 -0
- data/test_app/.rspec +1 -0
- data/test_app/lib/test_app.rb +5 -0
- data/test_app/lib/test_app/literal.rb +32 -0
- data/test_app/spec/shared/command_method_behavior.rb +7 -0
- data/test_app/spec/shared/each_method_behaviour.rb +15 -0
- data/test_app/spec/shared/hash_method_behavior.rb +17 -0
- data/test_app/spec/shared/idempotent_method_behavior.rb +7 -0
- data/test_app/spec/shared/invertible_method_behaviour.rb +9 -0
- data/test_app/spec/shared/method_filter_parse_behavior.rb +16 -0
- data/test_app/spec/shared/method_match_behavior.rb +39 -0
- data/test_app/spec/shared/mutator_behavior.rb +44 -0
- data/test_app/spec/spec_helper.rb +7 -0
- data/test_app/spec/unit/test_app/literal/command_spec.rb +9 -0
- data/test_app/spec/unit/test_app/literal/string_spec.rb +9 -0
- metadata +346 -124
- data/.rvmrc +0 -1
- data/Readme.md +0 -13
- data/exe/mutate +0 -6
- data/lib/mutant/extensions.rb +0 -8
- data/lib/mutant/formatter.rb +0 -19
- data/lib/mutant/implementation.rb +0 -70
- data/lib/mutant/literal.rb +0 -147
- data/lib/mutant/method.rb +0 -31
- data/lib/mutant/mutatee.rb +0 -61
- data/lib/mutant/node.rb +0 -26
- data/lib/mutant/runners/rspec.rb +0 -34
- data/lib/mutant/version.rb +0 -3
- data/spec/functional/class_spec.rb +0 -46
- data/spec/functional/instance_method/array_spec.rb +0 -53
- data/spec/functional/instance_method/boolean_spec.rb +0 -101
- data/spec/functional/instance_method/call_spec.rb +0 -161
- data/spec/functional/instance_method/fixnum_spec.rb +0 -53
- data/spec/functional/instance_method/float_spec.rb +0 -53
- data/spec/functional/instance_method/hash_spec.rb +0 -53
- data/spec/functional/instance_method/if_spec.rb +0 -57
- data/spec/functional/instance_method/ivar_assign_spec.rb +0 -62
- data/spec/functional/instance_method/range_spec.rb +0 -53
- data/spec/functional/instance_method/regex_spec.rb +0 -55
- data/spec/functional/instance_method/string_spec.rb +0 -53
- data/spec/functional/instance_method/symbol_spec.rb +0 -53
- data/spec/functional/reporter/method_loaded_spec.rb +0 -62
- data/spec/functional/reporter/running_mutations_spec.rb +0 -60
- data/spec/functional/runners/rspec_spec.rb +0 -26
- data/spec/functional/singleton_method/array_spec.rb +0 -53
- data/spec/functional/singleton_method/boolean_spec.rb +0 -101
- data/spec/functional/singleton_method/call_spec.rb +0 -161
- data/spec/functional/singleton_method/fixnum_spec.rb +0 -53
- data/spec/functional/singleton_method/float_spec.rb +0 -53
- data/spec/functional/singleton_method/hash_spec.rb +0 -53
- data/spec/functional/singleton_method/if_spec.rb +0 -57
- data/spec/functional/singleton_method/ivar_assign_spec.rb +0 -60
- data/spec/functional/singleton_method/range_spec.rb +0 -53
- data/spec/functional/singleton_method/regex_spec.rb +0 -55
- data/spec/functional/singleton_method/string_spec.rb +0 -53
- data/spec/functional/singleton_method/symbol_spec.rb +0 -53
- data/spec/mutant/extensions_spec.rb +0 -13
- data/spec/mutant/implementation_spec.rb +0 -223
- data/spec/mutant/literal_spec.rb +0 -129
- data/spec/mutant/mutatee_spec.rb +0 -28
- data/spec/mutant/node_spec.rb +0 -41
- data/spec/mutant/random_spec.rb +0 -33
- data/spec/mutant/reporter_spec.rb +0 -17
- data/spec/mutant_spec.rb +0 -28
- data/spec/support/example_group_helpers.rb +0 -11
- data/spec/support/example_helpers.rb +0 -5
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Mutator
|
|
3
|
+
class Node
|
|
4
|
+
# Class for mutations where messages are send to objects
|
|
5
|
+
class Send < self
|
|
6
|
+
|
|
7
|
+
handle(Rubinius::AST::Send)
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Return receiver AST node
|
|
12
|
+
#
|
|
13
|
+
# @return [Rubinius::AST::Node]
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
def receiver
|
|
18
|
+
node.receiver
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Return name of call
|
|
22
|
+
#
|
|
23
|
+
# @return [Symbol]
|
|
24
|
+
#
|
|
25
|
+
# @api private
|
|
26
|
+
#
|
|
27
|
+
def name
|
|
28
|
+
node.name
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Check if receiver is self
|
|
32
|
+
#
|
|
33
|
+
# @return [true]
|
|
34
|
+
# returns true when receiver is a Rubinius::AST::Self node
|
|
35
|
+
#
|
|
36
|
+
# @return [false]
|
|
37
|
+
# return false otherwise
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
#
|
|
41
|
+
def self?
|
|
42
|
+
receiver.kind_of?(Rubinius::AST::Self)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Emit mutation that replaces explicit send to self with implicit send to self
|
|
46
|
+
#
|
|
47
|
+
# @example:
|
|
48
|
+
#
|
|
49
|
+
# # This class does use Foo#a with explicitly specifing the receiver self.
|
|
50
|
+
# # But an implicit (privately) call should be used as there is no need for
|
|
51
|
+
# # specifing en explicit receiver.
|
|
52
|
+
#
|
|
53
|
+
# class Foo # Mutation
|
|
54
|
+
# def print_a # def print_a
|
|
55
|
+
# puts self.a # puts a
|
|
56
|
+
# end # end
|
|
57
|
+
#
|
|
58
|
+
# def a
|
|
59
|
+
# :bar
|
|
60
|
+
# end
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
63
|
+
# There will not be any exception so the mutant is not killed and such calls where
|
|
64
|
+
# implicit receiver should be used will be spotted.
|
|
65
|
+
#
|
|
66
|
+
# @return [undefined]
|
|
67
|
+
#
|
|
68
|
+
# @api private
|
|
69
|
+
#
|
|
70
|
+
def emit_implicit_self_receiver
|
|
71
|
+
# FIXME: Edge case that is currently not very well undestood
|
|
72
|
+
return if name == :block_given?
|
|
73
|
+
return unless self?
|
|
74
|
+
mutant = dup_node
|
|
75
|
+
mutant.privately = true
|
|
76
|
+
# TODO: Fix rubinius to allow this as an attr_accessor
|
|
77
|
+
mutant.instance_variable_set(:@vcall_style, true)
|
|
78
|
+
emit(mutant)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Emit mutations
|
|
82
|
+
#
|
|
83
|
+
# @return [undefined]
|
|
84
|
+
#
|
|
85
|
+
# @api private
|
|
86
|
+
#
|
|
87
|
+
def dispatch
|
|
88
|
+
emit_implicit_self_receiver
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
class SendWithArguments < self
|
|
92
|
+
|
|
93
|
+
handle(Rubinius::AST::SendWithArguments)
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
|
|
97
|
+
# Emit mutations
|
|
98
|
+
#
|
|
99
|
+
# @return [undefined]
|
|
100
|
+
#
|
|
101
|
+
# @api private
|
|
102
|
+
#
|
|
103
|
+
def dispatch
|
|
104
|
+
super
|
|
105
|
+
emit_attribute_mutations(:arguments)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Mutator
|
|
3
|
+
# Registry for mutators
|
|
4
|
+
module Registry
|
|
5
|
+
# Return registry state
|
|
6
|
+
#
|
|
7
|
+
# @return [Hash]
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
#
|
|
11
|
+
def self.registry
|
|
12
|
+
@registry ||= {}
|
|
13
|
+
end
|
|
14
|
+
private_class_method :registry
|
|
15
|
+
|
|
16
|
+
# Register mutator class for AST node class
|
|
17
|
+
#
|
|
18
|
+
# @param [Class] ast_class
|
|
19
|
+
# @param [Class] mutator_class
|
|
20
|
+
#
|
|
21
|
+
# @api private
|
|
22
|
+
#
|
|
23
|
+
# @return [self]
|
|
24
|
+
#
|
|
25
|
+
def self.register(ast_class,mutator_class)
|
|
26
|
+
registry[ast_class]=mutator_class
|
|
27
|
+
self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Lookup mutator class for AST node class
|
|
31
|
+
#
|
|
32
|
+
# @param [Class] ast_class
|
|
33
|
+
#
|
|
34
|
+
# @return [Class]
|
|
35
|
+
#
|
|
36
|
+
# @raise [ArgumentError]
|
|
37
|
+
# raises argument error when mutator class cannot be found
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
#
|
|
41
|
+
def self.lookup(ast_class)
|
|
42
|
+
registry.fetch(ast_class) do
|
|
43
|
+
raise ArgumentError,"No mutator to handle: #{ast_class.inspect}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Mutator
|
|
3
|
+
# Namespace for utility mutators
|
|
4
|
+
class Util < self
|
|
5
|
+
|
|
6
|
+
# Run ulitity mutator
|
|
7
|
+
#
|
|
8
|
+
# @param [Object]
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
#
|
|
12
|
+
def self.each(object, &block)
|
|
13
|
+
return to_enum(__method__, object) unless block_given?
|
|
14
|
+
|
|
15
|
+
new(object, block)
|
|
16
|
+
|
|
17
|
+
self
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Test if mutation is new
|
|
21
|
+
#
|
|
22
|
+
# @param [Object] generated
|
|
23
|
+
#
|
|
24
|
+
# @return [true]
|
|
25
|
+
# if object is new
|
|
26
|
+
#
|
|
27
|
+
# @return [false]
|
|
28
|
+
# otherwise
|
|
29
|
+
#
|
|
30
|
+
def new?(generated)
|
|
31
|
+
input != generated
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Mutators that mutates an array of inputs
|
|
35
|
+
class Array < self
|
|
36
|
+
|
|
37
|
+
handle(::Array)
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
# Emit mutations
|
|
42
|
+
#
|
|
43
|
+
# @return [undefined]
|
|
44
|
+
#
|
|
45
|
+
# @api private
|
|
46
|
+
#
|
|
47
|
+
def dispatch
|
|
48
|
+
emit_element_presence
|
|
49
|
+
emit_element_mutations
|
|
50
|
+
emit([])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Emit element mutations
|
|
54
|
+
#
|
|
55
|
+
# @return [undefined]
|
|
56
|
+
#
|
|
57
|
+
# @api private
|
|
58
|
+
#
|
|
59
|
+
def emit_element_mutations
|
|
60
|
+
input.each_with_index do |element, index|
|
|
61
|
+
dup = dup_input
|
|
62
|
+
|
|
63
|
+
Mutator.each(element).each do |mutation|
|
|
64
|
+
dup[index]=mutation
|
|
65
|
+
emit(dup)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Emit element presence mutations
|
|
71
|
+
#
|
|
72
|
+
# @return [undefined]
|
|
73
|
+
#
|
|
74
|
+
# @api private
|
|
75
|
+
#
|
|
76
|
+
def emit_element_presence
|
|
77
|
+
input.each_index do |index|
|
|
78
|
+
dup = dup_input
|
|
79
|
+
dup.delete_at(index)
|
|
80
|
+
emit(dup)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
data/lib/mutant/random.rb
CHANGED
|
@@ -1,37 +1,34 @@
|
|
|
1
1
|
module Mutant
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def self.symbol
|
|
13
|
-
ENV.fetch('RANDOM_SYMBOL') {
|
|
14
|
-
Array.new(rand(50).next) { ALLOWED_SYMBOL_CHARACTERS.send RANDOM_METHOD }.join
|
|
15
|
-
}.to_sym
|
|
2
|
+
# Module for generating random values
|
|
3
|
+
module Random
|
|
4
|
+
# Return random hex string
|
|
5
|
+
#
|
|
6
|
+
# @return [String]
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
#
|
|
10
|
+
def self.hex_string
|
|
11
|
+
SecureRandom.hex(10)
|
|
16
12
|
end
|
|
17
13
|
|
|
14
|
+
# Return random fixnum
|
|
15
|
+
#
|
|
16
|
+
# @return [Fixnum]
|
|
17
|
+
#
|
|
18
|
+
# @api private
|
|
19
|
+
#
|
|
18
20
|
def self.fixnum
|
|
19
|
-
|
|
21
|
+
::Random.rand(1000)
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
# Return random float
|
|
25
|
+
#
|
|
26
|
+
# @return [Float]
|
|
27
|
+
#
|
|
28
|
+
# @api private
|
|
29
|
+
#
|
|
22
30
|
def self.float
|
|
23
|
-
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def self.range
|
|
27
|
-
if ENV['RANDOM_RANGE_MIN'] and ENV['RANDOM_RANGE_MAX']
|
|
28
|
-
min, max = ENV['RANDOM_RANGE_MIN'].to_i, ENV['RANDOM_RANGE_MAX'].to_i
|
|
29
|
-
else
|
|
30
|
-
min, max = rand(50)
|
|
31
|
-
max = min + rand(50)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
Range.new(min, max)
|
|
31
|
+
::Random.rand
|
|
35
32
|
end
|
|
36
33
|
end
|
|
37
34
|
end
|
data/lib/mutant/reporter.rb
CHANGED
|
@@ -1,38 +1,56 @@
|
|
|
1
1
|
module Mutant
|
|
2
|
+
# Abstract reporter
|
|
2
3
|
class Reporter
|
|
3
|
-
|
|
4
|
+
include Adamantium::Flat, AbstractType
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
# Report subject
|
|
7
|
+
#
|
|
8
|
+
# @param [Subject] subject
|
|
9
|
+
#
|
|
10
|
+
# @return [self]
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
#
|
|
14
|
+
abstract_method :subject
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
16
|
+
# Report mutation
|
|
17
|
+
#
|
|
18
|
+
# @param [Mutation] mutation
|
|
19
|
+
#
|
|
20
|
+
# @return [self]
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
#
|
|
24
|
+
abstract_method :mutation
|
|
15
25
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
26
|
+
# Report notice
|
|
27
|
+
#
|
|
28
|
+
# @param [String] notice
|
|
29
|
+
#
|
|
30
|
+
# @return [self]
|
|
31
|
+
#
|
|
32
|
+
# @api private
|
|
33
|
+
#
|
|
34
|
+
abstract_method :notice
|
|
19
35
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
36
|
+
# Report killer
|
|
37
|
+
#
|
|
38
|
+
# @param [Killer] killer
|
|
39
|
+
#
|
|
40
|
+
# @return [self]
|
|
41
|
+
#
|
|
42
|
+
# @api private
|
|
43
|
+
#
|
|
44
|
+
abstract_method :killer
|
|
26
45
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
end
|
|
46
|
+
# Report config
|
|
47
|
+
#
|
|
48
|
+
# @param [Mutant::Config] config
|
|
49
|
+
#
|
|
50
|
+
# @return [self]
|
|
51
|
+
#
|
|
52
|
+
# @api private
|
|
53
|
+
#
|
|
54
|
+
abstract_method :config
|
|
37
55
|
end
|
|
38
|
-
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
# Reporter that reports in human readable format
|
|
4
|
+
class CLI < self
|
|
5
|
+
include Equalizer.new(:io)
|
|
6
|
+
|
|
7
|
+
# Reporter subject
|
|
8
|
+
#
|
|
9
|
+
# @param [Subject] subject
|
|
10
|
+
#
|
|
11
|
+
# @return [self]
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
#
|
|
15
|
+
def subject(subject)
|
|
16
|
+
stats.subject
|
|
17
|
+
puts("Subject: #{subject.identification}")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Report mutation
|
|
21
|
+
#
|
|
22
|
+
# @param [Mutation] mutation
|
|
23
|
+
#
|
|
24
|
+
# @return [self]
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
def mutation(mutation)
|
|
29
|
+
#colorized_diff(mutation.original_source, mutation.source)
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Report config
|
|
34
|
+
#
|
|
35
|
+
# @param [Mutant::Config] config
|
|
36
|
+
#
|
|
37
|
+
# @return [self]
|
|
38
|
+
#
|
|
39
|
+
# @api private
|
|
40
|
+
#
|
|
41
|
+
def config(config)
|
|
42
|
+
puts 'Mutant configuration:'
|
|
43
|
+
puts "Matcher: #{config.matcher.inspect}"
|
|
44
|
+
puts "Filter: #{config.filter.inspect}"
|
|
45
|
+
puts "Strategy: #{config.strategy.inspect}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Reporter killer
|
|
49
|
+
#
|
|
50
|
+
# @param [Killer] killer
|
|
51
|
+
#
|
|
52
|
+
# @return [self]
|
|
53
|
+
#
|
|
54
|
+
# @api private
|
|
55
|
+
#
|
|
56
|
+
def killer(killer)
|
|
57
|
+
stats.killer(killer)
|
|
58
|
+
|
|
59
|
+
color, word =
|
|
60
|
+
if killer.fail?
|
|
61
|
+
[Color::RED, 'Alive']
|
|
62
|
+
else
|
|
63
|
+
[Color::GREEN, 'Killed']
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
puts(colorize(color, "#{word}: #{killer.identification} (%02.2fs)" % killer.runtime))
|
|
67
|
+
|
|
68
|
+
if killer.fail?
|
|
69
|
+
mutation = killer.mutation
|
|
70
|
+
colorized_diff(mutation.original_source, mutation.source)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
self
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Report errors
|
|
77
|
+
#
|
|
78
|
+
# @param [Enumerable<Killer>]
|
|
79
|
+
#
|
|
80
|
+
# @api private
|
|
81
|
+
#
|
|
82
|
+
# @return [self]
|
|
83
|
+
#
|
|
84
|
+
def errors(errors)
|
|
85
|
+
errors.each do |error|
|
|
86
|
+
failure(error)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
puts
|
|
90
|
+
puts "subjects: #{stats.subject}"
|
|
91
|
+
puts "mutations: #{stats.mutation}"
|
|
92
|
+
puts "kills: #{stats.kill}"
|
|
93
|
+
puts "alive: #{stats.alive}"
|
|
94
|
+
puts "mtime: %02.2fs" % stats.time
|
|
95
|
+
puts "rtime: %02.2fs" % stats.runtime
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Return IO stream
|
|
99
|
+
#
|
|
100
|
+
# @return [IO]
|
|
101
|
+
#
|
|
102
|
+
# @api private
|
|
103
|
+
#
|
|
104
|
+
attr_reader :io
|
|
105
|
+
|
|
106
|
+
# Return stats
|
|
107
|
+
#
|
|
108
|
+
# @return [Stats]
|
|
109
|
+
#
|
|
110
|
+
# @api private
|
|
111
|
+
#
|
|
112
|
+
attr_reader :stats
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
# Initialize reporter
|
|
117
|
+
#
|
|
118
|
+
# @param [IO] io
|
|
119
|
+
#
|
|
120
|
+
# @return [undefined]
|
|
121
|
+
#
|
|
122
|
+
# @api private
|
|
123
|
+
#
|
|
124
|
+
def initialize(io)
|
|
125
|
+
@io = io
|
|
126
|
+
@stats = Stats.new
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Report failure on killer
|
|
130
|
+
#
|
|
131
|
+
# @param [Killer] killer
|
|
132
|
+
#
|
|
133
|
+
# @return [undefined]
|
|
134
|
+
#
|
|
135
|
+
# @api private
|
|
136
|
+
#
|
|
137
|
+
def failure(killer)
|
|
138
|
+
puts(colorize(Color::RED, "!!! Mutant alive: #{killer.identification} !!!"))
|
|
139
|
+
colorized_diff(killer.original_source, killer.mutation_source)
|
|
140
|
+
puts("Took: (%02.2fs)" % killer.runtime)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# Test for colored output
|
|
144
|
+
#
|
|
145
|
+
# @return [true]
|
|
146
|
+
# returns true if output is colored
|
|
147
|
+
#
|
|
148
|
+
# @return [false]
|
|
149
|
+
# returns false otherwise
|
|
150
|
+
#
|
|
151
|
+
# @api private
|
|
152
|
+
#
|
|
153
|
+
def color?
|
|
154
|
+
tty?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Colorize message
|
|
158
|
+
#
|
|
159
|
+
# @param [Color] color
|
|
160
|
+
# @param [String] message
|
|
161
|
+
#
|
|
162
|
+
# @api private
|
|
163
|
+
#
|
|
164
|
+
# @return [String]
|
|
165
|
+
# returns colorized string if color is enabled
|
|
166
|
+
# returns unmodified message otherwise
|
|
167
|
+
#
|
|
168
|
+
def colorize(color, message)
|
|
169
|
+
color = Color::NONE unless color?
|
|
170
|
+
color.format(message)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Write string to io
|
|
174
|
+
#
|
|
175
|
+
# @param [String] string
|
|
176
|
+
#
|
|
177
|
+
# @return [undefined]
|
|
178
|
+
#
|
|
179
|
+
# @api private
|
|
180
|
+
#
|
|
181
|
+
def puts(string="\n")
|
|
182
|
+
io.puts(string)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Write colorized diff
|
|
186
|
+
#
|
|
187
|
+
# @param [String] original
|
|
188
|
+
# @param [String] current
|
|
189
|
+
#
|
|
190
|
+
# @return [self]
|
|
191
|
+
#
|
|
192
|
+
# @api private
|
|
193
|
+
#
|
|
194
|
+
def colorized_diff(original, current)
|
|
195
|
+
differ = Differ.new(original, current)
|
|
196
|
+
diff = color? ? differ.colorized_diff : differ.diff
|
|
197
|
+
# FIXME remove this branch before release
|
|
198
|
+
if diff.empty?
|
|
199
|
+
raise "Unable to create a diff, so ast mutation or to_source has an error!"
|
|
200
|
+
end
|
|
201
|
+
puts(diff)
|
|
202
|
+
self
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Test for output to tty
|
|
206
|
+
#
|
|
207
|
+
# @return [true]
|
|
208
|
+
# returns true if output is a tty
|
|
209
|
+
#
|
|
210
|
+
# @return [false]
|
|
211
|
+
# returns false otherwise
|
|
212
|
+
#
|
|
213
|
+
# @api private
|
|
214
|
+
#
|
|
215
|
+
def tty?
|
|
216
|
+
@io.respond_to?(:tty?) && @io.tty?
|
|
217
|
+
end
|
|
218
|
+
memoize :tty?
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|