mutant 0.10.6 → 0.10.7
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/lib/mutant.rb +4 -3
- data/lib/mutant/cli/command/run.rb +5 -2
- data/lib/mutant/config.rb +59 -34
- 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/commercial.rb +2 -3
- data/lib/mutant/license/subscription/opensource.rb +0 -1
- 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 +81 -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 +15 -0
- metadata +3 -5
- 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
CHANGED
@@ -20,6 +20,7 @@ module Mutant
|
|
20
20
|
:stderr,
|
21
21
|
:stdout,
|
22
22
|
:thread,
|
23
|
+
:timer,
|
23
24
|
:warnings
|
24
25
|
)
|
25
26
|
|
@@ -48,5 +49,19 @@ module Mutant
|
|
48
49
|
Either::Left.new("Command #{command} failed!")
|
49
50
|
end
|
50
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
|
51
66
|
end # World
|
52
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.7
|
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-
|
11
|
+
date: 2020-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: abstract_type
|
@@ -416,16 +416,14 @@ files:
|
|
416
416
|
- lib/mutant/reporter/cli/format.rb
|
417
417
|
- lib/mutant/reporter/cli/printer.rb
|
418
418
|
- lib/mutant/reporter/cli/printer/config.rb
|
419
|
+
- lib/mutant/reporter/cli/printer/coverage_result.rb
|
419
420
|
- lib/mutant/reporter/cli/printer/env.rb
|
420
421
|
- lib/mutant/reporter/cli/printer/env_progress.rb
|
421
422
|
- lib/mutant/reporter/cli/printer/env_result.rb
|
422
423
|
- lib/mutant/reporter/cli/printer/isolation_result.rb
|
423
|
-
- lib/mutant/reporter/cli/printer/mutation_progress_result.rb
|
424
424
|
- lib/mutant/reporter/cli/printer/mutation_result.rb
|
425
425
|
- lib/mutant/reporter/cli/printer/status_progressive.rb
|
426
|
-
- lib/mutant/reporter/cli/printer/subject_progress.rb
|
427
426
|
- lib/mutant/reporter/cli/printer/subject_result.rb
|
428
|
-
- lib/mutant/reporter/cli/printer/test_result.rb
|
429
427
|
- lib/mutant/reporter/null.rb
|
430
428
|
- lib/mutant/reporter/sequence.rb
|
431
429
|
- lib/mutant/repository.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mutant
|
4
|
-
class Reporter
|
5
|
-
class CLI
|
6
|
-
class Printer
|
7
|
-
# Printer for mutation progress results
|
8
|
-
class MutationProgressResult < self
|
9
|
-
SUCCESS = '.'
|
10
|
-
FAILURE = 'F'
|
11
|
-
|
12
|
-
# Run printer
|
13
|
-
#
|
14
|
-
# @return [undefined]
|
15
|
-
def run
|
16
|
-
char(success? ? SUCCESS : FAILURE)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def char(char)
|
22
|
-
output.write(colorize(status_color, char))
|
23
|
-
end
|
24
|
-
end # MutationProgressResult
|
25
|
-
end # Printer
|
26
|
-
end # CLI
|
27
|
-
end # Reporter
|
28
|
-
end # Mutant
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mutant
|
4
|
-
class Reporter
|
5
|
-
class CLI
|
6
|
-
class Printer
|
7
|
-
# Reporter for subject progress
|
8
|
-
class SubjectProgress < self
|
9
|
-
FORMAT = '(%02d/%02d) %3d%% - killtime: %0.02fs runtime: %0.02fs overhead: %0.02fs'
|
10
|
-
|
11
|
-
delegate(
|
12
|
-
:tests,
|
13
|
-
:subject,
|
14
|
-
:coverage,
|
15
|
-
:runtime,
|
16
|
-
:amount_mutations_killed,
|
17
|
-
:amount_mutations,
|
18
|
-
:amount_mutation_results,
|
19
|
-
:killtime,
|
20
|
-
:overhead
|
21
|
-
)
|
22
|
-
|
23
|
-
# Run printer
|
24
|
-
#
|
25
|
-
# @return [undefined]
|
26
|
-
def run
|
27
|
-
puts("#{subject.identification} mutations: #{amount_mutations}")
|
28
|
-
print_mutation_results
|
29
|
-
print_progress_bar_finish
|
30
|
-
print_stats
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def print_stats
|
36
|
-
status(
|
37
|
-
FORMAT,
|
38
|
-
amount_mutations_killed,
|
39
|
-
amount_mutations,
|
40
|
-
coverage * 100,
|
41
|
-
killtime,
|
42
|
-
runtime,
|
43
|
-
overhead
|
44
|
-
)
|
45
|
-
end
|
46
|
-
|
47
|
-
def print_progress_bar_finish
|
48
|
-
puts(nil) unless amount_mutation_results.zero?
|
49
|
-
end
|
50
|
-
|
51
|
-
def print_mutation_results
|
52
|
-
visit_collection(MutationProgressResult, object.mutation_results)
|
53
|
-
end
|
54
|
-
end # SubjectProgress
|
55
|
-
end # Printer
|
56
|
-
end # CLI
|
57
|
-
end # Reporter
|
58
|
-
end # Mutant
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Mutant
|
4
|
-
class Reporter
|
5
|
-
class CLI
|
6
|
-
class Printer
|
7
|
-
# Test result reporter
|
8
|
-
class TestResult < self
|
9
|
-
|
10
|
-
delegate :tests, :runtime
|
11
|
-
|
12
|
-
STATUS_FORMAT = '- %d @ runtime: %s'
|
13
|
-
OUTPUT_HEADER = 'Test Output:'
|
14
|
-
TEST_FORMAT = ' - %s'
|
15
|
-
|
16
|
-
# Run test result reporter
|
17
|
-
#
|
18
|
-
# @return [undefined]
|
19
|
-
def run
|
20
|
-
info(STATUS_FORMAT, tests.length, runtime)
|
21
|
-
tests.each do |test|
|
22
|
-
info(TEST_FORMAT, test.identification)
|
23
|
-
end
|
24
|
-
puts(OUTPUT_HEADER)
|
25
|
-
puts(object.output)
|
26
|
-
end
|
27
|
-
|
28
|
-
end # TestResult
|
29
|
-
end # Printer
|
30
|
-
end # CLI
|
31
|
-
end # Reporter
|
32
|
-
end # Mutant
|