mutant 0.5.26 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|