mutant 0.9.2 → 0.9.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/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