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,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Maybe::Nothing do
4
- subject { described_class.new }
5
-
6
- let(:block) { -> {} }
7
-
8
- describe '#fmap' do
9
- def apply
10
- subject.fmap(&block)
11
- end
12
-
13
- include_examples 'no block evaluation'
14
- include_examples 'requires block'
15
- include_examples 'returns self'
16
- end
17
-
18
- describe '#apply' do
19
- def apply
20
- subject.apply(&block)
21
- end
22
-
23
- include_examples 'no block evaluation'
24
- include_examples 'requires block'
25
- include_examples 'returns self'
26
- end
27
- end
28
-
29
- RSpec.describe Mutant::Maybe::Just do
30
- subject { described_class.new(value) }
31
-
32
- let(:block_result) { instance_double(Object, 'block result') }
33
- let(:value) { instance_double(Object, 'value') }
34
- let(:yields) { [] }
35
-
36
- let(:block) do
37
- lambda do |value|
38
- yields << value
39
- block_result
40
- end
41
- end
42
-
43
- describe '#fmap' do
44
- def apply
45
- subject.fmap(&block)
46
- end
47
-
48
- include_examples 'requires block'
49
- include_examples 'Functor#fmap block evaluation'
50
- end
51
-
52
- describe '#apply' do
53
- def apply
54
- subject.apply(&block)
55
- end
56
-
57
- include_examples 'requires block'
58
- include_examples '#apply block evaluation'
59
- end
60
- end
@@ -1,618 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MutantSpec
4
- module VariableHelper
5
- def empty
6
- described_class.new(
7
- condition_variable: condition_variable_class,
8
- mutex: mutex_class
9
- )
10
- end
11
-
12
- def full(value)
13
- described_class.new(
14
- condition_variable: condition_variable_class,
15
- mutex: mutex_class,
16
- value: value
17
- )
18
- end
19
-
20
- # rubocop:disable Metrics/AbcSize
21
- # rubocop:disable Metrics/MethodLength
22
- def self.shared_setup
23
- lambda do |_host|
24
- let(:condition_variable_class) { class_double(ConditionVariable) }
25
- let(:expected_result) { value }
26
- let(:full_condition) { instance_double(ConditionVariable, 'full') }
27
- let(:mutex) { instance_double(Mutex) }
28
- let(:mutex_class) { class_double(Mutex) }
29
- let(:value) { instance_double(Object, 'value') }
30
-
31
- let(:synchronize) do
32
- {
33
- receiver: mutex,
34
- selector: :synchronize,
35
- reaction: { yields: [] }
36
- }
37
- end
38
-
39
- let(:signal_full) do
40
- {
41
- receiver: full_condition,
42
- selector: :signal
43
- }
44
- end
45
-
46
- let(:put) do
47
- {
48
- receiver: full_condition,
49
- selector: :wait,
50
- arguments: [mutex],
51
- reaction: { execute: -> { subject.put(value) } }
52
- }
53
- end
54
-
55
- let(:wait_empty) do
56
- {
57
- receiver: empty_condition,
58
- selector: :wait,
59
- arguments: [mutex]
60
- }
61
- end
62
-
63
- let(:wait_full) do
64
- {
65
- receiver: full_condition,
66
- selector: :wait,
67
- arguments: [mutex]
68
- }
69
- end
70
-
71
- let(:signal_empty) do
72
- {
73
- receiver: empty_condition,
74
- selector: :signal
75
- }
76
- end
77
-
78
- shared_examples 'consumes events' do
79
- specify do
80
- verify_events do
81
- expect(apply).to eql(expected_result)
82
- end
83
- end
84
- end
85
- end
86
- end
87
- end
88
- end
89
-
90
- RSpec.describe Mutant::Variable::IVar do
91
- include MutantSpec::VariableHelper
92
-
93
- class_eval(&MutantSpec::VariableHelper.shared_setup)
94
-
95
- subject { empty }
96
-
97
- let(:setup) do
98
- [
99
- {
100
- receiver: condition_variable_class,
101
- selector: :new,
102
- reaction: { return: full_condition }
103
- },
104
- {
105
- receiver: mutex_class,
106
- selector: :new,
107
- reaction: { return: mutex }
108
- },
109
- synchronize
110
- ]
111
- end
112
-
113
- describe '#take' do
114
- def apply
115
- subject.take
116
- end
117
-
118
- context 'when ivar is initially full' do
119
- subject { full(value) }
120
-
121
- let(:raw_expectations) { setup }
122
-
123
- include_examples 'consumes events'
124
- end
125
-
126
- context 'when ivar is initially empty' do
127
- let(:raw_expectations) do
128
- [
129
- *setup,
130
- put,
131
- synchronize,
132
- signal_full
133
- ]
134
- end
135
-
136
- include_examples 'consumes events'
137
- end
138
- end
139
-
140
- describe '#take_timeout' do
141
- def apply
142
- subject.take_timeout(1.0)
143
- end
144
-
145
- context 'when ivar is initially full' do
146
- subject { full(value) }
147
-
148
- let(:raw_expectations) { setup }
149
-
150
- let(:expected_result) do
151
- Mutant::Variable.const_get(:Result)::Value.new(value)
152
- end
153
-
154
- include_examples 'consumes events'
155
- end
156
-
157
- context 'when ivar is initially empty' do
158
- def wait(time)
159
- {
160
- receiver: full_condition,
161
- selector: :wait,
162
- arguments: [mutex, time]
163
- }
164
- end
165
-
166
- def elapsed(time)
167
- {
168
- receiver: Mutant::Timer,
169
- selector: :elapsed,
170
- reaction: { yields: [], return: time }
171
- }
172
- end
173
-
174
- context 'and timeout occurs before value is put' do
175
- let(:expected_result) do
176
- Mutant::Variable.const_get(:Result)::Timeout.new
177
- end
178
-
179
- context 'wait exactly runs to zero left time on the clock' do
180
- let(:raw_expectations) do
181
- [
182
- *setup,
183
- elapsed(0.5),
184
- wait(1.0),
185
- elapsed(0.5),
186
- wait(0.5)
187
- ]
188
- end
189
-
190
- include_examples 'consumes events'
191
- end
192
-
193
- context 'wait overruns timeout' do
194
- let(:raw_expectations) do
195
- [
196
- *setup,
197
- elapsed(1.5),
198
- wait(1.0)
199
- ]
200
- end
201
-
202
- include_examples 'consumes events'
203
- end
204
- end
205
-
206
- context 'and put occurs before timeout' do
207
- let(:expected_result) do
208
- Mutant::Variable.const_get(:Result)::Value.new(value)
209
- end
210
-
211
- let(:raw_expectations) do
212
- [
213
- *setup,
214
- elapsed(0.5),
215
- wait(1.0).merge(reaction: { execute: -> { subject.put(value) } }),
216
- synchronize,
217
- signal_full
218
- ]
219
- end
220
-
221
- include_examples 'consumes events'
222
- end
223
- end
224
- end
225
-
226
- describe '#put' do
227
- def apply
228
- subject.put(value)
229
- end
230
-
231
- context 'when ivar is initially empty' do
232
- context 'when not reading result' do
233
- let(:expected_result) { subject }
234
-
235
- let(:raw_expectations) do
236
- [
237
- *setup,
238
- signal_full
239
- ]
240
- end
241
-
242
- include_examples 'consumes events'
243
- end
244
-
245
- context 'when reading result back' do
246
- let(:expected_result) { value }
247
-
248
- def apply
249
- super
250
- subject.read
251
- end
252
-
253
- let(:raw_expectations) do
254
- [
255
- *setup,
256
- signal_full,
257
- synchronize
258
- ]
259
- end
260
-
261
- include_examples 'consumes events'
262
- end
263
- end
264
-
265
- context 'when ivar is initially full' do
266
- subject { full(value) }
267
-
268
- let(:raw_expectations) { setup }
269
-
270
- it 'raises expected exception' do
271
- verify_events do
272
- expect { apply }.to raise_error(Mutant::Variable::IVar::Error, 'is immutable')
273
- end
274
- end
275
- end
276
- end
277
-
278
- describe '#try_put' do
279
- def apply
280
- subject.try_put(value)
281
- end
282
-
283
- let(:expected_result) { subject }
284
-
285
- context 'when ivar is initially empty' do
286
- let(:raw_expectations) do
287
- [
288
- *setup,
289
- signal_full
290
- ]
291
- end
292
-
293
- include_examples 'consumes events'
294
-
295
- context 'reading the put value' do
296
- let(:expected_result) { value }
297
-
298
- let(:raw_expectations) do
299
- [
300
- *super(),
301
- synchronize
302
- ]
303
- end
304
-
305
- def apply
306
- super
307
- subject.read
308
- end
309
-
310
- include_examples 'consumes events'
311
- end
312
- end
313
-
314
- context 'when ivar is initially full' do
315
- subject { full(value) }
316
-
317
- let(:raw_expectations) { setup }
318
-
319
- include_examples 'consumes events'
320
- end
321
- end
322
-
323
- describe '#read' do
324
- def apply
325
- subject.read
326
- end
327
-
328
- context 'when ivar is initially empty' do
329
- let(:raw_expectations) do
330
- [
331
- *setup,
332
- wait_full.merge(reaction: { execute: -> { subject.put(value) } }),
333
- synchronize,
334
- signal_full
335
- ]
336
- end
337
-
338
- include_examples 'consumes events'
339
- end
340
-
341
- context 'when ivar is initially full' do
342
- subject { full(value) }
343
-
344
- let(:raw_expectations) { setup }
345
-
346
- include_examples 'consumes events'
347
- end
348
- end
349
-
350
- describe '#with' do
351
- def apply
352
- subject.with do |value|
353
- @value = value
354
- end
355
- end
356
-
357
- before { @value = nil }
358
-
359
- context 'when ivar is initially full' do
360
- subject { full(value) }
361
-
362
- let(:raw_expectations) { setup }
363
-
364
- include_examples 'consumes events'
365
-
366
- it 'should yield value' do
367
- verify_events do
368
- expect { apply }.to change { @value }.from(nil).to(value)
369
- end
370
- end
371
- end
372
-
373
- context 'when ivar is initially empty' do
374
- subject { empty }
375
-
376
- let(:raw_expectations) do
377
- [
378
- *setup,
379
- put,
380
- synchronize,
381
- signal_full
382
- ]
383
- end
384
-
385
- include_examples 'consumes events'
386
-
387
- it 'should yield value' do
388
- verify_events do
389
- expect { apply }.to change { @value }.from(nil).to(value)
390
- end
391
- end
392
- end
393
- end
394
- end
395
-
396
- describe Mutant::Variable::MVar do
397
- include MutantSpec::VariableHelper
398
-
399
- class_eval(&MutantSpec::VariableHelper.shared_setup)
400
-
401
- subject { empty }
402
-
403
- let(:empty_condition) { instance_double(ConditionVariable, 'empty') }
404
-
405
- let(:setup) do
406
- [
407
- {
408
- receiver: condition_variable_class,
409
- selector: :new,
410
- reaction: { return: full_condition }
411
- },
412
- {
413
- receiver: mutex_class,
414
- selector: :new,
415
- reaction: { return: mutex }
416
- },
417
- {
418
- receiver: condition_variable_class,
419
- selector: :new,
420
- reaction: { return: empty_condition }
421
- },
422
- synchronize
423
- ]
424
- end
425
-
426
- describe '#put' do
427
- def apply
428
- subject.put(value)
429
- end
430
-
431
- context 'when ivar is initially empty' do
432
- context 'when not reading result' do
433
- let(:expected_result) { subject }
434
-
435
- let(:raw_expectations) do
436
- [
437
- *setup,
438
- signal_full
439
- ]
440
- end
441
-
442
- include_examples 'consumes events'
443
- end
444
-
445
- context 'when reading result back' do
446
- let(:expected_result) { value }
447
-
448
- def apply
449
- super
450
- subject.read
451
- end
452
-
453
- let(:raw_expectations) do
454
- [
455
- *setup,
456
- signal_full,
457
- synchronize
458
- ]
459
- end
460
-
461
- include_examples 'consumes events'
462
- end
463
- end
464
-
465
- context 'when ivar is initially full' do
466
- context 'when not reading result' do
467
- subject { full(value) }
468
-
469
- let(:expected_result) { subject }
470
-
471
- let(:raw_expectations) do
472
- [
473
- *setup,
474
- wait_empty.merge(reaction: { execute: -> { subject.take } }),
475
- synchronize,
476
- signal_empty,
477
- signal_full
478
- ]
479
- end
480
-
481
- include_examples 'consumes events'
482
- end
483
-
484
- context 'when reading result back' do
485
- subject { full(value) }
486
-
487
- def apply
488
- super
489
- subject.read
490
- end
491
-
492
- let(:expected_result) { value }
493
-
494
- let(:raw_expectations) do
495
- [
496
- *setup,
497
- wait_empty.merge(reaction: { execute: -> { subject.take } }),
498
- synchronize,
499
- signal_empty,
500
- signal_full,
501
- synchronize
502
- ]
503
- end
504
-
505
- include_examples 'consumes events'
506
- end
507
- end
508
- end
509
-
510
- describe '#modify' do
511
- let(:expected_result) { 1 }
512
- let(:value) { 0 }
513
-
514
- def apply
515
- subject.modify(&:succ)
516
- end
517
-
518
- context 'when ivar is initially empty' do
519
- let(:raw_expectations) do
520
- [
521
- *setup,
522
- wait_full.merge(reaction: { execute: -> { subject.put(value) } }),
523
- synchronize,
524
- signal_full,
525
- signal_full
526
- ]
527
- end
528
-
529
- include_examples 'consumes events'
530
- end
531
-
532
- context 'when ivar is initially full' do
533
- subject { full(value) }
534
-
535
- let(:raw_expectations) do
536
- [
537
- *setup,
538
- signal_full
539
- ]
540
- end
541
-
542
- include_examples 'consumes events'
543
- end
544
- end
545
-
546
- describe '#take' do
547
- def apply
548
- subject.take
549
- end
550
-
551
- context 'when ivar is initially empty' do
552
- let(:expected_result) { value }
553
-
554
- let(:raw_expectations) do
555
- [
556
- *setup,
557
- wait_full.merge(reaction: { execute: -> { subject.put(value) } }),
558
- synchronize,
559
- signal_full,
560
- signal_empty
561
- ]
562
- end
563
-
564
- include_examples 'consumes events'
565
- end
566
-
567
- context 'when ivar is initially full' do
568
- subject { full(value) }
569
-
570
- let(:expected_result) { value }
571
-
572
- let(:raw_expectations) do
573
- [
574
- *setup,
575
- signal_empty
576
- ]
577
- end
578
-
579
- include_examples 'consumes events'
580
- end
581
- end
582
- end
583
-
584
- describe Mutant::Variable.const_get(:Result)::Value do
585
- subject { described_class.new(nil) }
586
-
587
- describe '#timeout?' do
588
- def apply
589
- subject.timeout?
590
- end
591
-
592
- it 'returns false' do
593
- expect(apply).to be(false)
594
- end
595
- end
596
- end
597
-
598
- describe Mutant::Variable.const_get(:Result)::Timeout do
599
- describe '.new' do
600
- it 'is instance of timeout' do
601
- expect(described_class.new.instance_of?(described_class)).to be(true)
602
- end
603
-
604
- it 'is idempotent' do
605
- expect(described_class.new).to be(described_class.new)
606
- end
607
- end
608
-
609
- describe '#timeout?' do
610
- def apply
611
- subject.timeout?
612
- end
613
-
614
- it 'returns true' do
615
- expect(apply).to be(true)
616
- end
617
- end
618
- end