mutant 0.15.1 → 0.16.2

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/mutant/ast/pattern/lexer.rb +119 -47
  4. data/lib/mutant/cli/command/root.rb +1 -1
  5. data/lib/mutant/cli/command/session.rb +281 -0
  6. data/lib/mutant/cli/command.rb +16 -2
  7. data/lib/mutant/config.rb +1 -1
  8. data/lib/mutant/expression/method.rb +0 -2
  9. data/lib/mutant/expression/methods.rb +0 -2
  10. data/lib/mutant/expression/namespace.rb +0 -2
  11. data/lib/mutant/integration/null.rb +1 -1
  12. data/lib/mutant/isolation/fork.rb +3 -7
  13. data/lib/mutant/isolation/none.rb +1 -1
  14. data/lib/mutant/isolation.rb +31 -0
  15. data/lib/mutant/log_capture.rb +89 -0
  16. data/lib/mutant/matcher/null.rb +1 -1
  17. data/lib/mutant/mutation/runner/sink.rb +23 -10
  18. data/lib/mutant/mutation/runner.rb +1 -0
  19. data/lib/mutant/mutation.rb +3 -20
  20. data/lib/mutant/mutator/node/literal/integer.rb +61 -0
  21. data/lib/mutant/parallel/connection.rb +2 -4
  22. data/lib/mutant/parallel/driver.rb +0 -2
  23. data/lib/mutant/reporter/cli/printer/alive_results.rb +27 -0
  24. data/lib/mutant/reporter/cli/printer/env_result.rb +52 -9
  25. data/lib/mutant/reporter/cli/printer/isolation_result.rb +3 -6
  26. data/lib/mutant/reporter/cli/printer/subject_result.rb +103 -5
  27. data/lib/mutant/reporter/cli/printer/test.rb +1 -1
  28. data/lib/mutant/reporter/cli/printer.rb +24 -1
  29. data/lib/mutant/repository/diff.rb +1 -2
  30. data/lib/mutant/result/exception.rb +29 -0
  31. data/lib/mutant/result/json_writer.rb +43 -0
  32. data/lib/mutant/result/process_status.rb +37 -0
  33. data/lib/mutant/result/session.rb +63 -0
  34. data/lib/mutant/result/test.rb +57 -0
  35. data/lib/mutant/result.rb +201 -96
  36. data/lib/mutant/segment/recorder.rb +0 -2
  37. data/lib/mutant/test/runner/sink.rb +1 -1
  38. data/lib/mutant/timer.rb +3 -1
  39. data/lib/mutant/transform/codec.rb +45 -0
  40. data/lib/mutant/transform.rb +33 -25
  41. data/lib/mutant/world.rb +6 -0
  42. data/lib/mutant/zombifier.rb +0 -2
  43. data/lib/mutant.rb +14 -4
  44. metadata +34 -7
  45. data/lib/mutant/reporter/cli/printer/coverage_result.rb +0 -19
  46. data/lib/mutant/reporter/cli/printer/mutation_result.rb +0 -84
@@ -117,8 +117,6 @@ module Mutant
117
117
  class Index < self
118
118
  include Anima.new(:index, :transform)
119
119
 
120
- private(*anima.attribute_names)
121
-
122
120
  # Create error at specified index
123
121
  #
124
122
  # @param [Error] cause
@@ -185,7 +183,7 @@ module Mutant
185
183
 
186
184
  # Transform guarding boolean primitives
187
185
  class Boolean < self
188
- include Concord.new
186
+ include Equalizer.new
189
187
 
190
188
  MESSAGE = 'Expected: boolean but got: %<actual>s'
191
189
 
@@ -258,8 +256,8 @@ module Mutant
258
256
  class Hash < self
259
257
  include Anima.new(:optional, :required)
260
258
 
261
- KEY_MESSAGE = 'Missing keys: %<missing>s, Unexpected keys: %<unexpected>s'
262
- PRIMITIVE = Primitive.new(primitive: ::Hash)
259
+ KEY_MESSAGE = 'Missing keys: %<missing>s, Unexpected keys: %<unexpected>s'
260
+ PRIMITIVE = Primitive.new(primitive: ::Hash)
263
261
 
264
262
  private_constant(*constants(false))
265
263
 
@@ -313,24 +311,16 @@ module Mutant
313
311
  private
314
312
 
315
313
  def transform(input)
316
- transform_required(input).bind do |required|
317
- transform_optional(input).fmap(&required.public_method(:merge))
314
+ coerce_keys(required, input).bind do |required|
315
+ coerce_keys(
316
+ optional.select { |key| input.key?(key.value) },
317
+ input
318
+ ).fmap(&required.public_method(:merge))
318
319
  end
319
320
  end
320
321
 
321
- def transform_required(input)
322
- transform_keys(required, input)
323
- end
324
-
325
- def transform_optional(input)
326
- transform_keys(
327
- optional.select { |key| input.key?(key.value) },
328
- input
329
- )
330
- end
331
-
332
322
  # rubocop:disable Metrics/MethodLength
333
- def transform_keys(keys, input)
323
+ def coerce_keys(keys, input)
334
324
  success(
335
325
  keys
336
326
  .to_h do |key|
@@ -375,6 +365,7 @@ module Mutant
375
365
 
376
366
  def required_keys = required.map(&:value)
377
367
  memoize :required_keys
368
+
378
369
  end # Hash
379
370
 
380
371
  # Sequence of transformations
@@ -411,7 +402,23 @@ module Mutant
411
402
  def call(input)
412
403
  success(block.call(input))
413
404
  end
414
- end # Sequence
405
+ end # Success
406
+
407
+ # Nullable wrapper: passes nil through, delegates non-nil to inner transform
408
+ class Nullable < self
409
+ include Anima.new(:transform)
410
+
411
+ # Apply transformation to input
412
+ #
413
+ # @param [Object]
414
+ #
415
+ # @return [Either<Error, Object>]
416
+ def call(input)
417
+ input.nil? ? success(nil) : transform.call(input)
418
+ end
419
+
420
+ def slug = "nullable(#{transform.slug})"
421
+ end # Nullable
415
422
 
416
423
  # Generic exception transformer
417
424
  class Exception < self
@@ -429,10 +436,11 @@ module Mutant
429
436
  end
430
437
  end # Exception
431
438
 
432
- BOOLEAN = Transform::Boolean.new
433
- FLOAT = Transform::Primitive.new(primitive: Float)
434
- INTEGER = Transform::Primitive.new(primitive: Integer)
435
- STRING = Transform::Primitive.new(primitive: String)
436
- STRING_ARRAY = Transform::Array.new(transform: STRING)
439
+ BOOLEAN = Transform::Boolean.new
440
+ FLOAT = Transform::Primitive.new(primitive: Float)
441
+ INTEGER = Transform::Primitive.new(primitive: Integer)
442
+ STRING = Transform::Primitive.new(primitive: String)
443
+ OPTIONAL_STRING = Nullable.new(transform: STRING)
444
+ STRING_ARRAY = Transform::Array.new(transform: STRING)
437
445
  end # Transform
438
446
  end # Mutant
data/lib/mutant/world.rb CHANGED
@@ -89,6 +89,12 @@ module Mutant
89
89
  recorder.record(name, &)
90
90
  end
91
91
 
92
+ def parse_json(string)
93
+ record(:json_parse) do
94
+ Either.wrap_error(json::ParserError) { json.parse(string) }
95
+ end
96
+ end
97
+
92
98
  def process_warmup
93
99
  process.warmup if process.respond_to?(:warmup)
94
100
  end
@@ -13,8 +13,6 @@ module Mutant
13
13
  :root_require
14
14
  )
15
15
 
16
- private(*anima.attribute_names)
17
-
18
16
  include AST::Sexp
19
17
 
20
18
  class LoadError < ::LoadError
data/lib/mutant.rb CHANGED
@@ -52,7 +52,6 @@ module Mutant
52
52
  AbstractType = Unparser::AbstractType
53
53
  Adamantium = Unparser::Adamantium
54
54
  Anima = Unparser::Anima
55
- Concord = Unparser::Concord
56
55
  Either = Unparser::Either
57
56
  Equalizer = Unparser::Equalizer
58
57
 
@@ -70,6 +69,8 @@ module Mutant
70
69
  record.call(:require_mutant_lib) do
71
70
  require 'mutant/procto'
72
71
  require 'mutant/transform'
72
+ require 'mutant/transform/codec'
73
+ require 'mutant/log_capture'
73
74
  require 'mutant/variable'
74
75
  require 'mutant/bootstrap'
75
76
  require 'mutant/version'
@@ -96,6 +97,9 @@ module Mutant
96
97
  require 'mutant/ast/pattern/token'
97
98
  require 'mutant/ast/structure'
98
99
  require 'mutant/parser'
100
+ require 'mutant/result/test'
101
+ require 'mutant/result/process_status'
102
+ require 'mutant/result/exception'
99
103
  require 'mutant/isolation'
100
104
  require 'mutant/isolation/exception'
101
105
  require 'mutant/isolation/fork'
@@ -237,10 +241,11 @@ module Mutant
237
241
  require 'mutant/cli/command/environment/subject'
238
242
  require 'mutant/cli/command/environment/test'
239
243
  require 'mutant/cli/command/util'
240
- require 'mutant/cli/command/root'
241
244
  require 'mutant/mutation/runner'
242
245
  require 'mutant/mutation/runner/sink'
243
246
  require 'mutant/result'
247
+ require 'mutant/result/session'
248
+ require 'mutant/result/json_writer'
244
249
  require 'mutant/reporter'
245
250
  require 'mutant/reporter/null'
246
251
  require 'mutant/reporter/sequence'
@@ -248,17 +253,18 @@ module Mutant
248
253
  require 'mutant/reporter/cli/progress_bar'
249
254
  require 'mutant/reporter/cli/printer'
250
255
  require 'mutant/reporter/cli/printer/config'
251
- require 'mutant/reporter/cli/printer/coverage_result'
252
256
  require 'mutant/reporter/cli/printer/env'
253
257
  require 'mutant/reporter/cli/printer/env_progress'
258
+ require 'mutant/reporter/cli/printer/alive_results'
254
259
  require 'mutant/reporter/cli/printer/env_result'
255
260
  require 'mutant/reporter/cli/printer/isolation_result'
256
261
  require 'mutant/reporter/cli/printer/mutation'
257
- require 'mutant/reporter/cli/printer/mutation_result'
258
262
  require 'mutant/reporter/cli/printer/status_progressive'
259
263
  require 'mutant/reporter/cli/printer/subject_result'
260
264
  require 'mutant/reporter/cli/printer/test'
261
265
  require 'mutant/reporter/cli/format'
266
+ require 'mutant/cli/command/session'
267
+ require 'mutant/cli/command/root'
262
268
  require 'mutant/repository'
263
269
  require 'mutant/repository/diff'
264
270
  require 'mutant/repository/diff/ranges'
@@ -343,6 +349,10 @@ module Mutant
343
349
  timer:
344
350
  )
345
351
 
352
+ # UUIDv7 identifying this mutant process invocation.
353
+ # Used as the JSON result filename and session identifier.
354
+ SESSION_ID = SecureRandom.uuid_v7
355
+
346
356
  # Reopen class to initialize constant to avoid dep circle
347
357
  class Config
348
358
  DEFAULT = new(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.16.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
@@ -71,6 +71,20 @@ dependencies:
71
71
  - - "~>"
72
72
  - !ruby/object:Gem::Version
73
73
  version: '2.10'
74
+ - !ruby/object:Gem::Dependency
75
+ name: securerandom
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0.3'
81
+ type: :runtime
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0.3'
74
88
  - !ruby/object:Gem::Dependency
75
89
  name: sorbet-runtime
76
90
  requirement: !ruby/object:Gem::Requirement
@@ -89,16 +103,22 @@ dependencies:
89
103
  name: unparser
90
104
  requirement: !ruby/object:Gem::Requirement
91
105
  requirements:
92
- - - "~>"
106
+ - - ">="
93
107
  - !ruby/object:Gem::Version
94
108
  version: 0.8.2
109
+ - - "<"
110
+ - !ruby/object:Gem::Version
111
+ version: '0.10'
95
112
  type: :runtime
96
113
  prerelease: false
97
114
  version_requirements: !ruby/object:Gem::Requirement
98
115
  requirements:
99
- - - "~>"
116
+ - - ">="
100
117
  - !ruby/object:Gem::Version
101
118
  version: 0.8.2
119
+ - - "<"
120
+ - !ruby/object:Gem::Version
121
+ version: '0.10'
102
122
  - !ruby/object:Gem::Dependency
103
123
  name: rspec
104
124
  requirement: !ruby/object:Gem::Requirement
@@ -211,6 +231,7 @@ files:
211
231
  - lib/mutant/cli/command/environment/subject.rb
212
232
  - lib/mutant/cli/command/environment/test.rb
213
233
  - lib/mutant/cli/command/root.rb
234
+ - lib/mutant/cli/command/session.rb
214
235
  - lib/mutant/cli/command/util.rb
215
236
  - lib/mutant/config.rb
216
237
  - lib/mutant/config/coverage_criteria.rb
@@ -231,6 +252,7 @@ files:
231
252
  - lib/mutant/isolation/fork.rb
232
253
  - lib/mutant/isolation/none.rb
233
254
  - lib/mutant/loader.rb
255
+ - lib/mutant/log_capture.rb
234
256
  - lib/mutant/matcher.rb
235
257
  - lib/mutant/matcher/chain.rb
236
258
  - lib/mutant/matcher/config.rb
@@ -342,14 +364,13 @@ files:
342
364
  - lib/mutant/reporter/cli.rb
343
365
  - lib/mutant/reporter/cli/format.rb
344
366
  - lib/mutant/reporter/cli/printer.rb
367
+ - lib/mutant/reporter/cli/printer/alive_results.rb
345
368
  - lib/mutant/reporter/cli/printer/config.rb
346
- - lib/mutant/reporter/cli/printer/coverage_result.rb
347
369
  - lib/mutant/reporter/cli/printer/env.rb
348
370
  - lib/mutant/reporter/cli/printer/env_progress.rb
349
371
  - lib/mutant/reporter/cli/printer/env_result.rb
350
372
  - lib/mutant/reporter/cli/printer/isolation_result.rb
351
373
  - lib/mutant/reporter/cli/printer/mutation.rb
352
- - lib/mutant/reporter/cli/printer/mutation_result.rb
353
374
  - lib/mutant/reporter/cli/printer/status_progressive.rb
354
375
  - lib/mutant/reporter/cli/printer/subject_result.rb
355
376
  - lib/mutant/reporter/cli/printer/test.rb
@@ -361,6 +382,11 @@ files:
361
382
  - lib/mutant/repository/diff/ranges.rb
362
383
  - lib/mutant/require_highjack.rb
363
384
  - lib/mutant/result.rb
385
+ - lib/mutant/result/exception.rb
386
+ - lib/mutant/result/json_writer.rb
387
+ - lib/mutant/result/process_status.rb
388
+ - lib/mutant/result/session.rb
389
+ - lib/mutant/result/test.rb
364
390
  - lib/mutant/scope.rb
365
391
  - lib/mutant/segment.rb
366
392
  - lib/mutant/segment/recorder.rb
@@ -378,6 +404,7 @@ files:
378
404
  - lib/mutant/test/runner/sink.rb
379
405
  - lib/mutant/timer.rb
380
406
  - lib/mutant/transform.rb
407
+ - lib/mutant/transform/codec.rb
381
408
  - lib/mutant/usage.rb
382
409
  - lib/mutant/util.rb
383
410
  - lib/mutant/variable.rb
@@ -397,14 +424,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
397
424
  requirements:
398
425
  - - ">="
399
426
  - !ruby/object:Gem::Version
400
- version: '3.2'
427
+ version: '3.3'
401
428
  required_rubygems_version: !ruby/object:Gem::Requirement
402
429
  requirements:
403
430
  - - ">="
404
431
  - !ruby/object:Gem::Version
405
432
  version: '0'
406
433
  requirements: []
407
- rubygems_version: 4.0.3
434
+ rubygems_version: 4.0.6
408
435
  specification_version: 4
409
436
  summary: ''
410
437
  test_files: []
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mutant
4
- class Reporter
5
- class CLI
6
- class Printer
7
- # Reporter for mutation coverage results
8
- class CoverageResult < self
9
- # Run report printer
10
- #
11
- # @return [undefined]
12
- def run
13
- visit(MutationResult, object.mutation_result)
14
- end
15
- end # Printer
16
- end # Coverage
17
- end # CLI
18
- end # Reporter
19
- end # Mutant
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mutant
4
- class Reporter
5
- class CLI
6
- class Printer
7
- # Reporter for mutation results
8
- class MutationResult < self
9
-
10
- delegate :mutation, :isolation_result
11
-
12
- MAP = {
13
- Mutant::Mutation::Evil => :evil_details,
14
- Mutant::Mutation::Neutral => :neutral_details,
15
- Mutant::Mutation::Noop => :noop_details
16
- }.freeze
17
-
18
- NEUTRAL_MESSAGE = <<~'MESSAGE'
19
- --- Neutral failure ---
20
- Original code was inserted unmutated. And the test did NOT PASS.
21
- Your tests do not pass initially or you found a bug in mutant / unparser.
22
- Subject AST:
23
- %s
24
- Unparsed Source:
25
- %s
26
- MESSAGE
27
-
28
- NO_DIFF_MESSAGE = <<~'MESSAGE'
29
- --- Internal failure ---
30
- BUG: A generated mutation did not result in exactly one diff hunk!
31
- This is an invariant violation by the mutation generation engine.
32
- Please report a reproduction to https://github.com/mbj/mutant
33
- Original unparsed source:
34
- %s
35
- Original AST:
36
- %s
37
- Mutated unparsed source:
38
- %s
39
- Mutated AST:
40
- %s
41
- MESSAGE
42
-
43
- NOOP_MESSAGE = <<~'MESSAGE'
44
- ---- Noop failure -----
45
- No code was inserted. And the test did NOT PASS.
46
- This is typically a problem of your specs not passing unmutated.
47
- MESSAGE
48
-
49
- SEPARATOR = '-----------------------'
50
-
51
- # Run report printer
52
- #
53
- # @return [undefined]
54
- def run
55
- puts(mutation.identification)
56
- puts(SEPARATOR)
57
- print_details
58
- puts(SEPARATOR)
59
- end
60
-
61
- private
62
-
63
- def print_details
64
- visit(IsolationResult, isolation_result)
65
- __send__(MAP.fetch(mutation.class))
66
- end
67
-
68
- def evil_details
69
- visit(Mutation, mutation)
70
- end
71
-
72
- def noop_details
73
- info(NOOP_MESSAGE)
74
- end
75
-
76
- def neutral_details
77
- info(NEUTRAL_MESSAGE, mutation.node.inspect, mutation.source)
78
- end
79
-
80
- end # MutationResult
81
- end # Printer
82
- end # CLI
83
- end # Reporter
84
- end # Mutant