mutant 0.9.10 → 0.10.0

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 (254) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mutant +16 -11
  3. data/lib/mutant.rb +8 -4
  4. data/lib/mutant/bootstrap.rb +14 -1
  5. data/lib/mutant/cli.rb +9 -162
  6. data/lib/mutant/cli/command.rb +196 -0
  7. data/lib/mutant/cli/command/root.rb +13 -0
  8. data/lib/mutant/cli/command/run.rb +151 -0
  9. data/lib/mutant/cli/command/subscription.rb +54 -0
  10. data/lib/mutant/expression.rb +0 -1
  11. data/lib/mutant/isolation.rb +1 -1
  12. data/lib/mutant/isolation/fork.rb +2 -2
  13. data/lib/mutant/isolation/none.rb +1 -1
  14. data/lib/mutant/license.rb +9 -35
  15. data/lib/mutant/license/subscription.rb +31 -9
  16. data/lib/mutant/license/subscription/commercial.rb +2 -4
  17. data/lib/mutant/license/subscription/opensource.rb +7 -7
  18. data/lib/mutant/matcher/config.rb +2 -0
  19. data/lib/mutant/meta/example.rb +16 -4
  20. data/lib/mutant/meta/example/dsl.rb +33 -16
  21. data/lib/mutant/meta/example/verification.rb +70 -28
  22. data/lib/mutant/minitest/coverage.rb +53 -0
  23. data/lib/mutant/mutator/node.rb +2 -2
  24. data/lib/mutant/mutator/node/block_pass.rb +29 -0
  25. data/lib/mutant/mutator/node/{dstr.rb → dynamic_literal.rb} +7 -5
  26. data/lib/mutant/mutator/node/index.rb +4 -4
  27. data/lib/mutant/mutator/node/literal/range.rb +5 -2
  28. data/lib/mutant/mutator/node/named_value/variable_assignment.rb +1 -1
  29. data/lib/mutant/mutator/node/noop.rb +1 -1
  30. data/lib/mutant/mutator/node/op_asgn.rb +15 -1
  31. data/lib/mutant/mutator/node/send.rb +25 -1
  32. data/lib/mutant/mutator/node/send/attribute_assignment.rb +1 -0
  33. data/lib/mutant/reporter/cli/printer/isolation_result.rb +9 -3
  34. data/lib/mutant/subject/method/instance.rb +1 -1
  35. data/lib/mutant/version.rb +1 -1
  36. metadata +18 -336
  37. data/.github/workflows/ci.yml +0 -121
  38. data/.gitignore +0 -38
  39. data/.rspec +0 -5
  40. data/.rubocop.yml +0 -210
  41. data/Changelog.md +0 -87
  42. data/Gemfile +0 -7
  43. data/Gemfile.lock +0 -107
  44. data/Gemfile.shared +0 -10
  45. data/README.md +0 -199
  46. data/Rakefile +0 -5
  47. data/config/devtools.yml +0 -2
  48. data/config/reek.yml +0 -139
  49. data/config/yardstick.yml +0 -2
  50. data/docs/commercial-support.md +0 -14
  51. data/docs/concurrency.md +0 -39
  52. data/docs/incremental.md +0 -76
  53. data/docs/known-problems.md +0 -30
  54. data/docs/limitations.md +0 -50
  55. data/docs/mutant-minitest.md +0 -149
  56. data/docs/mutant-rspec.md +0 -130
  57. data/docs/nomenclature.md +0 -82
  58. data/docs/reading-reports.md +0 -74
  59. data/lib/mutant/mutator/node/dsym.rb +0 -22
  60. data/meta/and.rb +0 -13
  61. data/meta/and_asgn.rb +0 -14
  62. data/meta/array.rb +0 -27
  63. data/meta/begin.rb +0 -20
  64. data/meta/block.rb +0 -199
  65. data/meta/block_pass.rb +0 -8
  66. data/meta/blockarg.rb +0 -10
  67. data/meta/break.rb +0 -9
  68. data/meta/case.rb +0 -217
  69. data/meta/casgn.rb +0 -25
  70. data/meta/cbase.rb +0 -8
  71. data/meta/class.rb +0 -12
  72. data/meta/const.rb +0 -17
  73. data/meta/csend.rb +0 -10
  74. data/meta/cvar.rb +0 -7
  75. data/meta/cvasgn.rb +0 -9
  76. data/meta/date.rb +0 -59
  77. data/meta/def.rb +0 -196
  78. data/meta/defined.rb +0 -9
  79. data/meta/dstr.rb +0 -13
  80. data/meta/dsym.rb +0 -14
  81. data/meta/ensure.rb +0 -8
  82. data/meta/false.rb +0 -7
  83. data/meta/file.rb +0 -5
  84. data/meta/float.rb +0 -37
  85. data/meta/gvar.rb +0 -7
  86. data/meta/gvasgn.rb +0 -9
  87. data/meta/hash.rb +0 -20
  88. data/meta/if.rb +0 -72
  89. data/meta/index.rb +0 -133
  90. data/meta/indexasgn.rb +0 -31
  91. data/meta/int.rb +0 -18
  92. data/meta/ivar.rb +0 -8
  93. data/meta/ivasgn.rb +0 -22
  94. data/meta/kwarg.rb +0 -10
  95. data/meta/kwbegin.rb +0 -8
  96. data/meta/kwoptarg.rb +0 -13
  97. data/meta/lambda.rb +0 -23
  98. data/meta/line.rb +0 -5
  99. data/meta/lvar.rb +0 -16
  100. data/meta/lvasgn.rb +0 -24
  101. data/meta/masgn.rb +0 -7
  102. data/meta/match_current_line.rb +0 -14
  103. data/meta/next.rb +0 -10
  104. data/meta/nil.rb +0 -5
  105. data/meta/nthref.rb +0 -14
  106. data/meta/op_assgn.rb +0 -17
  107. data/meta/or.rb +0 -13
  108. data/meta/or_asgn.rb +0 -50
  109. data/meta/range.rb +0 -65
  110. data/meta/redo.rb +0 -5
  111. data/meta/regexp.rb +0 -80
  112. data/meta/regopt.rb +0 -10
  113. data/meta/rescue.rb +0 -84
  114. data/meta/return.rb +0 -16
  115. data/meta/sclass.rb +0 -12
  116. data/meta/self.rb +0 -7
  117. data/meta/send.rb +0 -600
  118. data/meta/str.rb +0 -7
  119. data/meta/super.rb +0 -27
  120. data/meta/sym.rb +0 -8
  121. data/meta/true.rb +0 -7
  122. data/meta/until.rb +0 -16
  123. data/meta/while.rb +0 -24
  124. data/meta/yield.rb +0 -9
  125. data/mutant-minitest.gemspec +0 -22
  126. data/mutant-rspec.gemspec +0 -22
  127. data/mutant.gemspec +0 -44
  128. data/mutant.sh +0 -12
  129. data/mutant.yml +0 -6
  130. data/spec/integration/mutant/corpus_spec.rb +0 -15
  131. data/spec/integration/mutant/isolation/fork_spec.rb +0 -28
  132. data/spec/integration/mutant/minitest_spec.rb +0 -11
  133. data/spec/integration/mutant/null_spec.rb +0 -16
  134. data/spec/integration/mutant/rspec_spec.rb +0 -15
  135. data/spec/integration/mutant/test_mutator_handles_types_spec.rb +0 -9
  136. data/spec/integrations.yml +0 -63
  137. data/spec/shared/framework_integration_behavior.rb +0 -70
  138. data/spec/shared/method_matcher_behavior.rb +0 -47
  139. data/spec/spec_helper.rb +0 -90
  140. data/spec/support/corpus.rb +0 -318
  141. data/spec/support/file_system.rb +0 -62
  142. data/spec/support/ice_nine_config.rb +0 -10
  143. data/spec/support/ruby_vm.rb +0 -84
  144. data/spec/support/shared_context.rb +0 -169
  145. data/spec/support/xspec.rb +0 -183
  146. data/spec/unit/mutant/ast/find_metaclass_containing_spec.rb +0 -64
  147. data/spec/unit/mutant/ast/meta/optarg_spec.rb +0 -24
  148. data/spec/unit/mutant/ast/meta/send/proc_predicate_spec.rb +0 -30
  149. data/spec/unit/mutant/ast/meta/send/receiver_possible_top_level_const_predicate_spec.rb +0 -39
  150. data/spec/unit/mutant/ast/meta/send_spec.rb +0 -42
  151. data/spec/unit/mutant/ast/named_children_spec.rb +0 -89
  152. data/spec/unit/mutant/ast/sexp_spec.rb +0 -38
  153. data/spec/unit/mutant/ast_spec.rb +0 -57
  154. data/spec/unit/mutant/bootstrap_spec.rb +0 -216
  155. data/spec/unit/mutant/cli_spec.rb +0 -305
  156. data/spec/unit/mutant/clock_monotonic_spec.rb +0 -52
  157. data/spec/unit/mutant/config_spec.rb +0 -126
  158. data/spec/unit/mutant/context_spec.rb +0 -111
  159. data/spec/unit/mutant/env_spec.rb +0 -229
  160. data/spec/unit/mutant/expression/method_spec.rb +0 -62
  161. data/spec/unit/mutant/expression/methods_spec.rb +0 -66
  162. data/spec/unit/mutant/expression/namespace/exact_spec.rb +0 -28
  163. data/spec/unit/mutant/expression/namespace/recursive_spec.rb +0 -66
  164. data/spec/unit/mutant/expression/parser_spec.rb +0 -65
  165. data/spec/unit/mutant/expression_spec.rb +0 -45
  166. data/spec/unit/mutant/integration/rspec_spec.rb +0 -201
  167. data/spec/unit/mutant/integration_spec.rb +0 -150
  168. data/spec/unit/mutant/isolation/fork_spec.rb +0 -309
  169. data/spec/unit/mutant/isolation/none_spec.rb +0 -23
  170. data/spec/unit/mutant/isolation/result_spec.rb +0 -73
  171. data/spec/unit/mutant/license_spec.rb +0 -305
  172. data/spec/unit/mutant/loader_spec.rb +0 -79
  173. data/spec/unit/mutant/matcher/chain_spec.rb +0 -26
  174. data/spec/unit/mutant/matcher/compiler_spec.rb +0 -0
  175. data/spec/unit/mutant/matcher/config_spec.rb +0 -47
  176. data/spec/unit/mutant/matcher/filter_spec.rb +0 -22
  177. data/spec/unit/mutant/matcher/method/instance_spec.rb +0 -164
  178. data/spec/unit/mutant/matcher/method/metaclass_spec.rb +0 -108
  179. data/spec/unit/mutant/matcher/method/singleton_spec.rb +0 -90
  180. data/spec/unit/mutant/matcher/methods/instance_spec.rb +0 -54
  181. data/spec/unit/mutant/matcher/methods/metaclass_spec.rb +0 -62
  182. data/spec/unit/mutant/matcher/methods/singleton_spec.rb +0 -51
  183. data/spec/unit/mutant/matcher/namespace_spec.rb +0 -39
  184. data/spec/unit/mutant/matcher/null_spec.rb +0 -12
  185. data/spec/unit/mutant/matcher/scope_spec.rb +0 -45
  186. data/spec/unit/mutant/matcher/static_spec.rb +0 -13
  187. data/spec/unit/mutant/matcher_spec.rb +0 -102
  188. data/spec/unit/mutant/meta/example/dsl_spec.rb +0 -108
  189. data/spec/unit/mutant/meta/example/verification_spec.rb +0 -154
  190. data/spec/unit/mutant/meta/example_spec.rb +0 -34
  191. data/spec/unit/mutant/mutation_spec.rb +0 -140
  192. data/spec/unit/mutant/mutator/node_spec.rb +0 -47
  193. data/spec/unit/mutant/mutator_spec.rb +0 -21
  194. data/spec/unit/mutant/parallel/driver_spec.rb +0 -126
  195. data/spec/unit/mutant/parallel/source/array_spec.rb +0 -57
  196. data/spec/unit/mutant/parallel/worker_spec.rb +0 -206
  197. data/spec/unit/mutant/parallel_spec.rb +0 -115
  198. data/spec/unit/mutant/parser_spec.rb +0 -26
  199. data/spec/unit/mutant/range_spec.rb +0 -141
  200. data/spec/unit/mutant/registry_spec.rb +0 -74
  201. data/spec/unit/mutant/reporter/cli/printer/config_spec.rb +0 -17
  202. data/spec/unit/mutant/reporter/cli/printer/env_progress_spec.rb +0 -85
  203. data/spec/unit/mutant/reporter/cli/printer/env_result_spec.rb +0 -45
  204. data/spec/unit/mutant/reporter/cli/printer/isolation_result_spec.rb +0 -132
  205. data/spec/unit/mutant/reporter/cli/printer/mutation_progress_result_spec.rb +0 -25
  206. data/spec/unit/mutant/reporter/cli/printer/mutation_result_spec.rb +0 -153
  207. data/spec/unit/mutant/reporter/cli/printer/status_progressive_spec.rb +0 -45
  208. data/spec/unit/mutant/reporter/cli/printer/subject_progress_spec.rb +0 -36
  209. data/spec/unit/mutant/reporter/cli/printer/subject_result_spec.rb +0 -44
  210. data/spec/unit/mutant/reporter/cli/printer/test_result_spec.rb +0 -16
  211. data/spec/unit/mutant/reporter/cli/printer_spec.rb +0 -163
  212. data/spec/unit/mutant/reporter/cli_spec.rb +0 -137
  213. data/spec/unit/mutant/reporter/null_spec.rb +0 -14
  214. data/spec/unit/mutant/reporter/sequence_spec.rb +0 -31
  215. data/spec/unit/mutant/repository/diff/ranges_spec.rb +0 -180
  216. data/spec/unit/mutant/repository/diff_spec.rb +0 -122
  217. data/spec/unit/mutant/repository/subject_filter_spec.rb +0 -30
  218. data/spec/unit/mutant/require_highjack_spec.rb +0 -73
  219. data/spec/unit/mutant/result/class_methods_spec.rb +0 -51
  220. data/spec/unit/mutant/result/env_spec.rb +0 -161
  221. data/spec/unit/mutant/result/mutation_spec.rb +0 -70
  222. data/spec/unit/mutant/result/subject_spec.rb +0 -111
  223. data/spec/unit/mutant/result/test_spec.rb +0 -14
  224. data/spec/unit/mutant/result_spec.rb +0 -33
  225. data/spec/unit/mutant/runner/sink_spec.rb +0 -174
  226. data/spec/unit/mutant/runner_spec.rb +0 -121
  227. data/spec/unit/mutant/selector/expression_spec.rb +0 -62
  228. data/spec/unit/mutant/selector/null_spec.rb +0 -17
  229. data/spec/unit/mutant/subject/method/instance_spec.rb +0 -276
  230. data/spec/unit/mutant/subject/method/metaclass_spec.rb +0 -63
  231. data/spec/unit/mutant/subject/method/singleton_spec.rb +0 -61
  232. data/spec/unit/mutant/subject_spec.rb +0 -93
  233. data/spec/unit/mutant/transform/array_spec.rb +0 -92
  234. data/spec/unit/mutant/transform/bool_spec.rb +0 -63
  235. data/spec/unit/mutant/transform/error_spec.rb +0 -132
  236. data/spec/unit/mutant/transform/exception_spec.rb +0 -44
  237. data/spec/unit/mutant/transform/hash_spec.rb +0 -236
  238. data/spec/unit/mutant/transform/index_spec.rb +0 -92
  239. data/spec/unit/mutant/transform/named_spec.rb +0 -49
  240. data/spec/unit/mutant/transform/primitive_spec.rb +0 -56
  241. data/spec/unit/mutant/transform/sequence_spec.rb +0 -98
  242. data/spec/unit/mutant/util/one_spec.rb +0 -22
  243. data/spec/unit/mutant/warnings_spec.rb +0 -89
  244. data/spec/unit/mutant/world_spec.rb +0 -63
  245. data/spec/unit/mutant/zombifier_spec.rb +0 -122
  246. data/test_app/.rspec +0 -1
  247. data/test_app/Gemfile.minitest +0 -6
  248. data/test_app/Gemfile.rspec3.8 +0 -7
  249. data/test_app/lib/test_app.rb +0 -114
  250. data/test_app/lib/test_app/literal.rb +0 -35
  251. data/test_app/lib/test_app/metaclasses.rb +0 -108
  252. data/test_app/spec/spec_helper.rb +0 -9
  253. data/test_app/spec/unit/test_app/literal_spec.rb +0 -20
  254. data/test_app/test/unit/test_app/literal_test.rb +0 -16
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Mutator do
4
- describe '.handle' do
5
- subject do
6
- Class.new(described_class) do
7
- const_set(:REGISTRY, Mutant::Registry.new)
8
-
9
- handle :send
10
-
11
- def dispatch
12
- emit(parent)
13
- end
14
- end
15
- end
16
-
17
- it 'should register mutator' do
18
- expect(subject.mutate(s(:send), s(:parent))).to eql([s(:parent)].to_set)
19
- end
20
- end
21
- end
@@ -1,126 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Parallel::Driver do
4
- let(:active_jobs) { [] }
5
- let(:thread_a) { instance_double(Thread, alive?: true) }
6
- let(:thread_b) { instance_double(Thread, alive?: true) }
7
- let(:threads) { [thread_a, thread_b] }
8
- let(:timeout) { instance_double(Float) }
9
- let(:sink_status) { instance_double(Object) }
10
-
11
- let(:sink) do
12
- instance_double(
13
- Mutant::Parallel::Sink,
14
- status: sink_status
15
- )
16
- end
17
-
18
- let(:var_active_jobs) do
19
- instance_double(Variable::IVar, 'active jobs')
20
- end
21
-
22
- let(:var_final) do
23
- instance_double(Variable::IVar, 'final')
24
- end
25
-
26
- let(:var_sink) do
27
- instance_double(Variable::IVar, 'sink')
28
- end
29
-
30
- subject do
31
- described_class.new(
32
- threads: threads,
33
- var_active_jobs: var_active_jobs,
34
- var_final: var_final,
35
- var_sink: var_sink
36
- )
37
- end
38
-
39
- describe '#wait_timeout' do
40
- def apply
41
- subject.wait_timeout(timeout)
42
- end
43
-
44
- shared_examples 'returns expected status' do
45
- it 'returns expected status' do
46
- verify_events do
47
- expect(apply).to eql(expected_status)
48
- end
49
- end
50
-
51
- it 'returns frozen copy of active jobs' do
52
- verify_events do
53
- returned_active_jobs = apply.active_jobs
54
-
55
- expect(returned_active_jobs).to_not be(active_jobs)
56
- expect(returned_active_jobs.frozen?).to be(true)
57
- end
58
- end
59
- end
60
-
61
- let(:raw_expectations) do
62
- [
63
- {
64
- receiver: var_final,
65
- selector: :take_timeout,
66
- arguments: [timeout],
67
- reaction: { return: Variable.const_get(:Result)::Timeout.new }
68
- },
69
- {
70
- receiver: var_active_jobs,
71
- selector: :with,
72
- reaction: { yields: [active_jobs] }
73
- },
74
- {
75
- receiver: var_sink,
76
- selector: :with,
77
- reaction: { yields: [sink] }
78
- }
79
- ]
80
- end
81
-
82
- context 'when not done' do
83
- let(:expected_status) do
84
- Mutant::Parallel::Status.new(
85
- active_jobs: active_jobs,
86
- done: false,
87
- payload: sink_status
88
- )
89
- end
90
-
91
- include_examples 'returns expected status'
92
- end
93
-
94
- context 'when done' do
95
- before do
96
- allow(thread_a).to receive_messages(alive?: false)
97
- allow(thread_b).to receive_messages(alive?: false)
98
- end
99
-
100
- let(:raw_expectations) do
101
- [
102
- *super(),
103
- {
104
- receiver: thread_a,
105
- selector: :join
106
- },
107
- {
108
- receiver: thread_b,
109
- selector: :join
110
- }
111
- ]
112
-
113
- end
114
-
115
- let(:expected_status) do
116
- Mutant::Parallel::Status.new(
117
- active_jobs: active_jobs,
118
- done: true,
119
- payload: sink_status
120
- )
121
- end
122
-
123
- include_examples 'returns expected status'
124
- end
125
- end
126
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Parallel::Source::Array do
4
- subject { described_class.new(payloads) }
5
-
6
- let(:payloads) { %i[a b c] }
7
-
8
- describe '#next' do
9
- def job(**attributes)
10
- Mutant::Parallel::Source::Job.new(attributes)
11
- end
12
-
13
- def apply
14
- subject.next
15
- end
16
-
17
- context 'when there is a next job' do
18
- it 'returns that job' do
19
- expect(apply).to eql(job(index: 0, payload: :a))
20
- end
21
-
22
- it 'does not return the same job twice' do
23
- expect(apply).to eql(job(index: 0, payload: :a))
24
- expect(apply).to eql(job(index: 1, payload: :b))
25
- expect(apply).to eql(job(index: 2, payload: :c))
26
- end
27
- end
28
-
29
- context 'when there is no next job' do
30
- let(:payloads) { [] }
31
-
32
- it 'raises error' do
33
- expect { apply }.to raise_error(Mutant::Parallel::Source::NoJobError)
34
- end
35
- end
36
- end
37
-
38
- describe '#next?' do
39
- def apply
40
- subject.next?
41
- end
42
-
43
- context 'when there is a next job' do
44
- it 'returns true' do
45
- expect(apply).to be(true)
46
- end
47
- end
48
-
49
- context 'when there is no next job' do
50
- let(:payloads) { [] }
51
-
52
- it 'returns false' do
53
- expect(apply).to be(false)
54
- end
55
- end
56
- end
57
- end
@@ -1,206 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Parallel::Worker do
4
- describe '#call' do
5
- let(:active_jobs) { instance_double(Set) }
6
- let(:payload_a) { instance_double(Object) }
7
- let(:payload_b) { instance_double(Object) }
8
- let(:processor) { instance_double(Proc) }
9
- let(:result_a) { instance_double(Object) }
10
- let(:result_b) { instance_double(Object) }
11
- let(:running) { 1 }
12
- let(:sink) { instance_double(Mutant::Parallel::Sink) }
13
- let(:source) { instance_double(Mutant::Parallel::Source) }
14
- let(:thread_a) { instance_double(Thread, alive?: true) }
15
- let(:thread_b) { instance_double(Thread, alive?: true) }
16
- let(:threads) { [thread_a, thread_b] }
17
- let(:timeout) { instance_double(Float) }
18
-
19
- let(:job_a) do
20
- instance_double(
21
- Mutant::Parallel::Source::Job,
22
- payload: payload_a
23
- )
24
- end
25
-
26
- let(:job_b) do
27
- instance_double(
28
- Mutant::Parallel::Source::Job,
29
- payload: payload_b
30
- )
31
- end
32
-
33
- let(:var_active_jobs) do
34
- instance_double(Variable::IVar, 'active jobs')
35
- end
36
-
37
- let(:var_final) do
38
- instance_double(Variable::IVar, 'final')
39
- end
40
-
41
- let(:var_running) do
42
- instance_double(Variable::MVar, 'running')
43
- end
44
-
45
- let(:var_sink) do
46
- instance_double(Variable::IVar, 'sink')
47
- end
48
-
49
- let(:var_source) do
50
- instance_double(Variable::IVar, 'source')
51
- end
52
-
53
- subject do
54
- described_class.new(
55
- processor: processor,
56
- var_active_jobs: var_active_jobs,
57
- var_final: var_final,
58
- var_running: var_running,
59
- var_sink: var_sink,
60
- var_source: var_source
61
- )
62
- end
63
-
64
- def apply
65
- subject.call
66
- end
67
-
68
- def sink_result(result)
69
- {
70
- receiver: sink,
71
- selector: :result,
72
- arguments: [result]
73
- }
74
- end
75
-
76
- def sink_stop?(value)
77
- {
78
- receiver: sink,
79
- selector: :stop?,
80
- reaction: { return: value }
81
- }
82
- end
83
-
84
- def source_next?(value)
85
- {
86
- receiver: source,
87
- selector: :next?,
88
- reaction: { return: value }
89
- }
90
- end
91
-
92
- def source_next(value)
93
- {
94
- receiver: source,
95
- selector: :next,
96
- reaction: { return: value }
97
- }
98
- end
99
-
100
- def with(var, value)
101
- {
102
- receiver: var,
103
- selector: :with,
104
- reaction: { yields: [value] }
105
- }
106
- end
107
-
108
- def process(payload, result)
109
- {
110
- receiver: processor,
111
- selector: :call,
112
- arguments: [payload],
113
- reaction: { return: result }
114
- }
115
- end
116
-
117
- def add_job(job)
118
- {
119
- receiver: active_jobs,
120
- selector: :<<,
121
- arguments: [job]
122
- }
123
- end
124
-
125
- def remove_job(job)
126
- {
127
- receiver: active_jobs,
128
- selector: :delete,
129
- arguments: [job]
130
- }
131
- end
132
-
133
- shared_examples 'worker execution' do
134
- it 'terminates after processing all jobs' do
135
- verify_events { expect(apply).to be(subject) }
136
- end
137
- end
138
-
139
- def modify_running
140
- {
141
- receiver: var_running,
142
- selector: :modify,
143
- reaction: { yields: [running] }
144
- }
145
- end
146
-
147
- def finalize
148
- [
149
- modify_running,
150
- {
151
- receiver: var_final,
152
- selector: :put,
153
- arguments: [nil]
154
- }
155
- ]
156
- end
157
-
158
- context 'when processing jobs till sink stops accepting' do
159
- let(:raw_expectations) do
160
- [
161
- with(var_source, source),
162
- source_next?(true),
163
- source_next(job_a),
164
- with(var_active_jobs, active_jobs),
165
- add_job(job_a),
166
- process(payload_a, result_a),
167
- with(var_active_jobs, active_jobs),
168
- remove_job(job_a),
169
- with(var_sink, sink),
170
- sink_result(result_a),
171
- sink_stop?(true),
172
- *finalize
173
- ]
174
- end
175
-
176
- include_examples 'worker execution'
177
- end
178
-
179
- context 'when processing jobs till source is empty' do
180
- let(:raw_expectations) do
181
- [
182
- with(var_source, source),
183
- source_next?(false),
184
- *finalize
185
- ]
186
- end
187
-
188
- include_examples 'worker execution'
189
- end
190
-
191
- context 'when worker exits as others are still going' do
192
- let(:running) { 2 }
193
-
194
- let(:raw_expectations) do
195
- [
196
- with(var_source, source),
197
- source_next?(false),
198
- modify_running
199
- # no finalize
200
- ]
201
- end
202
-
203
- include_examples 'worker execution'
204
- end
205
- end
206
- end
@@ -1,115 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Mutant::Parallel do
4
- describe '.async' do
5
- def apply
6
- described_class.async(config)
7
- end
8
-
9
- let(:condition_variable) { class_double(ConditionVariable) }
10
- let(:jobs) { 2 }
11
- let(:mutex) { class_double(Mutex) }
12
- let(:processor) { instance_double(Proc) }
13
- let(:sink) { instance_double(described_class::Sink) }
14
- let(:source) { instance_double(described_class::Source) }
15
- let(:thread) { class_double(Thread) }
16
- let(:thread_a) { instance_double(Thread) }
17
- let(:thread_b) { instance_double(Thread) }
18
- let(:worker) { -> {} }
19
-
20
- let(:config) do
21
- Mutant::Parallel::Config.new(
22
- condition_variable: condition_variable,
23
- jobs: jobs,
24
- mutex: mutex,
25
- processor: processor,
26
- sink: sink,
27
- source: source,
28
- thread: thread
29
- )
30
- end
31
-
32
- let(:var_active_jobs) do
33
- instance_double(Variable::IVar, 'active jobs')
34
- end
35
-
36
- let(:var_final) do
37
- instance_double(Variable::IVar, 'final')
38
- end
39
-
40
- let(:var_running) do
41
- instance_double(Variable::MVar, 'running')
42
- end
43
-
44
- let(:var_sink) do
45
- instance_double(Variable::IVar, 'sink')
46
- end
47
-
48
- let(:var_source) do
49
- instance_double(Variable::IVar, 'source')
50
- end
51
-
52
- def ivar(value, **attributes)
53
- {
54
- receiver: Variable::IVar,
55
- selector: :new,
56
- arguments: [
57
- condition_variable: condition_variable,
58
- mutex: mutex,
59
- **attributes
60
- ],
61
- reaction: { return: value }
62
- }
63
- end
64
-
65
- def mvar(*arguments)
66
- ivar(*arguments).merge(receiver: Variable::MVar)
67
- end
68
-
69
- let(:raw_expectations) do
70
- [
71
- ivar(var_active_jobs, value: Set.new),
72
- ivar(var_final),
73
- ivar(var_sink, value: sink),
74
- mvar(var_running, value: 2),
75
- ivar(var_source, value: source),
76
- {
77
- receiver: Mutant::Parallel::Worker,
78
- selector: :new,
79
- arguments: [
80
- processor: processor,
81
- var_active_jobs: var_active_jobs,
82
- var_final: var_final,
83
- var_running: var_running,
84
- var_sink: var_sink,
85
- var_source: var_source
86
- ],
87
- reaction: { return: worker }
88
- },
89
- {
90
- receiver: thread,
91
- selector: :new,
92
- reaction: { yields: [], return: thread_a }
93
- },
94
- {
95
- receiver: thread,
96
- selector: :new,
97
- reaction: { yields: [], return: thread_b }
98
- }
99
- ]
100
- end
101
-
102
- it 'returns driver' do
103
- verify_events do
104
- expect(apply).to eql(
105
- described_class::Driver.new(
106
- threads: [thread_a, thread_b],
107
- var_active_jobs: var_active_jobs,
108
- var_final: var_final,
109
- var_sink: var_sink
110
- )
111
- )
112
- end
113
- end
114
- end
115
- end