extlib 0.9.8 → 0.9.9

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.

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