dramatis 0.0.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/History.txt +7 -0
- data/License.txt +20 -0
- data/Manifest.txt +119 -0
- data/README.txt +57 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +70 -0
- data/config/requirements.rb +17 -0
- data/examples/README.txt +20 -0
- data/examples/auction.rb +90 -0
- data/examples/bank/bank.rb +7 -0
- data/examples/bank/bank_test.rb +7 -0
- data/examples/exception.rb +40 -0
- data/examples/fib/conservative.rb +50 -0
- data/examples/fib/future.rb +5 -0
- data/examples/fib/original.rb +33 -0
- data/examples/fib/threads.rb +51 -0
- data/examples/im/distributed/chat/client.rb +49 -0
- data/examples/im/distributed/chat/screen/fox.rb +92 -0
- data/examples/im/distributed/chat/screen.rb +11 -0
- data/examples/im/distributed/chat/server.rb +72 -0
- data/examples/im/distributed/chat.rb +5 -0
- data/examples/im/distributed/client.rb +9 -0
- data/examples/im/distributed/run.rb +18 -0
- data/examples/im/distributed/server.rb +11 -0
- data/examples/im/single/chat/client.rb +50 -0
- data/examples/im/single/chat/screen/fox.rb +96 -0
- data/examples/im/single/chat/screen/wxs.rb +63 -0
- data/examples/im/single/chat/screen.rb +11 -0
- data/examples/im/single/chat/server.rb +72 -0
- data/examples/im/single/chat.rb +5 -0
- data/examples/im/single/fox.rb +18 -0
- data/examples/im/single/wxchat.rb +19 -0
- data/examples/pingpong/actor.rb +33 -0
- data/examples/pingpong/actor_rec.rb +34 -0
- data/examples/pingpong/pingpong.txt +315 -0
- data/examples/pingpong/scala.rb +41 -0
- data/examples/pingpong/serial.rb +26 -0
- data/examples/pretty.txt +108 -0
- data/examples/telephone/.irbrc +2 -0
- data/examples/telephone/3esl.txt +21877 -0
- data/examples/telephone/fifth/kid.rb +36 -0
- data/examples/telephone/fifth/run.rb +26 -0
- data/examples/telephone/first/kid.rb +31 -0
- data/examples/telephone/first/run.rb +20 -0
- data/examples/telephone/fourth/kid.rb +31 -0
- data/examples/telephone/fourth/run.rb +26 -0
- data/examples/telephone/mangler.rb +53 -0
- data/examples/telephone/second/kid.rb +26 -0
- data/examples/telephone/second/run.rb +20 -0
- data/examples/telephone/seventh/kid.rb +40 -0
- data/examples/telephone/seventh/run.rb +35 -0
- data/examples/telephone/seventh/test.rb +28 -0
- data/examples/telephone/seventh/test2.rb +10 -0
- data/examples/telephone/sixth/kid.rb +39 -0
- data/examples/telephone/sixth/run.rb +26 -0
- data/examples/telephone/third/kid.rb +31 -0
- data/examples/telephone/third/run.rb +21 -0
- data/lib/dramatis/actor/interface.rb +118 -0
- data/lib/dramatis/actor/name/interface.rb +128 -0
- data/lib/dramatis/actor/name.rb +44 -0
- data/lib/dramatis/actor.rb +96 -0
- data/lib/dramatis/deadlock.rb +123 -0
- data/lib/dramatis/error/uncaught.rb +19 -0
- data/lib/dramatis/error.rb +125 -0
- data/lib/dramatis/future/interface.rb +45 -0
- data/lib/dramatis/future.rb +32 -0
- data/lib/dramatis/runtime/actor/main.rb +3 -0
- data/lib/dramatis/runtime/actor.rb +294 -0
- data/lib/dramatis/runtime/gate.rb +244 -0
- data/lib/dramatis/runtime/scheduler.rb +374 -0
- data/lib/dramatis/runtime/task.rb +390 -0
- data/lib/dramatis/runtime/thread_pool.rb +149 -0
- data/lib/dramatis/runtime/timer.rb +5 -0
- data/lib/dramatis/runtime.rb +129 -0
- data/lib/dramatis/shoes/runtime.rb +7 -0
- data/lib/dramatis/shoes.rb +14 -0
- data/lib/dramatis/version.rb +8 -0
- data/lib/dramatis.rb +73 -0
- data/log/debug.log +0 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/dramatis/actor/become_spec.rb +17 -0
- data/spec/dramatis/actor/future_spec.rb +189 -0
- data/spec/dramatis/actor/name_spec.rb +141 -0
- data/spec/dramatis/actor/task_spec.rb +75 -0
- data/spec/dramatis/actor_spec.rb +492 -0
- data/spec/dramatis/dramatis_spec.rb +23 -0
- data/spec/dramatis/exc_spec.rb +78 -0
- data/spec/dramatis/runtime/gate_spec.rb +57 -0
- data/spec/dramatis/runtime/thread_pool.rb +30 -0
- data/spec/dramatis/shoes_spec.rb +11 -0
- data/spec/dramatis/simple_spec.rb +32 -0
- data/spec/exp_spec.rb +21 -0
- data/spec/simple2_spec.rb +36 -0
- data/spec/simple_spec.rb +30 -0
- data/spec/spec.opts +0 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/thread_spec.rb +13 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- data/test/jruby_lm.rb +13 -0
- data/test/test.rb +19 -0
- data/test/test10.rb +43 -0
- data/test/test11.rb +45 -0
- data/test/test12.rb +60 -0
- data/test/test13.rb +71 -0
- data/test/test2.rb +12 -0
- data/test/test3.rb +10 -0
- data/test/test4.rb +29 -0
- data/test/test5.rb +8 -0
- data/test/test6.rb +32 -0
- data/test/test7.rb +48 -0
- data/test/test8.rb +133 -0
- data/test/test9.rb +105 -0
- data/test/test_exc.rb +22 -0
- metadata +180 -0
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis/runtime'
|
|
4
|
+
require 'dramatis/actor/name'
|
|
5
|
+
|
|
6
|
+
# NB: don't use the module name here: rspec wants to include described
|
|
7
|
+
# modules ... and making the result into an actor, well, needless to say,
|
|
8
|
+
# it's not a good idea
|
|
9
|
+
|
|
10
|
+
describe "Dramatis::Actor" do
|
|
11
|
+
|
|
12
|
+
include Dramatis
|
|
13
|
+
|
|
14
|
+
include DramatisSpecHelper
|
|
15
|
+
|
|
16
|
+
after(:each) { runtime_check }
|
|
17
|
+
|
|
18
|
+
Actor = Dramatis::Actor
|
|
19
|
+
|
|
20
|
+
it "should be creatable from an include-ed class
|
|
21
|
+
and return the right type" do
|
|
22
|
+
|
|
23
|
+
f = Class.new do
|
|
24
|
+
include Dramatis::Actor
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
name = f.new
|
|
28
|
+
name.should be_a_kind_of( Actor::Name )
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should be possible to not get an actor name" do
|
|
33
|
+
|
|
34
|
+
f = Class.new do
|
|
35
|
+
include Dramatis::Actor
|
|
36
|
+
class << self
|
|
37
|
+
remove_method :new
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
name = f.new
|
|
42
|
+
name.should be_a_kind_of( f )
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should create a new name when invoked with new" do
|
|
47
|
+
name = Actor.new Object.new
|
|
48
|
+
name.should be_a_kind_of( Actor::Name )
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should deadlock if an rpc is made to an unbound name" do
|
|
52
|
+
lambda { Dramatis::Actor.new.foo }.should raise_error( Dramatis::Deadlock )
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should return NoMethodError even when not a direct call" do
|
|
56
|
+
cls = Class.new do
|
|
57
|
+
include Dramatis::Actor
|
|
58
|
+
def rpc other
|
|
59
|
+
other.foo
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
a = cls.new
|
|
63
|
+
b = cls.new
|
|
64
|
+
lambda { a.rpc b }.should raise_error( NoMethodError )
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should obey refuse" do
|
|
68
|
+
a = Class.new do
|
|
69
|
+
include Dramatis::Actor
|
|
70
|
+
def initialize
|
|
71
|
+
actor.refuse :fromB
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
b = Class.new do
|
|
76
|
+
include Dramatis::Actor
|
|
77
|
+
def initialize anA
|
|
78
|
+
@anA = anA
|
|
79
|
+
end
|
|
80
|
+
def startB
|
|
81
|
+
@anA.fromB
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
anA = a.new
|
|
86
|
+
aB = b.new anA
|
|
87
|
+
|
|
88
|
+
( interface( aB ).continue nil ).startB
|
|
89
|
+
|
|
90
|
+
Dramatis::Runtime.current.warnings = false
|
|
91
|
+
|
|
92
|
+
lambda {
|
|
93
|
+
begin
|
|
94
|
+
Dramatis::Runtime.current.at_exit
|
|
95
|
+
rescue Dramatis::Error::Uncaught => uc
|
|
96
|
+
raise uc
|
|
97
|
+
end
|
|
98
|
+
}.should raise_error( Dramatis::Error::Uncaught )
|
|
99
|
+
|
|
100
|
+
Dramatis::Runtime.current.warnings = true
|
|
101
|
+
|
|
102
|
+
Dramatis::Runtime.reset
|
|
103
|
+
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should obey refuse and then recover with default" do
|
|
107
|
+
|
|
108
|
+
a = Class.new do
|
|
109
|
+
include Dramatis::Actor
|
|
110
|
+
def initialize
|
|
111
|
+
actor.refuse :fromB
|
|
112
|
+
end
|
|
113
|
+
def allow
|
|
114
|
+
actor.default :fromB
|
|
115
|
+
class << self
|
|
116
|
+
def fromB; end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
b = Class.new do
|
|
122
|
+
include Dramatis::Actor
|
|
123
|
+
include Dramatis::Actor
|
|
124
|
+
def initialize anA
|
|
125
|
+
@anA = anA
|
|
126
|
+
@count = 0
|
|
127
|
+
actor.always :count, true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def startB
|
|
131
|
+
@anA.fromB
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def count
|
|
135
|
+
@count
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def increment
|
|
139
|
+
@count += 1
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
anA = a.new
|
|
144
|
+
aB = b.new anA
|
|
145
|
+
|
|
146
|
+
aB_cast = interface( aB ).continue nil
|
|
147
|
+
|
|
148
|
+
aB.count.should equal( 0 )
|
|
149
|
+
|
|
150
|
+
aB.increment
|
|
151
|
+
|
|
152
|
+
aB.count.should equal( 1 )
|
|
153
|
+
|
|
154
|
+
aB_cast.increment
|
|
155
|
+
|
|
156
|
+
Dramatis::Runtime.current.quiesce
|
|
157
|
+
|
|
158
|
+
aB.count.should equal( 2 )
|
|
159
|
+
|
|
160
|
+
aB_cast.startB
|
|
161
|
+
aB_cast.increment
|
|
162
|
+
|
|
163
|
+
Dramatis::Runtime.current.quiesce
|
|
164
|
+
|
|
165
|
+
aB.count.should equal( 2 )
|
|
166
|
+
|
|
167
|
+
anA.allow
|
|
168
|
+
|
|
169
|
+
Dramatis::Runtime.current.quiesce
|
|
170
|
+
|
|
171
|
+
aB.count.should equal( 3 )
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should block calls when in an rpc is inflight and there is no call threading" do
|
|
175
|
+
|
|
176
|
+
a = Class.new do
|
|
177
|
+
|
|
178
|
+
include Dramatis::Actor
|
|
179
|
+
|
|
180
|
+
def initialize
|
|
181
|
+
actor.refuse :fromB
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def allow
|
|
185
|
+
actor.default :fromB
|
|
186
|
+
|
|
187
|
+
# just for the hell of it,
|
|
188
|
+
# def fromB here; if called earlier
|
|
189
|
+
# should fail making timing errors
|
|
190
|
+
# more obvious
|
|
191
|
+
|
|
192
|
+
class << self
|
|
193
|
+
def fromB; end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
b = Class.new do
|
|
201
|
+
|
|
202
|
+
include Dramatis::Actor
|
|
203
|
+
|
|
204
|
+
def initialize anA
|
|
205
|
+
@anA = anA
|
|
206
|
+
@count = 0
|
|
207
|
+
actor.always :count, true
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def startB
|
|
211
|
+
@anA.fromB
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def count
|
|
215
|
+
@count
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def increment
|
|
219
|
+
@count += 1
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def shouldDeadlock; end
|
|
223
|
+
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
anA = a.new
|
|
227
|
+
aB = b.new anA
|
|
228
|
+
|
|
229
|
+
aB_cast = interface( aB ).continue nil
|
|
230
|
+
|
|
231
|
+
aB.count.should equal( 0 )
|
|
232
|
+
|
|
233
|
+
aB.increment
|
|
234
|
+
|
|
235
|
+
aB.count.should equal( 1 )
|
|
236
|
+
|
|
237
|
+
aB_cast.increment
|
|
238
|
+
|
|
239
|
+
Dramatis::Runtime.current.quiesce
|
|
240
|
+
|
|
241
|
+
aB.count.should equal( 2 )
|
|
242
|
+
|
|
243
|
+
aB_cast.startB
|
|
244
|
+
aB_cast.increment
|
|
245
|
+
|
|
246
|
+
Dramatis::Runtime.current.quiesce
|
|
247
|
+
|
|
248
|
+
aB.count.should equal( 2 )
|
|
249
|
+
|
|
250
|
+
Dramatis::Runtime.current.exceptions.length.should equal( 0 )
|
|
251
|
+
|
|
252
|
+
Dramatis::Runtime.current.warnings = false
|
|
253
|
+
|
|
254
|
+
lambda { aB.shouldDeadlock }.should raise_error( Dramatis::Deadlock )
|
|
255
|
+
|
|
256
|
+
lambda { Dramatis::Runtime.current.quiesce }.should raise_error( Dramatis::Error::Uncaught )
|
|
257
|
+
|
|
258
|
+
Dramatis::Runtime.current.warnings = true
|
|
259
|
+
|
|
260
|
+
Dramatis::Runtime.current.exceptions.length.should equal( 2 )
|
|
261
|
+
|
|
262
|
+
Dramatis::Runtime.current.clear_exceptions
|
|
263
|
+
|
|
264
|
+
Dramatis::Runtime.current.exceptions.length.should equal( 0 )
|
|
265
|
+
|
|
266
|
+
aB.count.should equal( 2 )
|
|
267
|
+
|
|
268
|
+
anA.allow
|
|
269
|
+
|
|
270
|
+
aB_cast.startB
|
|
271
|
+
aB_cast.increment
|
|
272
|
+
|
|
273
|
+
Dramatis::Runtime.current.quiesce
|
|
274
|
+
|
|
275
|
+
aB.count.should equal( 3 )
|
|
276
|
+
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "should block on recursion in the non-call threaded case" do
|
|
280
|
+
a = Class.new do
|
|
281
|
+
include Dramatis::Actor
|
|
282
|
+
def a
|
|
283
|
+
actor.name.b
|
|
284
|
+
end
|
|
285
|
+
def b; end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
lambda { a.new.a }.should raise_error( Dramatis::Deadlock )
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "should block block continuations during an rpc w/o call threading " do
|
|
292
|
+
a = Class.new do
|
|
293
|
+
include Dramatis::Actor
|
|
294
|
+
attr_reader :block_called
|
|
295
|
+
def initialize
|
|
296
|
+
@block_called = false
|
|
297
|
+
actor.refuse :c
|
|
298
|
+
actor.always :block_called, true
|
|
299
|
+
end
|
|
300
|
+
def a other
|
|
301
|
+
block = lambda { |c| @block_called = true }
|
|
302
|
+
( interface( other ).continue( &block ) ).b
|
|
303
|
+
other.c
|
|
304
|
+
end
|
|
305
|
+
def enable
|
|
306
|
+
actor.default :c
|
|
307
|
+
end
|
|
308
|
+
def b; end
|
|
309
|
+
def c; end
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
a1 = a.new
|
|
313
|
+
a2 = a.new
|
|
314
|
+
( interface( a1 ).continue nil ).a a2
|
|
315
|
+
|
|
316
|
+
Dramatis::Runtime.current.quiesce
|
|
317
|
+
|
|
318
|
+
a1.block_called.should be_false
|
|
319
|
+
|
|
320
|
+
a2.enable
|
|
321
|
+
|
|
322
|
+
Dramatis::Runtime.current.quiesce
|
|
323
|
+
|
|
324
|
+
a1.block_called.should be_true
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "should call exception blocks on exceptions" do
|
|
328
|
+
a = Class.new do
|
|
329
|
+
include Dramatis::Actor
|
|
330
|
+
attr_reader :block_called, :exception_raised
|
|
331
|
+
def initialize
|
|
332
|
+
actor.refuse :c
|
|
333
|
+
actor.always :block_called, true
|
|
334
|
+
actor.always :exception_raised, true
|
|
335
|
+
@block_called = @exception_raised = false
|
|
336
|
+
end
|
|
337
|
+
def a other
|
|
338
|
+
result = lambda { |r| @block_called = true }
|
|
339
|
+
except = lambda do |exception|
|
|
340
|
+
|
|
341
|
+
# FIX: lambda is overridden, I think, so get it back to
|
|
342
|
+
# the spec class and normal processing should work
|
|
343
|
+
|
|
344
|
+
# rspec seems to have problems with normal "should" stuff
|
|
345
|
+
# in this block ... this causes a failure, which is good
|
|
346
|
+
# (though it does cascacde, which isn't great, but not worth
|
|
347
|
+
# tracking down).
|
|
348
|
+
raise exception if exception.to_s != "hell"
|
|
349
|
+
@exception_raised = true
|
|
350
|
+
end
|
|
351
|
+
( interface( other ).continue :exception => except, &result ).bb
|
|
352
|
+
( interface( other ).continue :exception => except, &result ).b
|
|
353
|
+
other.c
|
|
354
|
+
end
|
|
355
|
+
def enable
|
|
356
|
+
actor.default :c
|
|
357
|
+
end
|
|
358
|
+
def bb; end
|
|
359
|
+
def b
|
|
360
|
+
raise "hell"
|
|
361
|
+
end
|
|
362
|
+
def c; end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
a1 = a.new
|
|
366
|
+
a2 = a.new
|
|
367
|
+
( interface( a1 ).continue nil ).a a2
|
|
368
|
+
|
|
369
|
+
Dramatis::Runtime.current.quiesce
|
|
370
|
+
|
|
371
|
+
a1.block_called.should be_false
|
|
372
|
+
a1.exception_raised.should be_true
|
|
373
|
+
|
|
374
|
+
a2.enable
|
|
375
|
+
|
|
376
|
+
Dramatis::Runtime.current.quiesce
|
|
377
|
+
|
|
378
|
+
a1.block_called.should be_true
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
it "should allow recursion and corecursion when call threading enabled" do
|
|
382
|
+
a = Class.new do
|
|
383
|
+
include Dramatis::Actor
|
|
384
|
+
def initialize
|
|
385
|
+
actor.enable_call_threading
|
|
386
|
+
end
|
|
387
|
+
def a
|
|
388
|
+
actor.name.b
|
|
389
|
+
end
|
|
390
|
+
def b; end
|
|
391
|
+
def c
|
|
392
|
+
other = self.class.new
|
|
393
|
+
other.d actor.name
|
|
394
|
+
end
|
|
395
|
+
def d first
|
|
396
|
+
first.a
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
a.new.a # recursion
|
|
400
|
+
a.new.c # co-recursion
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it "should map self returns into an actor name" do
|
|
404
|
+
a = Class.new do
|
|
405
|
+
include Dramatis::Actor
|
|
406
|
+
def me
|
|
407
|
+
self
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
anA = a.new
|
|
411
|
+
anA.should be_kind_of( Dramatis::Actor::Name )
|
|
412
|
+
anA.me.should be_kind_of( Dramatis::Actor::Name )
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
it "should map self in actor method calls to name" do
|
|
416
|
+
a = Class.new do
|
|
417
|
+
include Dramatis::Actor
|
|
418
|
+
def test
|
|
419
|
+
actor.always :f, true
|
|
420
|
+
actor.name.f self
|
|
421
|
+
end
|
|
422
|
+
def f ref
|
|
423
|
+
ref.object_id != self.object_id
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
anA = a.new
|
|
427
|
+
anA.test.should be_true
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it "should raise deadlocks with pretty backtraces" do
|
|
431
|
+
|
|
432
|
+
a = Class.new do
|
|
433
|
+
include Dramatis::Actor
|
|
434
|
+
def deadlock
|
|
435
|
+
@@first_line = __LINE__.to_i + 1
|
|
436
|
+
actor.name.deadlock
|
|
437
|
+
end
|
|
438
|
+
def self.first_line
|
|
439
|
+
@@first_line
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
anA = a.new
|
|
444
|
+
|
|
445
|
+
second_line = nil
|
|
446
|
+
|
|
447
|
+
begin
|
|
448
|
+
second_line = __LINE__.to_i + 1
|
|
449
|
+
anA.deadlock
|
|
450
|
+
raise "fail: should not get here"
|
|
451
|
+
rescue Dramatis::Deadlock => deadlock
|
|
452
|
+
bt = deadlock.backtrace
|
|
453
|
+
|
|
454
|
+
# pp bt
|
|
455
|
+
|
|
456
|
+
f, l = bt[0].split ':'
|
|
457
|
+
f.should == __FILE__
|
|
458
|
+
l.to_i.should == a.first_line
|
|
459
|
+
|
|
460
|
+
f, l = bt[1].split ':'
|
|
461
|
+
f.should == __FILE__
|
|
462
|
+
l.to_i.should == second_line
|
|
463
|
+
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
it "should yield when asked to" do
|
|
469
|
+
|
|
470
|
+
c = Class.new do
|
|
471
|
+
include Dramatis::Actor
|
|
472
|
+
def f
|
|
473
|
+
@a = 1
|
|
474
|
+
@a.should == 1
|
|
475
|
+
release( actor.name ).g
|
|
476
|
+
sleep 1
|
|
477
|
+
@a.should == 1
|
|
478
|
+
actor.yield
|
|
479
|
+
@a.should == 2
|
|
480
|
+
return @a
|
|
481
|
+
end
|
|
482
|
+
def g
|
|
483
|
+
@a += 1
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
aC = c.new
|
|
488
|
+
aC.f.should == 2
|
|
489
|
+
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis'
|
|
4
|
+
|
|
5
|
+
describe Dramatis do
|
|
6
|
+
|
|
7
|
+
it "should send exceptions to actors in the non-rpc case"
|
|
8
|
+
|
|
9
|
+
it "should give nice continuation-based backtraces on exceptions"
|
|
10
|
+
|
|
11
|
+
it "should not swallow exceptions when the continuation is null"
|
|
12
|
+
|
|
13
|
+
it "should limit actor() access"
|
|
14
|
+
|
|
15
|
+
it "should allow behavor access(?)"
|
|
16
|
+
|
|
17
|
+
it "should have a nice way to cast actor creation"
|
|
18
|
+
|
|
19
|
+
it "should allow threads to be locked to actors, e.g., for fox"
|
|
20
|
+
|
|
21
|
+
it "should gc actors"
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis/actor'
|
|
4
|
+
require 'dramatis/runtime'
|
|
5
|
+
|
|
6
|
+
# NB: don't use the module name here: rspec wants to include described
|
|
7
|
+
# modules ... and making the result into an actor, well, needless to say,
|
|
8
|
+
# it's not a good idea
|
|
9
|
+
|
|
10
|
+
describe "Dramatis::Actor" do
|
|
11
|
+
|
|
12
|
+
include DramatisSpecHelper
|
|
13
|
+
|
|
14
|
+
after(:each) { runtime_check }
|
|
15
|
+
|
|
16
|
+
it "should provide pretty backtraces" do
|
|
17
|
+
|
|
18
|
+
foo = Class.new do
|
|
19
|
+
include Dramatis::Actor
|
|
20
|
+
|
|
21
|
+
@@first_line = nil
|
|
22
|
+
|
|
23
|
+
def self.first_line
|
|
24
|
+
return @@first_line
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def foo that
|
|
28
|
+
@@first_line = __LINE__.to_i + 1
|
|
29
|
+
return that.bar
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
bar = Class.new do
|
|
35
|
+
include Dramatis::Actor
|
|
36
|
+
|
|
37
|
+
@@second_line = nil
|
|
38
|
+
|
|
39
|
+
def self.second_line
|
|
40
|
+
return @@second_line
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def bar
|
|
44
|
+
@@second_line = __LINE__.to_i + 1
|
|
45
|
+
name_error
|
|
46
|
+
return "foobar"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
aFoo = foo.new
|
|
52
|
+
aBar = bar.new
|
|
53
|
+
okay = false
|
|
54
|
+
r = "xyzzy"
|
|
55
|
+
begin
|
|
56
|
+
r = aFoo.foo aBar
|
|
57
|
+
rescue NameError => ne
|
|
58
|
+
tb = ne.backtrace
|
|
59
|
+
|
|
60
|
+
# puts tb.join("\n")
|
|
61
|
+
|
|
62
|
+
f,l = tb[0].split ":"
|
|
63
|
+
f.should == __FILE__
|
|
64
|
+
l.to_i.should == bar.second_line
|
|
65
|
+
|
|
66
|
+
f,l = tb[1].split ":"
|
|
67
|
+
f.should == __FILE__
|
|
68
|
+
l.to_i.should == foo.first_line
|
|
69
|
+
|
|
70
|
+
okay = true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
r.should == "xyzzy"
|
|
74
|
+
okay.should be_true
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis/runtime/gate'
|
|
4
|
+
|
|
5
|
+
describe Dramatis::Runtime::Gate do
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
@gate = Dramatis::Runtime::Gate.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should accept simple defaults" do
|
|
12
|
+
@gate.accepts?( :actor ).should be_true
|
|
13
|
+
@gate.accepts?( :continuation ).should be_true
|
|
14
|
+
@gate.accepts?( :object ).should be_true
|
|
15
|
+
@gate.accepts?( :foo ).should be_true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should return the gate list" do
|
|
19
|
+
@gate.list.should == [ [[:object], true],
|
|
20
|
+
[[:continuation], true],
|
|
21
|
+
[[:actor], true],
|
|
22
|
+
[[Object], true] ]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should obey simple changes" do
|
|
26
|
+
@gate.refuse :object
|
|
27
|
+
@gate.accepts?( :object ).should be_false
|
|
28
|
+
@gate.list.should == [ [[:object], false],
|
|
29
|
+
[[:continuation], true],
|
|
30
|
+
[[:actor], true],
|
|
31
|
+
[[Object], true] ]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should reorder on change" do
|
|
35
|
+
@gate.refuse :actor
|
|
36
|
+
@gate.accepts?( :actor ).should be_false
|
|
37
|
+
@gate.list.should == [ [[:actor], false],
|
|
38
|
+
[[:object], true],
|
|
39
|
+
[[:continuation], true],
|
|
40
|
+
[[Object], true] ]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should reorder on no change" do
|
|
44
|
+
@gate.accept :actor
|
|
45
|
+
@gate.accepts?( :actor ).should be_true
|
|
46
|
+
@gate.list.should == [ [[:actor], true],
|
|
47
|
+
[[:object], true],
|
|
48
|
+
[[:continuation], true],
|
|
49
|
+
[[Object], true] ]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should obey simple changes" do
|
|
53
|
+
@gate.refuse :object
|
|
54
|
+
@gate.accepts?( :object ).should be_false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis/runtime/thread_pool'
|
|
4
|
+
|
|
5
|
+
describe Dramatis::Runtime::ThreadPool do
|
|
6
|
+
|
|
7
|
+
it "should be resetable" do
|
|
8
|
+
thread_pool = Dramatis::Runtime::ThreadPool.new
|
|
9
|
+
thread_pool.reset
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# this could be done with join, but is not currently
|
|
13
|
+
# needed for anything but the test, so ...
|
|
14
|
+
it "should allocate threads that do stuff" do
|
|
15
|
+
thread_pool = Dramatis::Runtime::ThreadPool.new
|
|
16
|
+
@x = 1
|
|
17
|
+
t = thread_pool.new do
|
|
18
|
+
sleep 0.1
|
|
19
|
+
@x = 2
|
|
20
|
+
end
|
|
21
|
+
@x.should == 1
|
|
22
|
+
thread_pool.length.should == 0
|
|
23
|
+
sleep 0.2
|
|
24
|
+
@x.should == 2
|
|
25
|
+
thread_pool.length.should == 1
|
|
26
|
+
thread_pool.reset
|
|
27
|
+
thread_pool.length.should == 0
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require File.join( File.dirname(__FILE__), "..", '/spec_helper.rb' )
|
|
2
|
+
|
|
3
|
+
require 'dramatis/actor'
|
|
4
|
+
require 'dramatis/runtime'
|
|
5
|
+
|
|
6
|
+
# NB: don't use the module name here: rspec wants to include described
|
|
7
|
+
# modules ... and making the result into an actor, well, needless to say,
|
|
8
|
+
# it's not a good idea
|
|
9
|
+
|
|
10
|
+
describe "Dramatis::Actor" do
|
|
11
|
+
|
|
12
|
+
include DramatisSpecHelper
|
|
13
|
+
|
|
14
|
+
after(:each) { runtime_check }
|
|
15
|
+
|
|
16
|
+
it "should be creatable w/o requiring name" do
|
|
17
|
+
|
|
18
|
+
f = Class.new do
|
|
19
|
+
include Dramatis::Actor
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
name = f.new
|
|
23
|
+
|
|
24
|
+
# if we get here, we're fine
|
|
25
|
+
# is there an rspec "something" for this?
|
|
26
|
+
# note, this doesn't "test" in autotest,
|
|
27
|
+
# probably because it's eval'ing other tests that
|
|
28
|
+
# do bring in Actor::Name
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|