mutant 0.5.26 → 0.6.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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/.travis.yml +1 -0
- data/Changelog.md +16 -3
- data/Gemfile +0 -2
- data/Gemfile.devtools +2 -2
- data/README.md +9 -15
- data/bin/mutant +0 -1
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/mutant.yml +1 -1
- data/config/reek.yml +14 -11
- data/config/rubocop.yml +1 -1
- data/lib/mutant.rb +22 -21
- data/lib/mutant/ast.rb +47 -0
- data/lib/mutant/cli.rb +7 -4
- data/lib/mutant/config.rb +1 -0
- data/lib/mutant/context.rb +1 -1
- data/lib/mutant/diff.rb +38 -7
- data/lib/mutant/env.rb +22 -3
- data/lib/mutant/expression.rb +15 -4
- data/lib/mutant/integration.rb +1 -1
- data/lib/mutant/isolation.rb +2 -4
- data/lib/mutant/matcher.rb +1 -1
- data/lib/mutant/matcher/method.rb +1 -1
- data/lib/mutant/matcher/method/singleton.rb +1 -1
- data/lib/mutant/matcher/methods.rb +0 -2
- data/lib/mutant/meta/example.rb +0 -2
- data/lib/mutant/meta/example/dsl.rb +1 -1
- data/lib/mutant/mutator.rb +1 -1
- data/lib/mutant/mutator/node.rb +3 -3
- data/lib/mutant/mutator/node/begin.rb +1 -1
- data/lib/mutant/mutator/node/block.rb +16 -3
- data/lib/mutant/mutator/node/if.rb +1 -1
- data/lib/mutant/mutator/node/literal/fixnum.rb +1 -1
- data/lib/mutant/mutator/node/resbody.rb +0 -2
- data/lib/mutant/mutator/node/send.rb +17 -7
- data/lib/mutant/mutator/node/send/index.rb +0 -2
- data/lib/mutant/mutator/registry.rb +1 -1
- data/lib/mutant/mutator/util.rb +1 -1
- data/lib/mutant/mutator/util/array.rb +1 -1
- data/lib/mutant/reporter.rb +13 -3
- data/lib/mutant/reporter/cli.rb +54 -8
- data/lib/mutant/reporter/cli/format.rb +197 -0
- data/lib/mutant/reporter/cli/printer.rb +402 -22
- data/lib/mutant/reporter/cli/tput.rb +27 -0
- data/lib/mutant/reporter/null.rb +4 -34
- data/lib/mutant/reporter/trace.rb +6 -38
- data/lib/mutant/result.rb +44 -56
- data/lib/mutant/runner.rb +99 -52
- data/lib/mutant/runner/collector.rb +134 -0
- data/lib/mutant/subject/method/instance.rb +12 -4
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warning_filter.rb +0 -2
- data/lib/mutant/zombifier/file.rb +1 -1
- data/meta/block.rb +17 -1
- data/meta/send.rb +123 -1
- data/mutant-rspec.gemspec +3 -3
- data/mutant.gemspec +1 -1
- data/spec/integration/mutant/corpus_spec.rb +4 -195
- data/spec/integration/mutant/null_spec.rb +1 -3
- data/spec/integration/mutant/rspec_spec.rb +1 -3
- data/spec/integration/mutant/test_mutator_handles_types_spec.rb +1 -3
- data/spec/integration/mutant/zombie_spec.rb +1 -3
- data/spec/integrations.yml +7 -0
- data/spec/shared/method_matcher_behavior.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/compress_helper.rb +1 -0
- data/spec/support/corpus.rb +239 -0
- data/spec/support/mutation_verifier.rb +2 -4
- data/spec/unit/mutant/cli_spec.rb +20 -13
- data/spec/unit/mutant/context/root_spec.rb +1 -3
- data/spec/unit/mutant/context/scope/root_spec.rb +1 -3
- data/spec/unit/mutant/context/scope/unqualified_name_spec.rb +1 -3
- data/spec/unit/mutant/diff_spec.rb +37 -19
- data/spec/unit/mutant/expression/method_spec.rb +5 -7
- data/spec/unit/mutant/expression/methods_spec.rb +5 -7
- data/spec/unit/mutant/expression/namespace/flat_spec.rb +6 -8
- data/spec/unit/mutant/expression/namespace/recursive_spec.rb +6 -7
- data/spec/unit/mutant/expression_spec.rb +14 -5
- data/spec/unit/mutant/integration_spec.rb +14 -3
- data/spec/unit/mutant/isolation_spec.rb +2 -4
- data/spec/unit/mutant/loader/eval_spec.rb +1 -3
- data/spec/unit/mutant/matcher/chain_spec.rb +1 -3
- data/spec/unit/mutant/matcher/compiler/subject_prefix_spec.rb +21 -0
- data/spec/unit/mutant/matcher/compiler_spec.rb +28 -3
- data/spec/unit/mutant/matcher/filter_spec.rb +1 -3
- data/spec/unit/mutant/matcher/method/instance_spec.rb +3 -5
- data/spec/unit/mutant/matcher/method/singleton_spec.rb +22 -4
- data/spec/unit/mutant/matcher/methods/instance_spec.rb +7 -6
- data/spec/unit/mutant/matcher/methods/singleton_spec.rb +4 -6
- data/spec/unit/mutant/matcher/namespace_spec.rb +1 -3
- data/spec/unit/mutant/matcher/null_spec.rb +1 -3
- data/spec/unit/mutant/mutation_spec.rb +1 -3
- data/spec/unit/mutant/mutator/node_spec.rb +1 -3
- data/spec/unit/mutant/reporter/cli_spec.rb +444 -206
- data/spec/unit/mutant/reporter/null_spec.rb +1 -3
- data/spec/unit/mutant/require_highjack_spec.rb +1 -3
- data/spec/unit/mutant/runner_spec.rb +42 -28
- data/spec/unit/mutant/subject/context_spec.rb +1 -3
- data/spec/unit/mutant/subject/method/instance_spec.rb +27 -19
- data/spec/unit/mutant/subject/method/singleton_spec.rb +49 -17
- data/spec/unit/mutant/subject_spec.rb +1 -3
- data/spec/unit/mutant/test_spec.rb +1 -3
- data/spec/unit/mutant/warning_expectation.rb +1 -3
- data/spec/unit/mutant/warning_filter_spec.rb +1 -3
- data/spec/unit/mutant_spec.rb +13 -3
- data/test_app/Gemfile.devtools +2 -2
- data/test_app/spec/unit/test_app/literal/string_spec.rb +1 -1
- metadata +10 -21
- data/lib/mutant/matcher/method/finder.rb +0 -72
- data/lib/mutant/reporter/cli/progress.rb +0 -10
- data/lib/mutant/reporter/cli/progress/config.rb +0 -30
- data/lib/mutant/reporter/cli/progress/env.rb +0 -30
- data/lib/mutant/reporter/cli/progress/noop.rb +0 -27
- data/lib/mutant/reporter/cli/progress/result.rb +0 -12
- data/lib/mutant/reporter/cli/progress/result/mutation.rb +0 -45
- data/lib/mutant/reporter/cli/progress/result/subject.rb +0 -54
- data/lib/mutant/reporter/cli/progress/subject.rb +0 -27
- data/lib/mutant/reporter/cli/registry.rb +0 -81
- data/lib/mutant/reporter/cli/report.rb +0 -10
- data/lib/mutant/reporter/cli/report/env.rb +0 -92
- data/lib/mutant/reporter/cli/report/mutation.rb +0 -103
- data/lib/mutant/reporter/cli/report/subject.rb +0 -32
- data/lib/mutant/reporter/cli/report/test.rb +0 -28
- data/lib/mutant/walker.rb +0 -53
- data/spec/shared/mutator_behavior.rb +0 -55
data/lib/mutant/config.rb
CHANGED
data/lib/mutant/context.rb
CHANGED
data/lib/mutant/diff.rb
CHANGED
|
@@ -18,9 +18,11 @@ module Mutant
|
|
|
18
18
|
# @api private
|
|
19
19
|
#
|
|
20
20
|
def diff
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
return if diffs.empty?
|
|
22
|
+
|
|
23
|
+
minimized_hunks.map do |hunk|
|
|
24
|
+
hunk.diff(:unified) << NEWLINE
|
|
25
|
+
end.join
|
|
24
26
|
end
|
|
25
27
|
memoize :diff
|
|
26
28
|
|
|
@@ -36,9 +38,7 @@ module Mutant
|
|
|
36
38
|
#
|
|
37
39
|
def colorized_diff
|
|
38
40
|
return unless diff
|
|
39
|
-
diff.lines.map
|
|
40
|
-
self.class.colorize_line(line)
|
|
41
|
-
end.join
|
|
41
|
+
diff.lines.map(&self.class.method(:colorize_line)).join
|
|
42
42
|
end
|
|
43
43
|
memoize :colorized_diff
|
|
44
44
|
|
|
@@ -79,7 +79,37 @@ module Mutant
|
|
|
79
79
|
def diffs
|
|
80
80
|
::Diff::LCS.diff(old, new)
|
|
81
81
|
end
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
# Return hunks
|
|
84
|
+
#
|
|
85
|
+
# @return [Array<Diff::LCS::Hunk>]
|
|
86
|
+
#
|
|
87
|
+
# @api private
|
|
88
|
+
#
|
|
89
|
+
def hunks
|
|
90
|
+
diffs.map do |diff|
|
|
91
|
+
::Diff::LCS::Hunk.new(old, new, diff, max_length, 0)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Return minimized hunks
|
|
96
|
+
#
|
|
97
|
+
# @return [Array<Diff::LCS::Hunk>]
|
|
98
|
+
#
|
|
99
|
+
# @api private
|
|
100
|
+
#
|
|
101
|
+
def minimized_hunks
|
|
102
|
+
head, *tail = hunks()
|
|
103
|
+
|
|
104
|
+
tail.each_with_object([head]) do |right, aggregate|
|
|
105
|
+
left = aggregate.last
|
|
106
|
+
if right.overlaps?(left)
|
|
107
|
+
right.merge(left)
|
|
108
|
+
aggregate.pop
|
|
109
|
+
end
|
|
110
|
+
aggregate << right
|
|
111
|
+
end
|
|
112
|
+
end
|
|
83
113
|
|
|
84
114
|
# Return max length
|
|
85
115
|
#
|
|
@@ -109,6 +139,7 @@ module Mutant
|
|
|
109
139
|
Color::NONE
|
|
110
140
|
end.format(line)
|
|
111
141
|
end
|
|
142
|
+
private_class_method :colorize_line
|
|
112
143
|
|
|
113
144
|
end # Diff
|
|
114
145
|
end # Mutant
|
data/lib/mutant/env.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Mutant
|
|
2
2
|
# Abstract base class for mutant environments
|
|
3
3
|
class Env
|
|
4
|
-
include Adamantium, Concord::Public.new(:config, :cache), Procto.call(:run)
|
|
4
|
+
include Adamantium::Flat, Concord::Public.new(:config, :cache), Procto.call(:run)
|
|
5
5
|
|
|
6
6
|
# Return new env
|
|
7
7
|
#
|
|
@@ -27,6 +27,7 @@ module Mutant
|
|
|
27
27
|
infect
|
|
28
28
|
initialize_matchable_scopes
|
|
29
29
|
initialize_subjects
|
|
30
|
+
initialize_mutations
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
# Run mutant producing a report on configured env
|
|
@@ -60,6 +61,14 @@ module Mutant
|
|
|
60
61
|
#
|
|
61
62
|
attr_reader :subjects
|
|
62
63
|
|
|
64
|
+
# Return mutations
|
|
65
|
+
#
|
|
66
|
+
# @return [Array<Mutation>]
|
|
67
|
+
#
|
|
68
|
+
# @api private
|
|
69
|
+
#
|
|
70
|
+
attr_reader :mutations
|
|
71
|
+
|
|
63
72
|
# Return all usable match scopes
|
|
64
73
|
#
|
|
65
74
|
# @return [Array<Matcher::Scope>]
|
|
@@ -75,7 +84,7 @@ module Mutant
|
|
|
75
84
|
# @param [Class, Module] scope
|
|
76
85
|
#
|
|
77
86
|
# @return [String]
|
|
78
|
-
# if scope has a name and does not raise exceptions
|
|
87
|
+
# if scope has a name and does not raise exceptions obtaining it
|
|
79
88
|
#
|
|
80
89
|
# @return [nil]
|
|
81
90
|
# otherwise
|
|
@@ -87,7 +96,7 @@ module Mutant
|
|
|
87
96
|
def scope_name(scope)
|
|
88
97
|
scope.name
|
|
89
98
|
rescue => exception
|
|
90
|
-
warn("While
|
|
99
|
+
warn("While obtaining #{scope.class}#name from: #{scope.inspect} It raised an error: #{exception.inspect} fix your lib!")
|
|
91
100
|
nil
|
|
92
101
|
end
|
|
93
102
|
|
|
@@ -124,6 +133,16 @@ module Mutant
|
|
|
124
133
|
@subjects = Matcher::Compiler.call(self, config.matcher_config).to_a
|
|
125
134
|
end
|
|
126
135
|
|
|
136
|
+
# Initialize mutations
|
|
137
|
+
#
|
|
138
|
+
# @return [undefined]
|
|
139
|
+
#
|
|
140
|
+
# @api private
|
|
141
|
+
#
|
|
142
|
+
def initialize_mutations
|
|
143
|
+
@mutations = subjects.flat_map(&:mutations)
|
|
144
|
+
end
|
|
145
|
+
|
|
127
146
|
# Infect environment
|
|
128
147
|
#
|
|
129
148
|
# @return [undefined]
|
data/lib/mutant/expression.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Mutant
|
|
|
2
2
|
|
|
3
3
|
# Abstract base class for match expression
|
|
4
4
|
class Expression
|
|
5
|
-
include AbstractType, Adamantium, Concord::Public.new(:match)
|
|
5
|
+
include AbstractType, Adamantium::Flat, Concord::Public.new(:match)
|
|
6
6
|
|
|
7
7
|
include Equalizer.new(:syntax)
|
|
8
8
|
|
|
@@ -13,6 +13,8 @@ module Mutant
|
|
|
13
13
|
*AST::Types::OPERATOR_METHODS.map(&:to_s)
|
|
14
14
|
).freeze
|
|
15
15
|
|
|
16
|
+
INSPECT_FORMAT = '<Mutant::Expression: %s>'.freeze
|
|
17
|
+
|
|
16
18
|
SCOPE_PATTERN = /#{SCOPE_NAME_PATTERN}(?:#{SCOPE_OPERATOR}#{SCOPE_NAME_PATTERN})*/.freeze
|
|
17
19
|
|
|
18
20
|
REGISTRY = {}
|
|
@@ -20,8 +22,8 @@ module Mutant
|
|
|
20
22
|
# Error raised on invalid expressions
|
|
21
23
|
class InvalidExpressionError < RuntimeError; end
|
|
22
24
|
|
|
23
|
-
# Error raised on
|
|
24
|
-
class
|
|
25
|
+
# Error raised on ambiguous expressions
|
|
26
|
+
class AmbiguousExpressionError < RuntimeError; end
|
|
25
27
|
|
|
26
28
|
# Initialize expression
|
|
27
29
|
#
|
|
@@ -32,8 +34,17 @@ module Mutant
|
|
|
32
34
|
def initialize(*)
|
|
33
35
|
super
|
|
34
36
|
@syntax = match.to_s
|
|
37
|
+
@inspect = format(INSPECT_FORMAT, syntax)
|
|
35
38
|
end
|
|
36
39
|
|
|
40
|
+
# Return inspection
|
|
41
|
+
#
|
|
42
|
+
# @return [String]
|
|
43
|
+
#
|
|
44
|
+
# @api private
|
|
45
|
+
#
|
|
46
|
+
attr_reader :inspect
|
|
47
|
+
|
|
37
48
|
# Return syntax
|
|
38
49
|
#
|
|
39
50
|
# @return [String]
|
|
@@ -116,7 +127,7 @@ module Mutant
|
|
|
116
127
|
when 1
|
|
117
128
|
expressions.first
|
|
118
129
|
else
|
|
119
|
-
fail
|
|
130
|
+
fail AmbiguousExpressionError, "Ambiguous expression: #{input.inspect}"
|
|
120
131
|
end
|
|
121
132
|
end
|
|
122
133
|
|
data/lib/mutant/integration.rb
CHANGED
data/lib/mutant/isolation.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module Mutant
|
|
2
|
-
# Module providing
|
|
2
|
+
# Module providing isolation
|
|
3
3
|
module Isolation
|
|
4
4
|
Error = Class.new(RuntimeError)
|
|
5
5
|
|
|
@@ -38,9 +38,7 @@ module Mutant
|
|
|
38
38
|
# @api private
|
|
39
39
|
#
|
|
40
40
|
def self.call(&block)
|
|
41
|
-
Parallel.map([block], in_processes: 1)
|
|
42
|
-
block.call
|
|
43
|
-
end.first
|
|
41
|
+
Parallel.map([block], in_processes: 1, &block.method(:call)).first
|
|
44
42
|
rescue Parallel::DeadWorker => exception
|
|
45
43
|
fail Error, exception
|
|
46
44
|
end
|
data/lib/mutant/matcher.rb
CHANGED
data/lib/mutant/meta/example.rb
CHANGED
data/lib/mutant/mutator.rb
CHANGED
data/lib/mutant/mutator/node.rb
CHANGED
|
@@ -29,7 +29,7 @@ module Mutant
|
|
|
29
29
|
emit_child_update(index, node)
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
|
-
private_class_method :
|
|
32
|
+
private_class_method :define_named_child
|
|
33
33
|
|
|
34
34
|
private
|
|
35
35
|
|
|
@@ -176,7 +176,7 @@ module Mutant
|
|
|
176
176
|
# Return parent node
|
|
177
177
|
#
|
|
178
178
|
# @return [Parser::AST::Node] node
|
|
179
|
-
# if parent with node is
|
|
179
|
+
# if parent with node is present
|
|
180
180
|
#
|
|
181
181
|
# @return [nil]
|
|
182
182
|
# otherwise
|
|
@@ -190,7 +190,7 @@ module Mutant
|
|
|
190
190
|
# Return parent type
|
|
191
191
|
#
|
|
192
192
|
# @return [Symbol] type
|
|
193
|
-
# if parent with type is
|
|
193
|
+
# if parent with type is present
|
|
194
194
|
#
|
|
195
195
|
# @return [nil]
|
|
196
196
|
# otherwise
|
|
@@ -19,12 +19,25 @@ module Mutant
|
|
|
19
19
|
def dispatch
|
|
20
20
|
emit_singletons
|
|
21
21
|
emit(send)
|
|
22
|
+
emit_send_mutations(&method(:n_send?))
|
|
22
23
|
emit_arguments_mutations
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
|
|
25
|
+
mutate_body
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Emit body mutations
|
|
29
|
+
#
|
|
30
|
+
# @return [undefined]
|
|
31
|
+
#
|
|
32
|
+
# @api private
|
|
33
|
+
#
|
|
34
|
+
def mutate_body
|
|
26
35
|
emit_body(nil)
|
|
27
36
|
emit_body(N_RAISE)
|
|
37
|
+
|
|
38
|
+
return unless body
|
|
39
|
+
emit(body)
|
|
40
|
+
emit_body_mutations
|
|
28
41
|
end
|
|
29
42
|
|
|
30
43
|
end # Block
|
|
@@ -11,13 +11,23 @@ module Mutant
|
|
|
11
11
|
children :receiver, :selector
|
|
12
12
|
|
|
13
13
|
SELECTOR_REPLACEMENTS = IceNine.deep_freeze(
|
|
14
|
-
reverse_map:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
reverse_map: [:map, :each],
|
|
15
|
+
kind_of?: [:instance_of?],
|
|
16
|
+
is_a?: [:instance_of?],
|
|
17
|
+
reverse_each: [:each],
|
|
18
|
+
reverse_merge: [:merge],
|
|
19
|
+
map: [:each],
|
|
20
|
+
send: [:public_send],
|
|
21
|
+
gsub: [:sub],
|
|
22
|
+
eql?: [:equal?],
|
|
23
|
+
to_s: [:to_str],
|
|
24
|
+
to_i: [:to_int],
|
|
25
|
+
to_a: [:to_ary],
|
|
26
|
+
:== => [:eql?, :equal?],
|
|
27
|
+
:>= => [:>, :==, :eql?, :equal?],
|
|
28
|
+
:<= => [:<, :==, :eql?, :equal?],
|
|
29
|
+
:> => [:==, :eql?, :equal?],
|
|
30
|
+
:< => [:==, :eql?, :equal?]
|
|
21
31
|
)
|
|
22
32
|
|
|
23
33
|
private
|