fear 1.0.0 → 2.0.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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +39 -0
  4. data/.github/workflows/spec.yml +42 -0
  5. data/.rubocop.yml +4 -60
  6. data/.simplecov +17 -0
  7. data/CHANGELOG.md +29 -1
  8. data/Gemfile +5 -5
  9. data/Gemfile.lock +86 -50
  10. data/README.md +240 -209
  11. data/Rakefile +72 -65
  12. data/examples/pattern_extracting.rb +10 -8
  13. data/examples/pattern_matching_binary_tree_set.rb +7 -2
  14. data/examples/pattern_matching_number_in_words.rb +48 -42
  15. data/fear.gemspec +33 -34
  16. data/lib/dry/types/fear/option.rb +125 -0
  17. data/lib/dry/types/fear.rb +8 -0
  18. data/lib/fear/await.rb +33 -0
  19. data/lib/fear/awaitable.rb +28 -0
  20. data/lib/fear/either.rb +15 -4
  21. data/lib/fear/either_api.rb +4 -0
  22. data/lib/fear/either_pattern_match.rb +9 -5
  23. data/lib/fear/empty_partial_function.rb +3 -1
  24. data/lib/fear/failure.rb +7 -7
  25. data/lib/fear/failure_pattern_match.rb +4 -0
  26. data/lib/fear/for.rb +4 -2
  27. data/lib/fear/for_api.rb +5 -1
  28. data/lib/fear/future.rb +157 -82
  29. data/lib/fear/future_api.rb +17 -4
  30. data/lib/fear/left.rb +3 -9
  31. data/lib/fear/left_pattern_match.rb +2 -0
  32. data/lib/fear/none.rb +28 -10
  33. data/lib/fear/none_pattern_match.rb +2 -0
  34. data/lib/fear/option.rb +30 -2
  35. data/lib/fear/option_api.rb +4 -0
  36. data/lib/fear/option_pattern_match.rb +8 -3
  37. data/lib/fear/partial_function/and_then.rb +4 -2
  38. data/lib/fear/partial_function/any.rb +2 -0
  39. data/lib/fear/partial_function/combined.rb +3 -1
  40. data/lib/fear/partial_function/empty.rb +6 -0
  41. data/lib/fear/partial_function/guard/and.rb +2 -0
  42. data/lib/fear/partial_function/guard/and3.rb +2 -0
  43. data/lib/fear/partial_function/guard/or.rb +2 -0
  44. data/lib/fear/partial_function/guard.rb +8 -6
  45. data/lib/fear/partial_function/lifted.rb +2 -0
  46. data/lib/fear/partial_function/or_else.rb +5 -1
  47. data/lib/fear/partial_function.rb +18 -9
  48. data/lib/fear/partial_function_class.rb +3 -1
  49. data/lib/fear/pattern_match.rb +3 -11
  50. data/lib/fear/pattern_matching_api.rb +6 -28
  51. data/lib/fear/promise.rb +7 -5
  52. data/lib/fear/right.rb +3 -9
  53. data/lib/fear/right_biased.rb +5 -3
  54. data/lib/fear/right_pattern_match.rb +4 -0
  55. data/lib/fear/some.rb +35 -8
  56. data/lib/fear/some_pattern_match.rb +2 -0
  57. data/lib/fear/struct.rb +237 -0
  58. data/lib/fear/success.rb +7 -8
  59. data/lib/fear/success_pattern_match.rb +4 -0
  60. data/lib/fear/try.rb +8 -2
  61. data/lib/fear/try_api.rb +4 -0
  62. data/lib/fear/try_pattern_match.rb +9 -5
  63. data/lib/fear/unit.rb +6 -2
  64. data/lib/fear/utils.rb +14 -2
  65. data/lib/fear/version.rb +4 -1
  66. data/lib/fear.rb +26 -44
  67. data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
  68. data/spec/dry/types/fear/option/core_spec.rb +77 -0
  69. data/spec/dry/types/fear/option/default_spec.rb +21 -0
  70. data/spec/dry/types/fear/option/hash_spec.rb +58 -0
  71. data/spec/dry/types/fear/option/option_spec.rb +97 -0
  72. data/spec/fear/awaitable_spec.rb +19 -0
  73. data/spec/fear/done_spec.rb +7 -5
  74. data/spec/fear/either/mixin_spec.rb +4 -2
  75. data/spec/fear/either_pattern_match_spec.rb +10 -8
  76. data/spec/fear/either_pattern_matching_spec.rb +28 -0
  77. data/spec/fear/either_spec.rb +26 -0
  78. data/spec/fear/failure_spec.rb +57 -70
  79. data/spec/fear/for/mixin_spec.rb +15 -0
  80. data/spec/fear/for_spec.rb +19 -17
  81. data/spec/fear/future_spec.rb +477 -237
  82. data/spec/fear/guard_spec.rb +136 -24
  83. data/spec/fear/left_spec.rb +57 -70
  84. data/spec/fear/none_spec.rb +39 -43
  85. data/spec/fear/option/mixin_spec.rb +9 -7
  86. data/spec/fear/option_pattern_match_spec.rb +10 -8
  87. data/spec/fear/option_pattern_matching_spec.rb +34 -0
  88. data/spec/fear/option_spec.rb +142 -0
  89. data/spec/fear/partial_function/any_spec.rb +25 -0
  90. data/spec/fear/partial_function/empty_spec.rb +12 -10
  91. data/spec/fear/partial_function_and_then_spec.rb +39 -37
  92. data/spec/fear/partial_function_composition_spec.rb +46 -44
  93. data/spec/fear/partial_function_or_else_spec.rb +92 -90
  94. data/spec/fear/partial_function_spec.rb +91 -61
  95. data/spec/fear/pattern_match_spec.rb +19 -51
  96. data/spec/fear/pattern_matching_api_spec.rb +31 -0
  97. data/spec/fear/promise_spec.rb +23 -23
  98. data/spec/fear/right_biased/left.rb +28 -26
  99. data/spec/fear/right_biased/right.rb +51 -49
  100. data/spec/fear/right_spec.rb +48 -68
  101. data/spec/fear/some_spec.rb +30 -40
  102. data/spec/fear/success_spec.rb +40 -60
  103. data/spec/fear/try/mixin_spec.rb +19 -3
  104. data/spec/fear/try_api_spec.rb +23 -0
  105. data/spec/fear/try_pattern_match_spec.rb +10 -8
  106. data/spec/fear/try_pattern_matching_spec.rb +34 -0
  107. data/spec/fear/utils_spec.rb +16 -14
  108. data/spec/spec_helper.rb +13 -7
  109. data/spec/struct_pattern_matching_spec.rb +36 -0
  110. data/spec/struct_spec.rb +194 -0
  111. data/spec/support/dry_types.rb +6 -0
  112. metadata +128 -87
  113. data/.travis.yml +0 -13
  114. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -8
  115. data/lib/fear/extractor/any_matcher.rb +0 -15
  116. data/lib/fear/extractor/array_head_matcher.rb +0 -34
  117. data/lib/fear/extractor/array_matcher.rb +0 -38
  118. data/lib/fear/extractor/array_splat_matcher.rb +0 -14
  119. data/lib/fear/extractor/empty_list_matcher.rb +0 -18
  120. data/lib/fear/extractor/extractor_matcher.rb +0 -42
  121. data/lib/fear/extractor/grammar.rb +0 -201
  122. data/lib/fear/extractor/grammar.treetop +0 -129
  123. data/lib/fear/extractor/identifier_matcher.rb +0 -16
  124. data/lib/fear/extractor/matcher/and.rb +0 -36
  125. data/lib/fear/extractor/matcher.rb +0 -54
  126. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -15
  127. data/lib/fear/extractor/pattern.rb +0 -55
  128. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -24
  129. data/lib/fear/extractor/value_matcher.rb +0 -17
  130. data/lib/fear/extractor.rb +0 -108
  131. data/lib/fear/extractor_api.rb +0 -33
  132. data/spec/fear/extractor/array_matcher_spec.rb +0 -228
  133. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -151
  134. data/spec/fear/extractor/grammar_array_spec.rb +0 -23
  135. data/spec/fear/extractor/identified_matcher_spec.rb +0 -47
  136. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -66
  137. data/spec/fear/extractor/pattern_spec.rb +0 -32
  138. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -62
  139. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -77
  140. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -86
  141. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -69
  142. data/spec/fear/extractor_api_spec.rb +0 -113
  143. data/spec/fear/extractor_spec.rb +0 -59
@@ -1,66 +1,178 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.describe Fear::Future do
2
- let(:value) { 5 }
3
- let(:error) { StandardError.new('something went wrong') }
4
+ describe "#initialize" do
5
+ context "when promise and block are given at the same time" do
6
+ let(:promise) do
7
+ Concurrent::Promise.execute { 42 }
8
+ end
4
9
 
5
- def future(&block)
6
- described_class.new(executor: Concurrent::ImmediateExecutor.new, &block)
10
+ specify do
11
+ expect { described_class.new(promise) { 43 } }.to raise_error(ArgumentError, "pass block or promise")
12
+ end
13
+ end
7
14
  end
8
15
 
9
- context '#on_complete' do
10
- it 'run callback with value' do
16
+ context "#on_complete" do
17
+ it "run callback with value" do
11
18
  expect do |callback|
12
- future { value }.on_complete(&callback)
13
- end.to yield_with_args(Fear.success(value))
19
+ Fear::Future.successful(5).on_complete(&callback)
20
+ end.to yield_with_args(Fear.success(5))
14
21
  end
15
22
 
16
- it 'run callback with error' do
23
+ let(:error) { StandardError.new }
24
+
25
+ it "run callback with error" do
17
26
  expect do |callback|
18
- future { raise error }.on_complete(&callback)
27
+ Fear::Future.failed(error).on_complete(&callback)
19
28
  end.to yield_with_args(Fear.failure(error))
20
29
  end
21
30
  end
22
31
 
23
- context '#on_success' do
24
- it 'run callback if no error' do
25
- expect do |callback|
26
- future { value }.on_success(&callback)
27
- end.to yield_with_args(value)
32
+ context "#on_complete_match" do
33
+ context "successful covered" do
34
+ subject do
35
+ proc do |callback|
36
+ Fear::Future.successful(5).on_complete_match do |m|
37
+ m.success(&callback)
38
+ end
39
+ end
40
+ end
41
+
42
+ it { is_expected.to yield_with_args(5) }
28
43
  end
29
44
 
30
- it 'do not run callback if error occurred' do
31
- expect do |callback|
32
- future { raise error }.on_success(&callback)
33
- end.not_to yield_with_args
45
+ context "successful not covered" do
46
+ subject do
47
+ proc do |callback|
48
+ Fear::Future.successful(5).on_complete_match do |m|
49
+ m.failure(&callback)
50
+ end
51
+ end
52
+ end
53
+
54
+ it { is_expected.not_to yield_control }
34
55
  end
35
56
 
36
- specify 'call all registered callbacks' do
37
- expect do |second|
38
- expect do |first|
39
- future { value }
40
- .on_success(&first)
41
- .on_success(&second)
42
- end.to yield_with_args(value)
43
- end.to yield_with_args(value)
57
+ context "failed" do
58
+ subject do
59
+ proc do |callback|
60
+ Fear::Future.failed(error).on_complete_match do |m|
61
+ m.failure(&callback)
62
+ end
63
+ end
64
+ end
65
+ let(:error) { StandardError.new }
66
+
67
+ it { is_expected.to yield_with_args(error) }
68
+ end
69
+
70
+ context "failed not covered" do
71
+ subject do
72
+ proc do |callback|
73
+ Fear::Future.failed(error).on_complete_match do |m|
74
+ m.success(&callback)
75
+ end
76
+ end
77
+ end
78
+ let(:error) { StandardError.new }
79
+
80
+ it { is_expected.not_to yield_control }
81
+ end
82
+ end
83
+
84
+ shared_examples :on_success do |method_name|
85
+ context "##{method_name}" do
86
+ context "successful" do
87
+ subject do
88
+ proc do |callback|
89
+ Fear::Future.successful(5).__send__(method_name, &callback)
90
+ end
91
+ end
92
+
93
+ it { is_expected.to yield_with_args(5) }
94
+ end
95
+
96
+ context "failed" do
97
+ subject do
98
+ proc do |callback|
99
+ Fear::Future.failed(StandardError.new).__send__(method_name, &callback)
100
+ end
101
+ end
102
+
103
+ it { is_expected.not_to yield_control }
104
+ end
105
+
106
+ specify "call all registered callbacks" do
107
+ expect do |second|
108
+ expect do |first|
109
+ Fear::Future.successful(5)
110
+ .__send__(method_name, &first)
111
+ .__send__(method_name, &second)
112
+ end.to yield_with_args(5)
113
+ end.to yield_with_args(5)
114
+ end
44
115
  end
45
116
  end
46
117
 
47
- context '#on_failure' do
48
- it 'do not run callback if no error' do
118
+ include_examples :on_success, :on_success
119
+ include_examples :on_success, :each
120
+
121
+ context "#on_success_match" do
122
+ context "successful covered" do
123
+ subject do
124
+ proc do |callback|
125
+ Fear::Future.successful(5).on_success_match do |m|
126
+ m.case(5, &callback)
127
+ end
128
+ end
129
+ end
130
+
131
+ it { is_expected.to yield_with_args(5) }
132
+ end
133
+
134
+ context "successful not covered" do
135
+ subject do
136
+ proc do |callback|
137
+ Fear::Future.successful(5).on_success_match do |m|
138
+ m.case(0, &callback)
139
+ end
140
+ end
141
+ end
142
+
143
+ it { is_expected.not_to yield_control }
144
+ end
145
+
146
+ context "failed" do
147
+ subject do
148
+ proc do |callback|
149
+ Fear::Future.failed(StandardError.new).on_success_match(&callback)
150
+ end
151
+ end
152
+
153
+ it { is_expected.not_to yield_control }
154
+ end
155
+ end
156
+
157
+ context "#on_failure" do
158
+ let(:error) { StandardError.new }
159
+
160
+ it "do not run callback if no error" do
49
161
  expect do |callback|
50
- future { value }.on_failure(&callback)
162
+ Fear::Future.successful(5).on_failure(&callback)
51
163
  end.not_to yield_with_args
52
164
  end
53
165
 
54
- it 'run callback if error occurred' do
166
+ it "run callback if error occurred" do
55
167
  expect do |callback|
56
- future { raise error }.on_failure(&callback)
168
+ Fear::Future.failed(error).on_failure(&callback)
57
169
  end.to yield_with_args(error)
58
170
  end
59
171
 
60
- specify 'call all registered callbacks' do
172
+ specify "call all registered callbacks" do
61
173
  expect do |second|
62
174
  expect do |first|
63
- future { raise error }
175
+ Fear::Future.failed(error)
64
176
  .on_failure(&first)
65
177
  .on_failure(&second)
66
178
  end.to yield_with_args(error)
@@ -68,315 +180,384 @@ RSpec.describe Fear::Future do
68
180
  end
69
181
  end
70
182
 
71
- context '#completed?' do
72
- it 'completed with value' do
73
- completed_future = future { value }
74
-
75
- expect(completed_future).to be_completed
76
- end
77
-
78
- it 'completed with error' do
79
- completed_future = future { raise error }
183
+ context "#on_failure_match" do
184
+ context "failure covered" do
185
+ subject do
186
+ proc do |callback|
187
+ Fear::Future.failed(error).on_failure_match do |m|
188
+ m.case(StandardError, &callback)
189
+ end
190
+ end
191
+ end
192
+ let(:error) { StandardError.new }
80
193
 
81
- expect(completed_future).to be_completed
194
+ it { is_expected.to yield_with_args(error) }
82
195
  end
83
196
 
84
- it 'not completed with value' do
85
- not_completed_future =
86
- Fear.future do
87
- sleep 1
88
- value
197
+ context "failure not covered" do
198
+ subject do
199
+ proc do |callback|
200
+ Fear::Future.failed(error).on_failure_match do |m|
201
+ m.case(RuntimeError, &callback)
202
+ end
89
203
  end
204
+ end
205
+ let(:error) { StandardError.new }
90
206
 
91
- expect(not_completed_future).not_to be_completed
207
+ it { is_expected.not_to yield_control }
92
208
  end
93
209
 
94
- it 'not completed with error' do
95
- not_completed_future =
96
- Fear.future do
97
- sleep 1
98
- raise error
210
+ context "successful" do
211
+ subject do
212
+ proc do |callback|
213
+ Fear::Future.successful(5).on_failure_match(&callback)
99
214
  end
215
+ end
100
216
 
101
- expect(not_completed_future).not_to be_completed
217
+ it { is_expected.not_to yield_control }
102
218
  end
103
219
  end
104
220
 
105
- context '#value' do
106
- it 'None if not completed' do
107
- not_completed_future =
221
+ context "#completed?" do
222
+ context "not completed" do
223
+ subject do
108
224
  Fear.future do
109
- sleep 1
225
+ sleep 0.1
110
226
  value
111
227
  end
228
+ end
112
229
 
113
- future_value = not_completed_future.value
114
-
115
- expect(future_value).to eq(Fear.none)
230
+ it { is_expected.not_to be_completed }
116
231
  end
117
232
 
118
- it 'Some of Success if completed with result' do
119
- future_value = future { value }.value
233
+ context "completed with error" do
234
+ subject { Fear::Await.ready(Fear.future { raise StandardError }, 1) }
120
235
 
121
- expect(future_value).to eq Fear.some(Fear.success(value))
236
+ it { is_expected.to be_completed }
122
237
  end
123
238
 
124
- it 'Some of Failure if completed with error' do
125
- value = future { raise error }.value
239
+ context "completed with value" do
240
+ subject { Fear::Await.ready(Fear.future { 5 }, 0.5) }
126
241
 
127
- expect(value).to eq Fear.some(Fear.failure(error))
242
+ it { is_expected.to be_completed }
128
243
  end
129
244
  end
130
245
 
131
- context '#transform' do
132
- let(:failure) { ->(e) { e.message } }
133
- let(:success) { ->(v) { v * 2 } }
246
+ context "#value" do
247
+ subject { future.value }
134
248
 
135
- it 'call first callback if successful' do
136
- value = future { 2 }.transform(success, failure).value
249
+ context "future returns nil" do
250
+ let(:future) { Fear::Future.successful(nil) }
137
251
 
138
- expect(value).to eq Fear.some(Fear.success(4))
252
+ it { is_expected.to eq(Fear.some(Fear.success(nil))) }
139
253
  end
140
254
 
141
- it 'call second callback if failed' do
142
- value = future { raise error }.transform(success, failure).value
255
+ context "not completed" do
256
+ let(:future) do
257
+ Fear.future do
258
+ sleep 0.1
259
+ value
260
+ end
261
+ end
143
262
 
144
- expect(value).to eq Fear.some(Fear.failure('something went wrong'))
263
+ it { is_expected.to eq(Fear.none) }
145
264
  end
146
- end
147
265
 
148
- context '#map' do
149
- it 'successful result' do
150
- result = future { value }.map { |r| r * 2 }.value
266
+ context "completed with success" do
267
+ let(:future) { Fear::Future.successful(5) }
151
268
 
152
- expect(result).to eq Fear.some(Fear.success(10))
269
+ it { is_expected.to eq(Fear.some(Fear.success(5))) }
153
270
  end
154
271
 
155
- it 'failed result' do
156
- result = future { raise error }.map { |r| r * 2 }.value
272
+ context "completed with failure" do
273
+ let(:future) { Fear::Future.failed(error) }
274
+ let(:error) { StandardError.new }
157
275
 
158
- expect(result).to eq Fear.some(Fear.failure(error))
276
+ it { is_expected.to eq(Fear.some(Fear.failure(error))) }
159
277
  end
160
278
  end
161
279
 
162
- context '#flat_map' do
163
- it 'successful result' do
164
- result = future { value }.flat_map { |r| future { r * 2 } }.value
280
+ context "#transform" do
281
+ context "successful" do
282
+ subject { Fear::Await.result(future, 1) }
283
+
284
+ let(:future) { Fear.future { 2 }.transform(->(v) { v * 2 }, :itself.to_proc) }
165
285
 
166
- expect(result).to eq Fear.some(Fear.success(10))
286
+ it { is_expected.to eq(Fear.success(4)) }
167
287
  end
168
288
 
169
- it 'failed result' do
170
- result = future { raise error }.flat_map { |r| future { r * 2 } }.value
289
+ context "failed" do
290
+ subject { Fear::Await.result(future, 1) }
291
+
292
+ let(:future) { Fear.future { raise error }.transform(:itself.to_proc, :message.to_proc) }
293
+ let!(:error) { StandardError.new("fooo") }
171
294
 
172
- expect(result).to eq Fear.some(Fear.failure(error))
295
+ it { is_expected.to eq(Fear.failure("fooo")) }
173
296
  end
297
+ end
298
+
299
+ context "#map" do
300
+ subject { Fear::Await.result(future.map { |x| x * 2 }, 1) }
174
301
 
175
- it 'failed callback future' do
176
- result = future { value }.flat_map { future { raise error } }.value
302
+ context "successful" do
303
+ let(:future) { Fear.future { 5 } }
177
304
 
178
- expect(result).to eq Fear.some(Fear.failure(error))
305
+ it { is_expected.to eq(Fear.success(10)) }
179
306
  end
180
307
 
181
- it 'failured callback' do
182
- result = future { value }.flat_map { raise error }.value
308
+ context "failed" do
309
+ let(:future) { Fear.future { raise error } }
310
+ let!(:error) { StandardError.new("foo") }
183
311
 
184
- expect(result).to eq Fear.some(Fear.failure(error))
312
+ it { is_expected.to eq(Fear.failure(error)) }
185
313
  end
186
314
  end
187
315
 
188
- context '#each' do
189
- it 'successful result' do
190
- expect do |callback|
191
- future { value }.each(&callback)
192
- end.to yield_with_args(value)
193
- end
316
+ context "#flat_map" do
317
+ subject { Fear::Await.result(future, 1) }
194
318
 
195
- it 'failed result' do
196
- expect do |callback|
197
- future { raise error }.each(&callback)
198
- end.not_to yield_with_args
319
+ context "successful" do
320
+ let(:future) { Fear.future { 5 }.flat_map { |r| Fear.future { r * 2 } } }
321
+
322
+ it { is_expected.to eq(Fear.success(10)) }
199
323
  end
200
- end
201
324
 
202
- context '#select' do
203
- it 'satisfy predicate' do
204
- value = future { 2 }.select(&:even?).value
325
+ context "failed" do
326
+ let(:future) { Fear.future { raise error }.flat_map { |r| Fear.future { r * 2 } } }
327
+ let!(:error) { StandardError.new("foo") }
205
328
 
206
- expect(value).to eq Fear.some(Fear.success(2))
329
+ it { is_expected.to eq(Fear.failure(error)) }
207
330
  end
208
331
 
209
- it 'does not satisfy predicate' do
210
- value = future { 3 }.select(&:even?).value
332
+ context "failed callback future" do
333
+ let(:future) { Fear.future { 5 }.flat_map { Fear.future { raise error } } }
334
+ let!(:error) { StandardError.new("foo") }
211
335
 
212
- expect(value.get.exception).to be_kind_of(Fear::NoSuchElementError)
336
+ it { is_expected.to eq(Fear.failure(error)) }
213
337
  end
214
338
 
215
- it 'failure' do
216
- value = future { raise error }.select(&:even?).value
339
+ context "failed callback" do
340
+ let(:future) { Fear.future { 5 }.flat_map { raise error } }
341
+ let!(:error) { StandardError.new("foo") }
217
342
 
218
- expect(value.get.exception).to eq error
343
+ it { is_expected.to eq(Fear.failure(error)) }
219
344
  end
220
345
  end
221
346
 
222
- context '#recover' do
223
- it 'success' do
224
- value = future { 2 / 1 }.recover do |m|
225
- m.case { 0 }
226
- end.value
347
+ context "#select" do
348
+ context "successful and satisfies predicate" do
349
+ subject { Fear::Await.result(future, 1) }
350
+
351
+ let(:future) { Fear.future { 2 }.select(&:even?) }
227
352
 
228
- expect(value).to eq Fear.some(Fear.success(2))
353
+ it { is_expected.to eq(Fear.success(2)) }
229
354
  end
230
355
 
231
- it 'failure and error case covered by pattern match' do
232
- value = future { 2 / 0 }.recover do |m|
233
- m.case(RuntimeError, &:message)
234
- m.case(ZeroDivisionError) { 0 }
235
- end.value
356
+ context "successful and does not satisfy predicate" do
357
+ subject { Fear::Await.result(future, 1).exception }
358
+
359
+ let(:future) { Fear.future { 3 }.select(&:even?) }
236
360
 
237
- expect(value).to eq Fear.some(Fear.success(0))
361
+ it { is_expected.to be_kind_of(Fear::NoSuchElementError) }
238
362
  end
239
363
 
240
- it 'failure and error case not covered by pattern match' do
241
- value = future { 2 / 0 }.recover do |m|
242
- m.case(RuntimeError, &:message)
243
- end.value
364
+ context "failure" do
365
+ subject { Fear::Await.result(future, 1).exception }
244
366
 
245
- expect(value.get).to be_kind_of(Fear::Failure)
246
- expect(value.get.exception).to be_kind_of(ZeroDivisionError)
367
+ let(:future) { Fear.future { raise error }.select(&:even?) }
368
+ let!(:error) { StandardError.new }
369
+
370
+ it { is_expected.to eq(error) }
247
371
  end
248
372
  end
249
373
 
250
- context '#zip' do
251
- it 'success' do
252
- this = future { 1 }
253
- that = future { 2 }
374
+ context "#recover" do
375
+ subject { Fear::Await.result(future, 1) }
254
376
 
255
- value = this.zip(that).value
377
+ context "successful" do
378
+ let(:future) do
379
+ Fear.future { 2 }.recover do |m|
380
+ m.case { 0 }
381
+ end
382
+ end
256
383
 
257
- expect(value).to eq Fear.some(Fear.success([1, 2]))
384
+ it { is_expected.to eq(Fear.success(2)) }
258
385
  end
259
386
 
260
- it 'self fails' do
261
- this = future { raise error }
262
- that = future { 2 }
387
+ context "failure and managed to recover" do
388
+ let(:future) do
389
+ Fear.future { 2 / 0 }.recover do |m|
390
+ m.case(RuntimeError, &:message)
391
+ m.case(ZeroDivisionError) { Float::INFINITY }
392
+ end
393
+ end
263
394
 
264
- value = this.zip(that).value
395
+ it { is_expected.to eq(Fear.success(Float::INFINITY)) }
396
+ end
265
397
 
266
- expect(value).to eq Fear.some(Fear.failure(error))
398
+ context "failure and error case not covered by pattern match" do
399
+ let(:future) do
400
+ Fear.future { 2 / 0 }.recover do |m|
401
+ m.case(RuntimeError, &:message)
402
+ end
403
+ end
404
+
405
+ it { is_expected.to match(Fear.failure(be_kind_of(ZeroDivisionError))) }
267
406
  end
407
+ end
268
408
 
269
- it 'other fails' do
270
- this = future { 1 }
271
- that = future { raise error }
409
+ context "#zip" do
410
+ subject { Fear::Await.result(future, 1) }
272
411
 
273
- value = this.zip(that).value
412
+ context "successful" do
413
+ let!(:this) { Fear.future { 1 } }
414
+ let!(:that) { Fear.future { 2 } }
274
415
 
275
- expect(value).to eq Fear.some(Fear.failure(error))
416
+ context "without a block" do
417
+ let(:future) { this.zip(that) }
418
+
419
+ it { is_expected.to eq(Fear.success([1, 2])) }
420
+ end
421
+
422
+ context "with a block" do
423
+ let(:future) { this.zip(that) { |x, y| x + y } }
424
+
425
+ it { is_expected.to eq(Fear.success(3)) }
426
+ end
276
427
  end
277
428
 
278
- it 'both fail' do
279
- this = future { raise error }
280
- that = future { raise ArgumentError }
429
+ context "first failed" do
430
+ let(:future) { this.zip(that) }
431
+ let!(:error) { StandardError.new }
432
+ let!(:this) { Fear.future { raise error } }
433
+ let!(:that) { Fear.future { 2 } }
281
434
 
282
- value = this.zip(that).value
435
+ it { is_expected.to eq(Fear.failure(error)) }
436
+ end
283
437
 
284
- expect(value).to eq Fear.some(Fear.failure(error))
438
+ context "second failed" do
439
+ let(:future) { this.zip(that) }
440
+ let!(:error) { StandardError.new }
441
+ let!(:this) { Fear.future { 1 } }
442
+ let!(:that) { Fear.future { raise error } }
443
+
444
+ it { is_expected.to eq(Fear.failure(error)) }
285
445
  end
286
446
  end
287
447
 
288
- context '#fallback_to' do
289
- it 'success' do
290
- fallback = future { 42 }
291
- value = future { 2 }.fallback_to(fallback).value
448
+ context "#fallback_to" do
449
+ subject { Fear::Await.result(future, 1) }
450
+
451
+ context "successful" do
452
+ let(:future) { Fear.future { 2 }.fallback_to(fallback) }
453
+ let!(:fallback) { Fear.future { 42 } }
292
454
 
293
- expect(value).to eq Fear.some(Fear.success(2))
455
+ it { is_expected.to eq(Fear.success(2)) }
294
456
  end
295
457
 
296
- it 'failure' do
297
- fallback = future { 42 }
298
- value = future { raise error }.fallback_to(fallback).value
458
+ context "failed" do
459
+ let(:future) { Fear.future { raise error }.fallback_to(fallback) }
460
+ let!(:fallback) { Fear.future { 42 } }
461
+ let!(:error) { StandardError.new }
299
462
 
300
- expect(value).to eq Fear.some(Fear.success(42))
463
+ it { is_expected.to eq(Fear.success(42)) }
301
464
  end
302
465
 
303
- it 'failure with failed fallback' do
304
- fallback = future { raise ArumentError }
305
- value = future { raise error }.fallback_to(fallback).value
466
+ context "fallback failed" do
467
+ let(:future) { Fear.future { raise error }.fallback_to(fallback) }
468
+ let!(:fallback) { Fear.future { raise } }
469
+ let!(:error) { StandardError.new }
306
470
 
307
- expect(value).to eq Fear.some(Fear.failure(error))
471
+ it { is_expected.to eq(Fear.failure(error)) }
308
472
  end
309
473
  end
310
474
 
311
- context '#and_then' do
312
- context 'single callback' do
313
- context 'callback is called' do
314
- it 'returns result of future' do
475
+ context "#and_then" do
476
+ context "single callback" do
477
+ context "callback is called" do
478
+ it "calls callback" do
315
479
  expect do |callback|
316
- future { 5 }.and_then do |m|
480
+ Fear::Future.successful(5).and_then do |m|
317
481
  m.success(&callback)
318
482
  end
319
483
  end.to yield_with_args(5)
320
484
  end
321
485
  end
322
486
 
323
- context 'future with Success' do
324
- context 'callback is not failing' do
325
- it 'returns result of future' do
326
- value = future { 5 }.and_then {}.value
487
+ context "future with Success" do
488
+ subject { Fear::Await.result(future, 1) }
489
+
490
+ context "callback is not failing" do
491
+ let(:future) do
492
+ Fear.future { 5 }
493
+ .and_then { |m| m.success { |x| x * 2 } }
494
+ end
327
495
 
328
- expect(value).to eq Fear.some(Fear.success(5))
496
+ it "returns the same future" do
497
+ is_expected.to eq(Fear.success(5))
329
498
  end
330
499
  end
331
500
 
332
- context 'callback is failing' do
333
- it 'returns result of future' do
334
- value = future { 5 }.and_then { raise error }.value
501
+ context "callback is failing" do
502
+ let(:future) { Fear.future { 5 }.and_then { |m| m.success { raise "foo" } } }
335
503
 
336
- expect(value).to eq Fear.some(Fear.success(5))
337
- end
504
+ it { is_expected.to eq(Fear.success(5)) }
338
505
  end
339
506
  end
340
507
 
341
- context 'future with Failure' do
342
- it 'ensure callback is called' do
508
+ context "future with Failure" do
509
+ let(:error) { StandardError.new }
510
+
511
+ it "ensure callback is called" do
343
512
  expect do |callback|
344
- future { raise error }.and_then do |m|
513
+ Fear::Future.failed(error).and_then do |m|
345
514
  m.failure(&callback)
346
515
  end
347
516
  end.to yield_with_args(error)
348
517
  end
349
518
 
350
- context 'callback is not failing' do
351
- it 'returns result of future' do
352
- value = future { raise error }.and_then {}.value
519
+ context "callback is not failing" do
520
+ subject { Fear::Await.result(future, 1) }
353
521
 
354
- expect(value).to eq Fear.some(Fear.failure(error))
522
+ let(:future) { Fear.future { raise error }.and_then {} }
523
+ let!(:error) { StandardError.new }
524
+
525
+ it "returns result of future" do
526
+ is_expected.to eq(Fear.failure(error))
355
527
  end
356
528
  end
357
529
 
358
- context 'callback is failing' do
359
- it 'returns result of future' do
360
- value = future { raise error }.and_then { raise ArgumentError }.value
530
+ context "callback is failing" do
531
+ subject { Fear::Await.result(future, 1) }
532
+
533
+ let(:future) do
534
+ Fear.future { raise error }
535
+ .and_then { raise ArgumentError }
536
+ end
537
+ let!(:error) { StandardError.new }
361
538
 
362
- expect(value).to eq Fear.some(Fear.failure(error))
539
+ it "returns result of future" do
540
+ is_expected.to eq(Fear.failure(error))
363
541
  end
364
542
  end
365
543
  end
366
544
  end
367
545
 
368
- context 'multiple callbacks' do
369
- context 'on Future with Success' do
370
- it 'ensure callbacks are called' do
546
+ context "multiple callbacks" do
547
+ context "on Future with Success" do
548
+ it "ensure callbacks are called" do
371
549
  expect do |first|
372
550
  expect do |second|
373
- future { 5 }.and_then { |m| m.success(&first) }.and_then { |m| m.success(&second) }
551
+ future = Fear.future { 5 }
552
+ .and_then { |m| m.success(&first) }
553
+ .and_then { |m| m.success(&second) }
554
+
555
+ Fear::Await.ready(future, 2)
374
556
  end.to yield_with_args(5)
375
557
  end.to yield_with_args(5)
376
558
  end
377
559
 
378
- # rubocop: disable Style/MultilineBlockChain
379
- it 'ensure callbacks called in specified order' do
560
+ it "ensure callbacks called in specified order" do
380
561
  # REVIEW: could not write failing test
381
562
  last_called = nil
382
563
  Fear.future { 5 }.and_then do
@@ -385,7 +566,7 @@ RSpec.describe Fear::Future do
385
566
  last_called = :first
386
567
  end.and_then do
387
568
  expect(last_called).to(
388
- eq(:first), 'second callback called before first'
569
+ eq(:first), "second callback called before first"
389
570
  )
390
571
  last_called = :second
391
572
  end
@@ -394,73 +575,132 @@ RSpec.describe Fear::Future do
394
575
 
395
576
  expect(last_called).to eq(:second)
396
577
  end
397
- # rubocop: enable Style/MultilineBlockChain
398
578
 
399
- context 'first callback is not failing' do
400
- context 'and second callback is not failing' do
401
- it 'returns result of the Future' do
402
- value = future { 5 }.and_then {}.and_then {}.value
579
+ context "first callback is not failing" do
580
+ context "and second callback is not failing" do
581
+ subject { Fear::Await.result(future, 1) }
403
582
 
404
- expect(value).to eq Fear.some(Fear.success(5))
583
+ let(:future) do
584
+ Fear.future { 5 }
585
+ .and_then {}
586
+ .and_then {}
405
587
  end
588
+
589
+ it { is_expected.to eq(Fear.success(5)) }
406
590
  end
407
591
 
408
- context 'and second callback is failing' do
409
- it 'returns result of the Future' do
410
- value = future { 5 }.and_then {}.and_then do
411
- raise ArgumentError
412
- end.value
592
+ context "and second callback is failing" do
593
+ subject { Fear::Await.result(future, 1) }
413
594
 
414
- expect(value).to eq Fear.some(Fear.success(5))
595
+ let(:future) do
596
+ Fear.future { 5 }
597
+ .and_then {}
598
+ .and_then { raise }
415
599
  end
600
+
601
+ it { is_expected.to eq(Fear.success(5)) }
416
602
  end
417
603
  end
418
604
 
419
- context 'first callback is failing' do
420
- it 'calls second callback' do
605
+ context "first callback is failing" do
606
+ it "calls second callback" do
421
607
  expect do |callback|
422
- future { 5 }.and_then { raise error }.and_then { |m| m.success(&callback) }
608
+ future = Fear.future { 5 }.and_then { raise error }.and_then { |m| m.success(&callback) }
609
+ Fear::Await.ready(future, 2)
423
610
  end.to yield_with_args(5)
424
611
  end
425
612
 
426
- context 'and second callback is not failing' do
427
- it 'returns result of the Future' do
428
- value = future { 5 }.and_then { raise error }.and_then {}.value
613
+ context "and second callback is not failing" do
614
+ subject { Fear::Await.result(future, 1) }
429
615
 
430
- expect(value).to eq Fear.some(Fear.success(5))
616
+ let(:future) do
617
+ Fear.future { 5 }
618
+ .and_then { raise }
619
+ .and_then {}
431
620
  end
621
+
622
+ it { is_expected.to eq(Fear.success(5)) }
432
623
  end
433
624
 
434
- context 'and second callback is failing' do
435
- it 'returns result of the Future' do
436
- value = future { 5 }
437
- .and_then { raise error }
438
- .and_then { raise ArgumentError }
439
- .value
625
+ context "and second callback is failing" do
626
+ subject { Fear::Await.result(future, 1) }
440
627
 
441
- expect(value).to eq Fear.some(Fear.success(5))
628
+ let(:future) do
629
+ Fear.future { 5 }
630
+ .and_then { raise }
631
+ .and_then { raise ArgumentError }
442
632
  end
633
+
634
+ it { is_expected.to eq(Fear.success(5)) }
443
635
  end
444
636
  end
445
637
  end
446
638
  end
447
639
  end
448
640
 
449
- context '.successful' do
450
- it 'returns already succeed Future' do
451
- future = described_class.successful(value)
641
+ context ".successful" do
642
+ it "returns already succeed Future" do
643
+ future = described_class.successful(5)
452
644
 
453
645
  future_value = future.value
454
646
 
455
- expect(future_value).to eq Fear.some(Fear.success(value))
647
+ expect(future_value).to eq Fear.some(Fear.success(5))
456
648
  end
457
649
  end
458
650
 
459
- context '.failed' do
460
- it 'returns already failed Future' do
651
+ context ".failed" do
652
+ let(:error) { StandardError.new }
653
+
654
+ it "returns already failed Future" do
461
655
  value = described_class.failed(error).value
462
656
 
463
657
  expect(value).to eq Fear.some(Fear.failure(error))
464
658
  end
465
659
  end
660
+
661
+ describe Fear::Awaitable do
662
+ describe "#result" do
663
+ context "managed to complete within timeout" do
664
+ subject { Fear::Await.result(Fear.future { 5 }, 0.01) }
665
+
666
+ it { is_expected.to eq(Fear.success(5)) }
667
+ end
668
+
669
+ context "managed to complete within timeout with error" do
670
+ subject { Fear::Await.result(Fear.future { raise error }, 0.01) }
671
+
672
+ let!(:error) { StandardError.new }
673
+
674
+ it { is_expected.to eq(Fear.failure(error)) }
675
+ end
676
+
677
+ context "did not manage to complete within timeout" do
678
+ subject do
679
+ proc do
680
+ Fear::Await.result(Fear.future { sleep(1) }, 0.01)
681
+ end
682
+ end
683
+
684
+ it { is_expected.to raise_error(Timeout::Error) }
685
+ end
686
+ end
687
+
688
+ describe "#ready" do
689
+ context "managed to complete within timeout" do
690
+ subject { Fear::Await.ready(Fear.future { 5 }, 0.01).value }
691
+
692
+ it { is_expected.to eq(Fear.some(Fear.success(5))) }
693
+ end
694
+
695
+ context "did not manage to complete within timeout" do
696
+ subject do
697
+ proc do
698
+ Fear::Await.ready(Fear.future { sleep(1) }, 0.01)
699
+ end
700
+ end
701
+
702
+ it { is_expected.to raise_error(Timeout::Error) }
703
+ end
704
+ end
705
+ end
466
706
  end