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.
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