mutant 0.10.1 → 0.10.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/mutant +0 -2
- data/lib/mutant.rb +7 -5
- data/lib/mutant/cli/command.rb +8 -6
- data/lib/mutant/cli/command/run.rb +23 -10
- data/lib/mutant/config.rb +80 -77
- data/lib/mutant/env.rb +14 -4
- data/lib/mutant/integration.rb +7 -10
- data/lib/mutant/integration/null.rb +0 -1
- data/lib/mutant/isolation.rb +11 -48
- data/lib/mutant/isolation/fork.rb +107 -40
- data/lib/mutant/isolation/none.rb +18 -5
- data/lib/mutant/license/subscription.rb +1 -1
- data/lib/mutant/license/subscription/commercial.rb +2 -3
- data/lib/mutant/license/subscription/opensource.rb +2 -2
- data/lib/mutant/matcher/config.rb +13 -0
- data/lib/mutant/matcher/method/instance.rb +0 -2
- data/lib/mutant/mutator/node/send.rb +1 -1
- data/lib/mutant/parallel.rb +0 -1
- data/lib/mutant/parallel/worker.rb +0 -2
- data/lib/mutant/reporter/cli.rb +0 -2
- data/lib/mutant/reporter/cli/printer/config.rb +9 -5
- data/lib/mutant/reporter/cli/printer/coverage_result.rb +19 -0
- data/lib/mutant/reporter/cli/printer/env_progress.rb +2 -0
- data/lib/mutant/reporter/cli/printer/isolation_result.rb +19 -35
- data/lib/mutant/reporter/cli/printer/mutation_result.rb +4 -9
- data/lib/mutant/reporter/cli/printer/subject_result.rb +2 -2
- data/lib/mutant/result.rb +91 -30
- data/lib/mutant/runner/sink.rb +12 -5
- data/lib/mutant/timer.rb +60 -11
- data/lib/mutant/transform.rb +25 -21
- data/lib/mutant/version.rb +1 -1
- data/lib/mutant/warnings.rb +0 -1
- data/lib/mutant/world.rb +67 -0
- metadata +12 -14
- data/lib/mutant/minitest/coverage.rb +0 -51
- data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -28
- data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -58
- data/lib/mutant/reporter/cli/printer/test_result.rb +0 -32
data/lib/mutant/runner/sink.rb
CHANGED
@@ -10,7 +10,7 @@ module Mutant
|
|
10
10
|
# @return [undefined]
|
11
11
|
def initialize(*)
|
12
12
|
super
|
13
|
-
@start =
|
13
|
+
@start = env.world.timer.now
|
14
14
|
@subject_results = {}
|
15
15
|
end
|
16
16
|
|
@@ -20,7 +20,7 @@ module Mutant
|
|
20
20
|
def status
|
21
21
|
Result::Env.new(
|
22
22
|
env: env,
|
23
|
-
runtime:
|
23
|
+
runtime: env.world.timer.now - @start,
|
24
24
|
subject_results: @subject_results.values
|
25
25
|
)
|
26
26
|
end
|
@@ -42,7 +42,7 @@ module Mutant
|
|
42
42
|
|
43
43
|
@subject_results[subject] = Result::Subject.new(
|
44
44
|
subject: subject,
|
45
|
-
|
45
|
+
coverage_results: previous_coverage_results(subject).dup << coverage_result(mutation_result),
|
46
46
|
tests: env.selections.fetch(subject)
|
47
47
|
)
|
48
48
|
|
@@ -51,9 +51,16 @@ module Mutant
|
|
51
51
|
|
52
52
|
private
|
53
53
|
|
54
|
-
def
|
54
|
+
def coverage_result(mutation_result)
|
55
|
+
Result::Coverage.new(
|
56
|
+
mutation_result: mutation_result,
|
57
|
+
criteria_result: mutation_result.criteria_result(env.config.coverage_criteria)
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def previous_coverage_results(subject)
|
55
62
|
subject_result = @subject_results.fetch(subject) { return EMPTY_ARRAY }
|
56
|
-
subject_result.
|
63
|
+
subject_result.coverage_results
|
57
64
|
end
|
58
65
|
|
59
66
|
end # Sink
|
data/lib/mutant/timer.rb
CHANGED
@@ -1,21 +1,70 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Mutant
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
# @return [Float]
|
8
|
-
def self.elapsed
|
9
|
-
start = now
|
10
|
-
yield
|
11
|
-
now - start
|
12
|
-
end
|
4
|
+
class Timer
|
5
|
+
include Concord.new(:process)
|
13
6
|
|
14
7
|
# The now monotonic time
|
15
8
|
#
|
16
9
|
# @return [Float]
|
17
|
-
def
|
18
|
-
|
10
|
+
def now
|
11
|
+
process.clock_gettime(Process::CLOCK_MONOTONIC)
|
19
12
|
end
|
13
|
+
|
14
|
+
class Deadline
|
15
|
+
include Anima.new(:timer, :allowed_time)
|
16
|
+
|
17
|
+
def initialize(**arguments)
|
18
|
+
super(**arguments)
|
19
|
+
@start_at = timer.now
|
20
|
+
end
|
21
|
+
|
22
|
+
# Test if deadline is expired
|
23
|
+
#
|
24
|
+
# @return [Boolean]
|
25
|
+
def expired?
|
26
|
+
time_left <= 0
|
27
|
+
end
|
28
|
+
|
29
|
+
# Deadline status snapshot
|
30
|
+
class Status
|
31
|
+
include Concord::Public.new(:time_left)
|
32
|
+
|
33
|
+
# Test if deadline is not yet expired
|
34
|
+
def ok?
|
35
|
+
time_left.nil? || time_left.positive?
|
36
|
+
end
|
37
|
+
end # Status
|
38
|
+
|
39
|
+
# Capture a deadline status
|
40
|
+
#
|
41
|
+
# @return [Status]
|
42
|
+
def status
|
43
|
+
Status.new(time_left)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Probe the time left
|
47
|
+
#
|
48
|
+
# @return [Float, nil]
|
49
|
+
def time_left
|
50
|
+
allowed_time - (timer.now - @start_at)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Deadline that never expires
|
54
|
+
class None < self
|
55
|
+
include Concord.new
|
56
|
+
|
57
|
+
STATUS = Status.new(nil)
|
58
|
+
|
59
|
+
# The time left
|
60
|
+
#
|
61
|
+
# @return [Float, nil]
|
62
|
+
def time_left; end
|
63
|
+
|
64
|
+
def expired?
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end # Deadline
|
20
69
|
end # Timer
|
21
70
|
end # Mutant
|
data/lib/mutant/transform.rb
CHANGED
@@ -16,7 +16,7 @@ module Mutant
|
|
16
16
|
# @param [Object] input
|
17
17
|
#
|
18
18
|
# @return [Either<Error, Object>]
|
19
|
-
abstract_method :
|
19
|
+
abstract_method :call
|
20
20
|
|
21
21
|
# Deep error data structure
|
22
22
|
class Error
|
@@ -61,8 +61,8 @@ module Mutant
|
|
61
61
|
# Apply transformation to input
|
62
62
|
#
|
63
63
|
# @return [Either<Error, Object>]
|
64
|
-
def
|
65
|
-
transformer.
|
64
|
+
def call(input)
|
65
|
+
transformer.call(input).lmap(&method(:wrap_error))
|
66
66
|
end
|
67
67
|
|
68
68
|
# Named slug
|
@@ -126,8 +126,8 @@ module Mutant
|
|
126
126
|
# @param [Object] input
|
127
127
|
#
|
128
128
|
# @return [Either<Error, Object>]
|
129
|
-
def
|
130
|
-
transform.
|
129
|
+
def call(input)
|
130
|
+
transform.call(input).lmap(&method(:wrap_error))
|
131
131
|
end
|
132
132
|
|
133
133
|
# Rendering slug
|
@@ -152,7 +152,7 @@ module Mutant
|
|
152
152
|
# @param [Object] input
|
153
153
|
#
|
154
154
|
# @return [Either<Error, Object>]
|
155
|
-
def
|
155
|
+
def call(input)
|
156
156
|
if input.instance_of?(primitive)
|
157
157
|
success(input)
|
158
158
|
else
|
@@ -187,7 +187,7 @@ module Mutant
|
|
187
187
|
# @param [Object] input
|
188
188
|
#
|
189
189
|
# @return [Either<Error, Object>]
|
190
|
-
def
|
190
|
+
def call(input)
|
191
191
|
if input.equal?(true) || input.equal?(false)
|
192
192
|
success(input)
|
193
193
|
else
|
@@ -215,9 +215,9 @@ module Mutant
|
|
215
215
|
# @param [Object] input
|
216
216
|
#
|
217
217
|
# @return [Either<Error, Array<Object>>]
|
218
|
-
def
|
218
|
+
def call(input)
|
219
219
|
PRIMITIVE
|
220
|
-
.
|
220
|
+
.call(input)
|
221
221
|
.lmap(&method(:lift_error))
|
222
222
|
.bind(&method(:run))
|
223
223
|
end
|
@@ -229,7 +229,7 @@ module Mutant
|
|
229
229
|
output = []
|
230
230
|
|
231
231
|
input.each_with_index do |value, index|
|
232
|
-
output << transform.
|
232
|
+
output << transform.call(value).lmap do |error|
|
233
233
|
return failure(
|
234
234
|
error(
|
235
235
|
cause: Index.wrap(error, index),
|
@@ -261,7 +261,7 @@ module Mutant
|
|
261
261
|
# @param [Hash{String => Object}]
|
262
262
|
#
|
263
263
|
# @return [Hash{Symbol => Object}]
|
264
|
-
def
|
264
|
+
def call(input)
|
265
265
|
success(input.transform_keys(&:to_sym))
|
266
266
|
end
|
267
267
|
end # Symbolize
|
@@ -283,8 +283,8 @@ module Mutant
|
|
283
283
|
# @param [Object]
|
284
284
|
#
|
285
285
|
# @return [Either<Error, Object>]
|
286
|
-
def
|
287
|
-
transform.
|
286
|
+
def call(input)
|
287
|
+
transform.call(input).lmap do |error|
|
288
288
|
error(cause: error, input: input)
|
289
289
|
end
|
290
290
|
end
|
@@ -295,9 +295,9 @@ module Mutant
|
|
295
295
|
# @param [Object] input
|
296
296
|
#
|
297
297
|
# @return [Either<Error, Object>]
|
298
|
-
def
|
298
|
+
def call(input)
|
299
299
|
PRIMITIVE
|
300
|
-
.
|
300
|
+
.call(input)
|
301
301
|
.lmap(&method(:lift_error))
|
302
302
|
.bind(&method(:reject_keys))
|
303
303
|
.bind(&method(:transform))
|
@@ -322,8 +322,6 @@ module Mutant
|
|
322
322
|
)
|
323
323
|
end
|
324
324
|
|
325
|
-
# ignore :reek:NestedIterators
|
326
|
-
#
|
327
325
|
# rubocop:disable Metrics/MethodLength
|
328
326
|
def transform_keys(keys, input)
|
329
327
|
success(
|
@@ -342,7 +340,7 @@ module Mutant
|
|
342
340
|
# rubocop:enable Metrics/MethodLength
|
343
341
|
|
344
342
|
def coerce_key(key, input)
|
345
|
-
key.
|
343
|
+
key.call(input.fetch(key.value)).lmap do |error|
|
346
344
|
error(input: input, cause: error)
|
347
345
|
end
|
348
346
|
end
|
@@ -388,11 +386,11 @@ module Mutant
|
|
388
386
|
# ignore :reek:NestedIterators
|
389
387
|
#
|
390
388
|
# @return [Either<Error, Object>]
|
391
|
-
def
|
389
|
+
def call(input)
|
392
390
|
current = input
|
393
391
|
|
394
392
|
steps.each_with_index do |step, index|
|
395
|
-
current = step.
|
393
|
+
current = step.call(current).from_right do |error|
|
396
394
|
return failure(error(cause: Index.wrap(error, index), input: input))
|
397
395
|
end
|
398
396
|
end
|
@@ -410,11 +408,17 @@ module Mutant
|
|
410
408
|
# @param [Object]
|
411
409
|
#
|
412
410
|
# @return [Either<Error, Object>]
|
413
|
-
def
|
411
|
+
def call(input)
|
414
412
|
Either
|
415
413
|
.wrap_error(error_class) { block.call(input) }
|
416
414
|
.lmap { |exception| error(input: input, message: exception.to_s) }
|
417
415
|
end
|
418
416
|
end # Exception
|
417
|
+
|
418
|
+
BOOLEAN = Transform::Boolean.new
|
419
|
+
FLOAT = Transform::Primitive.new(Float)
|
420
|
+
INTEGER = Transform::Primitive.new(Integer)
|
421
|
+
STRING = Transform::Primitive.new(String)
|
422
|
+
STRING_ARRAY = Transform::Array.new(STRING)
|
419
423
|
end # Transform
|
420
424
|
end # Mutant
|
data/lib/mutant/version.rb
CHANGED
data/lib/mutant/warnings.rb
CHANGED
@@ -55,7 +55,6 @@ module Mutant
|
|
55
55
|
# For that reason we do have to use the original method capture to dispatch
|
56
56
|
# in disabled state.
|
57
57
|
#
|
58
|
-
# ignore :reek:RepeatedConditional
|
59
58
|
class Warnings
|
60
59
|
# Error raised when warning capture is used recursively
|
61
60
|
class RecursiveUseError < RuntimeError; end
|
data/lib/mutant/world.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mutant
|
4
|
+
# The outer world IO objects mutant does interact with
|
5
|
+
class World
|
6
|
+
include Adamantium::Flat, Anima.new(
|
7
|
+
:condition_variable,
|
8
|
+
:gem,
|
9
|
+
:gem_method,
|
10
|
+
:io,
|
11
|
+
:json,
|
12
|
+
:kernel,
|
13
|
+
:load_path,
|
14
|
+
:marshal,
|
15
|
+
:mutex,
|
16
|
+
:object_space,
|
17
|
+
:open3,
|
18
|
+
:pathname,
|
19
|
+
:process,
|
20
|
+
:stderr,
|
21
|
+
:stdout,
|
22
|
+
:thread,
|
23
|
+
:timer,
|
24
|
+
:warnings
|
25
|
+
)
|
26
|
+
|
27
|
+
INSPECT = '#<Mutant::World>'
|
28
|
+
|
29
|
+
private_constant(*constants(false))
|
30
|
+
|
31
|
+
# Object inspection
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
def inspect
|
35
|
+
INSPECT
|
36
|
+
end
|
37
|
+
|
38
|
+
# Capture stdout of a command
|
39
|
+
#
|
40
|
+
# @param [Array<String>] command
|
41
|
+
#
|
42
|
+
# @return [Either<String,String>]
|
43
|
+
def capture_stdout(command)
|
44
|
+
stdout, status = open3.capture2(*command, binmode: true)
|
45
|
+
|
46
|
+
if status.success?
|
47
|
+
Either::Right.new(stdout)
|
48
|
+
else
|
49
|
+
Either::Left.new("Command #{command} failed!")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Deadline
|
54
|
+
#
|
55
|
+
# @param [Float, nil] allowed_time
|
56
|
+
def deadline(allowed_time)
|
57
|
+
if allowed_time
|
58
|
+
Timer::Deadline.new(
|
59
|
+
allowed_time: allowed_time,
|
60
|
+
timer: timer
|
61
|
+
)
|
62
|
+
else
|
63
|
+
Timer::Deadline::None.new
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end # World
|
67
|
+
end # Mutant
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mutant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_type
|
@@ -184,14 +184,14 @@ dependencies:
|
|
184
184
|
requirements:
|
185
185
|
- - "~>"
|
186
186
|
- !ruby/object:Gem::Version
|
187
|
-
version: 0.5.
|
187
|
+
version: 0.5.4
|
188
188
|
type: :runtime
|
189
189
|
prerelease: false
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
191
191
|
requirements:
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
|
-
version: 0.5.
|
194
|
+
version: 0.5.4
|
195
195
|
- !ruby/object:Gem::Dependency
|
196
196
|
name: variable
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
@@ -226,28 +226,28 @@ dependencies:
|
|
226
226
|
requirements:
|
227
227
|
- - "~>"
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version: '3.
|
229
|
+
version: '3.10'
|
230
230
|
type: :development
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
233
233
|
requirements:
|
234
234
|
- - "~>"
|
235
235
|
- !ruby/object:Gem::Version
|
236
|
-
version: '3.
|
236
|
+
version: '3.10'
|
237
237
|
- !ruby/object:Gem::Dependency
|
238
238
|
name: rspec-core
|
239
239
|
requirement: !ruby/object:Gem::Requirement
|
240
240
|
requirements:
|
241
241
|
- - "~>"
|
242
242
|
- !ruby/object:Gem::Version
|
243
|
-
version: '3.
|
243
|
+
version: '3.10'
|
244
244
|
type: :development
|
245
245
|
prerelease: false
|
246
246
|
version_requirements: !ruby/object:Gem::Requirement
|
247
247
|
requirements:
|
248
248
|
- - "~>"
|
249
249
|
- !ruby/object:Gem::Version
|
250
|
-
version: '3.
|
250
|
+
version: '3.10'
|
251
251
|
- !ruby/object:Gem::Dependency
|
252
252
|
name: rspec-its
|
253
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -268,14 +268,14 @@ dependencies:
|
|
268
268
|
requirements:
|
269
269
|
- - "~>"
|
270
270
|
- !ruby/object:Gem::Version
|
271
|
-
version: '1.
|
271
|
+
version: '1.2'
|
272
272
|
type: :development
|
273
273
|
prerelease: false
|
274
274
|
version_requirements: !ruby/object:Gem::Requirement
|
275
275
|
requirements:
|
276
276
|
- - "~>"
|
277
277
|
- !ruby/object:Gem::Version
|
278
|
-
version: '1.
|
278
|
+
version: '1.2'
|
279
279
|
description: Mutation Testing for Ruby.
|
280
280
|
email:
|
281
281
|
- mbj@schirp-dso.com
|
@@ -342,7 +342,6 @@ files:
|
|
342
342
|
- lib/mutant/meta/example.rb
|
343
343
|
- lib/mutant/meta/example/dsl.rb
|
344
344
|
- lib/mutant/meta/example/verification.rb
|
345
|
-
- lib/mutant/minitest/coverage.rb
|
346
345
|
- lib/mutant/mutation.rb
|
347
346
|
- lib/mutant/mutator.rb
|
348
347
|
- lib/mutant/mutator/node.rb
|
@@ -417,16 +416,14 @@ files:
|
|
417
416
|
- lib/mutant/reporter/cli/format.rb
|
418
417
|
- lib/mutant/reporter/cli/printer.rb
|
419
418
|
- lib/mutant/reporter/cli/printer/config.rb
|
419
|
+
- lib/mutant/reporter/cli/printer/coverage_result.rb
|
420
420
|
- lib/mutant/reporter/cli/printer/env.rb
|
421
421
|
- lib/mutant/reporter/cli/printer/env_progress.rb
|
422
422
|
- lib/mutant/reporter/cli/printer/env_result.rb
|
423
423
|
- lib/mutant/reporter/cli/printer/isolation_result.rb
|
424
|
-
- lib/mutant/reporter/cli/printer/mutation_progress_result.rb
|
425
424
|
- lib/mutant/reporter/cli/printer/mutation_result.rb
|
426
425
|
- lib/mutant/reporter/cli/printer/status_progressive.rb
|
427
|
-
- lib/mutant/reporter/cli/printer/subject_progress.rb
|
428
426
|
- lib/mutant/reporter/cli/printer/subject_result.rb
|
429
|
-
- lib/mutant/reporter/cli/printer/test_result.rb
|
430
427
|
- lib/mutant/reporter/null.rb
|
431
428
|
- lib/mutant/reporter/sequence.rb
|
432
429
|
- lib/mutant/repository.rb
|
@@ -451,6 +448,7 @@ files:
|
|
451
448
|
- lib/mutant/util.rb
|
452
449
|
- lib/mutant/version.rb
|
453
450
|
- lib/mutant/warnings.rb
|
451
|
+
- lib/mutant/world.rb
|
454
452
|
- lib/mutant/zombifier.rb
|
455
453
|
homepage: https://github.com/mbj/mutant
|
456
454
|
licenses:
|