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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mutant.rb +4 -3
  3. data/lib/mutant/cli/command/run.rb +5 -2
  4. data/lib/mutant/config.rb +59 -34
  5. data/lib/mutant/env.rb +14 -4
  6. data/lib/mutant/integration.rb +7 -10
  7. data/lib/mutant/integration/null.rb +0 -1
  8. data/lib/mutant/isolation.rb +11 -48
  9. data/lib/mutant/isolation/fork.rb +107 -40
  10. data/lib/mutant/isolation/none.rb +18 -5
  11. data/lib/mutant/license/subscription/commercial.rb +2 -3
  12. data/lib/mutant/license/subscription/opensource.rb +0 -1
  13. data/lib/mutant/matcher/method/instance.rb +0 -2
  14. data/lib/mutant/mutator/node/send.rb +1 -1
  15. data/lib/mutant/parallel.rb +0 -1
  16. data/lib/mutant/parallel/worker.rb +0 -2
  17. data/lib/mutant/reporter/cli.rb +0 -2
  18. data/lib/mutant/reporter/cli/printer/config.rb +9 -5
  19. data/lib/mutant/reporter/cli/printer/coverage_result.rb +19 -0
  20. data/lib/mutant/reporter/cli/printer/env_progress.rb +2 -0
  21. data/lib/mutant/reporter/cli/printer/isolation_result.rb +19 -35
  22. data/lib/mutant/reporter/cli/printer/mutation_result.rb +4 -9
  23. data/lib/mutant/reporter/cli/printer/subject_result.rb +2 -2
  24. data/lib/mutant/result.rb +81 -30
  25. data/lib/mutant/runner/sink.rb +12 -5
  26. data/lib/mutant/timer.rb +60 -11
  27. data/lib/mutant/transform.rb +25 -21
  28. data/lib/mutant/version.rb +1 -1
  29. data/lib/mutant/warnings.rb +0 -1
  30. data/lib/mutant/world.rb +15 -0
  31. metadata +3 -5
  32. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -28
  33. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -58
  34. data/lib/mutant/reporter/cli/printer/test_result.rb +0 -32
@@ -10,7 +10,7 @@ module Mutant
10
10
  # @return [undefined]
11
11
  def initialize(*)
12
12
  super
13
- @start = Timer.now
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: Timer.now - @start,
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
- mutation_results: previous_mutation_results(subject) + [mutation_result],
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 previous_mutation_results(subject)
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.mutation_results
63
+ subject_result.coverage_results
57
64
  end
58
65
 
59
66
  end # Sink
@@ -1,21 +1,70 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mutant
4
- module Timer
5
- # Monotonic elapsed time of block execution
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 self.now
18
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
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
@@ -16,7 +16,7 @@ module Mutant
16
16
  # @param [Object] input
17
17
  #
18
18
  # @return [Either<Error, Object>]
19
- abstract_method :apply
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 apply(input)
65
- transformer.apply(input).lmap(&method(:wrap_error))
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 apply(input)
130
- transform.apply(input).lmap(&method(:wrap_error))
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 apply(input)
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 apply(input)
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 apply(input)
218
+ def call(input)
219
219
  PRIMITIVE
220
- .apply(input)
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.apply(value).lmap do |error|
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 apply(input)
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 apply(input)
287
- transform.apply(input).lmap do |error|
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 apply(input)
298
+ def call(input)
299
299
  PRIMITIVE
300
- .apply(input)
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.apply(input.fetch(key.value)).lmap do |error|
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 apply(input)
389
+ def call(input)
392
390
  current = input
393
391
 
394
392
  steps.each_with_index do |step, index|
395
- current = step.apply(current).from_right do |error|
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 apply(input)
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
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.10.6'
5
+ VERSION = '0.10.7'
6
6
  end # Mutant
@@ -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
@@ -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.6
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-06 00:00:00.000000000 Z
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