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