mutant 0.10.6 → 0.10.7

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