celluloid 0.14.1 → 0.15.0.pre
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.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/lib/celluloid.rb +92 -108
- data/lib/celluloid/actor.rb +42 -64
- data/lib/celluloid/autostart.rb +1 -1
- data/lib/celluloid/call_chain.rb +13 -0
- data/lib/celluloid/calls.rb +5 -8
- data/lib/celluloid/condition.rb +8 -10
- data/lib/celluloid/cpu_counter.rb +1 -1
- data/lib/celluloid/evented_mailbox.rb +7 -10
- data/lib/celluloid/fsm.rb +1 -1
- data/lib/celluloid/future.rb +1 -2
- data/lib/celluloid/internal_pool.rb +77 -20
- data/lib/celluloid/legacy.rb +0 -38
- data/lib/celluloid/mailbox.rb +17 -10
- data/lib/celluloid/pool_manager.rb +1 -1
- data/lib/celluloid/properties.rb +24 -0
- data/lib/celluloid/proxies/abstract_proxy.rb +3 -0
- data/lib/celluloid/proxies/actor_proxy.rb +3 -32
- data/lib/celluloid/proxies/async_proxy.rb +4 -8
- data/lib/celluloid/proxies/future_proxy.rb +8 -6
- data/lib/celluloid/proxies/sync_proxy.rb +12 -7
- data/lib/celluloid/rspec.rb +3 -1
- data/lib/celluloid/signals.rb +7 -35
- data/lib/celluloid/stack_dump.rb +50 -37
- data/lib/celluloid/supervision_group.rb +5 -5
- data/lib/celluloid/task_set.rb +49 -0
- data/lib/celluloid/tasks.rb +67 -42
- data/lib/celluloid/tasks/task_fiber.rb +3 -1
- data/lib/celluloid/tasks/task_thread.rb +2 -3
- data/lib/celluloid/thread.rb +2 -0
- data/spec/celluloid/actor_spec.rb +5 -0
- data/spec/celluloid/block_spec.rb +54 -0
- data/spec/celluloid/calls_spec.rb +42 -0
- data/spec/celluloid/condition_spec.rb +65 -0
- data/spec/celluloid/evented_mailbox_spec.rb +34 -0
- data/spec/celluloid/fsm_spec.rb +107 -0
- data/spec/celluloid/future_spec.rb +32 -0
- data/spec/celluloid/internal_pool_spec.rb +52 -0
- data/spec/celluloid/links_spec.rb +45 -0
- data/spec/celluloid/logging/ring_buffer_spec.rb +38 -0
- data/spec/celluloid/mailbox_spec.rb +5 -0
- data/spec/celluloid/notifications_spec.rb +120 -0
- data/spec/celluloid/pool_spec.rb +52 -0
- data/spec/celluloid/properties_spec.rb +42 -0
- data/spec/celluloid/registry_spec.rb +64 -0
- data/spec/celluloid/stack_dump_spec.rb +35 -0
- data/spec/celluloid/supervision_group_spec.rb +53 -0
- data/spec/celluloid/supervisor_spec.rb +92 -0
- data/spec/celluloid/tasks/task_fiber_spec.rb +5 -0
- data/spec/celluloid/tasks/task_thread_spec.rb +5 -0
- data/spec/celluloid/thread_handle_spec.rb +22 -0
- data/spec/celluloid/uuid_spec.rb +11 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/actor_examples.rb +161 -10
- data/spec/support/example_actor_class.rb +8 -0
- data/spec/support/mailbox_examples.rb +15 -3
- data/spec/support/task_examples.rb +2 -2
- metadata +28 -3
- data/lib/celluloid/version.rb +0 -4
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Celluloid::StackDump do
|
4
|
+
class BlockingActor
|
5
|
+
include Celluloid
|
6
|
+
|
7
|
+
def blocking
|
8
|
+
Kernel.sleep
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
[Celluloid::TaskFiber, Celluloid::TaskThread].each do |task_klass|
|
14
|
+
actor_klass = Class.new(BlockingActor) do
|
15
|
+
task_class task_klass
|
16
|
+
end
|
17
|
+
actor = actor_klass.new
|
18
|
+
actor.async.blocking
|
19
|
+
end
|
20
|
+
|
21
|
+
Celluloid.internal_pool.get do
|
22
|
+
Thread.current.role = :testing
|
23
|
+
sleep
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should include all actors' do
|
28
|
+
subject.actors.size.should == Celluloid::Actor.all.size
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should include threads that are not actors' do
|
32
|
+
pending "bugs"
|
33
|
+
subject.threads.size.should == 2
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Celluloid::SupervisionGroup do
|
4
|
+
before :all do
|
5
|
+
class MyActor
|
6
|
+
include Celluloid
|
7
|
+
|
8
|
+
def running?; :yep; end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MyGroup < Celluloid::SupervisionGroup
|
12
|
+
supervise MyActor, :as => :example
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "runs applications" do
|
17
|
+
MyGroup.run!
|
18
|
+
sleep 0.01 # startup time hax
|
19
|
+
|
20
|
+
Celluloid::Actor[:example].should be_running
|
21
|
+
end
|
22
|
+
|
23
|
+
it "accepts a private actor registry" do
|
24
|
+
my_registry = Celluloid::Registry.new
|
25
|
+
MyGroup.run!(my_registry)
|
26
|
+
sleep 0.01
|
27
|
+
|
28
|
+
my_registry[:example].should be_running
|
29
|
+
end
|
30
|
+
|
31
|
+
context "pool" do
|
32
|
+
before :all do
|
33
|
+
class MyActor
|
34
|
+
attr_reader :args
|
35
|
+
def initialize *args
|
36
|
+
@args = *args
|
37
|
+
end
|
38
|
+
end
|
39
|
+
class MyGroup
|
40
|
+
pool MyActor, :as => :example_pool, :args => 'foo', :size => 3
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it "runs applications and passes pool options and actor args" do
|
45
|
+
MyGroup.run!
|
46
|
+
sleep 0.001 # startup time hax
|
47
|
+
|
48
|
+
Celluloid::Actor[:example_pool].should be_running
|
49
|
+
Celluloid::Actor[:example_pool].args.should eq ['foo']
|
50
|
+
Celluloid::Actor[:example_pool].size.should be 3
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Celluloid::Supervisor do
|
4
|
+
class SubordinateDead < StandardError; end
|
5
|
+
|
6
|
+
class Subordinate
|
7
|
+
include Celluloid
|
8
|
+
attr_reader :state
|
9
|
+
|
10
|
+
def initialize(state)
|
11
|
+
@state = state
|
12
|
+
end
|
13
|
+
|
14
|
+
def crack_the_whip
|
15
|
+
case @state
|
16
|
+
when :idle
|
17
|
+
@state = :working
|
18
|
+
else raise SubordinateDead, "the spec purposely crashed me :("
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "restarts actors when they die" do
|
24
|
+
supervisor = Celluloid::Supervisor.supervise(Subordinate, :idle)
|
25
|
+
subordinate = supervisor.actors.first
|
26
|
+
subordinate.state.should be(:idle)
|
27
|
+
|
28
|
+
subordinate.crack_the_whip
|
29
|
+
subordinate.state.should be(:working)
|
30
|
+
|
31
|
+
expect do
|
32
|
+
subordinate.crack_the_whip
|
33
|
+
end.to raise_exception(SubordinateDead)
|
34
|
+
sleep 0.1 # hax to prevent race :(
|
35
|
+
subordinate.should_not be_alive
|
36
|
+
|
37
|
+
new_subordinate = supervisor.actors.first
|
38
|
+
new_subordinate.should_not eq subordinate
|
39
|
+
new_subordinate.state.should eq :idle
|
40
|
+
end
|
41
|
+
|
42
|
+
it "registers actors and reregisters them when they die" do
|
43
|
+
Celluloid::Supervisor.supervise_as(:subordinate, Subordinate, :idle)
|
44
|
+
subordinate = Celluloid::Actor[:subordinate]
|
45
|
+
subordinate.state.should be(:idle)
|
46
|
+
|
47
|
+
subordinate.crack_the_whip
|
48
|
+
subordinate.state.should be(:working)
|
49
|
+
|
50
|
+
expect do
|
51
|
+
subordinate.crack_the_whip
|
52
|
+
end.to raise_exception(SubordinateDead)
|
53
|
+
sleep 0.1 # hax to prevent race :(
|
54
|
+
subordinate.should_not be_alive
|
55
|
+
|
56
|
+
new_subordinate = Celluloid::Actor[:subordinate]
|
57
|
+
new_subordinate.should_not eq subordinate
|
58
|
+
new_subordinate.state.should eq :idle
|
59
|
+
end
|
60
|
+
|
61
|
+
it "creates supervisors via Actor.supervise" do
|
62
|
+
supervisor = Subordinate.supervise(:working)
|
63
|
+
subordinate = supervisor.actors.first
|
64
|
+
subordinate.state.should be(:working)
|
65
|
+
|
66
|
+
expect do
|
67
|
+
subordinate.crack_the_whip
|
68
|
+
end.to raise_exception(SubordinateDead)
|
69
|
+
sleep 0.1 # hax to prevent race :(
|
70
|
+
subordinate.should_not be_alive
|
71
|
+
|
72
|
+
new_subordinate = supervisor.actors.first
|
73
|
+
new_subordinate.should_not eq subordinate
|
74
|
+
new_subordinate.state.should eq :working
|
75
|
+
end
|
76
|
+
|
77
|
+
it "creates supervisors and registers actors via Actor.supervise_as" do
|
78
|
+
supervisor = Subordinate.supervise_as(:subordinate, :working)
|
79
|
+
subordinate = Celluloid::Actor[:subordinate]
|
80
|
+
subordinate.state.should be(:working)
|
81
|
+
|
82
|
+
expect do
|
83
|
+
subordinate.crack_the_whip
|
84
|
+
end.to raise_exception(SubordinateDead)
|
85
|
+
sleep 0.1 # hax to prevent race :(
|
86
|
+
subordinate.should_not be_alive
|
87
|
+
|
88
|
+
new_subordinate = supervisor.actors.first
|
89
|
+
new_subordinate.should_not eq subordinate
|
90
|
+
new_subordinate.state.should be(:working)
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Celluloid::ThreadHandle do
|
4
|
+
it "knows thread liveliness" do
|
5
|
+
queue = Queue.new
|
6
|
+
handle = Celluloid::ThreadHandle.new { queue.pop }
|
7
|
+
handle.should be_alive
|
8
|
+
|
9
|
+
queue << :die
|
10
|
+
|
11
|
+
sleep 0.01 # hax
|
12
|
+
handle.should_not be_alive
|
13
|
+
end
|
14
|
+
|
15
|
+
it "joins to thread handles" do
|
16
|
+
Celluloid::ThreadHandle.new { sleep 0.01 }.join
|
17
|
+
end
|
18
|
+
|
19
|
+
it "supports passing a role" do
|
20
|
+
Celluloid::ThreadHandle.new(:useful) { Thread.current.role.should == :useful }.join
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Celluloid::UUID do
|
4
|
+
U = Celluloid::UUID
|
5
|
+
|
6
|
+
it "generates unique IDs across the BLOCK_SIZE boundary" do
|
7
|
+
upper_bound = U::BLOCK_SIZE * 2 + 10
|
8
|
+
uuids = (1..upper_bound).map{ U.generate }
|
9
|
+
uuids.size.should == uuids.uniq.size
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
|
+
require 'celluloid'
|
7
|
+
require 'celluloid/rspec'
|
8
|
+
|
9
|
+
logfile = File.open(File.expand_path("../../log/test.log", __FILE__), 'a')
|
10
|
+
logfile.sync = true
|
11
|
+
|
12
|
+
logger = Celluloid.logger = Logger.new(logfile)
|
13
|
+
|
14
|
+
Celluloid.shutdown_timeout = 1
|
15
|
+
|
16
|
+
Dir['./spec/support/*.rb'].map {|f| require f }
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.filter_run :focus => true
|
20
|
+
config.run_all_when_everything_filtered = true
|
21
|
+
|
22
|
+
config.before do
|
23
|
+
Celluloid.logger = logger
|
24
|
+
Celluloid.shutdown
|
25
|
+
sleep 0.01
|
26
|
+
|
27
|
+
Celluloid.internal_pool.assert_inactive
|
28
|
+
|
29
|
+
Celluloid.boot
|
30
|
+
end
|
31
|
+
end
|
@@ -34,6 +34,11 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
34
34
|
actor.object_id.should_not eq(Kernel.object_id)
|
35
35
|
end
|
36
36
|
|
37
|
+
it "implements respond_to? correctly" do
|
38
|
+
actor = actor_class.new 'Troy McClure'
|
39
|
+
actor.should respond_to(:alive?)
|
40
|
+
end
|
41
|
+
|
37
42
|
it "supports synchronous calls" do
|
38
43
|
actor = actor_class.new "Troy McClure"
|
39
44
|
actor.greet.should eq("Hi, I'm Troy McClure")
|
@@ -91,6 +96,36 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
91
96
|
ponycopter.greet_by_proxy(actor).should eq("Hi, I'm a ponycopter!")
|
92
97
|
end
|
93
98
|
|
99
|
+
it "detects recursion" do
|
100
|
+
klass1 = Class.new do
|
101
|
+
include included_module
|
102
|
+
task_class task_klass
|
103
|
+
|
104
|
+
def recursion_test(recurse_through = nil)
|
105
|
+
if recurse_through
|
106
|
+
recurse_through.recursion_thunk(Celluloid::Actor.current)
|
107
|
+
else
|
108
|
+
Celluloid.detect_recursion
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
klass2 = Class.new do
|
114
|
+
include included_module
|
115
|
+
task_class task_klass
|
116
|
+
|
117
|
+
def recursion_thunk(other)
|
118
|
+
other.recursion_test
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
actor1 = klass1.new
|
123
|
+
actor2 = klass2.new
|
124
|
+
|
125
|
+
actor1.recursion_test.should be_false
|
126
|
+
actor1.recursion_test(actor2).should be_true
|
127
|
+
end
|
128
|
+
|
94
129
|
it "properly handles method_missing" do
|
95
130
|
actor = actor_class.new "Method Missing"
|
96
131
|
actor.should respond_to(:first)
|
@@ -103,6 +138,24 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
103
138
|
actor.respond_to?(:zomg_private, true).should be_true
|
104
139
|
end
|
105
140
|
|
141
|
+
it "warns about suspending the initialize" do
|
142
|
+
klass = Class.new do
|
143
|
+
include included_module
|
144
|
+
task_class task_klass
|
145
|
+
|
146
|
+
def initialize
|
147
|
+
sleep 0.1
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
Celluloid.logger = double.as_null_object
|
152
|
+
Celluloid.logger.should_receive(:warn).with(/Dangerously suspending task: type=:call, meta={:method_name=>:initialize}, status=:sleeping/)
|
153
|
+
|
154
|
+
actor = klass.new
|
155
|
+
actor.terminate
|
156
|
+
Celluloid::Actor.join(actor) unless defined?(JRUBY_VERSION)
|
157
|
+
end
|
158
|
+
|
106
159
|
it "calls the user defined finalizer" do
|
107
160
|
actor = actor_class.new "Mr. Bean"
|
108
161
|
actor.wrapped_object.should_receive(:my_finalizer)
|
@@ -110,6 +163,26 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
110
163
|
Celluloid::Actor.join(actor)
|
111
164
|
end
|
112
165
|
|
166
|
+
it "warns about suspending the finalizer" do
|
167
|
+
klass = Class.new do
|
168
|
+
include included_module
|
169
|
+
task_class task_klass
|
170
|
+
|
171
|
+
finalizer :cleanup
|
172
|
+
|
173
|
+
def cleanup
|
174
|
+
sleep 0.1
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
Celluloid.logger = double.as_null_object
|
179
|
+
Celluloid.logger.should_receive(:warn).with(/Dangerously suspending task: type=:finalizer, meta={:method_name=>:cleanup}, status=:sleeping/)
|
180
|
+
|
181
|
+
actor = klass.new
|
182
|
+
actor.terminate
|
183
|
+
Celluloid::Actor.join(actor)
|
184
|
+
end
|
185
|
+
|
113
186
|
it "supports async(:method) syntax for asynchronous calls" do
|
114
187
|
actor = actor_class.new "Troy McClure"
|
115
188
|
actor.async :change_name, "Charlie Sheen"
|
@@ -162,6 +235,27 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
162
235
|
actor.inspect.should include('dead')
|
163
236
|
end
|
164
237
|
|
238
|
+
it "supports recursive inspect with other actors" do
|
239
|
+
klass = Class.new do
|
240
|
+
include included_module
|
241
|
+
task_class task_klass
|
242
|
+
|
243
|
+
attr_accessor :other
|
244
|
+
|
245
|
+
def initialize(other = nil)
|
246
|
+
@other = other
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
itchy = klass.new
|
251
|
+
scratchy = klass.new(itchy)
|
252
|
+
itchy.other = scratchy
|
253
|
+
|
254
|
+
inspection = itchy.inspect
|
255
|
+
inspection.should match(/Celluloid::ActorProxy\(/)
|
256
|
+
inspection.should include("...")
|
257
|
+
end
|
258
|
+
|
165
259
|
it "allows access to the wrapped object" do
|
166
260
|
actor = actor_class.new "Troy McClure"
|
167
261
|
actor.wrapped_object.should be_a actor_class
|
@@ -239,6 +333,8 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
239
333
|
actor = actor_class.new "James Dean"
|
240
334
|
actor.crash rescue nil
|
241
335
|
|
336
|
+
sleep 0.1 # hax to prevent a race between exit handling and the next call
|
337
|
+
|
242
338
|
expect do
|
243
339
|
actor.greet
|
244
340
|
end.to raise_exception(Celluloid::DeadActorError)
|
@@ -283,6 +379,14 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
283
379
|
actor.should_not be_alive
|
284
380
|
end
|
285
381
|
|
382
|
+
it "can be terminated by a SyncCall" do
|
383
|
+
actor = actor_class.new "Arnold Schwarzenegger"
|
384
|
+
actor.should be_alive
|
385
|
+
actor.shutdown
|
386
|
+
Celluloid::Actor.join(actor)
|
387
|
+
actor.should_not be_alive
|
388
|
+
end
|
389
|
+
|
286
390
|
it "kills" do # THOU SHALT ALWAYS KILL
|
287
391
|
actor = actor_class.new "Woody Harrelson"
|
288
392
|
actor.should be_alive
|
@@ -308,6 +412,17 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
308
412
|
actor.terminate!
|
309
413
|
end.to raise_exception(Celluloid::DeadActorError, "actor already terminated")
|
310
414
|
end
|
415
|
+
|
416
|
+
it "logs a warning when terminating tasks" do
|
417
|
+
Celluloid.logger = double.as_null_object
|
418
|
+
Celluloid.logger.should_receive(:warn).with("Terminating task: type=:call, meta={:method_name=>:sleepy}, status=:sleeping")
|
419
|
+
|
420
|
+
actor = actor_class.new "Arnold Schwarzenegger"
|
421
|
+
actor.async.sleepy 10
|
422
|
+
actor.greet # make sure the actor has started sleeping
|
423
|
+
|
424
|
+
actor.terminate
|
425
|
+
end
|
311
426
|
end
|
312
427
|
|
313
428
|
context :current_actor do
|
@@ -438,8 +553,6 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
438
553
|
raise "already signaled" if @signaled
|
439
554
|
|
440
555
|
@waiting = true
|
441
|
-
signal :future
|
442
|
-
|
443
556
|
value = wait :ponycopter
|
444
557
|
|
445
558
|
@waiting = false
|
@@ -447,11 +560,6 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
447
560
|
value
|
448
561
|
end
|
449
562
|
|
450
|
-
def wait_for_future
|
451
|
-
return true if @waiting
|
452
|
-
wait :future
|
453
|
-
end
|
454
|
-
|
455
563
|
def send_signal(value)
|
456
564
|
signal :ponycopter, value
|
457
565
|
end
|
@@ -467,9 +575,11 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
467
575
|
|
468
576
|
obj.async.wait_for_signal
|
469
577
|
obj.should_not be_signaled
|
578
|
+
obj.should be_waiting
|
470
579
|
|
471
580
|
obj.send_signal :foobar
|
472
581
|
obj.should be_signaled
|
582
|
+
obj.should_not be_waiting
|
473
583
|
end
|
474
584
|
|
475
585
|
it "sends values along with signals" do
|
@@ -478,7 +588,6 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
478
588
|
|
479
589
|
future = obj.future(:wait_for_signal)
|
480
590
|
|
481
|
-
obj.wait_for_future
|
482
591
|
obj.should be_waiting
|
483
592
|
obj.should_not be_signaled
|
484
593
|
|
@@ -799,12 +908,12 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
799
908
|
end
|
800
909
|
end
|
801
910
|
|
802
|
-
context :
|
911
|
+
context :mailbox_size do
|
803
912
|
subject do
|
804
913
|
Class.new do
|
805
914
|
include included_module
|
806
915
|
task_class task_klass
|
807
|
-
|
916
|
+
mailbox_size 100
|
808
917
|
end
|
809
918
|
end
|
810
919
|
|
@@ -857,4 +966,46 @@ shared_examples "Celluloid::Actor examples" do |included_module, task_klass|
|
|
857
966
|
subclass.new.tasks.first.should be_a ExampleTask
|
858
967
|
end
|
859
968
|
end
|
969
|
+
|
970
|
+
context :timeouts do
|
971
|
+
let :actor_class do
|
972
|
+
Class.new do
|
973
|
+
include included_module
|
974
|
+
|
975
|
+
def name
|
976
|
+
sleep 0.5
|
977
|
+
:foo
|
978
|
+
end
|
979
|
+
|
980
|
+
def ask_name_with_timeout(other, duration)
|
981
|
+
timeout(duration) { other.name }
|
982
|
+
end
|
983
|
+
end
|
984
|
+
end
|
985
|
+
|
986
|
+
it "allows timing out tasks, raising Celluloid::Task::TimeoutError" do
|
987
|
+
a1 = actor_class.new
|
988
|
+
a2 = actor_class.new
|
989
|
+
|
990
|
+
expect { a1.ask_name_with_timeout a2, 0.3 }.to raise_error(Celluloid::Task::TimeoutError)
|
991
|
+
end
|
992
|
+
|
993
|
+
it "does not raise when it completes in time" do
|
994
|
+
a1 = actor_class.new
|
995
|
+
a2 = actor_class.new
|
996
|
+
|
997
|
+
a1.ask_name_with_timeout(a2, 0.6).should == :foo
|
998
|
+
end
|
999
|
+
end
|
1000
|
+
|
1001
|
+
context "raw message sends" do
|
1002
|
+
it "logs on unhandled messages" do
|
1003
|
+
Celluloid.logger = double.as_null_object
|
1004
|
+
Celluloid.logger.should_receive(:debug).with("Discarded message (unhandled): first")
|
1005
|
+
|
1006
|
+
actor = actor_class.new "Irma Gladden"
|
1007
|
+
actor.mailbox << :first
|
1008
|
+
sleep Celluloid::TIMER_QUANTUM
|
1009
|
+
end
|
1010
|
+
end
|
860
1011
|
end
|