concurrent-ruby/spec/concurrent/executor/safe_task_executor_spec.rb

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