concurrent-ruby 0.1.0 → 0.1.1.pre.1
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/LICENSE +21 -21
- data/README.md +279 -224
- data/lib/concurrent.rb +27 -20
- data/lib/concurrent/agent.rb +106 -130
- data/lib/concurrent/cached_thread_pool.rb +130 -122
- data/lib/concurrent/defer.rb +67 -69
- data/lib/concurrent/drb_async_demux.rb +72 -0
- data/lib/concurrent/event.rb +60 -60
- data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
- data/lib/concurrent/executor.rb +87 -0
- data/lib/concurrent/fixed_thread_pool.rb +89 -89
- data/lib/concurrent/functions.rb +120 -0
- data/lib/concurrent/future.rb +52 -42
- data/lib/concurrent/global_thread_pool.rb +3 -3
- data/lib/concurrent/goroutine.rb +29 -25
- data/lib/concurrent/obligation.rb +67 -121
- data/lib/concurrent/promise.rb +172 -194
- data/lib/concurrent/reactor.rb +162 -0
- data/lib/concurrent/smart_mutex.rb +66 -0
- data/lib/concurrent/tcp_sync_demux.rb +96 -0
- data/lib/concurrent/thread_pool.rb +65 -61
- data/lib/concurrent/utilities.rb +34 -0
- data/lib/concurrent/version.rb +3 -3
- data/lib/concurrent_ruby.rb +1 -1
- data/md/agent.md +123 -123
- data/md/defer.md +174 -174
- data/md/event.md +32 -32
- data/md/executor.md +176 -0
- data/md/future.md +83 -83
- data/md/goroutine.md +52 -52
- data/md/obligation.md +32 -32
- data/md/promise.md +225 -225
- data/md/thread_pool.md +197 -197
- data/spec/concurrent/agent_spec.rb +376 -405
- data/spec/concurrent/cached_thread_pool_spec.rb +112 -112
- data/spec/concurrent/defer_spec.rb +209 -199
- data/spec/concurrent/event_machine_defer_proxy_spec.rb +250 -246
- data/spec/concurrent/event_spec.rb +134 -134
- data/spec/concurrent/executor_spec.rb +146 -0
- data/spec/concurrent/fixed_thread_pool_spec.rb +84 -84
- data/spec/concurrent/functions_spec.rb +57 -0
- data/spec/concurrent/future_spec.rb +125 -115
- data/spec/concurrent/goroutine_spec.rb +67 -52
- data/spec/concurrent/obligation_shared.rb +121 -121
- data/spec/concurrent/promise_spec.rb +299 -310
- data/spec/concurrent/smart_mutex_spec.rb +234 -0
- data/spec/concurrent/thread_pool_shared.rb +209 -209
- data/spec/concurrent/utilities_spec.rb +74 -0
- data/spec/spec_helper.rb +21 -19
- metadata +38 -14
- checksums.yaml +0 -7
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
describe Agent do
|
6
|
+
|
7
|
+
it 'aliases #<< for Agent#post' do
|
8
|
+
subject = Agent.new(0)
|
9
|
+
subject << proc{ 100 }
|
10
|
+
sleep(0.1)
|
11
|
+
subject.value.should eq 100
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'aliases Kernel#agent for Agent.new' do
|
15
|
+
agent(10).should be_a(Agent)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'aliases Kernel#deref for #deref' do
|
19
|
+
deref(Agent.new(10)).should eq 10
|
20
|
+
deref(Agent.new(10), 10).should eq 10
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'aliases Kernel:post for Agent#post' do
|
24
|
+
subject = Agent.new(0)
|
25
|
+
post(subject){ 100 }
|
26
|
+
sleep(0.1)
|
27
|
+
subject.value.should eq 100
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe Defer do
|
32
|
+
|
33
|
+
it 'aliases Kernel#defer' do
|
34
|
+
defer{ nil }.should be_a(Defer)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe Future do
|
39
|
+
|
40
|
+
it 'aliases Kernel#future for Future.new' do
|
41
|
+
future().should be_a(Future)
|
42
|
+
future(){ nil }.should be_a(Future)
|
43
|
+
future(1, 2, 3).should be_a(Future)
|
44
|
+
future(1, 2, 3){ nil }.should be_a(Future)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe Promise do
|
49
|
+
|
50
|
+
it 'aliases Kernel#promise for Promise.new' do
|
51
|
+
promise().should be_a(Promise)
|
52
|
+
promise(){ nil }.should be_a(Promise)
|
53
|
+
promise(1, 2, 3).should be_a(Promise)
|
54
|
+
promise(1, 2, 3){ nil }.should be_a(Promise)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,115 +1,125 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require_relative 'obligation_shared'
|
3
|
-
|
4
|
-
module Concurrent
|
5
|
-
|
6
|
-
describe Future do
|
7
|
-
|
8
|
-
let!(:fulfilled_value) { 10 }
|
9
|
-
let!(:rejected_reason) { StandardError.new('mojo jojo') }
|
10
|
-
|
11
|
-
let(:pending_subject) do
|
12
|
-
Future.new{ sleep(2) }
|
13
|
-
end
|
14
|
-
|
15
|
-
let(:fulfilled_subject) do
|
16
|
-
Future.new{ fulfilled_value }.tap(){ sleep(0.1) }
|
17
|
-
end
|
18
|
-
|
19
|
-
let(:rejected_subject) do
|
20
|
-
Future.new{ raise rejected_reason }.tap(){ sleep(0.1) }
|
21
|
-
end
|
22
|
-
|
23
|
-
before(:each) do
|
24
|
-
$GLOBAL_THREAD_POOL =
|
25
|
-
end
|
26
|
-
|
27
|
-
it_should_behave_like Obligation
|
28
|
-
|
29
|
-
context 'behavior' do
|
30
|
-
|
31
|
-
it 'implements :future behavior' do
|
32
|
-
lambda {
|
33
|
-
Future.new{ nil }
|
34
|
-
}.should_not raise_error
|
35
|
-
|
36
|
-
Future.new{ nil }.behaves_as?(:future).should be_true
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
context '#initialize' do
|
41
|
-
|
42
|
-
it 'spawns a new thread when a block is given' do
|
43
|
-
$GLOBAL_THREAD_POOL.should_receive(:post).once.with(any_args())
|
44
|
-
Future.new{ nil }
|
45
|
-
end
|
46
|
-
|
47
|
-
it '
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
it '
|
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
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative 'obligation_shared'
|
3
|
+
|
4
|
+
module Concurrent
|
5
|
+
|
6
|
+
describe Future do
|
7
|
+
|
8
|
+
let!(:fulfilled_value) { 10 }
|
9
|
+
let!(:rejected_reason) { StandardError.new('mojo jojo') }
|
10
|
+
|
11
|
+
let(:pending_subject) do
|
12
|
+
Future.new{ sleep(2) }
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:fulfilled_subject) do
|
16
|
+
Future.new{ fulfilled_value }.tap(){ sleep(0.1) }
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:rejected_subject) do
|
20
|
+
Future.new{ raise rejected_reason }.tap(){ sleep(0.1) }
|
21
|
+
end
|
22
|
+
|
23
|
+
before(:each) do
|
24
|
+
$GLOBAL_THREAD_POOL = FixedThreadPool.new(2)
|
25
|
+
end
|
26
|
+
|
27
|
+
it_should_behave_like Obligation
|
28
|
+
|
29
|
+
context 'behavior' do
|
30
|
+
|
31
|
+
it 'implements :future behavior' do
|
32
|
+
lambda {
|
33
|
+
Future.new{ nil }
|
34
|
+
}.should_not raise_error
|
35
|
+
|
36
|
+
Future.new{ nil }.behaves_as?(:future).should be_true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context '#initialize' do
|
41
|
+
|
42
|
+
it 'spawns a new thread when a block is given' do
|
43
|
+
$GLOBAL_THREAD_POOL.should_receive(:post).once.with(any_args())
|
44
|
+
Future.new{ nil }
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'accepts an alternate thread pool as the first argument' do
|
48
|
+
pool = Concurrent::FixedThreadPool.new(2)
|
49
|
+
pool.should_receive(:post).with(no_args())
|
50
|
+
Future.new(pool, 1, 2, 3){ nil }
|
51
|
+
sleep(0.1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'does not spawns a new thread when no block given' do
|
55
|
+
Thread.should_not_receive(:new).with(any_args())
|
56
|
+
Future.new
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'immediately sets the state to :fulfilled when no block given' do
|
60
|
+
Future.new.should be_fulfilled
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'immediately sets the value to nil when no block given' do
|
64
|
+
Future.new.value.should be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'fulfillment' do
|
69
|
+
|
70
|
+
it 'passes all arguments to handler' do
|
71
|
+
@a = @b = @c = nil
|
72
|
+
f = Future.new(1, 2, 3) do |a, b, c|
|
73
|
+
@a, @b, @c = a, b, c
|
74
|
+
end
|
75
|
+
sleep(0.1)
|
76
|
+
[@a, @b, @c].should eq [1, 2, 3]
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'passes all other arguments to the handler when a thread pool is given' do
|
80
|
+
@expected = nil
|
81
|
+
pool = Concurrent::FixedThreadPool.new(2)
|
82
|
+
f = Future.new(pool, 1, 2, 3) do |a, b, c|
|
83
|
+
@a, @b, @c = a, b, c
|
84
|
+
end
|
85
|
+
sleep(0.1)
|
86
|
+
[@a, @b, @c].should eq [1, 2, 3]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'sets the value to the result of the handler' do
|
90
|
+
f = Future.new(10){|a| a * 2 }
|
91
|
+
sleep(0.1)
|
92
|
+
f.value.should eq 20
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'sets the state to :fulfilled when the block completes' do
|
96
|
+
f = Future.new(10){|a| a * 2 }
|
97
|
+
sleep(0.1)
|
98
|
+
f.should be_fulfilled
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'sets the value to nil when the handler raises an exception' do
|
102
|
+
f = Future.new{ raise StandardError }
|
103
|
+
sleep(0.1)
|
104
|
+
f.value.should be_nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'sets the state to :rejected when the handler raises an exception' do
|
108
|
+
f = Future.new{ raise StandardError }
|
109
|
+
sleep(0.1)
|
110
|
+
f.should be_rejected
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'aliases' do
|
114
|
+
|
115
|
+
it 'aliases #realized? for #fulfilled?' do
|
116
|
+
fulfilled_subject.should be_realized
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'aliases #deref for #value' do
|
120
|
+
fulfilled_subject.deref.should eq fulfilled_value
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -1,52 +1,67 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
describe '#go' do
|
6
|
-
|
7
|
-
before(:each) do
|
8
|
-
$GLOBAL_THREAD_POOL = CachedThreadPool.new
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'passes all arguments to the block' do
|
12
|
-
@expected = nil
|
13
|
-
go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
14
|
-
sleep(0.1)
|
15
|
-
@expected.should eq [3, 2, 1]
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'returns true if the thread is successfully created' do
|
19
|
-
$GLOBAL_THREAD_POOL.should_receive(:post).and_return(true)
|
20
|
-
go{ nil }.should be_true
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'returns false if the thread cannot be created' do
|
24
|
-
$GLOBAL_THREAD_POOL.should_receive(:post).and_return(false)
|
25
|
-
go{ nil }.should be_false
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'immediately returns false if no block is given' do
|
29
|
-
go().should be_false
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'does not create a thread if no block is given' do
|
33
|
-
$GLOBAL_THREAD_POOL.should_not_receive(:post)
|
34
|
-
go()
|
35
|
-
sleep(0.1)
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'supresses exceptions on the thread' do
|
39
|
-
lambda{
|
40
|
-
go{ raise StandardError }
|
41
|
-
sleep(0.1)
|
42
|
-
}.should_not raise_error
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'processes the block' do
|
46
|
-
@expected = false
|
47
|
-
go(1,2,3){|*args| @expected = args }
|
48
|
-
sleep(0.1)
|
49
|
-
@expected.should eq [1,2,3]
|
50
|
-
end
|
51
|
-
|
52
|
-
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
describe '#go' do
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
$GLOBAL_THREAD_POOL = CachedThreadPool.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'passes all arguments to the block' do
|
12
|
+
@expected = nil
|
13
|
+
go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
14
|
+
sleep(0.1)
|
15
|
+
@expected.should eq [3, 2, 1]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns true if the thread is successfully created' do
|
19
|
+
$GLOBAL_THREAD_POOL.should_receive(:post).and_return(true)
|
20
|
+
go{ nil }.should be_true
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns false if the thread cannot be created' do
|
24
|
+
$GLOBAL_THREAD_POOL.should_receive(:post).and_return(false)
|
25
|
+
go{ nil }.should be_false
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'immediately returns false if no block is given' do
|
29
|
+
go().should be_false
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'does not create a thread if no block is given' do
|
33
|
+
$GLOBAL_THREAD_POOL.should_not_receive(:post)
|
34
|
+
go()
|
35
|
+
sleep(0.1)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'supresses exceptions on the thread' do
|
39
|
+
lambda{
|
40
|
+
go{ raise StandardError }
|
41
|
+
sleep(0.1)
|
42
|
+
}.should_not raise_error
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'processes the block' do
|
46
|
+
@expected = false
|
47
|
+
go(1,2,3){|*args| @expected = args }
|
48
|
+
sleep(0.1)
|
49
|
+
@expected.should eq [1,2,3]
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'accepts an alternate thread pool as the first argument' do
|
53
|
+
pool = Concurrent::FixedThreadPool.new(2)
|
54
|
+
pool.should_receive(:post).with(no_args())
|
55
|
+
go(pool){ sleep(0.1) }
|
56
|
+
sleep(0.2)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'passes all other arguments to the block when a thread pool is given' do
|
60
|
+
@expected = nil
|
61
|
+
pool = Concurrent::FixedThreadPool.new(2)
|
62
|
+
go(pool, 1, 2, 3){|a, b, c| @expected = [c, b, a] }
|
63
|
+
sleep(0.1)
|
64
|
+
@expected.should eq [3, 2, 1]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,121 +1,121 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Concurrent
|
4
|
-
|
5
|
-
share_examples_for Obligation do
|
6
|
-
|
7
|
-
context '#state' do
|
8
|
-
|
9
|
-
it 'is :pending when first created' do
|
10
|
-
f = pending_subject
|
11
|
-
f.state.should == :pending
|
12
|
-
f.should be_pending
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'is :fulfilled when the handler completes' do
|
16
|
-
f = fulfilled_subject
|
17
|
-
f.state.should == :fulfilled
|
18
|
-
f.should be_fulfilled
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'is :rejected when the handler raises an exception' do
|
22
|
-
f = rejected_subject
|
23
|
-
f.state.should == :rejected
|
24
|
-
f.should be_rejected
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context '#value' do
|
29
|
-
|
30
|
-
it 'blocks the caller when :pending and timeout is nil' do
|
31
|
-
f = pending_subject
|
32
|
-
sleep(0.1)
|
33
|
-
f.value.should be_true
|
34
|
-
f.should be_fulfilled
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'returns nil when reaching the optional timeout value' do
|
38
|
-
f = pending_subject
|
39
|
-
sleep(0.1)
|
40
|
-
f.value(0.1).should be_nil
|
41
|
-
f.should be_pending
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'returns immediately when timeout is zero' do
|
45
|
-
Timeout.should_not_receive(:timeout).with(any_args())
|
46
|
-
f = pending_subject
|
47
|
-
sleep(0.1)
|
48
|
-
f.value(0).should be_nil
|
49
|
-
f.should be_pending
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'is nil when :pending' do
|
53
|
-
expected = pending_subject.value
|
54
|
-
expected.should be_nil
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'is nil when :rejected' do
|
58
|
-
expected = rejected_subject.value
|
59
|
-
expected.should be_nil
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'is set to the return value of the block when :fulfilled' do
|
63
|
-
expected = fulfilled_subject.value
|
64
|
-
expected.should eq fulfilled_value
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context '#reason' do
|
69
|
-
|
70
|
-
it 'is nil when :pending' do
|
71
|
-
pending_subject.reason.should be_nil
|
72
|
-
end
|
73
|
-
|
74
|
-
it 'is nil when :fulfilled' do
|
75
|
-
fulfilled_subject.reason.should be_nil
|
76
|
-
end
|
77
|
-
|
78
|
-
it 'is set to error object of the exception when :rejected' do
|
79
|
-
rejected_subject.reason.should be_a(Exception)
|
80
|
-
rejected_subject.reason.to_s.should =~ /#{rejected_reason}/
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
context 'Kernel aliases' do
|
85
|
-
|
86
|
-
it 'aliases Kernel#deref for #deref' do
|
87
|
-
deref(fulfilled_subject).should eq fulfilled_value
|
88
|
-
deref(fulfilled_subject, 0).should eq fulfilled_value
|
89
|
-
end
|
90
|
-
|
91
|
-
it 'aliases Kernel#pending? for #pending?' do
|
92
|
-
#NOTE: was structured like others but was incorrectly failing
|
93
|
-
# on fulfilled_subject
|
94
|
-
fulfilled_subject.should_receive(:pending?).once
|
95
|
-
pending?(fulfilled_subject)
|
96
|
-
pending_subject.should_receive(:pending?).once
|
97
|
-
pending?(pending_subject)
|
98
|
-
rejected_subject.should_receive(:pending?).once
|
99
|
-
pending?(rejected_subject)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'aliases Kernel#fulfilled? for #fulfilled?' do
|
103
|
-
fulfilled?(fulfilled_subject).should be_true
|
104
|
-
fulfilled?(pending_subject).should be_false
|
105
|
-
fulfilled?(rejected_subject).should be_false
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'aliases Kernel#realized? for #realized?' do
|
109
|
-
realized?(fulfilled_subject).should be_true
|
110
|
-
realized?(pending_subject).should be_false
|
111
|
-
realized?(rejected_subject).should be_false
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'aliases Kernel#rejected? for #rejected?' do
|
115
|
-
rejected?(rejected_subject).should be_true
|
116
|
-
rejected?(fulfilled_subject).should be_false
|
117
|
-
rejected?(pending_subject).should be_false
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Concurrent
|
4
|
+
|
5
|
+
share_examples_for Obligation do
|
6
|
+
|
7
|
+
context '#state' do
|
8
|
+
|
9
|
+
it 'is :pending when first created' do
|
10
|
+
f = pending_subject
|
11
|
+
f.state.should == :pending
|
12
|
+
f.should be_pending
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'is :fulfilled when the handler completes' do
|
16
|
+
f = fulfilled_subject
|
17
|
+
f.state.should == :fulfilled
|
18
|
+
f.should be_fulfilled
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'is :rejected when the handler raises an exception' do
|
22
|
+
f = rejected_subject
|
23
|
+
f.state.should == :rejected
|
24
|
+
f.should be_rejected
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#value' do
|
29
|
+
|
30
|
+
it 'blocks the caller when :pending and timeout is nil' do
|
31
|
+
f = pending_subject
|
32
|
+
sleep(0.1)
|
33
|
+
f.value.should be_true
|
34
|
+
f.should be_fulfilled
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns nil when reaching the optional timeout value' do
|
38
|
+
f = pending_subject
|
39
|
+
sleep(0.1)
|
40
|
+
f.value(0.1).should be_nil
|
41
|
+
f.should be_pending
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns immediately when timeout is zero' do
|
45
|
+
Timeout.should_not_receive(:timeout).with(any_args())
|
46
|
+
f = pending_subject
|
47
|
+
sleep(0.1)
|
48
|
+
f.value(0).should be_nil
|
49
|
+
f.should be_pending
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'is nil when :pending' do
|
53
|
+
expected = pending_subject.value
|
54
|
+
expected.should be_nil
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'is nil when :rejected' do
|
58
|
+
expected = rejected_subject.value
|
59
|
+
expected.should be_nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'is set to the return value of the block when :fulfilled' do
|
63
|
+
expected = fulfilled_subject.value
|
64
|
+
expected.should eq fulfilled_value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context '#reason' do
|
69
|
+
|
70
|
+
it 'is nil when :pending' do
|
71
|
+
pending_subject.reason.should be_nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'is nil when :fulfilled' do
|
75
|
+
fulfilled_subject.reason.should be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'is set to error object of the exception when :rejected' do
|
79
|
+
rejected_subject.reason.should be_a(Exception)
|
80
|
+
rejected_subject.reason.to_s.should =~ /#{rejected_reason}/
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'Kernel aliases' do
|
85
|
+
|
86
|
+
it 'aliases Kernel#deref for #deref' do
|
87
|
+
deref(fulfilled_subject).should eq fulfilled_value
|
88
|
+
deref(fulfilled_subject, 0).should eq fulfilled_value
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'aliases Kernel#pending? for #pending?' do
|
92
|
+
#NOTE: was structured like others but was incorrectly failing
|
93
|
+
# on fulfilled_subject
|
94
|
+
fulfilled_subject.should_receive(:pending?).once
|
95
|
+
pending?(fulfilled_subject)
|
96
|
+
pending_subject.should_receive(:pending?).once
|
97
|
+
pending?(pending_subject)
|
98
|
+
rejected_subject.should_receive(:pending?).once
|
99
|
+
pending?(rejected_subject)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'aliases Kernel#fulfilled? for #fulfilled?' do
|
103
|
+
fulfilled?(fulfilled_subject).should be_true
|
104
|
+
fulfilled?(pending_subject).should be_false
|
105
|
+
fulfilled?(rejected_subject).should be_false
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'aliases Kernel#realized? for #realized?' do
|
109
|
+
realized?(fulfilled_subject).should be_true
|
110
|
+
realized?(pending_subject).should be_false
|
111
|
+
realized?(rejected_subject).should be_false
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'aliases Kernel#rejected? for #rejected?' do
|
115
|
+
rejected?(rejected_subject).should be_true
|
116
|
+
rejected?(fulfilled_subject).should be_false
|
117
|
+
rejected?(pending_subject).should be_false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|