mutant 0.10.24 → 0.10.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mutant.rb +15 -11
  3. data/lib/mutant/ast/find_metaclass_containing.rb +1 -1
  4. data/lib/mutant/ast/regexp.rb +17 -0
  5. data/lib/mutant/ast/regexp/transformer.rb +2 -2
  6. data/lib/mutant/ast/regexp/transformer/quantifier.rb +4 -2
  7. data/lib/mutant/bootstrap.rb +1 -1
  8. data/lib/mutant/cli/command.rb +4 -0
  9. data/lib/mutant/cli/command/environment/subject.rb +0 -4
  10. data/lib/mutant/cli/command/environment/test.rb +36 -0
  11. data/lib/mutant/cli/command/root.rb +1 -1
  12. data/lib/mutant/config.rb +1 -1
  13. data/lib/mutant/context.rb +1 -1
  14. data/lib/mutant/env.rb +2 -2
  15. data/lib/mutant/expression/method.rb +4 -4
  16. data/lib/mutant/expression/methods.rb +5 -4
  17. data/lib/mutant/integration.rb +8 -2
  18. data/lib/mutant/isolation/exception.rb +22 -0
  19. data/lib/mutant/isolation/fork.rb +9 -12
  20. data/lib/mutant/loader.rb +1 -1
  21. data/lib/mutant/matcher.rb +1 -1
  22. data/lib/mutant/matcher/config.rb +6 -3
  23. data/lib/mutant/matcher/method.rb +12 -10
  24. data/lib/mutant/matcher/method/instance.rb +6 -2
  25. data/lib/mutant/matcher/method/metaclass.rb +1 -1
  26. data/lib/mutant/matcher/methods.rb +2 -4
  27. data/lib/mutant/meta/example.rb +1 -1
  28. data/lib/mutant/meta/example/dsl.rb +0 -1
  29. data/lib/mutant/meta/example/verification.rb +1 -1
  30. data/lib/mutant/mutation.rb +1 -1
  31. data/lib/mutant/mutator.rb +8 -1
  32. data/lib/mutant/mutator/node.rb +0 -5
  33. data/lib/mutant/mutator/node/argument.rb +2 -2
  34. data/lib/mutant/mutator/node/dynamic_literal.rb +1 -1
  35. data/lib/mutant/mutator/node/index.rb +1 -0
  36. data/lib/mutant/mutator/node/literal/float.rb +1 -3
  37. data/lib/mutant/mutator/node/literal/integer.rb +3 -6
  38. data/lib/mutant/mutator/node/literal/range.rb +1 -1
  39. data/lib/mutant/mutator/node/literal/regex.rb +3 -17
  40. data/lib/mutant/mutator/node/module.rb +19 -0
  41. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +3 -3
  42. data/lib/mutant/mutator/node/regexp.rb +0 -11
  43. data/lib/mutant/mutator/node/regexp/beginning_of_line_anchor.rb +20 -0
  44. data/lib/mutant/mutator/node/regexp/character_type.rb +1 -1
  45. data/lib/mutant/mutator/node/regexp/named_group.rb +39 -0
  46. data/lib/mutant/mutator/node/regexp/zero_or_more.rb +34 -0
  47. data/lib/mutant/mutator/node/regopt.rb +1 -1
  48. data/lib/mutant/mutator/node/sclass.rb +1 -1
  49. data/lib/mutant/mutator/node/send.rb +73 -6
  50. data/lib/mutant/parallel.rb +2 -2
  51. data/lib/mutant/parallel/driver.rb +1 -1
  52. data/lib/mutant/parallel/worker.rb +1 -1
  53. data/lib/mutant/parser.rb +1 -1
  54. data/lib/mutant/pipe.rb +1 -1
  55. data/lib/mutant/procto.rb +23 -0
  56. data/lib/mutant/reporter/cli/printer.rb +10 -4
  57. data/lib/mutant/reporter/cli/printer/env.rb +3 -3
  58. data/lib/mutant/reporter/cli/printer/env_progress.rb +2 -2
  59. data/lib/mutant/reporter/cli/printer/isolation_result.rb +3 -1
  60. data/lib/mutant/selector.rb +1 -1
  61. data/lib/mutant/subject.rb +1 -1
  62. data/lib/mutant/subject/method/instance.rb +5 -42
  63. data/lib/mutant/transform.rb +25 -0
  64. data/lib/mutant/variable.rb +322 -0
  65. data/lib/mutant/version.rb +1 -1
  66. data/lib/mutant/world.rb +1 -1
  67. metadata +13 -160
  68. data/lib/mutant/mutator/node/regexp/greedy_zero_or_more.rb +0 -24
@@ -73,6 +73,31 @@ module Mutant
73
73
  end
74
74
  end # Named
75
75
 
76
+ class Block < self
77
+ include Anima.new(:block, :name)
78
+
79
+ def self.capture(name, &block)
80
+ new(block: block, name: name)
81
+ end
82
+
83
+ def call(input)
84
+ block
85
+ .call(input)
86
+ .lmap do |message|
87
+ Error.new(
88
+ cause: nil,
89
+ input: input,
90
+ message: message,
91
+ transform: self
92
+ )
93
+ end
94
+ end
95
+
96
+ def slug
97
+ name
98
+ end
99
+ end
100
+
76
101
  private
77
102
 
78
103
  def error(cause: nil, input:, message: nil)
@@ -0,0 +1,322 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mutant
4
+ # Lightweight concurrency variables
5
+ #
6
+ # These are inspired by Haskells MVar and IVar types.
7
+ class Variable
8
+ EMPTY = Class.new do
9
+ const_set(:INSPECT, 'Variable::EMPTY')
10
+ end.new.freeze
11
+
12
+ TIMEOUT = Class.new do
13
+ const_set(:INSPECT, 'Variable::TIMEOUT')
14
+ end.new.freeze
15
+
16
+ # Result of operation that may time out
17
+ class Result
18
+ include Equalizer.new(:value)
19
+ attr_reader :value
20
+
21
+ # Initialize result
22
+ #
23
+ # @return [undefined]
24
+ def initialize(value)
25
+ @value = value
26
+ freeze
27
+ end
28
+
29
+ # Test if take resulted in a timeout
30
+ #
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ def timeout?
35
+ instance_of?(Timeout)
36
+ end
37
+
38
+ # Instance returned on timeouts
39
+ class Timeout < self
40
+ INSTANCE = new(nil)
41
+
42
+ # Construct new object
43
+ #
44
+ # @return [Timeout]
45
+ def self.new
46
+ INSTANCE
47
+ end
48
+ end # Timeout
49
+
50
+ # Instance returned without timeouts
51
+ class Value < self
52
+ end # Value
53
+ end # Result
54
+
55
+ private_constant(*constants(false))
56
+
57
+ module Timer
58
+ # Monotonic elapsed time of block execution
59
+ #
60
+ # @return [Float]
61
+ def self.elapsed
62
+ start = now
63
+ yield
64
+ now - start
65
+ end
66
+
67
+ # The now monotonic time
68
+ #
69
+ # @return [Float]
70
+ def self.now
71
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
72
+ end
73
+ private_class_method :now
74
+ end # Timer
75
+
76
+ # Initialize object
77
+ #
78
+ # @param [Object] value
79
+ # the initial value
80
+ #
81
+ # @return [undefined]
82
+ def initialize(condition_variable:, mutex:, value: EMPTY)
83
+ @full = condition_variable.new
84
+ @mutex = mutex.new
85
+ @value = value
86
+ end
87
+
88
+ # Take value, block on empty
89
+ #
90
+ # @return [Object]
91
+ def take
92
+ synchronize do
93
+ wait_full
94
+ perform_take
95
+ end
96
+ end
97
+
98
+ # Take value, with timeout
99
+ #
100
+ # @param [Float] Timeout
101
+ #
102
+ # @return [Result::Timeout]
103
+ # in case take resulted in a timeout
104
+ #
105
+ # @return [Result::Value]
106
+ # in case take resulted in a value
107
+ def take_timeout(timeout)
108
+ synchronize do
109
+ if wait_timeout(@full, timeout, &method(:full?))
110
+ Result::Timeout.new
111
+ else
112
+ Result::Value.new(perform_take)
113
+ end
114
+ end
115
+ end
116
+
117
+ # Read value, block on empty
118
+ #
119
+ # @return [Object]
120
+ # the variable value
121
+ def read
122
+ synchronize do
123
+ wait_full
124
+ @value
125
+ end
126
+ end
127
+
128
+ # Try put value into the variable, non blocking
129
+ #
130
+ # @param [Object] value
131
+ #
132
+ # @return [self]
133
+ def try_put(value)
134
+ synchronize do
135
+ perform_put(value) if empty?
136
+ end
137
+
138
+ self
139
+ end
140
+
141
+ # Execute block with value, blocking
142
+ #
143
+ # @yield [Object]
144
+ #
145
+ # @return [Object]
146
+ # the blocks return value
147
+ def with
148
+ synchronize do
149
+ wait_full
150
+ yield @value
151
+ end
152
+ end
153
+
154
+ private
155
+
156
+ # Perform the put
157
+ #
158
+ # @param [Object] value
159
+ def perform_put(value)
160
+ (@value = value).tap { @full.signal }
161
+ end
162
+
163
+ # Execute block under mutex
164
+ #
165
+ # @return [self]
166
+ def synchronize(&block)
167
+ @mutex.synchronize(&block)
168
+ end
169
+
170
+ # Wait for block predicate
171
+ #
172
+ # @param [ConditionVariable] event
173
+ #
174
+ # @return [undefined]
175
+ def wait(event)
176
+ event.wait(@mutex) until yield
177
+ end
178
+
179
+ # Wait with timeout for block predicate
180
+ #
181
+ # @param [ConditionVariable] event
182
+ #
183
+ # @return [Boolean]
184
+ # if wait was terminated due a timeout
185
+ #
186
+ # @return [undefined]
187
+ # otherwise
188
+ def wait_timeout(event, timeout)
189
+ loop do
190
+ break true if timeout <= 0
191
+ break if yield
192
+ timeout -= Timer.elapsed { event.wait(@mutex, timeout) }
193
+ end
194
+ end
195
+
196
+ # Wait till mvar is full
197
+ #
198
+ # @return [undefined]
199
+ def wait_full
200
+ wait(@full, &method(:full?))
201
+ end
202
+
203
+ # Test if state is full
204
+ #
205
+ # @return [Boolean]
206
+ def full?
207
+ !empty?
208
+ end
209
+
210
+ # Test if state is empty
211
+ #
212
+ # @return [Boolean]
213
+ def empty?
214
+ @value.equal?(EMPTY)
215
+ end
216
+
217
+ # Shared variable that can be written at most once
218
+ #
219
+ # ignore :reek:InstanceVariableAssumption
220
+ class IVar < self
221
+
222
+ # Exception raised on ivar errors
223
+ class Error < RuntimeError; end
224
+
225
+ # Put value, raises if already full
226
+ #
227
+ # @param [Object] value
228
+ #
229
+ # @return [self]
230
+ #
231
+ # @raise Error
232
+ # if already full
233
+ def put(value)
234
+ synchronize do
235
+ fail Error, 'is immutable' if full?
236
+ perform_put(value)
237
+ end
238
+
239
+ self
240
+ end
241
+
242
+ # Populate and return value, use block to compute value if empty
243
+ #
244
+ # The block is guaranteed to be executed at max once.
245
+ #
246
+ # Subsequent reads are guaranteed to return the block value.
247
+ #
248
+ # @return [Object]
249
+ def populate_with
250
+ return @value if full?
251
+
252
+ synchronize do
253
+ perform_put(yield) if empty?
254
+ end
255
+
256
+ @value
257
+ end
258
+
259
+ private
260
+
261
+ # Perform take operation
262
+ #
263
+ # @return [Object]
264
+ def perform_take
265
+ @value
266
+ end
267
+ end # IVar
268
+
269
+ # Shared variable that can be written multiple times
270
+ #
271
+ # ignore :reek:InstanceVariableAssumption
272
+ class MVar < self
273
+
274
+ # Initialize object
275
+ #
276
+ # @param [Object] value
277
+ # the initial value
278
+ #
279
+ # @return [undefined]
280
+ def initialize(condition_variable:, mutex:, value: EMPTY)
281
+ super
282
+ @empty = condition_variable.new
283
+ end
284
+
285
+ # Put value, block on full
286
+ #
287
+ # @param [Object] value
288
+ #
289
+ # @return [self]
290
+ def put(value)
291
+ synchronize do
292
+ wait(@empty, &method(:empty?))
293
+ perform_put(value)
294
+ end
295
+
296
+ self
297
+ end
298
+
299
+ # Modify value, blocks if empty
300
+ #
301
+ # @return [Object]
302
+ def modify
303
+ synchronize do
304
+ wait_full
305
+ perform_put(yield(@value))
306
+ end
307
+ end
308
+
309
+ private
310
+
311
+ # Empty the variable
312
+ #
313
+ # @return [Object]
314
+ def perform_take
315
+ @value.tap do
316
+ @value = EMPTY
317
+ @empty.signal
318
+ end
319
+ end
320
+ end # MVar
321
+ end # Variable
322
+ end # Mutant
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mutant
4
4
  # Current mutant version
5
- VERSION = '0.10.24'
5
+ VERSION = '0.10.29'
6
6
  end # Mutant
data/lib/mutant/world.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Mutant
4
4
  # The outer world IO objects mutant does interact with
5
5
  class World
6
- include Adamantium::Flat, Anima.new(
6
+ include Adamantium, Anima.new(
7
7
  :condition_variable,
8
8
  :gem,
9
9
  :gem_method,
metadata CHANGED
@@ -1,85 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mutant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.24
4
+ version: 0.10.29
5
5
  platform: ruby
6
6
  authors:
7
7
  - Markus Schirp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-01 00:00:00.000000000 Z
11
+ date: 2021-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: abstract_type
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.0.7
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.0.7
27
- - !ruby/object:Gem::Dependency
28
- name: adamantium
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 0.2.0
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: 0.2.0
41
- - !ruby/object:Gem::Dependency
42
- name: anima
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.3.1
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.3.1
55
- - !ruby/object:Gem::Dependency
56
- name: ast
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '2.2'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '2.2'
69
- - !ruby/object:Gem::Dependency
70
- name: concord
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 0.1.5
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 0.1.5
83
13
  - !ruby/object:Gem::Dependency
84
14
  name: diff-lcs
85
15
  requirement: !ruby/object:Gem::Requirement
@@ -94,62 +24,6 @@ dependencies:
94
24
  - - "~>"
95
25
  - !ruby/object:Gem::Version
96
26
  version: '1.3'
97
- - !ruby/object:Gem::Dependency
98
- name: equalizer
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: 0.0.9
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: 0.0.9
111
- - !ruby/object:Gem::Dependency
112
- name: ice_nine
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: 0.11.1
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: 0.11.1
125
- - !ruby/object:Gem::Dependency
126
- name: memoizable
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: 0.4.2
132
- type: :runtime
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: 0.4.2
139
- - !ruby/object:Gem::Dependency
140
- name: mprelude
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: 0.1.0
146
- type: :runtime
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: 0.1.0
153
27
  - !ruby/object:Gem::Dependency
154
28
  name: parser
155
29
  requirement: !ruby/object:Gem::Requirement
@@ -164,20 +38,6 @@ dependencies:
164
38
  - - "~>"
165
39
  - !ruby/object:Gem::Version
166
40
  version: 3.0.0
167
- - !ruby/object:Gem::Dependency
168
- name: procto
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - "~>"
172
- - !ruby/object:Gem::Version
173
- version: 0.0.2
174
- type: :runtime
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: 0.0.2
181
41
  - !ruby/object:Gem::Dependency
182
42
  name: regexp_parser
183
43
  requirement: !ruby/object:Gem::Requirement
@@ -204,28 +64,14 @@ dependencies:
204
64
  requirements:
205
65
  - - "~>"
206
66
  - !ruby/object:Gem::Version
207
- version: 0.5.6
208
- type: :runtime
209
- prerelease: false
210
- version_requirements: !ruby/object:Gem::Requirement
211
- requirements:
212
- - - "~>"
213
- - !ruby/object:Gem::Version
214
- version: 0.5.6
215
- - !ruby/object:Gem::Dependency
216
- name: variable
217
- requirement: !ruby/object:Gem::Requirement
218
- requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: 0.0.1
67
+ version: 0.6.0
222
68
  type: :runtime
223
69
  prerelease: false
224
70
  version_requirements: !ruby/object:Gem::Requirement
225
71
  requirements:
226
72
  - - "~>"
227
73
  - !ruby/object:Gem::Version
228
- version: 0.0.1
74
+ version: 0.6.0
229
75
  - !ruby/object:Gem::Dependency
230
76
  name: parallel
231
77
  requirement: !ruby/object:Gem::Requirement
@@ -337,6 +183,7 @@ files:
337
183
  - lib/mutant/cli/command/environment/run.rb
338
184
  - lib/mutant/cli/command/environment/show.rb
339
185
  - lib/mutant/cli/command/environment/subject.rb
186
+ - lib/mutant/cli/command/environment/test.rb
340
187
  - lib/mutant/cli/command/root.rb
341
188
  - lib/mutant/cli/command/subscription.rb
342
189
  - lib/mutant/config.rb
@@ -351,6 +198,7 @@ files:
351
198
  - lib/mutant/integration.rb
352
199
  - lib/mutant/integration/null.rb
353
200
  - lib/mutant/isolation.rb
201
+ - lib/mutant/isolation/exception.rb
354
202
  - lib/mutant/isolation/fork.rb
355
203
  - lib/mutant/isolation/none.rb
356
204
  - lib/mutant/license.rb
@@ -412,6 +260,7 @@ files:
412
260
  - lib/mutant/mutator/node/masgn.rb
413
261
  - lib/mutant/mutator/node/match_current_line.rb
414
262
  - lib/mutant/mutator/node/mlhs.rb
263
+ - lib/mutant/mutator/node/module.rb
415
264
  - lib/mutant/mutator/node/named_value/access.rb
416
265
  - lib/mutant/mutator/node/named_value/constant_assignment.rb
417
266
  - lib/mutant/mutator/node/named_value/variable_assignment.rb
@@ -423,11 +272,13 @@ files:
423
272
  - lib/mutant/mutator/node/procarg_zero.rb
424
273
  - lib/mutant/mutator/node/regexp.rb
425
274
  - lib/mutant/mutator/node/regexp/alternation_meta.rb
275
+ - lib/mutant/mutator/node/regexp/beginning_of_line_anchor.rb
426
276
  - lib/mutant/mutator/node/regexp/capture_group.rb
427
277
  - lib/mutant/mutator/node/regexp/character_type.rb
428
278
  - lib/mutant/mutator/node/regexp/end_of_line_anchor.rb
429
279
  - lib/mutant/mutator/node/regexp/end_of_string_or_before_end_of_line_anchor.rb
430
- - lib/mutant/mutator/node/regexp/greedy_zero_or_more.rb
280
+ - lib/mutant/mutator/node/regexp/named_group.rb
281
+ - lib/mutant/mutator/node/regexp/zero_or_more.rb
431
282
  - lib/mutant/mutator/node/regopt.rb
432
283
  - lib/mutant/mutator/node/resbody.rb
433
284
  - lib/mutant/mutator/node/rescue.rb
@@ -451,6 +302,7 @@ files:
451
302
  - lib/mutant/parallel/worker.rb
452
303
  - lib/mutant/parser.rb
453
304
  - lib/mutant/pipe.rb
305
+ - lib/mutant/procto.rb
454
306
  - lib/mutant/range.rb
455
307
  - lib/mutant/registry.rb
456
308
  - lib/mutant/reporter.rb
@@ -488,6 +340,7 @@ files:
488
340
  - lib/mutant/timer.rb
489
341
  - lib/mutant/transform.rb
490
342
  - lib/mutant/util.rb
343
+ - lib/mutant/variable.rb
491
344
  - lib/mutant/version.rb
492
345
  - lib/mutant/world.rb
493
346
  - lib/mutant/zombifier.rb
@@ -510,7 +363,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
510
363
  - !ruby/object:Gem::Version
511
364
  version: '0'
512
365
  requirements: []
513
- rubygems_version: 3.2.3
366
+ rubygems_version: 3.1.4
514
367
  signing_key:
515
368
  specification_version: 4
516
369
  summary: ''