132 lines
3.7 KiB
Ruby
132 lines
3.7 KiB
Ruby
module Concurrent
|
|
|
|
RSpec.describe SafeTaskExecutor do
|
|
|
|
describe '#execute' do
|
|
|
|
context 'happy execution' do
|
|
|
|
let(:task) { Proc.new { 42 } }
|
|
subject { SafeTaskExecutor.new(task) }
|
|
|
|
it 'should return success' do
|
|
success, _value, _reason = subject.execute
|
|
expect(success).to be_truthy
|
|
end
|
|
|
|
it 'should return task value' do
|
|
_success, value, _reason = subject.execute
|
|
expect(value).to eq 42
|
|
end
|
|
|
|
it 'should return a nil reason' do
|
|
_success, _value, reason = subject.execute
|
|
expect(reason).to be_nil
|
|
end
|
|
|
|
it 'passes all arguments to #execute to the task' do
|
|
expected = nil
|
|
task = proc {|*args| expected = args }
|
|
SafeTaskExecutor.new(task).execute(1, 2, 3)
|
|
expect(expected).to eq [1, 2, 3]
|
|
end
|
|
|
|
it 'protectes #execute with a mutex' do
|
|
expect(subject).to receive(:synchronize).with(no_args)
|
|
subject.execute
|
|
end
|
|
end
|
|
|
|
context 'failing execution' do
|
|
|
|
let(:task) { Proc.new { raise StandardError.new('an error') } }
|
|
subject { SafeTaskExecutor.new(task) }
|
|
|
|
it 'should return false success' do
|
|
success, _value, _reason = subject.execute
|
|
expect(success).to be_falsey
|
|
end
|
|
|
|
it 'should return a nil value' do
|
|
_success, value, _reason = subject.execute
|
|
expect(value).to be_nil
|
|
end
|
|
|
|
it 'should return the reason' do
|
|
_success, _value, reason = subject.execute
|
|
expect(reason).to be_a(StandardError)
|
|
expect(reason.message).to eq 'an error'
|
|
end
|
|
|
|
it 'rescues Exception when :rescue_exception is true' do
|
|
task = proc { raise Exception }
|
|
subject = SafeTaskExecutor.new(task, rescue_exception: true)
|
|
expect {
|
|
subject.execute
|
|
}.to_not raise_error
|
|
end
|
|
|
|
it 'rescues StandardError when :rescue_exception is false' do
|
|
task = proc { raise StandardError }
|
|
subject = SafeTaskExecutor.new(task, rescue_exception: false)
|
|
expect {
|
|
subject.execute
|
|
}.to_not raise_error
|
|
|
|
task = proc { raise Exception }
|
|
subject = SafeTaskExecutor.new(task, rescue_exception: false)
|
|
expect {
|
|
subject.execute
|
|
}.to raise_error(Exception)
|
|
end
|
|
|
|
it 'rescues StandardError by default' do
|
|
task = proc { raise StandardError }
|
|
subject = SafeTaskExecutor.new(task)
|
|
expect {
|
|
subject.execute
|
|
}.to_not raise_error
|
|
|
|
task = proc { raise Exception }
|
|
subject = SafeTaskExecutor.new(task)
|
|
expect {
|
|
subject.execute
|
|
}.to raise_error(Exception)
|
|
end
|
|
end
|
|
|
|
# These tests only make sense on CRuby as they test a workaround for CRuby bugs: https://github.com/ruby-concurrency/concurrent-ruby/issues/931
|
|
if Concurrent.on_cruby?
|
|
context 'local jump error' do
|
|
def execute
|
|
Thread.new do
|
|
executor = SafeTaskExecutor.new(-> { yield 42 })
|
|
@result = executor.execute
|
|
end.join
|
|
end
|
|
|
|
subject do
|
|
to_enum(:execute).first
|
|
@result
|
|
end
|
|
|
|
it 'should return success' do
|
|
success, _value, _reason = subject
|
|
expect(success).to be_truthy
|
|
end
|
|
|
|
it 'should return a nil value' do
|
|
_success, value, _reason = subject
|
|
expect(value).to be_nil
|
|
end
|
|
|
|
it 'should return a nil reason' do
|
|
_success, _value, reason = subject
|
|
expect(reason).to be_nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|