mt-libuv 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.gitmodules +6 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +24 -0
  6. data/Gemfile +9 -0
  7. data/LICENSE +24 -0
  8. data/README.md +195 -0
  9. data/Rakefile +31 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +28 -0
  12. data/lib/mt-libuv/async.rb +51 -0
  13. data/lib/mt-libuv/check.rb +59 -0
  14. data/lib/mt-libuv/coroutines.rb +79 -0
  15. data/lib/mt-libuv/dns.rb +98 -0
  16. data/lib/mt-libuv/error.rb +88 -0
  17. data/lib/mt-libuv/ext/ext.rb +322 -0
  18. data/lib/mt-libuv/ext/platform/darwin_x64.rb +61 -0
  19. data/lib/mt-libuv/ext/platform/unix.rb +69 -0
  20. data/lib/mt-libuv/ext/platform/windows.rb +83 -0
  21. data/lib/mt-libuv/ext/tasks/mac.rb +24 -0
  22. data/lib/mt-libuv/ext/tasks/unix.rb +42 -0
  23. data/lib/mt-libuv/ext/tasks/win.rb +29 -0
  24. data/lib/mt-libuv/ext/tasks.rb +27 -0
  25. data/lib/mt-libuv/ext/types.rb +253 -0
  26. data/lib/mt-libuv/fiber_pool.rb +83 -0
  27. data/lib/mt-libuv/file.rb +309 -0
  28. data/lib/mt-libuv/filesystem.rb +263 -0
  29. data/lib/mt-libuv/fs_event.rb +37 -0
  30. data/lib/mt-libuv/handle.rb +108 -0
  31. data/lib/mt-libuv/idle.rb +59 -0
  32. data/lib/mt-libuv/mixins/accessors.rb +41 -0
  33. data/lib/mt-libuv/mixins/assertions.rb +25 -0
  34. data/lib/mt-libuv/mixins/fs_checks.rb +96 -0
  35. data/lib/mt-libuv/mixins/listener.rb +69 -0
  36. data/lib/mt-libuv/mixins/net.rb +42 -0
  37. data/lib/mt-libuv/mixins/resource.rb +30 -0
  38. data/lib/mt-libuv/mixins/stream.rb +276 -0
  39. data/lib/mt-libuv/pipe.rb +217 -0
  40. data/lib/mt-libuv/prepare.rb +59 -0
  41. data/lib/mt-libuv/q.rb +475 -0
  42. data/lib/mt-libuv/reactor.rb +567 -0
  43. data/lib/mt-libuv/signal.rb +62 -0
  44. data/lib/mt-libuv/spawn.rb +113 -0
  45. data/lib/mt-libuv/tcp.rb +465 -0
  46. data/lib/mt-libuv/timer.rb +107 -0
  47. data/lib/mt-libuv/tty.rb +42 -0
  48. data/lib/mt-libuv/udp.rb +302 -0
  49. data/lib/mt-libuv/version.rb +5 -0
  50. data/lib/mt-libuv/work.rb +86 -0
  51. data/lib/mt-libuv.rb +80 -0
  52. data/mt-libuv.gemspec +62 -0
  53. data/spec/async_spec.rb +67 -0
  54. data/spec/coroutines_spec.rb +121 -0
  55. data/spec/cpu_spec.rb +10 -0
  56. data/spec/defer_spec.rb +906 -0
  57. data/spec/dns_spec.rb +110 -0
  58. data/spec/dsl_spec.rb +43 -0
  59. data/spec/filesystem_spec.rb +270 -0
  60. data/spec/idle_spec.rb +44 -0
  61. data/spec/pipe_spec.rb +151 -0
  62. data/spec/spawn_spec.rb +119 -0
  63. data/spec/tcp_spec.rb +272 -0
  64. data/spec/test.sh +4 -0
  65. data/spec/test_fail.sh +3 -0
  66. data/spec/test_read.sh +3 -0
  67. data/spec/timer_spec.rb +14 -0
  68. data/spec/udp_spec.rb +73 -0
  69. data/spec/zen_spec.rb +34 -0
  70. metadata +196 -0
@@ -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