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