extlib 0.9.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of extlib might be problematic. Click here for more details.

@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe Module do
4
+
5
+ before(:all) do
6
+ module Foo
7
+ class Bar
8
+ end
9
+ end
10
+
11
+ class Baz
12
+ end
13
+
14
+ class Bar
15
+ end
16
+ end
17
+
18
+ it "should be able to get a recursive constant" do
19
+ Object::find_const('Foo::Bar').should == Foo::Bar
20
+ end
21
+
22
+ it "should ignore get Constants from the Kernel namespace correctly" do
23
+ Object::find_const('::Foo::Bar').should == ::Foo::Bar
24
+ end
25
+
26
+ it "should not cache unresolvable class string" do
27
+ lambda { find_const('Foo::Bar::Baz') }.should raise_error(NameError)
28
+ Object::send(:__nested_constants__).has_key?('Foo::Bar::Baz').should == false
29
+ end
30
+
31
+ it "should find relative constants" do
32
+ Foo.find_const('Bar').should == Foo::Bar
33
+ Foo.find_const('Baz').should == Baz
34
+ end
35
+
36
+ end
@@ -0,0 +1,4 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe Object do
4
+ end
@@ -0,0 +1,490 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+ require 'timeout'
3
+
4
+ describe "Extlib::Pooling" do
5
+ before(:all) do
6
+
7
+ module Extlib::Pooling
8
+ def self.scavenger_interval
9
+ 0.1
10
+ end
11
+ end
12
+
13
+ class Person
14
+ include Extlib::Pooling
15
+
16
+ attr_accessor :name
17
+
18
+ def initialize(name)
19
+ @name = name
20
+ end
21
+
22
+ def dispose
23
+ @name = nil
24
+ end
25
+
26
+ def self.scavenge_interval
27
+ 0.2
28
+ end
29
+ end
30
+
31
+ class Overwriter
32
+
33
+ def self.new(*args)
34
+ instance = allocate
35
+ instance.send(:initialize, *args)
36
+ instance.overwritten = true
37
+ instance
38
+ end
39
+
40
+ include Extlib::Pooling
41
+
42
+ attr_accessor :name
43
+
44
+ def initialize(name)
45
+ @name = name
46
+ @overwritten = false
47
+ end
48
+
49
+ def overwritten?
50
+ @overwritten
51
+ end
52
+
53
+ def overwritten=(value)
54
+ @overwritten = value
55
+ end
56
+
57
+ def self.pool_size
58
+ pool_size = if RUBY_PLATFORM =~ /java/
59
+ 20
60
+ else
61
+ 2
62
+ end
63
+ pool_size
64
+ end
65
+
66
+ def dispose
67
+ @name = nil
68
+ end
69
+ end
70
+ end
71
+
72
+ it "should track the initialized pools" do
73
+ bob = Person.new('Bob') # Ensure the pool is "primed"
74
+ bob.name.should == 'Bob'
75
+ bob.instance_variable_get(:@__pool).should_not be_nil
76
+ Person.__pools.size.should == 1
77
+ bob.release
78
+ Person.__pools.size.should == 1
79
+
80
+ Extlib::Pooling::pools.should_not be_empty
81
+ sleep(1)
82
+ Extlib::Pooling::pools.should be_empty
83
+ bob.name.should be_nil
84
+ end
85
+
86
+ it "should maintain a size of 1" do
87
+ bob = Person.new('Bob')
88
+ fred = Person.new('Fred')
89
+ ted = Person.new('Ted')
90
+
91
+ Person.__pools.each do |args, pool|
92
+ pool.size.should == 1
93
+ end
94
+
95
+ bob.release
96
+ fred.release
97
+ ted.release
98
+
99
+ Person.__pools.each do |args, pool|
100
+ pool.size.should == 1
101
+ end
102
+ end
103
+
104
+ it "should allow you to overwrite Class#new" do
105
+ bob = Overwriter.new('Bob')
106
+ bob.should be_overwritten
107
+ bob.release
108
+ end
109
+
110
+ it "should raise a ThreadStopError when the pool is exhausted in a single thread" do
111
+ lambda do
112
+ begin
113
+ bob = Person.new('Bob')
114
+ Person.new('Bob')
115
+ ensure
116
+ bob.release
117
+ end
118
+ end.should raise_error(Extlib::Pooling::ThreadStopError)
119
+ end
120
+
121
+ it "should allow multiple threads to access the pool" do
122
+ t1 = Thread.new do
123
+ bob = Person.new('Bob')
124
+ sleep(0.1)
125
+ bob.release
126
+ end
127
+
128
+ lambda do
129
+ bob = Person.new('Bob')
130
+ t1.join
131
+ bob.release
132
+ end.should_not raise_error(Extlib::Pooling::ThreadStopError)
133
+ end
134
+
135
+ it "should allow you to flush a pool" do
136
+ bob = Overwriter.new('Bob')
137
+ Overwriter.new('Bob').release
138
+ bob.release
139
+
140
+ bob.name.should == 'Bob'
141
+
142
+ Overwriter.__pools[['Bob']].size.should == 2
143
+ Overwriter.__pools[['Bob']].flush!
144
+ Overwriter.__pools[['Bob']].size.should == 0
145
+
146
+ bob.name.should be_nil
147
+ end
148
+ end
149
+
150
+ # describe Extlib::Pooling::ResourcePool do
151
+ # before :each do
152
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, :expiration_period => 50)
153
+ # end
154
+ #
155
+ # it "responds to flush!" do
156
+ # @pool.should respond_to(:flush!)
157
+ # end
158
+ #
159
+ # it "responds to aquire" do
160
+ # @pool.should respond_to(:aquire)
161
+ # end
162
+ #
163
+ # it "responds to release" do
164
+ # @pool.should respond_to(:release)
165
+ # end
166
+ #
167
+ # it "responds to :available?" do
168
+ # @pool.should respond_to(:available?)
169
+ # end
170
+ #
171
+ # it "has a size limit" do
172
+ # @pool.size_limit.should == 7
173
+ # end
174
+ #
175
+ # it "has initial size of zero" do
176
+ # @pool.size.should == 0
177
+ # end
178
+ #
179
+ # it "has a set of reserved resources" do
180
+ # @pool.instance_variable_get("@reserved").should be_empty
181
+ # end
182
+ #
183
+ # it "has a set of available resources" do
184
+ # @pool.instance_variable_get("@available").should be_empty
185
+ # end
186
+ #
187
+ # it "knows class of resources (objects) it works with" do
188
+ # @pool.class_of_resources.should == DisposableResource
189
+ # end
190
+ #
191
+ # it "raises exception when given anything but class for resources class" do
192
+ # lambda {
193
+ # @pool = Extlib::Pooling::ResourcePool.new(7, "Hooray!", {})
194
+ # }.should raise_error(ArgumentError, /class/)
195
+ # end
196
+ #
197
+ # it "requires class of resources (objects) it works with to have a dispose instance method" do
198
+ # lambda {
199
+ # @pool = Extlib::Pooling::ResourcePool.new(3, UndisposableResource, {})
200
+ # }.should raise_error(ArgumentError, /dispose/)
201
+ # end
202
+ #
203
+ # it "may take initialization arguments" do
204
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, { :initialization_args => ["paper"] })
205
+ # @pool.instance_variable_get("@initialization_args").should == ["paper"]
206
+ # end
207
+ #
208
+ # it "may take expiration period option" do
209
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, { :expiration_period => 100 })
210
+ # @pool.expiration_period.should == 100
211
+ # end
212
+ #
213
+ # it "has default expiration period of one minute" do
214
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, {})
215
+ # @pool.expiration_period.should == 60
216
+ # end
217
+ #
218
+ # it "spawns a thread to dispose objects haven't been used for a while" do
219
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, {})
220
+ # @pool.instance_variable_get("@pool_expiration_thread").should be_an_instance_of(Thread)
221
+ # end
222
+ # end
223
+ #
224
+ #
225
+ #
226
+ # describe "Aquire from contant size pool" do
227
+ # before :each do
228
+ # DisposableResource.initialize_pool(2)
229
+ # end
230
+ #
231
+ # after :each do
232
+ # DisposableResource.instance_variable_set("@__pool", nil)
233
+ # end
234
+ #
235
+ # it "increased size of the pool" do
236
+ # @time = DisposableResource.pool.aquire
237
+ # DisposableResource.pool.size.should == 1
238
+ # end
239
+ #
240
+ # it "places initialized instance in the reserved set" do
241
+ # @time = DisposableResource.pool.aquire
242
+ # DisposableResource.pool.instance_variable_get("@reserved").size.should == 1
243
+ # end
244
+ #
245
+ # it "raises an exception when pool size limit is hit" do
246
+ # @t1 = DisposableResource.pool.aquire
247
+ # @t2 = DisposableResource.pool.aquire
248
+ #
249
+ # lambda { DisposableResource.pool.aquire }.should raise_error(RuntimeError)
250
+ # end
251
+ #
252
+ # it "returns last released resource" do
253
+ # @t1 = DisposableResource.pool.aquire
254
+ # @t2 = DisposableResource.pool.aquire
255
+ # DisposableResource.pool.release(@t1)
256
+ #
257
+ # DisposableResource.pool.aquire.should == @t1
258
+ # end
259
+ #
260
+ # it "really truly returns last released resource" do
261
+ # @t1 = DisposableResource.pool.aquire
262
+ # DisposableResource.pool.release(@t1)
263
+ #
264
+ # @t2 = DisposableResource.pool.aquire
265
+ # DisposableResource.pool.release(@t2)
266
+ #
267
+ # @t3 = DisposableResource.pool.aquire
268
+ # DisposableResource.pool.release(@t3)
269
+ #
270
+ # DisposableResource.pool.aquire.should == @t1
271
+ # @t1.should == @t3
272
+ # end
273
+ #
274
+ # it "sets allocation timestamp on resource instance" do
275
+ # @t1 = DisposableResource.new
276
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
277
+ # end
278
+ # end
279
+ #
280
+ #
281
+ #
282
+ # describe "Releasing from contant size pool" do
283
+ # before :each do
284
+ # DisposableResource.initialize_pool(2)
285
+ # end
286
+ #
287
+ # after :each do
288
+ # DisposableResource.instance_variable_set("@__pool", nil)
289
+ # end
290
+ #
291
+ # it "decreases size of the pool" do
292
+ # @t1 = DisposableResource.pool.aquire
293
+ # @t2 = DisposableResource.pool.aquire
294
+ # DisposableResource.pool.release(@t1)
295
+ #
296
+ # DisposableResource.pool.size.should == 1
297
+ # end
298
+ #
299
+ # it "raises an exception on attempt to releases object not in pool" do
300
+ # @t1 = DisposableResource.new
301
+ # @t2 = Set.new
302
+ #
303
+ # DisposableResource.pool.release(@t1)
304
+ # lambda { DisposableResource.pool.release(@t2) }.should raise_error(RuntimeError)
305
+ # end
306
+ #
307
+ # it "removes released object from reserved set" do
308
+ # @t1 = DisposableResource.pool.aquire
309
+ #
310
+ # lambda {
311
+ # DisposableResource.pool.release(@t1)
312
+ # }.should change(DisposableResource.pool.instance_variable_get("@reserved"), :size).by(-1)
313
+ # end
314
+ #
315
+ # it "returns released object back to available set" do
316
+ # @t1 = DisposableResource.pool.aquire
317
+ #
318
+ # lambda {
319
+ # DisposableResource.pool.release(@t1)
320
+ # }.should change(DisposableResource.pool.instance_variable_get("@available"), :size).by(1)
321
+ # end
322
+ #
323
+ # it "updates aquire timestamp on already allocated resource instance" do
324
+ # # aquire it once
325
+ # @t1 = DisposableResource.new
326
+ # # wait a bit
327
+ # sleep 3
328
+ #
329
+ # # check old timestamp
330
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 4)
331
+ #
332
+ # # re-aquire
333
+ # DisposableResource.pool.release(@t1)
334
+ # @t1 = DisposableResource.new
335
+ # # see timestamp is updated
336
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
337
+ # end
338
+ # end
339
+ #
340
+ #
341
+ #
342
+ # describe Extlib::Pooling::ResourcePool, "#available?" do
343
+ # before :each do
344
+ # DisposableResource.initialize_pool(2)
345
+ # DisposableResource.new
346
+ # end
347
+ #
348
+ # after :each do
349
+ # DisposableResource.instance_variable_set("@__pool", nil)
350
+ # end
351
+ #
352
+ # it "returns true when pool has available instances" do
353
+ # DisposableResource.pool.should be_available
354
+ # end
355
+ #
356
+ # it "returns false when pool is exhausted" do
357
+ # # aquires the last available resource
358
+ # DisposableResource.new
359
+ # DisposableResource.pool.should_not be_available
360
+ # end
361
+ # end
362
+ #
363
+ #
364
+ #
365
+ # describe "Flushing of contant size pool" do
366
+ # before :each do
367
+ # DisposableResource.initialize_pool(2)
368
+ #
369
+ # @t1 = DisposableResource.new
370
+ # @t2 = DisposableResource.new
371
+ #
372
+ # # sanity check
373
+ # DisposableResource.pool.instance_variable_get("@reserved").should_not be_empty
374
+ # end
375
+ #
376
+ # after :each do
377
+ # DisposableResource.instance_variable_set("@__pool", nil)
378
+ # end
379
+ #
380
+ # it "disposes all pooled objects" do
381
+ # [@t1, @t2].each { |instance| instance.should_receive(:dispose) }
382
+ #
383
+ # DisposableResource.pool.flush!
384
+ # end
385
+ #
386
+ # it "empties reserved set" do
387
+ # DisposableResource.pool.flush!
388
+ #
389
+ # DisposableResource.pool.instance_variable_get("@reserved").should be_empty
390
+ # end
391
+ #
392
+ # it "returns all instances to available set" do
393
+ # DisposableResource.pool.flush!
394
+ #
395
+ # DisposableResource.pool.instance_variable_get("@available").size.should == 2
396
+ # end
397
+ # end
398
+ #
399
+ #
400
+ #
401
+ # describe "Poolable resource class" do
402
+ # before :each do
403
+ # DisposableResource.initialize_pool(3, :initialization_args => ["paper"])
404
+ # end
405
+ #
406
+ # after :each do
407
+ # DisposableResource.instance_variable_set("@__pool", nil)
408
+ # end
409
+ #
410
+ # it "aquires new instances from pool" do
411
+ # @instance_one = DisposableResource.new
412
+ #
413
+ # DisposableResource.pool.aquired?(@instance_one).should be(true)
414
+ # end
415
+ #
416
+ # it "flushed existing pool on re-initialization" do
417
+ # DisposableResource.pool.should_receive(:flush!)
418
+ # DisposableResource.initialize_pool(5)
419
+ # end
420
+ #
421
+ # it "replaces pool on re-initialization" do
422
+ # DisposableResource.initialize_pool(5)
423
+ # DisposableResource.pool.size_limit.should == 5
424
+ # end
425
+ #
426
+ # it "passes initialization parameters to newly created resource instances" do
427
+ # DisposableResource.new.name.should == "paper"
428
+ # end
429
+ # end
430
+ #
431
+ #
432
+ #
433
+ # describe "Pooled object", "on initialization" do
434
+ # after :each do
435
+ # DisposableResource.instance_variable_set("@__pool", nil)
436
+ # end
437
+ #
438
+ # it "does not flush pool" do
439
+ # # using pool here initializes the pool first
440
+ # # so we use instance variable directly
441
+ # DisposableResource.instance_variable_get("@__pool").should_not_receive(:flush!)
442
+ # DisposableResource.initialize_pool(23)
443
+ # end
444
+ #
445
+ # it "flushes pool first when re-initialized" do
446
+ # DisposableResource.initialize_pool(5)
447
+ # DisposableResource.pool.should_receive(:flush!)
448
+ # DisposableResource.initialize_pool(23)
449
+ # end
450
+ # end
451
+ #
452
+ #
453
+ #
454
+ # describe Extlib::Pooling::ResourcePool, "#time_to_dispose?" do
455
+ # before :each do
456
+ # DisposableResource.initialize_pool(7, :expiration_period => 2)
457
+ # end
458
+ #
459
+ # after :each do
460
+ # DisposableResource.instance_variable_set("@__pool", nil)
461
+ # end
462
+ #
463
+ # it "returns true when object's last aquisition time is greater than limit" do
464
+ # @t1 = DisposableResource.new
465
+ # DisposableResource.pool.time_to_release?(@t1).should be(false)
466
+ #
467
+ # sleep 3
468
+ # DisposableResource.pool.time_to_release?(@t1).should be(true)
469
+ # end
470
+ # end
471
+ #
472
+ #
473
+ #
474
+ # describe Extlib::Pooling::ResourcePool, "#dispose_outdated" do
475
+ # before :each do
476
+ # DisposableResource.initialize_pool(7, :expiration_period => 2)
477
+ # end
478
+ #
479
+ # after :each do
480
+ # DisposableResource.instance_variable_set("@__pool", nil)
481
+ # end
482
+ #
483
+ # it "releases and thus disposes outdated instances" do
484
+ # @t1 = DisposableResource.new
485
+ # DisposableResource.pool.should_receive(:time_to_release?).with(@t1).and_return(true)
486
+ # DisposableResource.pool.should_receive(:release).with(@t1)
487
+ #
488
+ # DisposableResource.pool.dispose_outdated
489
+ # end
490
+ # end