mt-libuv 4.1.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.gitmodules +6 -0
- data/.rspec +1 -0
- data/.travis.yml +24 -0
- data/Gemfile +9 -0
- data/LICENSE +24 -0
- data/README.md +195 -0
- data/Rakefile +31 -0
- data/ext/README.md +6 -0
- data/ext/Rakefile +28 -0
- data/lib/mt-libuv/async.rb +51 -0
- data/lib/mt-libuv/check.rb +59 -0
- data/lib/mt-libuv/coroutines.rb +79 -0
- data/lib/mt-libuv/dns.rb +98 -0
- data/lib/mt-libuv/error.rb +88 -0
- data/lib/mt-libuv/ext/ext.rb +322 -0
- data/lib/mt-libuv/ext/platform/darwin_x64.rb +61 -0
- data/lib/mt-libuv/ext/platform/unix.rb +69 -0
- data/lib/mt-libuv/ext/platform/windows.rb +83 -0
- data/lib/mt-libuv/ext/tasks/mac.rb +24 -0
- data/lib/mt-libuv/ext/tasks/unix.rb +42 -0
- data/lib/mt-libuv/ext/tasks/win.rb +29 -0
- data/lib/mt-libuv/ext/tasks.rb +27 -0
- data/lib/mt-libuv/ext/types.rb +253 -0
- data/lib/mt-libuv/fiber_pool.rb +83 -0
- data/lib/mt-libuv/file.rb +309 -0
- data/lib/mt-libuv/filesystem.rb +263 -0
- data/lib/mt-libuv/fs_event.rb +37 -0
- data/lib/mt-libuv/handle.rb +108 -0
- data/lib/mt-libuv/idle.rb +59 -0
- data/lib/mt-libuv/mixins/accessors.rb +41 -0
- data/lib/mt-libuv/mixins/assertions.rb +25 -0
- data/lib/mt-libuv/mixins/fs_checks.rb +96 -0
- data/lib/mt-libuv/mixins/listener.rb +69 -0
- data/lib/mt-libuv/mixins/net.rb +42 -0
- data/lib/mt-libuv/mixins/resource.rb +30 -0
- data/lib/mt-libuv/mixins/stream.rb +276 -0
- data/lib/mt-libuv/pipe.rb +217 -0
- data/lib/mt-libuv/prepare.rb +59 -0
- data/lib/mt-libuv/q.rb +475 -0
- data/lib/mt-libuv/reactor.rb +567 -0
- data/lib/mt-libuv/signal.rb +62 -0
- data/lib/mt-libuv/spawn.rb +113 -0
- data/lib/mt-libuv/tcp.rb +465 -0
- data/lib/mt-libuv/timer.rb +107 -0
- data/lib/mt-libuv/tty.rb +42 -0
- data/lib/mt-libuv/udp.rb +302 -0
- data/lib/mt-libuv/version.rb +5 -0
- data/lib/mt-libuv/work.rb +86 -0
- data/lib/mt-libuv.rb +80 -0
- data/mt-libuv.gemspec +62 -0
- data/spec/async_spec.rb +67 -0
- data/spec/coroutines_spec.rb +121 -0
- data/spec/cpu_spec.rb +10 -0
- data/spec/defer_spec.rb +906 -0
- data/spec/dns_spec.rb +110 -0
- data/spec/dsl_spec.rb +43 -0
- data/spec/filesystem_spec.rb +270 -0
- data/spec/idle_spec.rb +44 -0
- data/spec/pipe_spec.rb +151 -0
- data/spec/spawn_spec.rb +119 -0
- data/spec/tcp_spec.rb +272 -0
- data/spec/test.sh +4 -0
- data/spec/test_fail.sh +3 -0
- data/spec/test_read.sh +3 -0
- data/spec/timer_spec.rb +14 -0
- data/spec/udp_spec.rb +73 -0
- data/spec/zen_spec.rb +34 -0
- metadata +196 -0
data/spec/defer_spec.rb
ADDED
@@ -0,0 +1,906 @@
|
|
1
|
+
require 'mt-libuv'
|
2
|
+
|
3
|
+
|
4
|
+
describe MTLibuv::Q do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@reactor = MTLibuv::Reactor.default
|
8
|
+
@reactor.notifier {}
|
9
|
+
@deferred = @reactor.defer
|
10
|
+
@promise = @deferred.promise
|
11
|
+
@log = []
|
12
|
+
@default_fail = proc { |reason|
|
13
|
+
@reactor.stop
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
after :each do
|
18
|
+
@reactor.notifier
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
describe 'resolve' do
|
23
|
+
|
24
|
+
|
25
|
+
it "should call the callback in the next turn" do
|
26
|
+
@reactor.run {
|
27
|
+
@promise.then nil, @default_fail do |result|
|
28
|
+
@log << result
|
29
|
+
end
|
30
|
+
|
31
|
+
@deferred.resolve(:foo)
|
32
|
+
}
|
33
|
+
|
34
|
+
expect(@log).to eq([:foo])
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
it "should be able to resolve the callback after it has already been resolved" do
|
40
|
+
@reactor.run {
|
41
|
+
@promise.then nil, @default_fail do |result|
|
42
|
+
@log << result
|
43
|
+
@promise.then nil, @default_fail do |result|
|
44
|
+
@log << result
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@deferred.resolve(:foo)
|
49
|
+
}
|
50
|
+
expect(@log).to eq([:foo, :foo])
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
it "should fulfill success callbacks in the registration order" do
|
56
|
+
@reactor.run {
|
57
|
+
@promise.then nil, @default_fail do |result|
|
58
|
+
@log << :first
|
59
|
+
end
|
60
|
+
|
61
|
+
@promise.then nil, @default_fail do |result|
|
62
|
+
@log << :second
|
63
|
+
end
|
64
|
+
|
65
|
+
@deferred.resolve(:foo)
|
66
|
+
}
|
67
|
+
expect(@log).to eq([:first, :second])
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
it "should do nothing if a promise was previously resolved" do
|
72
|
+
@reactor.run {
|
73
|
+
@promise.then nil, @default_fail do |result|
|
74
|
+
@log << result
|
75
|
+
expect(@log).to eq([:foo])
|
76
|
+
@deferred.resolve(:bar)
|
77
|
+
end
|
78
|
+
|
79
|
+
@deferred.resolve(:foo)
|
80
|
+
@deferred.reject(:baz)
|
81
|
+
}
|
82
|
+
expect(@log).to eq([:foo])
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
it "should allow deferred resolution with a new promise" do
|
87
|
+
deferred2 = @reactor.defer
|
88
|
+
@reactor.run {
|
89
|
+
@promise.then nil, @default_fail do |result|
|
90
|
+
@log << result
|
91
|
+
@reactor.stop
|
92
|
+
end
|
93
|
+
|
94
|
+
@deferred.resolve(deferred2.promise)
|
95
|
+
deferred2.resolve(:foo)
|
96
|
+
}
|
97
|
+
expect(@log).to eq([:foo])
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
it "should not break if a callbacks registers another callback" do
|
102
|
+
@reactor.run {
|
103
|
+
@promise.then nil, @default_fail do |result|
|
104
|
+
@log << :outer
|
105
|
+
@promise.then nil, @default_fail do |result|
|
106
|
+
@log << :inner
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
@deferred.resolve(:foo)
|
111
|
+
}
|
112
|
+
|
113
|
+
expect(@log).to eq([:outer, :inner])
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
it "can modify the result of a promise before returning" do
|
119
|
+
@reactor.run {
|
120
|
+
proc { |name|
|
121
|
+
@reactor.work { @deferred.resolve("Hello #{name}") }
|
122
|
+
@promise.then nil, @default_fail do |result|
|
123
|
+
@log << result
|
124
|
+
result += "?"
|
125
|
+
result
|
126
|
+
end
|
127
|
+
}.call('Robin Hood').then nil, @default_fail do |greeting|
|
128
|
+
@log << greeting
|
129
|
+
@reactor.stop
|
130
|
+
end
|
131
|
+
}
|
132
|
+
|
133
|
+
expect(@log).to eq(['Hello Robin Hood', 'Hello Robin Hood?'])
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
describe 'reject' do
|
140
|
+
|
141
|
+
it "should reject the promise and execute all error callbacks" do
|
142
|
+
@reactor.run {
|
143
|
+
@promise.then(@default_fail, proc {|result|
|
144
|
+
@log << :first
|
145
|
+
})
|
146
|
+
@promise.then(@default_fail, proc {|result|
|
147
|
+
@log << :second
|
148
|
+
})
|
149
|
+
|
150
|
+
@deferred.reject(:foo)
|
151
|
+
}
|
152
|
+
expect(@log).to eq([:first, :second])
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
it "should do nothing if a promise was previously rejected" do
|
157
|
+
@reactor.run {
|
158
|
+
@promise.then(@default_fail, proc {|result|
|
159
|
+
@log << result
|
160
|
+
@deferred.resolve(:bar)
|
161
|
+
})
|
162
|
+
|
163
|
+
@deferred.reject(:baz)
|
164
|
+
@deferred.resolve(:foo)
|
165
|
+
}
|
166
|
+
expect(@log).to eq([:baz])
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
it "should not defer rejection with a new promise" do
|
171
|
+
deferred2 = @reactor.defer
|
172
|
+
@reactor.run {
|
173
|
+
@promise.then(@default_fail, @default_fail)
|
174
|
+
begin
|
175
|
+
@deferred.reject(deferred2.promise)
|
176
|
+
rescue => e
|
177
|
+
@log << e.is_a?(ArgumentError)
|
178
|
+
@reactor.stop
|
179
|
+
end
|
180
|
+
}
|
181
|
+
|
182
|
+
expect(@log).to eq([true])
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
describe 'notify' do
|
189
|
+
it "should execute all progress callbacks in the registration order" do
|
190
|
+
@reactor.run {
|
191
|
+
@promise.progress do |update|
|
192
|
+
@log << :first
|
193
|
+
end
|
194
|
+
|
195
|
+
@promise.progress do |update|
|
196
|
+
@log << :second
|
197
|
+
end
|
198
|
+
|
199
|
+
@deferred.notify(:foo)
|
200
|
+
}
|
201
|
+
|
202
|
+
expect(@log).to eq([:first, :second])
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should do nothing if a promise was previously resolved" do
|
206
|
+
@reactor.run {
|
207
|
+
|
208
|
+
@promise.progress do |update|
|
209
|
+
@log << update
|
210
|
+
end
|
211
|
+
|
212
|
+
@deferred.resolve(:foo)
|
213
|
+
@deferred.notify(:baz)
|
214
|
+
}
|
215
|
+
|
216
|
+
expect(@log).to eq([])
|
217
|
+
end
|
218
|
+
|
219
|
+
it "should do nothing if a promise was previously rejected" do
|
220
|
+
@reactor.run {
|
221
|
+
|
222
|
+
@promise.progress do |update|
|
223
|
+
@log << update
|
224
|
+
end
|
225
|
+
@deferred.reject(:foo)
|
226
|
+
@deferred.notify(:baz)
|
227
|
+
}
|
228
|
+
|
229
|
+
expect(@log).to eq([])
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
it "should not apply any special treatment to promises passed to notify" do
|
234
|
+
@reactor.run {
|
235
|
+
deferred2 = @reactor.defer
|
236
|
+
|
237
|
+
@promise.progress do |update|
|
238
|
+
@log << update.is_a?(::MTLibuv::Q::Promise)
|
239
|
+
end
|
240
|
+
@deferred.notify(deferred2.promise)
|
241
|
+
}
|
242
|
+
|
243
|
+
expect(@log).to eq([true])
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
it "should call the progress callbacks in the next turn" do
|
248
|
+
@reactor.run {
|
249
|
+
@promise.progress do |update|
|
250
|
+
@log << :first
|
251
|
+
end
|
252
|
+
|
253
|
+
@promise.progress do |update|
|
254
|
+
@log << :second
|
255
|
+
end
|
256
|
+
|
257
|
+
@deferred.notify(:foo)
|
258
|
+
|
259
|
+
@log << @log.length # Has notify run in this tick
|
260
|
+
}
|
261
|
+
|
262
|
+
expect(@log).to eq([0, :first, :second])
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should ignore notifications sent out in the same turn before listener registration" do
|
266
|
+
@reactor.run {
|
267
|
+
@deferred.notify(:foo)
|
268
|
+
|
269
|
+
@promise.progress do |update|
|
270
|
+
@log << :first
|
271
|
+
end
|
272
|
+
|
273
|
+
@promise.progress do |update|
|
274
|
+
@log << :second
|
275
|
+
end
|
276
|
+
}
|
277
|
+
|
278
|
+
expect(@log).to eq([])
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
describe MTLibuv::Q::Promise do
|
284
|
+
|
285
|
+
describe 'then' do
|
286
|
+
|
287
|
+
it "should allow registration of a success callback without an errback and resolve" do
|
288
|
+
@reactor.run {
|
289
|
+
@promise.then do |result|
|
290
|
+
@log << result
|
291
|
+
end
|
292
|
+
|
293
|
+
@deferred.resolve(:foo)
|
294
|
+
}
|
295
|
+
|
296
|
+
expect(@log).to eq([:foo])
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
it "should allow registration of a success callback without an errback and reject" do
|
301
|
+
@reactor.run {
|
302
|
+
@promise.then do |result|
|
303
|
+
@log << result
|
304
|
+
end
|
305
|
+
|
306
|
+
@deferred.reject(:foo)
|
307
|
+
}
|
308
|
+
|
309
|
+
expect(@log).to eq([])
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
it "should allow registration of an errback without a success callback and reject" do
|
314
|
+
@reactor.run {
|
315
|
+
@promise.catch { |reason|
|
316
|
+
@log << reason
|
317
|
+
}
|
318
|
+
|
319
|
+
@deferred.reject(:foo)
|
320
|
+
}
|
321
|
+
|
322
|
+
expect(@log).to eq([:foo])
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
it "should allow registration of an errback without a success callback and resolve" do
|
327
|
+
@reactor.run {
|
328
|
+
@promise.catch { |reason|
|
329
|
+
@log << reason
|
330
|
+
}
|
331
|
+
|
332
|
+
@deferred.resolve(:foo)
|
333
|
+
}
|
334
|
+
|
335
|
+
expect(@log).to eq([])
|
336
|
+
end
|
337
|
+
|
338
|
+
|
339
|
+
it "should resolve all callbacks with the original value" do
|
340
|
+
@reactor.run {
|
341
|
+
@promise.then nil, @default_fail do |result|
|
342
|
+
@log << result
|
343
|
+
:alt1
|
344
|
+
end
|
345
|
+
@promise.then nil, @default_fail do |result|
|
346
|
+
@log << result
|
347
|
+
'ERROR'
|
348
|
+
end
|
349
|
+
@promise.then nil, @default_fail do |result|
|
350
|
+
@log << result
|
351
|
+
MTLibuv::Q.reject(@reactor, 'some reason')
|
352
|
+
end
|
353
|
+
@promise.then nil, @default_fail do |result|
|
354
|
+
@log << result
|
355
|
+
:alt2
|
356
|
+
end
|
357
|
+
|
358
|
+
@deferred.resolve(:foo)
|
359
|
+
}
|
360
|
+
|
361
|
+
expect(@log).to eq([:foo, :foo, :foo, :foo])
|
362
|
+
end
|
363
|
+
|
364
|
+
|
365
|
+
it "should notify all callbacks with the original value" do
|
366
|
+
@reactor.run { |reactor_promise|
|
367
|
+
@promise.progress do |result|
|
368
|
+
@log << result
|
369
|
+
:alt1
|
370
|
+
end
|
371
|
+
@promise.progress do |result|
|
372
|
+
@log << result
|
373
|
+
'ERROR'
|
374
|
+
end
|
375
|
+
@promise.progress do |result|
|
376
|
+
@log << result
|
377
|
+
MTLibuv::Q.reject(@reactor, 'some reason')
|
378
|
+
end
|
379
|
+
@promise.progress do |result|
|
380
|
+
@log << result
|
381
|
+
:alt2
|
382
|
+
end
|
383
|
+
|
384
|
+
|
385
|
+
@deferred.notify(:foo)
|
386
|
+
}
|
387
|
+
|
388
|
+
expect(@log).to eq([:foo, :foo, :foo, :foo])
|
389
|
+
end
|
390
|
+
|
391
|
+
|
392
|
+
it "should reject all callbacks with the original reason" do
|
393
|
+
@reactor.run {
|
394
|
+
@promise.then(@default_fail, proc {|result|
|
395
|
+
@log << result
|
396
|
+
:alt1
|
397
|
+
})
|
398
|
+
@promise.then(@default_fail, proc {|result|
|
399
|
+
@log << result
|
400
|
+
'ERROR'
|
401
|
+
})
|
402
|
+
@promise.then(@default_fail, proc {|result|
|
403
|
+
@log << result
|
404
|
+
MTLibuv::Q.reject(@reactor, 'some reason')
|
405
|
+
})
|
406
|
+
@promise.then(@default_fail, proc {|result|
|
407
|
+
@log << result
|
408
|
+
:alt2
|
409
|
+
})
|
410
|
+
|
411
|
+
@deferred.reject(:foo)
|
412
|
+
}
|
413
|
+
|
414
|
+
expect(@log).to eq([:foo, :foo, :foo, :foo])
|
415
|
+
end
|
416
|
+
|
417
|
+
|
418
|
+
it "should propagate resolution and rejection between dependent promises" do
|
419
|
+
@reactor.run {
|
420
|
+
@promise.then(proc { |result|
|
421
|
+
@log << result
|
422
|
+
:bar
|
423
|
+
}, @default_fail).then(proc { |result|
|
424
|
+
@log << result
|
425
|
+
raise 'baz'
|
426
|
+
}, @default_fail).then(@default_fail, proc {|result|
|
427
|
+
@log << result.message
|
428
|
+
raise 'bob'
|
429
|
+
}).then(@default_fail, proc {|result|
|
430
|
+
@log << result.message
|
431
|
+
:done
|
432
|
+
}).then(proc { |result|
|
433
|
+
@log << result
|
434
|
+
}, @default_fail)
|
435
|
+
|
436
|
+
@deferred.resolve(:foo)
|
437
|
+
}
|
438
|
+
|
439
|
+
expect(@log).to eq([:foo, :bar, 'baz', 'bob', :done])
|
440
|
+
end
|
441
|
+
|
442
|
+
|
443
|
+
it "should propagate notification between dependent promises" do
|
444
|
+
@reactor.run { |reactor|
|
445
|
+
reactor.notifier do |type, id, error|
|
446
|
+
@log << id
|
447
|
+
end
|
448
|
+
|
449
|
+
|
450
|
+
@promise.progress { |result|
|
451
|
+
@log << result
|
452
|
+
:bar
|
453
|
+
}.progress { |result|
|
454
|
+
@log << result
|
455
|
+
result
|
456
|
+
}.progress { |result|
|
457
|
+
@log << result
|
458
|
+
result
|
459
|
+
}.progress { |result|
|
460
|
+
@log << result
|
461
|
+
:done
|
462
|
+
}.progress { |result|
|
463
|
+
@log << result
|
464
|
+
result
|
465
|
+
}
|
466
|
+
|
467
|
+
|
468
|
+
@deferred.notify(:foo)
|
469
|
+
}
|
470
|
+
|
471
|
+
expect(@log).to eq([:foo, :bar, :bar, :bar, :done])
|
472
|
+
end
|
473
|
+
|
474
|
+
|
475
|
+
it "should stop notification propagation in case of error" do
|
476
|
+
@reactor.run { |reactor|
|
477
|
+
reactor.notifier do |error, context|
|
478
|
+
@log << context
|
479
|
+
end
|
480
|
+
|
481
|
+
|
482
|
+
@promise.progress { |result|
|
483
|
+
@log << result
|
484
|
+
:bar
|
485
|
+
}.progress { |result|
|
486
|
+
@log << result
|
487
|
+
raise 'err'
|
488
|
+
result
|
489
|
+
}.progress {|result|
|
490
|
+
@log << result
|
491
|
+
result
|
492
|
+
}.progress {|result|
|
493
|
+
@log << result
|
494
|
+
:done
|
495
|
+
}.progress { |result|
|
496
|
+
@log << result
|
497
|
+
result
|
498
|
+
}
|
499
|
+
|
500
|
+
|
501
|
+
@deferred.notify(:foo)
|
502
|
+
}
|
503
|
+
|
504
|
+
expect(@log).to eq([:foo, :bar, "performing promise progress callback"])
|
505
|
+
end
|
506
|
+
|
507
|
+
|
508
|
+
it "should call error callback in the next turn even if promise is already rejected" do
|
509
|
+
@reactor.run {
|
510
|
+
@deferred.reject(:foo)
|
511
|
+
|
512
|
+
@promise.catch { |reason|
|
513
|
+
@log << reason
|
514
|
+
}
|
515
|
+
|
516
|
+
@reactor.next_tick do
|
517
|
+
@reactor.stop
|
518
|
+
end
|
519
|
+
}
|
520
|
+
|
521
|
+
expect(@log).to eq([:foo])
|
522
|
+
end
|
523
|
+
|
524
|
+
|
525
|
+
end
|
526
|
+
|
527
|
+
|
528
|
+
describe 'finally' do
|
529
|
+
|
530
|
+
describe 'when the promise is fulfilled' do
|
531
|
+
|
532
|
+
it "should call the callback" do
|
533
|
+
@reactor.run {
|
534
|
+
@promise.finally do
|
535
|
+
@log << :finally
|
536
|
+
end
|
537
|
+
|
538
|
+
@deferred.resolve(:foo)
|
539
|
+
}
|
540
|
+
|
541
|
+
expect(@log).to eq([:finally])
|
542
|
+
end
|
543
|
+
|
544
|
+
it "should fulfill with the original value" do
|
545
|
+
@reactor.run {
|
546
|
+
@promise.finally {
|
547
|
+
@log << :finally
|
548
|
+
:finally
|
549
|
+
}.then do |result|
|
550
|
+
@log << result
|
551
|
+
end
|
552
|
+
|
553
|
+
|
554
|
+
@deferred.resolve(:foo)
|
555
|
+
}
|
556
|
+
|
557
|
+
expect(@log).to eq([:finally, :foo])
|
558
|
+
end
|
559
|
+
|
560
|
+
it "should fulfill with the original value (larger test)" do
|
561
|
+
@reactor.run {
|
562
|
+
@promise.then { |result|
|
563
|
+
@log << result
|
564
|
+
result
|
565
|
+
}.finally {
|
566
|
+
@log << :finally
|
567
|
+
:finally
|
568
|
+
}.then { |result|
|
569
|
+
@log << result
|
570
|
+
:change
|
571
|
+
}.then { |result|
|
572
|
+
@log << result
|
573
|
+
result
|
574
|
+
}.finally {
|
575
|
+
@log << :finally
|
576
|
+
:finally
|
577
|
+
}.then { |result|
|
578
|
+
@log << result
|
579
|
+
result
|
580
|
+
}
|
581
|
+
|
582
|
+
|
583
|
+
@deferred.resolve(:foo)
|
584
|
+
}
|
585
|
+
|
586
|
+
expect(@log).to eq([:foo, :finally, :foo, :change, :finally, :change])
|
587
|
+
end
|
588
|
+
|
589
|
+
describe "when the callback throws an exception" do
|
590
|
+
it "should reject with this new exception" do
|
591
|
+
@reactor.run {
|
592
|
+
@promise.finally {
|
593
|
+
@log << :finally
|
594
|
+
raise 'error'
|
595
|
+
}.catch do |reason|
|
596
|
+
@log.push reason.is_a?(Exception)
|
597
|
+
end
|
598
|
+
|
599
|
+
@deferred.resolve(:foo)
|
600
|
+
}
|
601
|
+
|
602
|
+
expect(@log).to eq([:finally, true])
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
describe "when the callback returns a promise" do
|
607
|
+
it "should fulfill with the original reason after that promise resolves" do
|
608
|
+
@reactor.run {
|
609
|
+
deferred2 = @reactor.defer
|
610
|
+
|
611
|
+
@promise.finally {
|
612
|
+
@log << :finally
|
613
|
+
deferred2.promise
|
614
|
+
}.then do |result|
|
615
|
+
@log << result
|
616
|
+
end
|
617
|
+
|
618
|
+
@deferred.resolve(:foo)
|
619
|
+
|
620
|
+
@reactor.next_tick do
|
621
|
+
@reactor.next_tick do
|
622
|
+
@reactor.next_tick do
|
623
|
+
@reactor.next_tick do
|
624
|
+
@log << :resolving
|
625
|
+
deferred2.resolve('working')
|
626
|
+
end
|
627
|
+
end
|
628
|
+
end
|
629
|
+
end
|
630
|
+
}
|
631
|
+
|
632
|
+
expect(@log).to eq([:finally, :resolving, :foo])
|
633
|
+
end
|
634
|
+
|
635
|
+
|
636
|
+
it "should reject with the new reason when it is rejected" do
|
637
|
+
@reactor.run {
|
638
|
+
deferred2 = @reactor.defer
|
639
|
+
|
640
|
+
@promise.finally {
|
641
|
+
@log << :finally
|
642
|
+
deferred2.promise
|
643
|
+
}.catch do |result|
|
644
|
+
@log << result
|
645
|
+
end
|
646
|
+
|
647
|
+
@deferred.resolve(:foo)
|
648
|
+
|
649
|
+
@reactor.next_tick do
|
650
|
+
@reactor.next_tick do
|
651
|
+
@reactor.next_tick do
|
652
|
+
@reactor.next_tick do
|
653
|
+
@log << :rejecting
|
654
|
+
deferred2.reject(:rejected)
|
655
|
+
end
|
656
|
+
end
|
657
|
+
end
|
658
|
+
end
|
659
|
+
}
|
660
|
+
|
661
|
+
expect(@log).to eq([:finally, :rejecting, :rejected])
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
end
|
666
|
+
|
667
|
+
end
|
668
|
+
|
669
|
+
|
670
|
+
describe 'value' do
|
671
|
+
it "should resolve a promise value as a future" do
|
672
|
+
@reactor.run {
|
673
|
+
@reactor.next_tick do
|
674
|
+
@deferred.resolve(:foo)
|
675
|
+
end
|
676
|
+
@log << @deferred.promise.value
|
677
|
+
}
|
678
|
+
|
679
|
+
expect(@log).to eq([:foo])
|
680
|
+
end
|
681
|
+
|
682
|
+
it "should reject a promise value as a future" do
|
683
|
+
@reactor.run {
|
684
|
+
@reactor.next_tick do
|
685
|
+
@deferred.reject(:foo)
|
686
|
+
end
|
687
|
+
|
688
|
+
begin
|
689
|
+
@deferred.promise.value
|
690
|
+
@log << 'should raise exception'
|
691
|
+
rescue => e
|
692
|
+
expect(e.class).to eq(CoroutineRejection)
|
693
|
+
@log << e.value
|
694
|
+
end
|
695
|
+
}
|
696
|
+
|
697
|
+
expect(@log).to eq([:foo])
|
698
|
+
end
|
699
|
+
|
700
|
+
it "should resolve a deferred value as a future" do
|
701
|
+
@reactor.run {
|
702
|
+
@reactor.next_tick do
|
703
|
+
@deferred.resolve(:foo)
|
704
|
+
end
|
705
|
+
@log << @deferred.value
|
706
|
+
}
|
707
|
+
|
708
|
+
expect(@log).to eq([:foo])
|
709
|
+
end
|
710
|
+
|
711
|
+
it "should reject a deferred value as a future" do
|
712
|
+
@reactor.run {
|
713
|
+
@reactor.next_tick do
|
714
|
+
@deferred.reject(:foo)
|
715
|
+
end
|
716
|
+
|
717
|
+
begin
|
718
|
+
@deferred.value
|
719
|
+
@log << 'should raise exception'
|
720
|
+
rescue => e
|
721
|
+
expect(e.class).to eq(CoroutineRejection)
|
722
|
+
@log << e.value
|
723
|
+
end
|
724
|
+
}
|
725
|
+
|
726
|
+
expect(@log).to eq([:foo])
|
727
|
+
end
|
728
|
+
|
729
|
+
it "should reject with message when rejection was a string" do
|
730
|
+
@reactor.run {
|
731
|
+
@reactor.next_tick do
|
732
|
+
@deferred.reject('foo')
|
733
|
+
end
|
734
|
+
|
735
|
+
begin
|
736
|
+
@deferred.value
|
737
|
+
@log << 'should raise exception'
|
738
|
+
rescue => e
|
739
|
+
expect(e.class).to eq(CoroutineRejection)
|
740
|
+
@log << e.message
|
741
|
+
@log << e.value
|
742
|
+
end
|
743
|
+
}
|
744
|
+
|
745
|
+
expect(@log).to eq(['foo', 'foo'])
|
746
|
+
end
|
747
|
+
|
748
|
+
it "should pass through exceptions without modification" do
|
749
|
+
@reactor.run {
|
750
|
+
@reactor.next_tick do
|
751
|
+
@deferred.reject(RuntimeError.new('fail'))
|
752
|
+
end
|
753
|
+
|
754
|
+
begin
|
755
|
+
@deferred.value
|
756
|
+
@log << 'should raise exception'
|
757
|
+
rescue => e
|
758
|
+
expect(e.class).to eq(RuntimeError)
|
759
|
+
@log << e.message
|
760
|
+
end
|
761
|
+
}
|
762
|
+
|
763
|
+
expect(@log).to eq(['fail'])
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
767
|
+
end
|
768
|
+
|
769
|
+
|
770
|
+
|
771
|
+
describe 'reject' do
|
772
|
+
|
773
|
+
it "should package a string into a rejected promise" do
|
774
|
+
@reactor.run {
|
775
|
+
rejectedPromise = MTLibuv::Q.reject(@reactor, 'not gonna happen')
|
776
|
+
|
777
|
+
@promise.then(@default_fail, proc {|reason|
|
778
|
+
@log << reason
|
779
|
+
})
|
780
|
+
|
781
|
+
@deferred.resolve(rejectedPromise)
|
782
|
+
}
|
783
|
+
|
784
|
+
expect(@log).to eq(['not gonna happen'])
|
785
|
+
end
|
786
|
+
|
787
|
+
|
788
|
+
it "should return a promise that forwards callbacks if the callbacks are missing" do
|
789
|
+
@reactor.run {
|
790
|
+
rejectedPromise = MTLibuv::Q.reject(@reactor, 'not gonna happen')
|
791
|
+
|
792
|
+
@promise.then(@default_fail, proc {|reason|
|
793
|
+
@log << reason
|
794
|
+
})
|
795
|
+
|
796
|
+
@deferred.resolve(rejectedPromise.then())
|
797
|
+
}
|
798
|
+
|
799
|
+
expect(@log).to eq(['not gonna happen'])
|
800
|
+
end
|
801
|
+
|
802
|
+
end
|
803
|
+
|
804
|
+
|
805
|
+
|
806
|
+
describe 'all' do
|
807
|
+
|
808
|
+
it "should resolve all of nothing" do
|
809
|
+
@reactor.run {
|
810
|
+
MTLibuv::Q.all(@reactor).then nil, @default_fail do |result|
|
811
|
+
@log << result
|
812
|
+
end
|
813
|
+
}
|
814
|
+
|
815
|
+
expect(@log).to eq([[]])
|
816
|
+
end
|
817
|
+
|
818
|
+
it "should take an array of promises and return a promise for an array of results" do
|
819
|
+
@reactor.run {
|
820
|
+
deferred1 = @reactor.defer
|
821
|
+
deferred2 = @reactor.defer
|
822
|
+
|
823
|
+
MTLibuv::Q.all(@reactor, @promise, deferred1.promise, deferred2.promise).then nil, @default_fail do |result|
|
824
|
+
@log = result
|
825
|
+
end
|
826
|
+
|
827
|
+
@reactor.work { @deferred.resolve(:foo) }
|
828
|
+
@reactor.work { deferred2.resolve(:baz) }
|
829
|
+
@reactor.work { deferred1.resolve(:bar) }
|
830
|
+
}
|
831
|
+
|
832
|
+
expect(@log).to eq([:foo, :bar, :baz])
|
833
|
+
end
|
834
|
+
|
835
|
+
|
836
|
+
it "should reject the derived promise if at least one of the promises in the array is rejected" do
|
837
|
+
@reactor.run {
|
838
|
+
deferred1 = @reactor.defer
|
839
|
+
deferred2 = @reactor.defer
|
840
|
+
|
841
|
+
MTLibuv::Q.all(@reactor, @promise, deferred1.promise, deferred2.promise).then(@default_fail, proc {|reason|
|
842
|
+
@log << reason
|
843
|
+
})
|
844
|
+
|
845
|
+
@reactor.work { @deferred.resolve(:foo) }
|
846
|
+
@reactor.work { deferred2.reject(:baz) }
|
847
|
+
}
|
848
|
+
|
849
|
+
expect(@log).to eq([:baz])
|
850
|
+
end
|
851
|
+
|
852
|
+
end
|
853
|
+
|
854
|
+
describe 'any' do
|
855
|
+
|
856
|
+
it "should resolve any of nothing" do
|
857
|
+
@reactor.run {
|
858
|
+
MTLibuv::Q.any(@reactor).then nil, @default_fail do |result|
|
859
|
+
@log = result
|
860
|
+
end
|
861
|
+
}
|
862
|
+
|
863
|
+
expect(@log).to eq(true)
|
864
|
+
end
|
865
|
+
|
866
|
+
it "should take an array of promises and return the first to succeed" do
|
867
|
+
@reactor.run {
|
868
|
+
deferred1 = @reactor.defer
|
869
|
+
deferred2 = @reactor.defer
|
870
|
+
|
871
|
+
MTLibuv::Q.any(@reactor, @promise, deferred1.promise, deferred2.promise).then nil, @default_fail do |result|
|
872
|
+
@log = result
|
873
|
+
end
|
874
|
+
|
875
|
+
@reactor.work {
|
876
|
+
@deferred.resolve(:foo)
|
877
|
+
deferred2.resolve(:baz)
|
878
|
+
deferred1.resolve(:bar)
|
879
|
+
}
|
880
|
+
}
|
881
|
+
|
882
|
+
expect(@log).to eq(:foo)
|
883
|
+
end
|
884
|
+
|
885
|
+
|
886
|
+
it "should take an array of promises and return the first to fail" do
|
887
|
+
@reactor.run {
|
888
|
+
deferred1 = @reactor.defer
|
889
|
+
deferred2 = @reactor.defer
|
890
|
+
|
891
|
+
MTLibuv::Q.any(@reactor, @promise, deferred1.promise, deferred2.promise).then(@default_fail, proc { |result|
|
892
|
+
@log = result
|
893
|
+
})
|
894
|
+
|
895
|
+
@reactor.work {
|
896
|
+
@deferred.reject(:foo)
|
897
|
+
deferred2.resolve(:baz)
|
898
|
+
}
|
899
|
+
}
|
900
|
+
|
901
|
+
expect(@log).to eq(:foo)
|
902
|
+
end
|
903
|
+
|
904
|
+
end
|
905
|
+
|
906
|
+
end
|