spec/defer_spec.rb in libuv-2.0.12 vs spec/defer_spec.rb in libuv-3.0.0
- old
+ new
@@ -2,161 +2,128 @@
describe Libuv::Q do
before :each do
- @loop = Libuv::Loop.default
- @deferred = @loop.defer
+ @reactor = Libuv::Reactor.default
+ @deferred = @reactor.defer
@promise = @deferred.promise
@log = []
@default_fail = proc { |reason|
- @loop.stop
+ @reactor.stop
}
end
describe 'resolve' do
it "should call the callback in the next turn" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << result
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:foo])
end
it "should be able to resolve the callback after it has already been resolved" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << result
@promise.then nil, @default_fail do |result|
@log << result
end
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
}
expect(@log).to eq([:foo, :foo])
end
it "should fulfill success callbacks in the registration order" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << :first
end
@promise.then nil, @default_fail do |result|
@log << :second
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:first, :second])
end
it "should do nothing if a promise was previously resolved" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << result
expect(@log).to eq([:foo])
@deferred.resolve(:bar)
end
@deferred.resolve(:foo)
@deferred.reject(:baz)
-
- #
- # 4 ticks should detect any errors
- #
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
}
expect(@log).to eq([:foo])
end
it "should allow deferred resolution with a new promise" do
- deferred2 = @loop.defer
- @loop.run {
+ deferred2 = @reactor.defer
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << result
- @loop.stop
+ @reactor.stop
end
@deferred.resolve(deferred2.promise)
deferred2.resolve(:foo)
}
expect(@log).to eq([:foo])
end
it "should not break if a callbacks registers another callback" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << :outer
@promise.then nil, @default_fail do |result|
@log << :inner
end
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
}
expect(@log).to eq([:outer, :inner])
end
it "can modify the result of a promise before returning" do
- @loop.run {
+ @reactor.run {
proc { |name|
- @loop.work { @deferred.resolve("Hello #{name}") }
+ @reactor.work { @deferred.resolve("Hello #{name}") }
@promise.then nil, @default_fail do |result|
@log << result
result += "?"
result
end
}.call('Robin Hood').then nil, @default_fail do |greeting|
@log << greeting
- @loop.stop
+ @reactor.stop
end
}
expect(@log).to eq(['Hello Robin Hood', 'Hello Robin Hood?'])
end
@@ -165,64 +132,47 @@
describe 'reject' do
it "should reject the promise and execute all error callbacks" do
- @loop.run {
+ @reactor.run {
@promise.then(@default_fail, proc {|result|
@log << :first
})
@promise.then(@default_fail, proc {|result|
@log << :second
})
@deferred.reject(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:first, :second])
end
it "should do nothing if a promise was previously rejected" do
- @loop.run {
+ @reactor.run {
@promise.then(@default_fail, proc {|result|
@log << result
@deferred.resolve(:bar)
})
@deferred.reject(:baz)
@deferred.resolve(:foo)
-
- #
- # 4 ticks should detect any errors
- #
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
}
expect(@log).to eq([:baz])
end
it "should not defer rejection with a new promise" do
- deferred2 = @loop.defer
- @loop.run {
+ deferred2 = @reactor.defer
+ @reactor.run {
@promise.then(@default_fail, @default_fail)
begin
@deferred.reject(deferred2.promise)
rescue => e
@log << e.is_a?(ArgumentError)
- @loop.stop
+ @reactor.stop
end
}
expect(@log).to eq([true])
end
@@ -230,106 +180,69 @@
end
describe 'notify' do
it "should execute all progress callbacks in the registration order" do
- @loop.run {
+ @reactor.run {
@promise.progress do |update|
@log << :first
end
@promise.progress do |update|
@log << :second
end
@deferred.notify(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:first, :second])
end
it "should do nothing if a promise was previously resolved" do
- @loop.run {
+ @reactor.run {
@promise.progress do |update|
@log << update
end
@deferred.resolve(:foo)
@deferred.notify(:baz)
-
-
- #
- # 4 ticks should detect any errors
- #
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
}
expect(@log).to eq([])
end
it "should do nothing if a promise was previously rejected" do
- @loop.run {
+ @reactor.run {
@promise.progress do |update|
@log << update
end
@deferred.reject(:foo)
@deferred.notify(:baz)
-
-
-
- #
- # 4 ticks should detect any errors
- #
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
}
expect(@log).to eq([])
end
it "should not apply any special treatment to promises passed to notify" do
- @loop.run {
- deferred2 = @loop.defer
+ @reactor.run {
+ deferred2 = @reactor.defer
@promise.progress do |update|
@log << update.is_a?(::Libuv::Q::Promise)
end
@deferred.notify(deferred2.promise)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([true])
end
it "should call the progress callbacks in the next turn" do
- @loop.run {
+ @reactor.run {
@promise.progress do |update|
@log << :first
end
@promise.progress do |update|
@@ -337,211 +250,170 @@
end
@deferred.notify(:foo)
@log << @log.length # Has notify run in this tick
- @loop.stop # Stop will run through the next tick before stopping
}
expect(@log).to eq([0, :first, :second])
end
it "should ignore notifications sent out in the same turn before listener registration" do
- @loop.run {
+ @reactor.run {
@deferred.notify(:foo)
@promise.progress do |update|
@log << :first
end
@promise.progress do |update|
@log << :second
end
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([])
end
end
describe Libuv::Q::Promise do
-
+
describe 'then' do
it "should allow registration of a success callback without an errback and resolve" do
- @loop.run {
+ @reactor.run {
@promise.then do |result|
@log << result
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:foo])
end
it "should allow registration of a success callback without an errback and reject" do
- @loop.run {
+ @reactor.run {
@promise.then do |result|
@log << result
end
@deferred.reject(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([])
end
it "should allow registration of an errback without a success callback and reject" do
- @loop.run {
+ @reactor.run {
@promise.catch(proc {|reason|
@log << reason
})
@deferred.reject(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:foo])
end
it "should allow registration of an errback without a success callback and resolve" do
- @loop.run {
+ @reactor.run {
@promise.catch(proc {|reason|
@log << reason
})
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([])
end
it "should resolve all callbacks with the original value" do
- @loop.run {
+ @reactor.run {
@promise.then nil, @default_fail do |result|
@log << result
:alt1
end
@promise.then nil, @default_fail do |result|
@log << result
'ERROR'
end
@promise.then nil, @default_fail do |result|
@log << result
- Libuv::Q.reject(@loop, 'some reason')
+ Libuv::Q.reject(@reactor, 'some reason')
end
@promise.then nil, @default_fail do |result|
@log << result
:alt2
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:foo, :foo, :foo, :foo])
end
it "should notify all callbacks with the original value" do
- @loop.run { |loop_promise|
+ @reactor.run { |reactor_promise|
@promise.progress do |result|
@log << result
:alt1
end
@promise.progress do |result|
@log << result
'ERROR'
end
@promise.progress do |result|
@log << result
- Libuv::Q.reject(@loop, 'some reason')
+ Libuv::Q.reject(@reactor, 'some reason')
end
@promise.progress do |result|
@log << result
:alt2
end
@deferred.notify(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
- end
}
expect(@log).to eq([:foo, :foo, :foo, :foo])
end
it "should reject all callbacks with the original reason" do
- @loop.run {
+ @reactor.run {
@promise.then(@default_fail, proc {|result|
@log << result
:alt1
})
@promise.then(@default_fail, proc {|result|
@log << result
'ERROR'
})
@promise.then(@default_fail, proc {|result|
@log << result
- Libuv::Q.reject(@loop, 'some reason')
+ Libuv::Q.reject(@reactor, 'some reason')
})
@promise.then(@default_fail, proc {|result|
@log << result
:alt2
})
@deferred.reject(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:foo, :foo, :foo, :foo])
end
it "should propagate resolution and rejection between dependent promises" do
- @loop.run {
+ @reactor.run {
@promise.then(proc { |result|
@log << result
:bar
}, @default_fail).then(proc { |result|
@log << result
@@ -555,33 +427,19 @@
}).then(proc { |result|
@log << result
}, @default_fail)
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do # extra tick?
- @loop.stop
- end
- end
- end
- end
- end
- end
}
expect(@log).to eq([:foo, :bar, 'baz', 'bob', :done])
end
it "should propagate notification between dependent promises" do
- @loop.run { |loop_promise|
- loop_promise.progress do |type, id, error|
+ @reactor.run { |reactor|
+ reactor.notifier do |type, id, error|
@log << id
end
@promise.progress(proc { |result|
@@ -601,34 +459,20 @@
result
})
@deferred.notify(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do # extra tick?
- @loop.stop
- end
- end
- end
- end
- end
- end
}
expect(@log).to eq([:foo, :bar, :bar, :bar, :done])
end
it "should stop notification propagation in case of error" do
- @loop.run { |loop_logger|
- loop_logger.progress do |type, id, error|
- @log << id
+ @reactor.run { |reactor|
+ reactor.notifier do |error, context|
+ @log << context
end
@promise.progress(proc { |result|
@log << result
@@ -648,38 +492,26 @@
result
})
@deferred.notify(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
- end
}
- expect(@log).to eq([:foo, :bar, :q_progress_cb])
+ expect(@log).to eq([:foo, :bar, "performing promise progress callback"])
end
it "should call error callback in the next turn even if promise is already rejected" do
- @loop.run {
+ @reactor.run {
@deferred.reject(:foo)
@promise.catch(proc {|reason|
@log << reason
})
- @loop.next_tick do
- @loop.stop
+ @reactor.next_tick do
+ @reactor.stop
end
}
expect(@log).to eq([:foo])
end
@@ -691,49 +523,39 @@
describe 'finally' do
describe 'when the promise is fulfilled' do
it "should call the callback" do
- @loop.run {
+ @reactor.run {
@promise.finally do
@log << :finally
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([:finally])
end
it "should fulfill with the original value" do
- @loop.run {
+ @reactor.run {
@promise.finally(proc {
@log << :finally
:finally
}).then do |result|
@log << result
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
}
expect(@log).to eq([:finally, :foo])
end
it "should fulfill with the original value (larger test)" do
- @loop.run {
+ @reactor.run {
@promise.then(proc { |result|
@log << result
result
}).finally(proc {
@log << :finally
@@ -752,82 +574,52 @@
result
})
@deferred.resolve(:foo)
-
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
- end
- end
- end
- end
- end
- end
}
expect(@log).to eq([:foo, :finally, :foo, :change, :finally, :change])
end
describe "when the callback throws an exception" do
it "should reject with this new exception" do
- @loop.run {
+ @reactor.run {
@promise.finally(proc {
@log << :finally
raise 'error'
}).catch do |reason|
@log.push reason.is_a?(Exception)
end
@deferred.resolve(:foo)
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
}
expect(@log).to eq([:finally, true])
end
end
describe "when the callback returns a promise" do
it "should fulfill with the original reason after that promise resolves" do
- @loop.run {
- deferred2 = @loop.defer
+ @reactor.run {
+ deferred2 = @reactor.defer
@promise.finally(proc {
@log << :finally
deferred2.promise
}).then do |result|
@log << result
end
@deferred.resolve(:foo)
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
@log << :resolving
deferred2.resolve('working')
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
end
end
end
end
}
@@ -835,33 +627,28 @@
expect(@log).to eq([:finally, :resolving, :foo])
end
it "should reject with the new reason when it is rejected" do
- @loop.run {
- deferred2 = @loop.defer
+ @reactor.run {
+ deferred2 = @reactor.defer
@promise.finally(proc {
@log << :finally
deferred2.promise
}).catch do |result|
@log << result
end
@deferred.resolve(:foo)
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
- @loop.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
+ @reactor.next_tick do
@log << :rejecting
deferred2.reject(:rejected)
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
end
end
end
end
}
@@ -871,51 +658,139 @@
end
end
end
+
+
+ describe 'value' do
+ it "should resolve a promise value as a future" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.resolve(:foo)
+ end
+ @log << @deferred.promise.value
+ }
+
+ expect(@log).to eq([:foo])
+ end
+
+ it "should reject a promise value as a future" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.reject(:foo)
+ end
+
+ begin
+ @deferred.promise.value
+ @log << 'should raise exception'
+ rescue => e
+ expect(e.class).to eq(CoroutineRejection)
+ @log << e.value
+ end
+ }
+
+ expect(@log).to eq([:foo])
+ end
+
+ it "should resolve a deferred value as a future" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.resolve(:foo)
+ end
+ @log << @deferred.value
+ }
+
+ expect(@log).to eq([:foo])
+ end
+
+ it "should reject a deferred value as a future" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.reject(:foo)
+ end
+
+ begin
+ @deferred.value
+ @log << 'should raise exception'
+ rescue => e
+ expect(e.class).to eq(CoroutineRejection)
+ @log << e.value
+ end
+ }
+
+ expect(@log).to eq([:foo])
+ end
+
+ it "should reject with message when rejection was a string" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.reject('foo')
+ end
+
+ begin
+ @deferred.value
+ @log << 'should raise exception'
+ rescue => e
+ expect(e.class).to eq(CoroutineRejection)
+ @log << e.message
+ @log << e.value
+ end
+ }
+
+ expect(@log).to eq(['foo', 'foo'])
+ end
+
+ it "should pass through exceptions without modification" do
+ @reactor.run {
+ @reactor.next_tick do
+ @deferred.reject(RuntimeError.new('fail'))
+ end
+
+ begin
+ @deferred.value
+ @log << 'should raise exception'
+ rescue => e
+ expect(e.class).to eq(RuntimeError)
+ @log << e.message
+ end
+ }
+
+ expect(@log).to eq(['fail'])
+ end
+ end
end
describe 'reject' do
it "should package a string into a rejected promise" do
- @loop.run {
- rejectedPromise = Libuv::Q.reject(@loop, 'not gonna happen')
+ @reactor.run {
+ rejectedPromise = Libuv::Q.reject(@reactor, 'not gonna happen')
@promise.then(@default_fail, proc {|reason|
@log << reason
})
@deferred.resolve(rejectedPromise)
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq(['not gonna happen'])
end
it "should return a promise that forwards callbacks if the callbacks are missing" do
- @loop.run {
- rejectedPromise = Libuv::Q.reject(@loop, 'not gonna happen')
+ @reactor.run {
+ rejectedPromise = Libuv::Q.reject(@reactor, 'not gonna happen')
@promise.then(@default_fail, proc {|reason|
@log << reason
})
@deferred.resolve(rejectedPromise.then())
-
- @loop.next_tick do
- @loop.next_tick do
- @loop.stop
- end
- end
}
expect(@log).to eq(['not gonna happen'])
end
@@ -924,53 +799,49 @@
describe 'all' do
it "should resolve all of nothing" do
- @loop.run {
- Libuv::Q.all(@loop).then nil, @default_fail do |result|
+ @reactor.run {
+ Libuv::Q.all(@reactor).then nil, @default_fail do |result|
@log << result
end
-
- @loop.next_tick do
- @loop.stop
- end
}
expect(@log).to eq([[]])
end
it "should take an array of promises and return a promise for an array of results" do
- @loop.run {
- deferred1 = @loop.defer
- deferred2 = @loop.defer
+ @reactor.run {
+ deferred1 = @reactor.defer
+ deferred2 = @reactor.defer
- Libuv::Q.all(@loop, @promise, deferred1.promise, deferred2.promise).then nil, @default_fail do |result|
+ Libuv::Q.all(@reactor, @promise, deferred1.promise, deferred2.promise).then nil, @default_fail do |result|
@log = result
- @loop.stop
+ @reactor.stop
end
- @loop.work { @deferred.resolve(:foo) }
- @loop.work { deferred2.resolve(:baz) }
- @loop.work { deferred1.resolve(:bar) }
+ @reactor.work { @deferred.resolve(:foo) }
+ @reactor.work { deferred2.resolve(:baz) }
+ @reactor.work { deferred1.resolve(:bar) }
}
expect(@log).to eq([:foo, :bar, :baz])
end
it "should reject the derived promise if at least one of the promises in the array is rejected" do
- @loop.run {
- deferred1 = @loop.defer
- deferred2 = @loop.defer
+ @reactor.run {
+ deferred1 = @reactor.defer
+ deferred2 = @reactor.defer
- Libuv::Q.all(@loop, @promise, deferred1.promise, deferred2.promise).then(@default_fail, proc {|reason|
+ Libuv::Q.all(@reactor, @promise, deferred1.promise, deferred2.promise).then(@default_fail, proc {|reason|
@log << reason
- @loop.stop
+ @reactor.stop
})
- @loop.work { @deferred.resolve(:foo) }
- @loop.work { deferred2.reject(:baz) }
+ @reactor.work { @deferred.resolve(:foo) }
+ @reactor.work { deferred2.reject(:baz) }
}
expect(@log).to eq([:baz])
end