mutant 0.9.2 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +26 -0
  3. data/Gemfile +0 -8
  4. data/Gemfile.lock +55 -59
  5. data/LICENSE +1 -1
  6. data/README.md +9 -0
  7. data/config/rubocop.yml +10 -3
  8. data/docs/commercial-support.md +14 -0
  9. data/lib/mutant.rb +5 -4
  10. data/lib/mutant/cli.rb +5 -5
  11. data/lib/mutant/config.rb +1 -0
  12. data/lib/mutant/integration.rb +1 -1
  13. data/lib/mutant/license.rb +33 -6
  14. data/lib/mutant/license/subscription/opensource.rb +1 -1
  15. data/lib/mutant/meta.rb +1 -3
  16. data/lib/mutant/meta/example/verification.rb +1 -1
  17. data/lib/mutant/mutator/node/generic.rb +25 -2
  18. data/lib/mutant/mutator/node/send.rb +1 -1
  19. data/lib/mutant/parallel.rb +1 -1
  20. data/lib/mutant/reporter/cli/format.rb +1 -1
  21. data/lib/mutant/transform.rb +6 -5
  22. data/lib/mutant/version.rb +1 -1
  23. data/lib/mutant/warnings.rb +1 -1
  24. data/lib/mutant/zombifier.rb +2 -0
  25. data/mutant.gemspec +17 -16
  26. data/spec/integrations.yml +3 -1
  27. data/spec/support/corpus.rb +3 -3
  28. data/spec/support/ruby_vm.rb +1 -2
  29. data/spec/support/shared_context.rb +3 -3
  30. data/spec/support/xspec.rb +2 -2
  31. data/spec/unit/mutant/license_spec.rb +43 -7
  32. data/spec/unit/mutant/parallel/driver_spec.rb +4 -4
  33. data/spec/unit/mutant/parallel/worker_spec.rb +5 -5
  34. data/spec/unit/mutant/parallel_spec.rb +7 -7
  35. data/spec/unit/mutant/repository/diff/ranges_spec.rb +2 -2
  36. metadata +31 -24
  37. data/lib/mutant/base.rb +0 -192
  38. data/lib/mutant/variable.rb +0 -282
  39. data/spec/unit/mutant/either_spec.rb +0 -247
  40. data/spec/unit/mutant/maybe_spec.rb +0 -60
  41. data/spec/unit/mutant/variable_spec.rb +0 -618
@@ -1,282 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Mutant
4
- # Lightweight shared variables
5
- #
6
- # ignore :reek:TooManyMethods
7
- class Variable
8
- EMPTY = Class.new do
9
- const_set(:INSPECT, 'Mutant::Variable::EMPTY')
10
- end.new.freeze
11
-
12
- TIMEOUT = Class.new do
13
- const_set(:INSPECT, 'Mutant::Variable::TIMEOUT')
14
- end.new.freeze
15
-
16
- # Result of operation that may time out
17
- class Result
18
- include AbstractType, Adamantium::Flat
19
-
20
- # Test if take resulted in a timeout
21
- #
22
- # @return [Boolean]
23
- #
24
- # @api private
25
- def timeout?
26
- instance_of?(Timeout)
27
- end
28
-
29
- abstract_method :value
30
-
31
- # Instance returned on timeouts
32
- class Timeout < self
33
- include Equalizer.new
34
-
35
- INSTANCE = new
36
-
37
- # Construct new object
38
- #
39
- # @return [Timeout]
40
- def self.new
41
- INSTANCE
42
- end
43
- end # Timeout
44
-
45
- # Instance returned without timeouts
46
- class Value < self
47
- include Concord::Public.new(:value)
48
- end # Value
49
- end # Result
50
-
51
- private_constant(*constants(false))
52
-
53
- # Initialize object
54
- #
55
- # @param [Object] value
56
- # the initial value
57
- #
58
- # @return [undefined]
59
- def initialize(condition_variable:, mutex:, value: EMPTY)
60
- @full = condition_variable.new
61
- @mutex = mutex.new
62
- @value = value
63
- end
64
-
65
- # Take value from mvar, block on empty
66
- #
67
- # @return [Object]
68
- def take
69
- synchronize do
70
- wait_full
71
- perform_take
72
- end
73
- end
74
-
75
- # Take value from mvar, with timeout
76
- #
77
- # @param [Float] Timeout
78
- #
79
- # @return [Result::Timeout]
80
- # in case take resulted in a timeout
81
- #
82
- # @return [Result::Value]
83
- # in case take resulted in a value
84
- def take_timeout(timeout)
85
- synchronize do
86
- if wait_timeout(@full, timeout, &method(:full?))
87
- Result::Timeout.new
88
- else
89
- Result::Value.new(perform_take)
90
- end
91
- end
92
- end
93
-
94
- # Read value from variable
95
- #
96
- # @return [Object]
97
- # the contents of the mvar
98
- def read
99
- synchronize do
100
- wait_full
101
- @value
102
- end
103
- end
104
-
105
- # Try put value into the variable, non blocking
106
- #
107
- # @param [Object] value
108
- #
109
- # @return [self]
110
- def try_put(value)
111
- synchronize do
112
- perform_put(value) if empty?
113
- end
114
-
115
- self
116
- end
117
-
118
- # Execute block with value, blocking
119
- #
120
- # @yield [Object]
121
- #
122
- # @return [Object]
123
- # the blocks return value
124
- def with
125
- synchronize do
126
- wait_full
127
- yield @value
128
- end
129
- end
130
-
131
- private
132
-
133
- # Perform the put
134
- #
135
- # @param [Object] value
136
- def perform_put(value)
137
- (@value = value).tap { @full.signal }
138
- end
139
-
140
- # Execute block under mutex
141
- #
142
- # @return [self]
143
- def synchronize(&block)
144
- @mutex.synchronize(&block)
145
- end
146
-
147
- # Wait for block predicate
148
- #
149
- # @param [ConditionVariable] event
150
- #
151
- # @return [undefined]
152
- def wait(event)
153
- event.wait(@mutex) until yield
154
- end
155
-
156
- # Wait with timeout for block predicate
157
- #
158
- # @param [ConditionVariable] event
159
- #
160
- # @return [Boolean]
161
- # if wait was terminated due a timeout
162
- #
163
- # @return [undefined]
164
- # otherwise
165
- def wait_timeout(event, timeout)
166
- loop do
167
- break true if timeout <= 0
168
- break if yield
169
- timeout -= Timer.elapsed { event.wait(@mutex, timeout) }
170
- end
171
- end
172
-
173
- # Wait till mvar is full
174
- #
175
- # @return [undefined]
176
- def wait_full
177
- wait(@full, &method(:full?))
178
- end
179
-
180
- # Test if state is full
181
- #
182
- # @return [Boolean]
183
- def full?
184
- !empty?
185
- end
186
-
187
- # Test if state is empty
188
- #
189
- # @return [Boolean]
190
- def empty?
191
- @value.equal?(EMPTY)
192
- end
193
-
194
- # Shared variable that can be written at most once
195
- #
196
- # ignore :reek:InstanceVariableAssumption
197
- class IVar < self
198
-
199
- # Exception raised on ivar errors
200
- class Error < RuntimeError; end
201
-
202
- # Put valie into the mvar, raises if already full
203
- #
204
- # @param [Object] value
205
- #
206
- # @return [self]
207
- #
208
- # @raise Error
209
- # if already full
210
- def put(value)
211
- synchronize do
212
- fail Error, 'is immutable' if full?
213
- perform_put(value)
214
- end
215
-
216
- self
217
- end
218
-
219
- private
220
-
221
- # Perform take operation
222
- #
223
- # @return [Object]
224
- def perform_take
225
- @value
226
- end
227
- end # IVar
228
-
229
- # Shared variable that can be written multiple times
230
- #
231
- # ignore :reek:InstanceVariableAssumption
232
- class MVar < self
233
-
234
- # Initialize object
235
- #
236
- # @param [Object] value
237
- # the initial value
238
- #
239
- # @return [undefined]
240
- def initialize(condition_variable:, mutex:, value: EMPTY)
241
- super
242
- @empty = condition_variable.new
243
- end
244
-
245
- # Put value into mvar, block on full
246
- #
247
- # @param [Object] value
248
- #
249
- # @return [self]
250
- def put(value)
251
- synchronize do
252
- wait(@empty, &method(:empty?))
253
- perform_put(value)
254
- end
255
-
256
- self
257
- end
258
-
259
- # Modify mvar
260
- #
261
- # @return [Object]
262
- def modify
263
- synchronize do
264
- wait_full
265
- perform_put(yield(@value))
266
- end
267
- end
268
-
269
- private
270
-
271
- # Empty the mvar
272
- #
273
- # @return [Object]
274
- def perform_take
275
- @value.tap do
276
- @value = EMPTY
277
- @empty.signal
278
- end
279
- end
280
- end # MVar
281
- end # Variable
282
- end # Mutant
@@ -1,247 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Either do
4
- describe '.wrap_error' do
5
- def apply
6
- described_class.wrap_error(error, &block)
7
- end
8
-
9
- let(:error) { TestError }
10
-
11
- class TestError < RuntimeError; end
12
-
13
- context 'when block returns' do
14
- let(:value) { instance_double(Object, 'value') }
15
- let(:block) { -> { value } }
16
-
17
- it 'returns right wrapping block value' do
18
- expect(apply).to eql(described_class::Right.new(value))
19
- end
20
- end
21
-
22
- context 'when block raises' do
23
- let(:exception) { error.new }
24
- let(:block) { -> { fail exception } }
25
-
26
- context 'with covered exception' do
27
- it 'returns left wrapping exception' do
28
- expect(apply).to eql(described_class::Left.new(exception))
29
- end
30
- end
31
-
32
- context 'with uncovered exception' do
33
- let(:exception) { StandardError.new }
34
-
35
- it 'returns raises error' do
36
- expect { apply }.to raise_error(StandardError)
37
- end
38
- end
39
- end
40
- end
41
- end
42
-
43
- RSpec.describe Mutant::Either::Left do
44
- subject { described_class.new(value) }
45
-
46
- let(:block_result) { instance_double(Object, 'block result') }
47
- let(:value) { instance_double(Object, 'value') }
48
- let(:yields) { [] }
49
-
50
- let(:block) do
51
- lambda do |value|
52
- yields << value
53
- block_result
54
- end
55
- end
56
-
57
- class TestError < RuntimeError; end
58
-
59
- describe '#fmap' do
60
- def apply
61
- subject.fmap(&block)
62
- end
63
-
64
- include_examples 'no block evaluation'
65
- include_examples 'requires block'
66
- include_examples 'returns self'
67
- end
68
-
69
- describe '#apply' do
70
- def apply
71
- subject.apply(&block)
72
- end
73
-
74
- include_examples 'no block evaluation'
75
- include_examples 'requires block'
76
- include_examples 'returns self'
77
- end
78
-
79
- describe '#from_left' do
80
- def apply
81
- subject.from_left(&block)
82
- end
83
-
84
- it 'returns left value' do
85
- expect(apply).to be(value)
86
- end
87
-
88
- include_examples 'no block evaluation'
89
- end
90
-
91
- describe '#from_right' do
92
- def apply
93
- subject.from_right(&block)
94
- end
95
-
96
- context 'without block' do
97
- let(:block) { nil }
98
-
99
- it 'raises RuntimeError error' do
100
- expect { apply }.to raise_error(
101
- RuntimeError,
102
- "Expected right value, got #{subject.inspect}"
103
- )
104
- end
105
- end
106
-
107
- context 'with block' do
108
- let(:yields) { [] }
109
- let(:block_return) { instance_double(Object, 'block-return') }
110
-
111
- let(:block) do
112
- lambda do |value|
113
- yields << value
114
- block_return
115
- end
116
- end
117
-
118
- it 'calls block with left value' do
119
- expect { apply }.to change(yields, :to_a).from([]).to([value])
120
- end
121
-
122
- it 'returns block value' do
123
- expect(apply).to be(block_return)
124
- end
125
- end
126
- end
127
-
128
- describe '#lmap' do
129
- def apply
130
- subject.lmap(&block)
131
- end
132
-
133
- include_examples 'requires block'
134
- include_examples 'Functor#fmap block evaluation'
135
- end
136
-
137
- describe '#either' do
138
- def apply
139
- subject.either(block, -> { fail })
140
- end
141
-
142
- include_examples '#apply block evaluation'
143
- end
144
- end
145
-
146
- RSpec.describe Mutant::Either::Right do
147
- subject { described_class.new(value) }
148
-
149
- let(:block_result) { instance_double(Object, 'block result') }
150
- let(:value) { instance_double(Object, 'value') }
151
- let(:yields) { [] }
152
-
153
- let(:block) do
154
- lambda do |value|
155
- yields << value
156
- block_result
157
- end
158
- end
159
-
160
- describe '#fmap' do
161
- def apply
162
- subject.fmap(&block)
163
- end
164
-
165
- include_examples 'requires block'
166
- include_examples 'Functor#fmap block evaluation'
167
- end
168
-
169
- describe '#apply' do
170
- def apply
171
- subject.apply(&block)
172
- end
173
-
174
- include_examples 'requires block'
175
- include_examples '#apply block evaluation'
176
- end
177
-
178
- describe '#from_left' do
179
- def apply
180
- subject.from_left(&block)
181
- end
182
-
183
- context 'without block' do
184
- let(:block) { nil }
185
-
186
- it 'raises RuntimeError error' do
187
- expect { apply }.to raise_error(
188
- RuntimeError,
189
- "Expected left value, got #{subject.inspect}"
190
- )
191
- end
192
- end
193
-
194
- context 'with block' do
195
- let(:yields) { [] }
196
- let(:block_return) { instance_double(Object, 'block-return') }
197
-
198
- let(:block) do
199
- lambda do |value|
200
- yields << value
201
- block_return
202
- end
203
- end
204
-
205
- it 'calls block with right value' do
206
- expect { apply }.to change(yields, :to_a).from([]).to([value])
207
- end
208
-
209
- it 'returns block value' do
210
- expect(apply).to be(block_return)
211
- end
212
- end
213
- end
214
-
215
- describe '#from_right' do
216
- def apply
217
- subject.from_right(&block)
218
- end
219
-
220
- it 'returns right value' do
221
- expect(apply).to be(value)
222
- end
223
-
224
- include_examples 'no block evaluation'
225
- end
226
-
227
- describe '#lmap' do
228
- def apply
229
- subject.lmap(&block)
230
- end
231
-
232
- include_examples 'requires block'
233
- include_examples 'no block evaluation'
234
-
235
- it 'returns self' do
236
- expect(apply).to be(subject)
237
- end
238
- end
239
-
240
- describe '#either' do
241
- def apply
242
- subject.either(-> { fail }, block)
243
- end
244
-
245
- include_examples '#apply block evaluation'
246
- end
247
- end