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
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Mutant
|
|
2
|
+
class Reporter
|
|
3
|
+
class CLI
|
|
4
|
+
# Interface to the optionally present tput binary
|
|
5
|
+
class Tput
|
|
6
|
+
include Adamantium, Concord::Public.new(:available, :prepare, :restore)
|
|
7
|
+
|
|
8
|
+
private_class_method :new
|
|
9
|
+
|
|
10
|
+
capture = lambda do |command|
|
|
11
|
+
stdout, _stderr, exitstatus = Open3.capture3(command)
|
|
12
|
+
stdout if exitstatus.success?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
reset = capture.('tput reset')
|
|
16
|
+
save = capture.('tput sc') if reset
|
|
17
|
+
restore = capture.('tput rc') if save
|
|
18
|
+
clean = capture.('tput ed') if restore
|
|
19
|
+
|
|
20
|
+
UNAVAILABLE = new(false, nil, nil)
|
|
21
|
+
|
|
22
|
+
INSTANCE = clean ? new(true, reset + save, restore + clean) : UNAVAILABLE
|
|
23
|
+
|
|
24
|
+
end # TPUT
|
|
25
|
+
end # CLI
|
|
26
|
+
end # Reporter
|
|
27
|
+
end # Mutant
|
data/lib/mutant/reporter/null.rb
CHANGED
|
@@ -5,40 +5,10 @@ module Mutant
|
|
|
5
5
|
class Null < self
|
|
6
6
|
include Equalizer.new
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# @return [self]
|
|
13
|
-
#
|
|
14
|
-
# @api private
|
|
15
|
-
#
|
|
16
|
-
def warn(_message)
|
|
17
|
-
self
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Report object
|
|
21
|
-
#
|
|
22
|
-
# @param [Object] _object
|
|
23
|
-
#
|
|
24
|
-
# @return [self]
|
|
25
|
-
#
|
|
26
|
-
# @api private
|
|
27
|
-
#
|
|
28
|
-
def report(_object)
|
|
29
|
-
self
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Report progress on object
|
|
33
|
-
#
|
|
34
|
-
# @param [Object] _object
|
|
35
|
-
#
|
|
36
|
-
# @return [self]
|
|
37
|
-
#
|
|
38
|
-
# @api private
|
|
39
|
-
#
|
|
40
|
-
def progress(_object)
|
|
41
|
-
self
|
|
8
|
+
%w[warn report start progress].each do |name|
|
|
9
|
+
define_method name do |_object|
|
|
10
|
+
self
|
|
11
|
+
end
|
|
42
12
|
end
|
|
43
13
|
|
|
44
14
|
end # Null
|
|
@@ -2,7 +2,7 @@ module Mutant
|
|
|
2
2
|
class Reporter
|
|
3
3
|
# Reporter to trace report calls, used as a spec adapter
|
|
4
4
|
class Trace
|
|
5
|
-
include Adamantium::Mutable, Anima.new(:progress_calls, :report_calls, :warn_calls)
|
|
5
|
+
include Adamantium::Mutable, Anima.new(:start_calls, :progress_calls, :report_calls, :warn_calls)
|
|
6
6
|
|
|
7
7
|
# Return new trace reporter
|
|
8
8
|
#
|
|
@@ -14,43 +14,11 @@ module Mutant
|
|
|
14
14
|
super(Hash[anima.attribute_names.map { |name| [name, []] }])
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
# @api private
|
|
24
|
-
#
|
|
25
|
-
def warn(message)
|
|
26
|
-
warn_calls << message
|
|
27
|
-
self
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Report object
|
|
31
|
-
#
|
|
32
|
-
# @param [Object] object
|
|
33
|
-
#
|
|
34
|
-
# @return [self]
|
|
35
|
-
#
|
|
36
|
-
# @api private
|
|
37
|
-
#
|
|
38
|
-
def report(object)
|
|
39
|
-
report_calls << object
|
|
40
|
-
self
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# Report new progress on object
|
|
44
|
-
#
|
|
45
|
-
# @param [Object] object
|
|
46
|
-
#
|
|
47
|
-
# @return [self]
|
|
48
|
-
#
|
|
49
|
-
# @api private
|
|
50
|
-
#
|
|
51
|
-
def progress(object)
|
|
52
|
-
progress_calls << object
|
|
53
|
-
self
|
|
17
|
+
%w[start progress report warn].each do |name|
|
|
18
|
+
define_method(name) do |object|
|
|
19
|
+
public_send(:"#{name}_calls") << object
|
|
20
|
+
self
|
|
21
|
+
end
|
|
54
22
|
end
|
|
55
23
|
|
|
56
24
|
end # Tracker
|
data/lib/mutant/result.rb
CHANGED
|
@@ -12,9 +12,9 @@ module Mutant
|
|
|
12
12
|
# @api private
|
|
13
13
|
#
|
|
14
14
|
def coverage
|
|
15
|
-
return Rational(0) if
|
|
15
|
+
return Rational(0) if amount_mutation_results.zero?
|
|
16
16
|
|
|
17
|
-
Rational(amount_mutations_killed,
|
|
17
|
+
Rational(amount_mutations_killed, amount_mutation_results)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# Hook called when module gets included
|
|
@@ -31,22 +31,12 @@ module Mutant
|
|
|
31
31
|
host.memoize :coverage
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Test if operation is failing
|
|
37
|
-
#
|
|
38
|
-
# @return [Boolean]
|
|
39
|
-
#
|
|
40
|
-
# @api private
|
|
41
|
-
#
|
|
42
|
-
def fail?
|
|
43
|
-
!success?
|
|
44
|
-
end
|
|
34
|
+
end # Coverage
|
|
45
35
|
|
|
46
36
|
# Class level mixin
|
|
47
37
|
module ClassMethods
|
|
48
38
|
|
|
49
|
-
# Generate a sum
|
|
39
|
+
# Generate a sum method from name and collection
|
|
50
40
|
#
|
|
51
41
|
# @param [Symbol] name
|
|
52
42
|
# the attribute name on collection item and method name to use
|
|
@@ -64,6 +54,28 @@ module Mutant
|
|
|
64
54
|
end
|
|
65
55
|
memoize name
|
|
66
56
|
end
|
|
57
|
+
|
|
58
|
+
# Compute result tracking runtime
|
|
59
|
+
#
|
|
60
|
+
# @return [Result]
|
|
61
|
+
#
|
|
62
|
+
# @api private
|
|
63
|
+
#
|
|
64
|
+
def compute
|
|
65
|
+
start = Time.now
|
|
66
|
+
new(yield.merge(runtime: Time.now - start))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end # ClassMethods
|
|
70
|
+
|
|
71
|
+
# Test if operation is failing
|
|
72
|
+
#
|
|
73
|
+
# @return [Boolean]
|
|
74
|
+
#
|
|
75
|
+
# @api private
|
|
76
|
+
#
|
|
77
|
+
def fail?
|
|
78
|
+
!success?
|
|
67
79
|
end
|
|
68
80
|
|
|
69
81
|
# Return overhead
|
|
@@ -78,7 +90,7 @@ module Mutant
|
|
|
78
90
|
|
|
79
91
|
# Hook called when module gets included
|
|
80
92
|
#
|
|
81
|
-
# @param [Class, Module]
|
|
93
|
+
# @param [Class, Module] host
|
|
82
94
|
#
|
|
83
95
|
# @return [undefined]
|
|
84
96
|
#
|
|
@@ -93,11 +105,11 @@ module Mutant
|
|
|
93
105
|
|
|
94
106
|
# Env result object
|
|
95
107
|
class Env
|
|
96
|
-
include Coverage, Result, Anima.new(:runtime, :env, :subject_results)
|
|
108
|
+
include Coverage, Result, Anima.new(:runtime, :env, :subject_results, :done)
|
|
97
109
|
|
|
98
110
|
COVERAGE_PRECISION = 1
|
|
99
111
|
|
|
100
|
-
# Test if run
|
|
112
|
+
# Test if run is successful
|
|
101
113
|
#
|
|
102
114
|
# @return [Boolean]
|
|
103
115
|
#
|
|
@@ -119,6 +131,7 @@ module Mutant
|
|
|
119
131
|
end
|
|
120
132
|
|
|
121
133
|
sum :amount_mutations, :subject_results
|
|
134
|
+
sum :amount_mutation_results, :subject_results
|
|
122
135
|
sum :amount_mutations_alive, :subject_results
|
|
123
136
|
sum :amount_mutations_killed, :subject_results
|
|
124
137
|
sum :killtime, :subject_results
|
|
@@ -137,7 +150,7 @@ module Mutant
|
|
|
137
150
|
|
|
138
151
|
# Test result
|
|
139
152
|
class Test
|
|
140
|
-
include Result,
|
|
153
|
+
include Result, Anima.new(
|
|
141
154
|
:test,
|
|
142
155
|
:output,
|
|
143
156
|
:mutation,
|
|
@@ -145,16 +158,6 @@ module Mutant
|
|
|
145
158
|
:runtime
|
|
146
159
|
)
|
|
147
160
|
|
|
148
|
-
# NOTE:
|
|
149
|
-
#
|
|
150
|
-
# The test is intentionally NOT part of the mashalled data.
|
|
151
|
-
# In rspec the example group cannot deterministically being marshalled, because
|
|
152
|
-
# they reference a crazy mix of IO objects, global objects etc.
|
|
153
|
-
#
|
|
154
|
-
MARSHALLED_IVARS = (anima.attribute_names - [:test]).map do |name|
|
|
155
|
-
:"@#{name}"
|
|
156
|
-
end
|
|
157
|
-
|
|
158
161
|
# Return killtime
|
|
159
162
|
#
|
|
160
163
|
# @return [Float]
|
|
@@ -173,31 +176,6 @@ module Mutant
|
|
|
173
176
|
mutation.killed_by?(self)
|
|
174
177
|
end
|
|
175
178
|
|
|
176
|
-
# Return marshallable data
|
|
177
|
-
#
|
|
178
|
-
#
|
|
179
|
-
# @return [Array]
|
|
180
|
-
#
|
|
181
|
-
# @api private
|
|
182
|
-
#
|
|
183
|
-
def marshal_dump
|
|
184
|
-
MARSHALLED_IVARS.map(&method(:instance_variable_get))
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
# Load marshalled data
|
|
188
|
-
#
|
|
189
|
-
# @param [Array] array
|
|
190
|
-
#
|
|
191
|
-
# @return [undefined]
|
|
192
|
-
#
|
|
193
|
-
# @api private
|
|
194
|
-
#
|
|
195
|
-
def marshal_load(array)
|
|
196
|
-
MARSHALLED_IVARS.zip(array) do |instance_variable_name, value|
|
|
197
|
-
instance_variable_set(instance_variable_name, value)
|
|
198
|
-
end
|
|
199
|
-
end
|
|
200
|
-
|
|
201
179
|
end # Test
|
|
202
180
|
|
|
203
181
|
# Subject result
|
|
@@ -227,6 +205,16 @@ module Mutant
|
|
|
227
205
|
end
|
|
228
206
|
memoize :alive_mutation_results
|
|
229
207
|
|
|
208
|
+
# Return amount of mutations
|
|
209
|
+
#
|
|
210
|
+
# @return [Fixnum]
|
|
211
|
+
#
|
|
212
|
+
# @api private
|
|
213
|
+
#
|
|
214
|
+
def amount_mutation_results
|
|
215
|
+
mutation_results.length
|
|
216
|
+
end
|
|
217
|
+
|
|
230
218
|
# Return amount of mutations
|
|
231
219
|
#
|
|
232
220
|
# @return [Fixnum]
|
|
@@ -254,7 +242,7 @@ module Mutant
|
|
|
254
242
|
# @api private
|
|
255
243
|
#
|
|
256
244
|
def amount_mutations_alive
|
|
257
|
-
|
|
245
|
+
alive_mutation_results.length
|
|
258
246
|
end
|
|
259
247
|
|
|
260
248
|
# Return alive mutations
|
|
@@ -272,9 +260,9 @@ module Mutant
|
|
|
272
260
|
|
|
273
261
|
# Mutation result
|
|
274
262
|
class Mutation
|
|
275
|
-
include Result, Anima.new(:runtime, :mutation, :test_results)
|
|
263
|
+
include Result, Anima.new(:runtime, :mutation, :test_results, :index)
|
|
276
264
|
|
|
277
|
-
# Test if mutation was
|
|
265
|
+
# Test if mutation was handled successfully
|
|
278
266
|
#
|
|
279
267
|
# @return [Boolean]
|
|
280
268
|
#
|
data/lib/mutant/runner.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Mutant
|
|
2
2
|
# Runner baseclass
|
|
3
3
|
class Runner
|
|
4
|
-
include Adamantium, Concord.new(:env), Procto.call(:result)
|
|
4
|
+
include Adamantium::Flat, Concord.new(:env), Procto.call(:result)
|
|
5
5
|
|
|
6
6
|
# Initialize object
|
|
7
7
|
#
|
|
@@ -12,21 +12,19 @@ module Mutant
|
|
|
12
12
|
def initialize(env)
|
|
13
13
|
super
|
|
14
14
|
|
|
15
|
-
@
|
|
15
|
+
@collector = Collector.new(env)
|
|
16
|
+
@mutex = Mutex.new
|
|
17
|
+
@mutations = env.mutations.dup
|
|
16
18
|
|
|
17
19
|
config.integration.setup
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
config.reporter.start(env)
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
run
|
|
22
24
|
|
|
23
|
-
@result =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
runtime: Time.now - start
|
|
27
|
-
).tap do |report|
|
|
28
|
-
config.reporter.report(report)
|
|
29
|
-
end
|
|
25
|
+
@result = @collector.result.update(done: true)
|
|
26
|
+
|
|
27
|
+
config.reporter.report(result)
|
|
30
28
|
end
|
|
31
29
|
|
|
32
30
|
# Return result
|
|
@@ -39,79 +37,128 @@ module Mutant
|
|
|
39
37
|
|
|
40
38
|
private
|
|
41
39
|
|
|
42
|
-
# Run
|
|
40
|
+
# Run mutation analysis
|
|
43
41
|
#
|
|
44
42
|
# @return [Report::Subject]
|
|
45
43
|
#
|
|
46
44
|
# @api private
|
|
47
45
|
#
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
def run
|
|
47
|
+
Parallel.map(
|
|
48
|
+
@mutations,
|
|
49
|
+
in_processes: config.processes,
|
|
50
|
+
finish: method(:finish),
|
|
51
|
+
start: method(:start),
|
|
52
|
+
&method(:run_mutation)
|
|
53
53
|
)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
#
|
|
56
|
+
# Handle started mutation
|
|
57
57
|
#
|
|
58
|
-
# @
|
|
58
|
+
# @param [Mutation] mutation
|
|
59
|
+
# @param [Fixnum] _index
|
|
60
|
+
#
|
|
61
|
+
# @return [undefined]
|
|
59
62
|
#
|
|
60
63
|
# @api private
|
|
61
64
|
#
|
|
62
|
-
def
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
results << result = run_mutation_test(mutation, test).tap(&method(:progress))
|
|
66
|
-
break results if mutation.killed_by?(result)
|
|
65
|
+
def start(mutation, _index)
|
|
66
|
+
@mutex.synchronize do
|
|
67
|
+
@collector.start(mutation)
|
|
67
68
|
end
|
|
69
|
+
end
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
# Handle finished mutation
|
|
72
|
+
#
|
|
73
|
+
# @param [Mutation] mutation
|
|
74
|
+
# @param [Fixnum] index
|
|
75
|
+
# @param [Object] result
|
|
76
|
+
#
|
|
77
|
+
# @return [undefined]
|
|
78
|
+
#
|
|
79
|
+
# @api private
|
|
80
|
+
#
|
|
81
|
+
def finish(mutation, index, result)
|
|
82
|
+
return unless result.kind_of?(Mutant::Result::Mutation)
|
|
83
|
+
|
|
84
|
+
test_results = result.test_results.zip(mutation.subject.tests).map do |test_result, test|
|
|
85
|
+
test_result.update(test: test, mutation: mutation) if test_result
|
|
86
|
+
end.compact
|
|
87
|
+
|
|
88
|
+
@mutex.synchronize do
|
|
89
|
+
process_result(result.update(index: index, mutation: mutation, test_results: test_results))
|
|
90
|
+
end
|
|
74
91
|
end
|
|
75
92
|
|
|
76
|
-
#
|
|
93
|
+
# Process result
|
|
77
94
|
#
|
|
78
|
-
# @
|
|
95
|
+
# @param [Result::Mutation] result
|
|
96
|
+
#
|
|
97
|
+
# @return [undefined]
|
|
79
98
|
#
|
|
80
99
|
# @api private
|
|
81
100
|
#
|
|
82
|
-
def
|
|
83
|
-
|
|
101
|
+
def process_result(result)
|
|
102
|
+
@collector.finish(result)
|
|
103
|
+
config.reporter.progress(@collector)
|
|
104
|
+
handle_exit(result)
|
|
84
105
|
end
|
|
85
106
|
|
|
86
|
-
#
|
|
107
|
+
# Handle exit if needed
|
|
108
|
+
#
|
|
109
|
+
# @param [Result::Mutation] mutation
|
|
87
110
|
#
|
|
88
|
-
# @return [
|
|
111
|
+
# @return [undefined]
|
|
89
112
|
#
|
|
90
113
|
# @api private
|
|
91
114
|
#
|
|
92
|
-
def
|
|
93
|
-
|
|
115
|
+
def handle_exit(result)
|
|
116
|
+
return if !config.fail_fast || result.success?
|
|
94
117
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
start = Time.now
|
|
98
|
-
results << result = yield(item).update(runtime: Time.now - start).tap(&method(:progress))
|
|
99
|
-
break if @stop ||= config.fail_fast? && result.fail?
|
|
100
|
-
end
|
|
118
|
+
@mutations.clear
|
|
119
|
+
end
|
|
101
120
|
|
|
102
|
-
|
|
121
|
+
# Run mutation
|
|
122
|
+
#
|
|
123
|
+
# @param [Mutation] mutation
|
|
124
|
+
#
|
|
125
|
+
# @return [Report::Mutation]
|
|
126
|
+
#
|
|
127
|
+
# @api private
|
|
128
|
+
#
|
|
129
|
+
def run_mutation(mutation)
|
|
130
|
+
Result::Mutation.compute do
|
|
131
|
+
{
|
|
132
|
+
index: nil,
|
|
133
|
+
mutation: nil,
|
|
134
|
+
test_results: kill_mutation(mutation)
|
|
135
|
+
}
|
|
136
|
+
end
|
|
103
137
|
end
|
|
104
138
|
|
|
105
|
-
#
|
|
139
|
+
# Kill mutation
|
|
106
140
|
#
|
|
107
|
-
# @param [
|
|
141
|
+
# @param [Mutation] mutation
|
|
108
142
|
#
|
|
109
|
-
# @return [
|
|
143
|
+
# @return [Array<Result::Test>]
|
|
110
144
|
#
|
|
111
145
|
# @api private
|
|
112
146
|
#
|
|
113
|
-
def
|
|
114
|
-
|
|
147
|
+
def kill_mutation(mutation)
|
|
148
|
+
mutation.subject.tests.each_with_object([]) do |test, results|
|
|
149
|
+
results << result = run_mutation_test(mutation, test)
|
|
150
|
+
return results if mutation.killed_by?(result)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Return config
|
|
155
|
+
#
|
|
156
|
+
# @return [Config]
|
|
157
|
+
#
|
|
158
|
+
# @api private
|
|
159
|
+
#
|
|
160
|
+
def config
|
|
161
|
+
env.config
|
|
115
162
|
end
|
|
116
163
|
|
|
117
164
|
# Return test result
|
|
@@ -125,11 +172,11 @@ module Mutant
|
|
|
125
172
|
config.isolation.call do
|
|
126
173
|
mutation.insert
|
|
127
174
|
test.run
|
|
128
|
-
end
|
|
175
|
+
end
|
|
129
176
|
rescue Isolation::Error => exception
|
|
130
177
|
Result::Test.new(
|
|
131
|
-
test:
|
|
132
|
-
mutation:
|
|
178
|
+
test: nil,
|
|
179
|
+
mutation: nil,
|
|
133
180
|
runtime: Time.now - time,
|
|
134
181
|
output: exception.message,
|
|
135
182
|
passed: false
|