mutant 0.10.1 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) 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 +80 -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 +91 -30
  29. data/lib/mutant/runner/sink.rb +12 -5
  30. data/lib/mutant/timer.rb +60 -11
  31. data/lib/mutant/transform.rb +25 -21
  32. data/lib/mutant/version.rb +1 -1
  33. data/lib/mutant/warnings.rb +0 -1
  34. data/lib/mutant/world.rb +67 -0
  35. metadata +12 -14
  36. data/lib/mutant/minitest/coverage.rb +0 -51
  37. data/lib/mutant/reporter/cli/printer/mutation_progress_result.rb +0 -28
  38. data/lib/mutant/reporter/cli/printer/subject_progress.rb +0 -58
  39. 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.1'
5
+ VERSION = '0.10.8'
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.1
4
+ version: 0.10.8
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: