mutant 0.10.0 → 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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mutant +0 -2
  3. data/lib/mutant.rb +7 -5
  4. data/lib/mutant/cli/command.rb +8 -6
  5. data/lib/mutant/cli/command/run.rb +23 -10
  6. data/lib/mutant/config.rb +78 -77
  7. data/lib/mutant/env.rb +14 -4
  8. data/lib/mutant/integration.rb +7 -10
  9. data/lib/mutant/integration/null.rb +0 -1
  10. data/lib/mutant/isolation.rb +11 -48
  11. data/lib/mutant/isolation/fork.rb +107 -40
  12. data/lib/mutant/isolation/none.rb +18 -5
  13. data/lib/mutant/license/subscription.rb +1 -1
  14. data/lib/mutant/license/subscription/commercial.rb +2 -3
  15. data/lib/mutant/license/subscription/opensource.rb +2 -2
  16. data/lib/mutant/matcher/config.rb +13 -0
  17. data/lib/mutant/matcher/method/instance.rb +0 -2
  18. data/lib/mutant/mutator/node/send.rb +1 -1
  19. data/lib/mutant/parallel.rb +0 -1
  20. data/lib/mutant/parallel/worker.rb +0 -2
  21. data/lib/mutant/reporter/cli.rb +0 -2
  22. data/lib/mutant/reporter/cli/printer/config.rb +9 -5
  23. data/lib/mutant/reporter/cli/printer/coverage_result.rb +19 -0
  24. data/lib/mutant/reporter/cli/printer/env_progress.rb +2 -0
  25. data/lib/mutant/reporter/cli/printer/isolation_result.rb +19 -35
  26. data/lib/mutant/reporter/cli/printer/mutation_result.rb +4 -9
  27. data/lib/mutant/reporter/cli/printer/subject_result.rb +2 -2
  28. data/lib/mutant/result.rb +81 -30
  29. data/lib/mutant/runner/sink.rb +12 -5
  30. data/lib/mutant/selector/expression.rb +3 -1
  31. data/lib/mutant/test.rb +1 -1
  32. data/lib/mutant/timer.rb +60 -11
  33. data/lib/mutant/transform.rb +25 -21
  34. data/lib/mutant/version.rb +1 -1
  35. data/lib/mutant/warnings.rb +0 -1
  36. data/lib/mutant/world.rb +67 -0
  37. metadata +13 -15
  38. data/lib/mutant/minitest/coverage.rb +0 -53
  39. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -28
  40. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -58
  41. 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
@@ -14,7 +14,9 @@ module Mutant
14
14
  def call(subject)
15
15
  subject.match_expressions.each do |match_expression|
16
16
  subject_tests = integration.all_tests.select do |test|
17
- match_expression.prefix?(test.expression)
17
+ test.expressions.any? do |test_expression|
18
+ match_expression.prefix?(test_expression)
19
+ end
18
20
  end
19
21
  return subject_tests if subject_tests.any?
20
22
  end
@@ -4,7 +4,7 @@ module Mutant
4
4
  # Abstract base class for test that might kill a mutation
5
5
  class Test
6
6
  include Adamantium::Flat, Anima.new(
7
- :expression,
7
+ :expressions,
8
8
  :id
9
9
  )
10
10
 
@@ -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.0'
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
@@ -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.0
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-10-29 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
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.5.3
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.3
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.9'
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.9'
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.9'
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.9'
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.0'
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.0'
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:
@@ -471,7 +469,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
471
469
  - !ruby/object:Gem::Version
472
470
  version: '0'
473
471
  requirements: []
474
- rubygems_version: 3.2.0.rc.1
472
+ rubygems_version: 3.1.4
475
473
  signing_key:
476
474
  specification_version: 4
477
475
  summary: ''