File: safe_task_executor_spec.rb

package info (click to toggle)
ruby-concurrent 1.3.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,136 kB
  • sloc: ruby: 30,875; java: 6,128; ansic: 265; makefile: 26; sh: 19
file content (133 lines) | stat: -rw-r--r-- 3,918 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
require 'concurrent/executor/safe_task_executor'

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 'protects #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? and Concurrent.ruby_version(:<, 3, 2, 0)
        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