mutant 0.2.20 → 0.3.0.beta2
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.
- checksums.yaml +7 -0
- data/.travis.yml +10 -11
- data/Changelog.md +93 -38
- data/Gemfile +3 -1
- data/Gemfile.devtools +16 -20
- data/Guardfile +1 -1
- data/README.md +36 -16
- data/Rakefile +21 -2
- data/TODO +11 -7
- data/bin/mutant +4 -0
- data/bin/zombie +4 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/{site.reek → reek.yml} +94 -70
- data/lib/mutant/cli/classifier/method.rb +100 -0
- data/lib/mutant/cli/classifier/namespace.rb +47 -0
- data/lib/mutant/cli/classifier/scope.rb +35 -0
- data/lib/mutant/cli/classifier.rb +141 -0
- data/lib/mutant/cli.rb +115 -162
- data/lib/mutant/color.rb +2 -2
- data/lib/mutant/config.rb +27 -0
- data/lib/mutant/constants.rb +32 -17
- data/lib/mutant/context/scope.rb +33 -51
- data/lib/mutant/context.rb +8 -19
- data/lib/mutant/differ.rb +5 -5
- data/lib/mutant/helper.rb +2 -17
- data/lib/mutant/killer/forked.rb +44 -0
- data/lib/mutant/killer/forking.rb +3 -57
- data/lib/mutant/killer/rspec.rb +16 -20
- data/lib/mutant/killer/static.rb +6 -7
- data/lib/mutant/killer.rb +48 -74
- data/lib/mutant/loader.rb +6 -6
- data/lib/mutant/matcher/chain.rb +4 -25
- data/lib/mutant/matcher/method/instance.rb +14 -24
- data/lib/mutant/matcher/method/singleton.rb +35 -46
- data/lib/mutant/matcher/method.rb +95 -83
- data/lib/mutant/matcher/{scope_methods.rb → methods.rb} +53 -76
- data/lib/mutant/matcher/namespace.rb +71 -0
- data/lib/mutant/matcher/scope.rb +34 -0
- data/lib/mutant/matcher.rb +24 -34
- data/lib/mutant/mutation/evil.rb +35 -0
- data/lib/mutant/mutation/filter/code.rb +7 -28
- data/lib/mutant/mutation/filter/regexp.rb +6 -18
- data/lib/mutant/mutation/filter/whitelist.rb +5 -4
- data/lib/mutant/mutation/filter.rb +10 -9
- data/lib/mutant/mutation/neutral.rb +35 -0
- data/lib/mutant/mutation.rb +21 -61
- data/lib/mutant/mutator/node/argument.rb +88 -0
- data/lib/mutant/mutator/node/arguments.rb +52 -0
- data/lib/mutant/mutator/node/assignment.rb +34 -38
- data/lib/mutant/mutator/node/begin.rb +33 -0
- data/lib/mutant/mutator/node/block.rb +14 -14
- data/lib/mutant/mutator/node/case.rb +59 -0
- data/lib/mutant/mutator/node/define.rb +26 -22
- data/lib/mutant/mutator/node/if.rb +31 -71
- data/lib/mutant/mutator/node/literal/array.rb +25 -9
- data/lib/mutant/mutator/node/literal/boolean.rb +13 -30
- data/lib/mutant/mutator/node/literal/dynamic.rb +6 -5
- data/lib/mutant/mutator/node/literal/fixnum.rb +18 -7
- data/lib/mutant/mutator/node/literal/float.rb +15 -8
- data/lib/mutant/mutator/node/literal/hash.rb +33 -52
- data/lib/mutant/mutator/node/literal/nil.rb +8 -7
- data/lib/mutant/mutator/node/literal/range.rb +25 -50
- data/lib/mutant/mutator/node/literal/regex.rb +15 -23
- data/lib/mutant/mutator/node/literal/string.rb +7 -6
- data/lib/mutant/mutator/node/literal/symbol.rb +7 -6
- data/lib/mutant/mutator/node/literal.rb +4 -46
- data/lib/mutant/mutator/node/mlhs.rb +27 -0
- data/lib/mutant/mutator/node/noop.rb +18 -43
- data/lib/mutant/mutator/node/return.rb +8 -8
- data/lib/mutant/mutator/node/send/binary.rb +31 -0
- data/lib/mutant/mutator/node/send.rb +106 -72
- data/lib/mutant/mutator/node/super.rb +15 -20
- data/lib/mutant/mutator/node/when.rb +32 -7
- data/lib/mutant/mutator/node/while.rb +9 -7
- data/lib/mutant/mutator/node.rb +116 -66
- data/lib/mutant/mutator/registry.rb +14 -11
- data/lib/mutant/mutator/util/array.rb +9 -9
- data/lib/mutant/mutator/util/symbol.rb +6 -20
- data/lib/mutant/mutator/util.rb +6 -3
- data/lib/mutant/mutator.rb +12 -28
- data/lib/mutant/node_helpers.rb +28 -0
- data/lib/mutant/random.rb +3 -2
- data/lib/mutant/reporter/cli/printer/config.rb +174 -0
- data/lib/mutant/reporter/cli/printer/killer.rb +42 -0
- data/lib/mutant/reporter/cli/printer/mutation.rb +55 -0
- data/lib/mutant/reporter/cli/printer/subject.rb +147 -0
- data/lib/mutant/reporter/cli/printer.rb +165 -0
- data/lib/mutant/reporter/cli.rb +9 -277
- data/lib/mutant/reporter/null.rb +6 -30
- data/lib/mutant/reporter.rb +6 -73
- data/lib/mutant/runner/config.rb +82 -0
- data/lib/mutant/runner/mutation.rb +58 -0
- data/lib/mutant/runner/subject.rb +81 -0
- data/lib/mutant/runner.rb +42 -92
- data/lib/mutant/singleton_methods.rb +2 -2
- data/lib/mutant/strategy/method_expansion.rb +51 -0
- data/lib/mutant/strategy/rspec/dm2/lookup/method.rb +142 -0
- data/lib/mutant/strategy/rspec/dm2/lookup.rb +61 -0
- data/lib/mutant/strategy/rspec/dm2.rb +22 -0
- data/lib/mutant/strategy/rspec.rb +20 -22
- data/lib/mutant/strategy/static.rb +18 -0
- data/lib/mutant/strategy.rb +15 -50
- data/lib/mutant/subject/method.rb +100 -0
- data/lib/mutant/subject.rb +18 -49
- data/lib/mutant/support/method_object.rb +4 -2
- data/lib/mutant.rb +40 -35
- data/mutant.gemspec +9 -8
- data/spec/integration/mutant/rspec_killer_spec.rb +3 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +9 -0
- data/spec/integration/mutant/zombie_spec.rb +1 -1
- data/spec/shared/method_matcher_behavior.rb +35 -0
- data/spec/shared/mutator_behavior.rb +63 -32
- data/spec/spec_helper.rb +13 -3
- data/spec/support/ice_nine_config.rb +8 -0
- data/spec/support/rspec.rb +1 -1
- data/spec/support/zombie.rb +1 -1
- data/spec/unit/mutant/cli/class_methods/new_spec.rb +42 -28
- data/spec/unit/mutant/cli/class_methods/run_spec.rb +15 -13
- data/spec/unit/mutant/cli/classifier/class_methods/build_spec.rb +44 -0
- data/spec/unit/mutant/context/scope/root_spec.rb +4 -4
- data/spec/unit/mutant/killer/rspec/class_methods/new_spec.rb +6 -5
- data/spec/unit/mutant/killer/success_predicate_spec.rb +28 -0
- data/spec/unit/mutant/loader/eval/class_methods/run_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/each_spec.rb +1 -1
- data/spec/unit/mutant/matcher/chain/matchers_spec.rb +1 -1
- data/spec/unit/mutant/matcher/method/instance/each_spec.rb +112 -0
- data/spec/unit/mutant/matcher/method/singleton/each_spec.rb +93 -0
- data/spec/unit/mutant/matcher/methods/instance/each_spec.rb +59 -0
- data/spec/unit/mutant/matcher/methods/singleton/each_spec.rb +53 -0
- data/spec/unit/mutant/matcher/namespace/each_spec.rb +37 -0
- data/spec/unit/mutant/mutator/node/begin/mutation_spec.rb +33 -0
- data/spec/unit/mutant/mutator/node/block/mutation_spec.rb +42 -14
- data/spec/unit/mutant/mutator/node/case/mutation_spec.rb +319 -0
- data/spec/unit/mutant/mutator/node/define/mutation_spec.rb +31 -27
- data/spec/unit/mutant/mutator/node/if/mutation_spec.rb +75 -0
- data/spec/unit/mutant/mutator/node/literal/fixnum_spec.rb +1 -1
- data/spec/unit/mutant/mutator/node/literal/hash_spec.rb +2 -2
- data/spec/unit/mutant/mutator/node/literal/nil_spec.rb +1 -3
- data/spec/unit/mutant/mutator/node/literal/regex_spec.rb +1 -9
- data/spec/unit/mutant/mutator/node/return/mutation_spec.rb +6 -2
- data/spec/unit/mutant/mutator/node/send/mutation_spec.rb +111 -108
- data/spec/unit/mutant/mutator/node/super/mutation_spec.rb +0 -33
- data/spec/unit/mutant/mutator/node/while/mutation_spec.rb +2 -2
- data/spec/unit/mutant/runner/config/subjects_spec.rb +38 -0
- data/spec/unit/mutant/runner/config/success_predicate_spec.rb +53 -0
- data/spec/unit/mutant/runner/failed_predicte_spec.rb +33 -0
- data/spec/unit/mutant/runner/mutation/killer_spec.rb +39 -0
- data/spec/unit/mutant/runner/subject/success_predicate_spec.rb +49 -0
- data/spec/unit/mutant/strategy/method_expansion/class_methods/run_spec.rb +49 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/instance/spec_files_spec.rb +52 -0
- data/spec/unit/mutant/strategy/rspec/dm2/lookup/method/singleton/spec_files_spec.rb +42 -0
- data/spec/unit/mutant/subject/context_spec.rb +6 -3
- data/spec/unit/mutant/subject/each_spec.rb +11 -8
- data/spec/unit/mutant/subject/node_spec.rb +6 -2
- data/test_app/spec/shared/method_filter_parse_behavior.rb +0 -2
- data/test_app/spec/shared/method_match_behavior.rb +1 -1
- data/test_app/spec/spec_helper.rb +4 -2
- metadata +101 -109
- data/config/roodi.yml +0 -26
- data/lib/mutant/matcher/method/classifier.rb +0 -141
- data/lib/mutant/matcher/object_space.rb +0 -114
- data/lib/mutant/mutator/node/actual_arguments.rb +0 -25
- data/lib/mutant/mutator/node/default_arguments.rb +0 -25
- data/lib/mutant/mutator/node/formal_arguments_19/default_mutations.rb +0 -33
- data/lib/mutant/mutator/node/formal_arguments_19/pattern_argument_expansion.rb +0 -35
- data/lib/mutant/mutator/node/formal_arguments_19/require_defaults.rb +0 -37
- data/lib/mutant/mutator/node/formal_arguments_19.rb +0 -41
- data/lib/mutant/mutator/node/iter_19.rb +0 -27
- data/lib/mutant/mutator/node/literal/empty_array.rb +0 -26
- data/lib/mutant/mutator/node/pattern_arguments.rb +0 -41
- data/lib/mutant/mutator/node/pattern_variable.rb +0 -23
- data/lib/mutant/mutator/node/receiver_case.rb +0 -122
- data/lib/mutant/mutator/node/send/binary_operator_method.rb +0 -61
- data/lib/mutant/mutator/node/send/with_arguments.rb +0 -81
- data/lib/mutant/reporter/stats.rb +0 -120
- data/lib/mutant/strategy/rspec/example_lookup.rb +0 -163
- data/spec/integration/mutant/method_matching_spec.rb +0 -269
- data/spec/shared/method_match_behavior.rb +0 -39
- data/spec/unit/mutant/killer/fail_ques_spec.rb +0 -39
- data/spec/unit/mutant/matcher/class_methods/from_string_spec.rb +0 -49
- data/spec/unit/mutant/matcher/class_methods/parse_spec.rb +0 -12
- data/spec/unit/mutant/matcher/method/class_methods/parse_spec.rb +0 -21
- data/spec/unit/mutant/matcher/method/classifier/class_methods/run_spec.rb +0 -52
- data/spec/unit/mutant/matcher/object_space/class_methods/parse_spec.rb +0 -24
- data/spec/unit/mutant/matcher/object_space/each_spec.rb +0 -31
- data/spec/unit/mutant/mutator/node/if_statement/mutation_spec.rb +0 -60
- data/spec/unit/mutant/mutator/node/receiver_case/mutation_spec.rb +0 -27
- data/spec/unit/mutant/strategy/rspec/example_lookup/spec_file_spec.rb +0 -236
- data/spec/unit/mutant/subject/class_methods/new_spec.rb +0 -13
- data/tasks/metrics/ci.rake +0 -7
- data/tasks/metrics/flay.rake +0 -41
- data/tasks/metrics/flog.rake +0 -43
- data/tasks/metrics/heckle.rake +0 -216
- data/tasks/metrics/metric_fu.rake +0 -31
- data/tasks/metrics/reek.rake +0 -15
- data/tasks/metrics/roodi.rake +0 -15
- data/tasks/metrics/yardstick.rake +0 -23
- data/tasks/spec.rake +0 -45
- data/tasks/yard.rake +0 -9
|
@@ -2,10 +2,20 @@ module Mutant
|
|
|
2
2
|
class Mutator
|
|
3
3
|
class Node
|
|
4
4
|
class Literal
|
|
5
|
+
|
|
5
6
|
# Abstract literal range mutator
|
|
6
7
|
class Range < self
|
|
7
8
|
include AbstractType
|
|
8
9
|
|
|
10
|
+
MAP = {
|
|
11
|
+
:irange => :erange,
|
|
12
|
+
:erange => :irange
|
|
13
|
+
}.freeze
|
|
14
|
+
|
|
15
|
+
children :start, :_end
|
|
16
|
+
|
|
17
|
+
handle(*MAP.keys)
|
|
18
|
+
|
|
9
19
|
private
|
|
10
20
|
|
|
11
21
|
# Emit mutants
|
|
@@ -16,30 +26,19 @@ module Mutant
|
|
|
16
26
|
#
|
|
17
27
|
def dispatch
|
|
18
28
|
emit_nil
|
|
19
|
-
|
|
20
|
-
|
|
29
|
+
emit_inverse
|
|
30
|
+
emit_start_mutations
|
|
31
|
+
emit_end_mutations
|
|
21
32
|
end
|
|
22
33
|
|
|
23
34
|
# Return inverse node
|
|
24
35
|
#
|
|
25
|
-
# @return [
|
|
36
|
+
# @return [Parser::AST::Node]
|
|
26
37
|
#
|
|
27
38
|
# @api private
|
|
28
39
|
#
|
|
29
|
-
def
|
|
30
|
-
node
|
|
31
|
-
new(inverse_class, node.start, node.finish)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
# Emit range specific mutants
|
|
35
|
-
#
|
|
36
|
-
# @return [undefined]
|
|
37
|
-
#
|
|
38
|
-
# @api private
|
|
39
|
-
#
|
|
40
|
-
def emit_range
|
|
41
|
-
emit_finish_mutations
|
|
42
|
-
emit_start_mutations
|
|
40
|
+
def emit_inverse
|
|
41
|
+
emit(s(MAP.fetch(node.type), *children))
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
# Emit range start mutations
|
|
@@ -48,10 +47,9 @@ module Mutant
|
|
|
48
47
|
#
|
|
49
48
|
# @api private
|
|
50
49
|
#
|
|
51
|
-
def
|
|
52
|
-
finish = node.finish
|
|
50
|
+
def emit_end_mutations
|
|
53
51
|
#emit_self(negative_infinity, finish)
|
|
54
|
-
emit_self(
|
|
52
|
+
emit_self(NAN, _end)
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
# Emit start mutations
|
|
@@ -61,35 +59,12 @@ module Mutant
|
|
|
61
59
|
# @api private
|
|
62
60
|
#
|
|
63
61
|
def emit_start_mutations
|
|
64
|
-
start
|
|
65
|
-
emit_self(start,
|
|
66
|
-
emit_self(start, nan)
|
|
62
|
+
emit_self(start, INFINITY)
|
|
63
|
+
emit_self(start, NAN)
|
|
67
64
|
end
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
def inverse_class
|
|
76
|
-
self.class::INVERSE_CLASS
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Mutator for range exclude literals
|
|
80
|
-
class Exclude < self
|
|
81
|
-
INVERSE_CLASS = Rubinius::AST::Range
|
|
82
|
-
handle(Rubinius::AST::RangeExclude)
|
|
83
|
-
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# Mutator for range include literals
|
|
87
|
-
class Include < self
|
|
88
|
-
INVERSE_CLASS = Rubinius::AST::RangeExclude
|
|
89
|
-
handle(Rubinius::AST::Range)
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
end
|
|
66
|
+
end # Range
|
|
67
|
+
end # Literal
|
|
68
|
+
end # Node
|
|
69
|
+
end # Mutator
|
|
70
|
+
end # Mutant
|
|
@@ -5,7 +5,14 @@ module Mutant
|
|
|
5
5
|
# Mutator for regexp literals
|
|
6
6
|
class Regex < self
|
|
7
7
|
|
|
8
|
-
handle(
|
|
8
|
+
handle(:regexp)
|
|
9
|
+
|
|
10
|
+
EMPTY_STRING = ''.freeze
|
|
11
|
+
|
|
12
|
+
# No input can ever be matched with this
|
|
13
|
+
NULL_REGEXP_SOURCE = 'a\A'.freeze
|
|
14
|
+
|
|
15
|
+
children :source, :options
|
|
9
16
|
|
|
10
17
|
private
|
|
11
18
|
|
|
@@ -17,27 +24,12 @@ module Mutant
|
|
|
17
24
|
#
|
|
18
25
|
def dispatch
|
|
19
26
|
emit_nil
|
|
20
|
-
emit_self(
|
|
21
|
-
emit_self(
|
|
22
|
-
emit_new { new_self(Random.hex_string) }
|
|
27
|
+
emit_self(s(:str, EMPTY_STRING), options)
|
|
28
|
+
emit_self(s(:str, NULL_REGEXP_SOURCE), options)
|
|
23
29
|
end
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
# options of regexp, defaults to mutation subject node options
|
|
31
|
-
#
|
|
32
|
-
# @return [undefined]
|
|
33
|
-
#
|
|
34
|
-
# @api private
|
|
35
|
-
#
|
|
36
|
-
def new_self(source,options=nil)
|
|
37
|
-
super(source,options || node.options)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
31
|
+
end # Regex
|
|
32
|
+
end # Literal
|
|
33
|
+
end # Node
|
|
34
|
+
end # Mutator
|
|
35
|
+
end # Mutant
|
|
@@ -5,7 +5,7 @@ module Mutant
|
|
|
5
5
|
# Mutator for string literals
|
|
6
6
|
class String < self
|
|
7
7
|
|
|
8
|
-
handle(
|
|
8
|
+
handle(:str)
|
|
9
9
|
|
|
10
10
|
private
|
|
11
11
|
|
|
@@ -19,8 +19,9 @@ module Mutant
|
|
|
19
19
|
emit_nil
|
|
20
20
|
emit_new { new_self(Random.hex_string) }
|
|
21
21
|
end
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
22
|
+
|
|
23
|
+
end # String
|
|
24
|
+
end # Literal
|
|
25
|
+
end # Node
|
|
26
|
+
end # Mutator
|
|
27
|
+
end # Mutant
|
|
@@ -5,7 +5,7 @@ module Mutant
|
|
|
5
5
|
# Mutator for symbol literals
|
|
6
6
|
class Symbol < self
|
|
7
7
|
|
|
8
|
-
handle(
|
|
8
|
+
handle(:sym)
|
|
9
9
|
|
|
10
10
|
private
|
|
11
11
|
|
|
@@ -19,8 +19,9 @@ module Mutant
|
|
|
19
19
|
emit_nil
|
|
20
20
|
emit_new { new_self(('s'+Random.hex_string).to_sym) }
|
|
21
21
|
end
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
end
|
|
22
|
+
|
|
23
|
+
end # Symbol
|
|
24
|
+
end # Literal
|
|
25
|
+
end # Node
|
|
26
|
+
end # Mutator
|
|
27
|
+
end # Mutant
|
|
@@ -7,18 +7,6 @@ module Mutant
|
|
|
7
7
|
|
|
8
8
|
private
|
|
9
9
|
|
|
10
|
-
# Return new float literal
|
|
11
|
-
#
|
|
12
|
-
# @param [#to_f] value
|
|
13
|
-
#
|
|
14
|
-
# @return [Rubinius::Node::FloatLiteral]
|
|
15
|
-
#
|
|
16
|
-
# @api private
|
|
17
|
-
#
|
|
18
|
-
def new_float(value)
|
|
19
|
-
new(Rubinius::AST::FloatLiteral, value)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
10
|
# Emit a new node with wrapping class for each entry in values
|
|
23
11
|
#
|
|
24
12
|
# @param [Array] values
|
|
@@ -33,37 +21,7 @@ module Mutant
|
|
|
33
21
|
end
|
|
34
22
|
end
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
# @api private
|
|
41
|
-
#
|
|
42
|
-
def nan
|
|
43
|
-
zero_float = new_float(0)
|
|
44
|
-
new_send_with_arguments(zero_float, :/, zero_float)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Return AST representing negative infinity
|
|
48
|
-
#
|
|
49
|
-
# @return [Rubinius::Node::AST]
|
|
50
|
-
#
|
|
51
|
-
# @api private
|
|
52
|
-
#
|
|
53
|
-
def negative_infinity
|
|
54
|
-
new_send_with_arguments(new_float(-1), :/, new_float(0))
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Return AST representing infinity
|
|
58
|
-
#
|
|
59
|
-
# @return [Rubinius::Node::AST]
|
|
60
|
-
#
|
|
61
|
-
# @api private
|
|
62
|
-
#
|
|
63
|
-
def infinity
|
|
64
|
-
new_send_with_arguments(new_float(1), :/, new_float(0))
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
end
|
|
24
|
+
end # Literal
|
|
25
|
+
end # Node
|
|
26
|
+
end # Mutator
|
|
27
|
+
end # Mutant
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Mutator
|
|
3
|
+
class Node
|
|
4
|
+
# Mutator for multiple assignment left hand side nodes
|
|
5
|
+
class MLHS < self
|
|
6
|
+
|
|
7
|
+
handle(:mlhs)
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
# Emit mutations
|
|
12
|
+
#
|
|
13
|
+
# @return [undefined]
|
|
14
|
+
#
|
|
15
|
+
# @api private
|
|
16
|
+
#
|
|
17
|
+
def dispatch
|
|
18
|
+
children.each_index do |index|
|
|
19
|
+
mutate_child(index)
|
|
20
|
+
delete_child(index)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # MLHS
|
|
25
|
+
end # Node
|
|
26
|
+
end # Mutator
|
|
27
|
+
end # Mutant
|
|
@@ -5,45 +5,20 @@ module Mutant
|
|
|
5
5
|
class Noop < self
|
|
6
6
|
|
|
7
7
|
# Literal references to self do not need to be mutated?
|
|
8
|
-
handle(
|
|
8
|
+
handle(:self)
|
|
9
|
+
|
|
10
|
+
# These nodes still need a mutator, your contribution is that close!
|
|
11
|
+
handle(
|
|
12
|
+
:zsuper, :not, :or, :and, :defined,
|
|
13
|
+
:next, :break, :match, :gvar, :cvar, :ensure,
|
|
14
|
+
:dstr, :dsym, :yield, :rescue, :redo, :defined?,
|
|
15
|
+
:lvar, :splat, :const, :blockarg, :block_pass, :op_asgn, :regopt,
|
|
16
|
+
:ivar, :restarg, :casgn, :masgn, :resbody, :retry, :arg_expr,
|
|
17
|
+
:kwrestarg, :kwoptarg, :kwarg, :undef, :module, :cbase, :empty,
|
|
18
|
+
:alias, :for, :xstr, :back_ref, :nth_ref, :class, :sclass, :match_with_lvasgn,
|
|
19
|
+
:match_current_line, :or_asgn
|
|
20
|
+
)
|
|
9
21
|
|
|
10
|
-
# Currently unhandled node classes. Feel free to contribute your mutator!
|
|
11
|
-
handle(Rubinius::AST::ZSuper)
|
|
12
|
-
handle(Rubinius::AST::ElementAssignment)
|
|
13
|
-
handle(Rubinius::AST::AttributeAssignment)
|
|
14
|
-
handle(Rubinius::AST::Not)
|
|
15
|
-
handle(Rubinius::AST::And)
|
|
16
|
-
handle(Rubinius::AST::Or)
|
|
17
|
-
handle(Rubinius::AST::Defined)
|
|
18
|
-
handle(Rubinius::AST::Super)
|
|
19
|
-
handle(Rubinius::AST::Next)
|
|
20
|
-
handle(Rubinius::AST::Break)
|
|
21
|
-
handle(Rubinius::AST::Match3)
|
|
22
|
-
handle(Rubinius::AST::ZSuper)
|
|
23
|
-
handle(Rubinius::AST::MultipleAssignment)
|
|
24
|
-
handle(Rubinius::AST::ScopedConstant)
|
|
25
|
-
handle(Rubinius::AST::LocalVariableAccess)
|
|
26
|
-
handle(Rubinius::AST::InstanceVariableAccess)
|
|
27
|
-
handle(Rubinius::AST::GlobalVariableAccess)
|
|
28
|
-
handle(Rubinius::AST::ClassVariableAccess)
|
|
29
|
-
handle(Rubinius::AST::ToplevelConstant)
|
|
30
|
-
handle(Rubinius::AST::Ensure)
|
|
31
|
-
handle(Rubinius::AST::Rescue)
|
|
32
|
-
handle(Rubinius::AST::DynamicString)
|
|
33
|
-
handle(Rubinius::AST::DynamicSymbol)
|
|
34
|
-
handle(Rubinius::AST::DynamicRegex)
|
|
35
|
-
handle(Rubinius::AST::File)
|
|
36
|
-
handle(Rubinius::AST::NthRef)
|
|
37
|
-
handle(Rubinius::AST::OpAssignOr19)
|
|
38
|
-
handle(Rubinius::AST::BlockPass19)
|
|
39
|
-
handle(Rubinius::AST::OpAssign1)
|
|
40
|
-
handle(Rubinius::AST::OpAssign2)
|
|
41
|
-
handle(Rubinius::AST::SplatValue)
|
|
42
|
-
handle(Rubinius::AST::ConstantAccess)
|
|
43
|
-
handle(Rubinius::AST::Yield)
|
|
44
|
-
handle(Rubinius::AST::Begin)
|
|
45
|
-
handle(Rubinius::AST::Rescue)
|
|
46
|
-
|
|
47
22
|
private
|
|
48
23
|
|
|
49
24
|
# Emit mutations
|
|
@@ -53,9 +28,9 @@ module Mutant
|
|
|
53
28
|
# @api private
|
|
54
29
|
#
|
|
55
30
|
def dispatch
|
|
56
|
-
# noop
|
|
57
31
|
end
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
end
|
|
32
|
+
|
|
33
|
+
end # Noop
|
|
34
|
+
end # Node
|
|
35
|
+
end # Mutator
|
|
36
|
+
end # Mutant
|
|
@@ -4,10 +4,11 @@ module Mutant
|
|
|
4
4
|
# Mutator for return statements
|
|
5
5
|
class Return < self
|
|
6
6
|
|
|
7
|
-
handle(
|
|
7
|
+
handle(:return)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
children :value
|
|
10
10
|
|
|
11
|
+
private
|
|
11
12
|
|
|
12
13
|
# Emit mutants
|
|
13
14
|
#
|
|
@@ -16,16 +17,15 @@ module Mutant
|
|
|
16
17
|
# @api private
|
|
17
18
|
#
|
|
18
19
|
def dispatch
|
|
19
|
-
value = node.value
|
|
20
20
|
if value
|
|
21
21
|
emit(value)
|
|
22
|
+
emit_value_mutations
|
|
22
23
|
else
|
|
23
24
|
emit_nil
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
end
|
|
28
|
+
end # Return
|
|
29
|
+
end # Node
|
|
30
|
+
end # Mutator
|
|
31
|
+
end # Mutant
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Mutator
|
|
3
|
+
class Node
|
|
4
|
+
class Send
|
|
5
|
+
|
|
6
|
+
# Mutator for sends that correspond to a binary operator
|
|
7
|
+
class Binary < self
|
|
8
|
+
|
|
9
|
+
children :left, :operator, :right
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# Emit mutations
|
|
14
|
+
#
|
|
15
|
+
# @return [undefined]
|
|
16
|
+
#
|
|
17
|
+
# @api private
|
|
18
|
+
#
|
|
19
|
+
def dispatch
|
|
20
|
+
emit(left)
|
|
21
|
+
emit_left_mutations
|
|
22
|
+
emit(right) unless right.type == :splat
|
|
23
|
+
emit_right_mutations
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end # Binary
|
|
27
|
+
|
|
28
|
+
end # Send
|
|
29
|
+
end # Node
|
|
30
|
+
end # Mutator
|
|
31
|
+
end # Mutant
|
|
@@ -5,137 +5,171 @@ module Mutant
|
|
|
5
5
|
# Namespace for send mutators
|
|
6
6
|
class Send < self
|
|
7
7
|
|
|
8
|
-
handle(
|
|
8
|
+
handle(:send)
|
|
9
|
+
|
|
10
|
+
children :receiver, :selector
|
|
11
|
+
|
|
12
|
+
INDEX_REFERENCE = :[]
|
|
13
|
+
INDEX_ASSIGN = :[]=
|
|
14
|
+
ASSIGN_SUFFIX = :'='
|
|
15
|
+
|
|
16
|
+
# Base mutator for index operations
|
|
17
|
+
class Index < self
|
|
18
|
+
|
|
19
|
+
# Mutator for index references
|
|
20
|
+
class Reference < self
|
|
21
|
+
|
|
22
|
+
# Perform dispatch
|
|
23
|
+
#
|
|
24
|
+
# @return [undefined]
|
|
25
|
+
#
|
|
26
|
+
# @api private
|
|
27
|
+
#
|
|
28
|
+
def dispatch
|
|
29
|
+
emit(receiver)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end # Reference
|
|
33
|
+
|
|
34
|
+
# Mutator for index assignments
|
|
35
|
+
class Assign < self
|
|
36
|
+
|
|
37
|
+
# Perform dispatch
|
|
38
|
+
#
|
|
39
|
+
# @return [undefined]
|
|
40
|
+
#
|
|
41
|
+
# @api private
|
|
42
|
+
#
|
|
43
|
+
def dispatch
|
|
44
|
+
emit(receiver)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end # Assign
|
|
48
|
+
end # Index
|
|
9
49
|
|
|
10
50
|
private
|
|
11
51
|
|
|
12
|
-
#
|
|
52
|
+
# Perform dispatch
|
|
13
53
|
#
|
|
14
54
|
# @return [undefined]
|
|
15
55
|
#
|
|
16
56
|
# @api private
|
|
17
57
|
#
|
|
18
58
|
def dispatch
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
59
|
+
case selector
|
|
60
|
+
when INDEX_REFERENCE
|
|
61
|
+
run(Index::Reference)
|
|
62
|
+
when INDEX_ASSIGN
|
|
63
|
+
run(Index::Assign)
|
|
64
|
+
else
|
|
65
|
+
non_index_dispatch
|
|
66
|
+
end
|
|
24
67
|
end
|
|
25
68
|
|
|
26
|
-
#
|
|
69
|
+
# Perform non index dispatch
|
|
27
70
|
#
|
|
28
71
|
# @return [undefined]
|
|
29
72
|
#
|
|
30
73
|
# @api private
|
|
31
74
|
#
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
75
|
+
def non_index_dispatch
|
|
76
|
+
if binary_operator?
|
|
77
|
+
run(Binary)
|
|
78
|
+
return
|
|
35
79
|
end
|
|
80
|
+
normal_dispatch
|
|
36
81
|
end
|
|
37
82
|
|
|
38
|
-
#
|
|
83
|
+
# Return arguments
|
|
39
84
|
#
|
|
40
|
-
# @return [
|
|
85
|
+
# @return [Enumerable<Parser::AST::Node>]
|
|
41
86
|
#
|
|
42
87
|
# @api private
|
|
43
88
|
#
|
|
44
|
-
|
|
45
|
-
emit_attribute_mutations(:block) if node.block
|
|
46
|
-
end
|
|
89
|
+
alias_method :arguments, :remaining_children
|
|
47
90
|
|
|
48
|
-
#
|
|
91
|
+
# Perform normal, non special case dispatch
|
|
49
92
|
#
|
|
50
93
|
# @return [undefined]
|
|
51
94
|
#
|
|
52
95
|
# @api private
|
|
53
96
|
#
|
|
54
|
-
def
|
|
55
|
-
|
|
97
|
+
def normal_dispatch
|
|
98
|
+
emit(receiver) if receiver
|
|
99
|
+
mutate_receiver
|
|
100
|
+
emit_argument_propagation
|
|
101
|
+
mutate_arguments
|
|
56
102
|
end
|
|
57
103
|
|
|
58
|
-
#
|
|
104
|
+
# Test for binary operator
|
|
59
105
|
#
|
|
60
|
-
# @return [
|
|
106
|
+
# @return [true]
|
|
107
|
+
# if send is a binary operator
|
|
108
|
+
#
|
|
109
|
+
# @return [false]
|
|
110
|
+
# otherwise
|
|
61
111
|
#
|
|
62
112
|
# @api private
|
|
63
113
|
#
|
|
64
|
-
def
|
|
65
|
-
|
|
66
|
-
dup.block = nil
|
|
67
|
-
emit(dup)
|
|
114
|
+
def binary_operator?
|
|
115
|
+
arguments.one? && BINARY_METHOD_OPERATORS.include?(selector)
|
|
68
116
|
end
|
|
69
117
|
|
|
70
|
-
#
|
|
118
|
+
# Mutate arguments
|
|
71
119
|
#
|
|
72
|
-
# @return [
|
|
120
|
+
# @return [undefined]
|
|
73
121
|
#
|
|
74
122
|
# @api private
|
|
75
123
|
#
|
|
76
|
-
def
|
|
77
|
-
|
|
124
|
+
def mutate_arguments
|
|
125
|
+
return if arguments.empty?
|
|
126
|
+
emit_self(receiver, selector)
|
|
127
|
+
remaining_children_with_index.each do |node, index|
|
|
128
|
+
mutate_child(index)
|
|
129
|
+
delete_child(index)
|
|
130
|
+
end
|
|
78
131
|
end
|
|
79
132
|
|
|
80
|
-
|
|
133
|
+
NO_PROPAGATE = [ :splat, :block_pass ].to_set
|
|
134
|
+
|
|
135
|
+
# Emit argument propagation
|
|
81
136
|
#
|
|
82
|
-
# @return [
|
|
137
|
+
# @return [undefined]
|
|
83
138
|
#
|
|
84
139
|
# @api private
|
|
85
140
|
#
|
|
86
|
-
def
|
|
87
|
-
|
|
141
|
+
def emit_argument_propagation
|
|
142
|
+
return unless arguments.one?
|
|
143
|
+
node = arguments.first
|
|
144
|
+
return if NO_PROPAGATE.include?(node.type)
|
|
145
|
+
emit(arguments.first)
|
|
88
146
|
end
|
|
89
147
|
|
|
90
|
-
#
|
|
91
|
-
#
|
|
92
|
-
# @return [true]
|
|
93
|
-
# if receiver is a Rubinius::AST::Self node
|
|
148
|
+
# Emit receiver mutations
|
|
94
149
|
#
|
|
95
|
-
# @return [
|
|
96
|
-
# return false otherwise
|
|
150
|
+
# @return [undefined]
|
|
97
151
|
#
|
|
98
152
|
# @api private
|
|
99
153
|
#
|
|
100
|
-
def
|
|
101
|
-
receiver
|
|
154
|
+
def mutate_receiver
|
|
155
|
+
return unless receiver
|
|
156
|
+
emit_implicit_self
|
|
157
|
+
emit_receiver_mutations
|
|
102
158
|
end
|
|
103
159
|
|
|
104
|
-
# Emit
|
|
105
|
-
#
|
|
106
|
-
# @example:
|
|
107
|
-
#
|
|
108
|
-
# # This class does use Foo#a with explicitly specifing the receiver self.
|
|
109
|
-
# # But an implicit (privately) call should be used as there is no need for
|
|
110
|
-
# # specifing en explicit receiver.
|
|
111
|
-
#
|
|
112
|
-
# class Foo # Mutation
|
|
113
|
-
# def print_a # def print_a
|
|
114
|
-
# puts self.a # puts a
|
|
115
|
-
# end # end
|
|
116
|
-
#
|
|
117
|
-
# def a
|
|
118
|
-
# :bar
|
|
119
|
-
# end
|
|
120
|
-
# end
|
|
121
|
-
#
|
|
122
|
-
# There will not be any exception so the mutant is not killed and such calls where
|
|
123
|
-
# implicit receiver should be used will be spotted.
|
|
160
|
+
# Emit implicit self mutation
|
|
124
161
|
#
|
|
125
162
|
# @return [undefined]
|
|
126
163
|
#
|
|
127
164
|
# @api private
|
|
128
165
|
#
|
|
129
|
-
def
|
|
130
|
-
|
|
131
|
-
|
|
166
|
+
def emit_implicit_self
|
|
167
|
+
if receiver.type == :self and !KEYWORDS.include?(selector)
|
|
168
|
+
emit_receiver(nil)
|
|
132
169
|
end
|
|
133
|
-
|
|
134
|
-
mutant = dup_node
|
|
135
|
-
mutant.privately = true
|
|
136
|
-
emit(mutant)
|
|
137
170
|
end
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
171
|
+
|
|
172
|
+
end # Send
|
|
173
|
+
end # Node
|
|
174
|
+
end # Mutator
|
|
175
|
+
end # Mutant
|