thorero 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/History.txt +1 -0
  2. data/LICENSE +20 -0
  3. data/Manifest +45 -0
  4. data/Manifest.txt +29 -0
  5. data/README.txt +3 -0
  6. data/Rakefile +180 -0
  7. data/lib/extlib.rb +32 -0
  8. data/lib/extlib/assertions.rb +8 -0
  9. data/lib/extlib/blank.rb +42 -0
  10. data/lib/extlib/class.rb +175 -0
  11. data/lib/extlib/hash.rb +410 -0
  12. data/lib/extlib/hook.rb +366 -0
  13. data/lib/extlib/inflection.rb +141 -0
  14. data/lib/extlib/lazy_array.rb +106 -0
  15. data/lib/extlib/logger.rb +202 -0
  16. data/lib/extlib/mash.rb +143 -0
  17. data/lib/extlib/module.rb +37 -0
  18. data/lib/extlib/object.rb +165 -0
  19. data/lib/extlib/object_space.rb +13 -0
  20. data/lib/extlib/pathname.rb +5 -0
  21. data/lib/extlib/pooling.rb +233 -0
  22. data/lib/extlib/rubygems.rb +38 -0
  23. data/lib/extlib/simple_set.rb +39 -0
  24. data/lib/extlib/string.rb +132 -0
  25. data/lib/extlib/struct.rb +8 -0
  26. data/lib/extlib/tasks/release.rb +11 -0
  27. data/lib/extlib/time.rb +12 -0
  28. data/lib/extlib/version.rb +3 -0
  29. data/lib/extlib/virtual_file.rb +10 -0
  30. data/spec/blank_spec.rb +85 -0
  31. data/spec/hash_spec.rb +524 -0
  32. data/spec/hook_spec.rb +1198 -0
  33. data/spec/inflection_spec.rb +50 -0
  34. data/spec/lazy_array_spec.rb +896 -0
  35. data/spec/mash_spec.rb +244 -0
  36. data/spec/module_spec.rb +58 -0
  37. data/spec/object_space_spec.rb +9 -0
  38. data/spec/object_spec.rb +98 -0
  39. data/spec/pooling_spec.rb +486 -0
  40. data/spec/simple_set_spec.rb +26 -0
  41. data/spec/spec_helper.rb +8 -0
  42. data/spec/string_spec.rb +200 -0
  43. data/spec/struct_spec.rb +12 -0
  44. data/spec/time_spec.rb +16 -0
  45. data/spec/virtual_file_spec.rb +21 -0
  46. data/thorero.gemspec +147 -0
  47. metadata +146 -0
data/spec/mash_spec.rb ADDED
@@ -0,0 +1,244 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe Mash do
4
+ before(:each) do
5
+ @hash = { "mash" => "indifferent", :hash => "different" }
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it 'converts all keys into strings when param is a Hash' do
10
+ mash = Mash.new(@hash)
11
+
12
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be(false)
13
+ end
14
+
15
+ it 'converts all Hash values into Mashes if param is a Hash' do
16
+ mash = Mash.new :hash => @hash
17
+
18
+ mash["hash"].should be_an_instance_of(Mash)
19
+ # sanity check
20
+ mash["hash"]["hash"].should == "different"
21
+ end
22
+
23
+ it 'converts all value items if value is an Array' do
24
+ mash = Mash.new :arry => { :hash => [@hash] }
25
+
26
+ mash["arry"].should be_an_instance_of(Mash)
27
+ # sanity check
28
+ mash["arry"]["hash"].first["hash"].should == "different"
29
+
30
+ end
31
+
32
+ it 'delegates to superclass constructor if param is not a Hash' do
33
+ mash = Mash.new("dash berlin")
34
+
35
+ mash["unexisting key"].should == "dash berlin"
36
+ end
37
+ end # describe "#initialize"
38
+
39
+
40
+
41
+ describe "#update" do
42
+ it 'converts all keys into strings when param is a Hash' do
43
+ mash = Mash.new(@hash)
44
+ mash.update("starry" => "night")
45
+
46
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be(false)
47
+ end
48
+
49
+ it 'converts all Hash values into Mashes if param is a Hash' do
50
+ mash = Mash.new :hash => @hash
51
+ mash.update(:hash => { :hash => "is buggy in Ruby 1.8.6" })
52
+
53
+ mash["hash"].should be_an_instance_of(Mash)
54
+ end
55
+ end # describe "#update"
56
+
57
+
58
+
59
+ describe "#[]=" do
60
+ it 'converts key into string' do
61
+ mash = Mash.new(@hash)
62
+ mash[:hash] = { "starry" => "night" }
63
+
64
+ mash.keys.any? { |key| key.is_a?(Symbol) }.should be(false)
65
+ end
66
+
67
+ it 'converts all Hash value into Mash' do
68
+ mash = Mash.new :hash => @hash
69
+ mash[:hash] = { :hash => "is buggy in Ruby 1.8.6" }
70
+
71
+ mash["hash"].should be_an_instance_of(Mash)
72
+ end
73
+ end # describe "#[]="
74
+
75
+
76
+
77
+ describe "#key?" do
78
+ before(:each) do
79
+ @mash = Mash.new(@hash)
80
+ end
81
+
82
+ it 'converts key before lookup' do
83
+ @mash.key?("mash").should be(true)
84
+ @mash.key?(:mash).should be(true)
85
+
86
+ @mash.key?("hash").should be(true)
87
+ @mash.key?(:hash).should be(true)
88
+
89
+ @mash.key?(:rainclouds).should be(false)
90
+ @mash.key?("rainclouds").should be(false)
91
+ end
92
+
93
+ it 'is aliased as include?' do
94
+ @mash.include?("mash").should be(true)
95
+ @mash.include?(:mash).should be(true)
96
+
97
+ @mash.include?("hash").should be(true)
98
+ @mash.include?(:hash).should be(true)
99
+
100
+ @mash.include?(:rainclouds).should be(false)
101
+ @mash.include?("rainclouds").should be(false)
102
+ end
103
+
104
+ it 'is aliased as member?' do
105
+ @mash.member?("mash").should be(true)
106
+ @mash.member?(:mash).should be(true)
107
+
108
+ @mash.member?("hash").should be(true)
109
+ @mash.member?(:hash).should be(true)
110
+
111
+ @mash.member?(:rainclouds).should be(false)
112
+ @mash.member?("rainclouds").should be(false)
113
+ end
114
+ end # describe "#key?"
115
+
116
+
117
+ describe "#dup" do
118
+ it 'returns instance of Mash' do
119
+ Mash.new(@hash).dup.should be_an_instance_of(Mash)
120
+ end
121
+
122
+ it 'preserves keys' do
123
+ mash = Mash.new(@hash)
124
+ dup = mash.dup
125
+
126
+ mash.keys.sort.should == dup.keys.sort
127
+ end
128
+
129
+ it 'preserves value' do
130
+ mash = Mash.new(@hash)
131
+ dup = mash.dup
132
+
133
+ mash.values.sort.should == dup.values.sort
134
+ end
135
+ end
136
+
137
+
138
+
139
+ describe "#to_hash" do
140
+ it 'returns instance of Mash' do
141
+ Mash.new(@hash).to_hash.should be_an_instance_of(Hash)
142
+ end
143
+
144
+ it 'preserves keys' do
145
+ mash = Mash.new(@hash)
146
+ converted = mash.to_hash
147
+
148
+ mash.keys.sort.should == converted.keys.sort
149
+ end
150
+
151
+ it 'preserves value' do
152
+ mash = Mash.new(@hash)
153
+ converted = mash.to_hash
154
+
155
+ mash.values.sort.should == converted.values.sort
156
+ end
157
+ end
158
+
159
+
160
+
161
+ describe "#delete" do
162
+ it 'converts Symbol key into String before deleting' do
163
+ mash = Mash.new(@hash)
164
+
165
+ mash.delete(:hash)
166
+ mash.key?("hash").should be(false)
167
+ end
168
+
169
+ it 'works with String keys as well' do
170
+ mash = Mash.new(@hash)
171
+
172
+ mash.delete("mash")
173
+ mash.key?("mash").should be(false)
174
+ end
175
+ end
176
+
177
+
178
+
179
+ describe "#merge" do
180
+ before(:each) do
181
+ @mash = Mash.new(@hash).merge(:no => "in between")
182
+ end
183
+
184
+ it 'returns instance of Mash' do
185
+ @mash.should be_an_instance_of(Mash)
186
+ end
187
+
188
+ it 'merges in give Hash' do
189
+ @mash["no"].should == "in between"
190
+ end
191
+ end
192
+
193
+
194
+
195
+ describe "#fetch" do
196
+ before(:each) do
197
+ @mash = Mash.new(@hash).merge(:no => "in between")
198
+ end
199
+
200
+ it 'converts key before fetching' do
201
+ @mash.fetch("no").should == "in between"
202
+ end
203
+
204
+ it 'returns alternative value if key lookup fails' do
205
+ @mash.fetch("flying", "screwdriver").should == "screwdriver"
206
+ end
207
+ end
208
+
209
+
210
+ describe "#default" do
211
+ before(:each) do
212
+ @mash = Mash.new(:yet_another_technical_revolution)
213
+ end
214
+
215
+ it 'returns default value unless key exists in mash' do
216
+ @mash.default("peak oil is now behind, baby").should == :yet_another_technical_revolution
217
+ end
218
+
219
+ it 'returns existing value if key is Symbol and exists in mash' do
220
+ @mash.update(:no => "in between")
221
+ @mash.default(:no).should == "in between"
222
+ end
223
+ end
224
+
225
+
226
+ describe "#values_at" do
227
+ before(:each) do
228
+ @mash = Mash.new(@hash).merge(:no => "in between")
229
+ end
230
+
231
+ it 'is indifferent to whether keys are strings or symbols' do
232
+ @mash.values_at("hash", :mash, :no).should == ["different", "indifferent", "in between"]
233
+ end
234
+ end
235
+
236
+
237
+ describe "#stringify_keys!" do
238
+ it 'returns the mash itself' do
239
+ mash = Mash.new(@hash)
240
+
241
+ mash.stringify_keys!.object_id.should == mash.object_id
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,58 @@
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
+ module Bar
8
+ module Noo
9
+ module Too
10
+ end
11
+ end
12
+ end
13
+
14
+ class Zed
15
+ end
16
+ end
17
+
18
+ class Baz
19
+ end
20
+
21
+ class Bar
22
+ end
23
+ end
24
+
25
+ it "should raise NameError for a missing constant" do
26
+ lambda { Foo.find_const('Moo') }.should raise_error(NameError)
27
+ lambda { Object.find_const('MissingConstant') }.should raise_error(NameError)
28
+ end
29
+
30
+ it "should be able to get a recursive constant" do
31
+ Object.find_const('Foo::Bar').should == Foo::Bar
32
+ end
33
+
34
+ it "should ignore get Constants from the Kernel namespace correctly" do
35
+ Object.find_const('::Foo::Bar').should == ::Foo::Bar
36
+ end
37
+
38
+ it "should find relative constants" do
39
+ Foo.find_const('Bar').should == Foo::Bar
40
+ Foo.find_const('Baz').should == Baz
41
+ end
42
+
43
+ it "should find sibling constants" do
44
+ Foo::Bar.find_const("Zed").should == Foo::Zed
45
+ end
46
+
47
+ it "should find nested constants on nested constants" do
48
+ Foo::Bar.find_const('Noo::Too')
49
+ end
50
+
51
+ it "should be able to deal with constants being added and removed" do
52
+ Object.find_const('Bar') # First we load Bar with find_const
53
+ Object.module_eval { remove_const('Bar') } # Now we delete it
54
+ module Bar; end; # Now we redefine it
55
+ Object.find_const('Bar').should == Bar
56
+ end
57
+
58
+ end
@@ -0,0 +1,9 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe ObjectSpace, "#classes" do
4
+ it 'returns only classes, nothing else' do
5
+ ObjectSpace.classes.each do |klass|
6
+ Class.should === klass
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ module HactiveSupport
4
+ class MemoizeConsideredUseless
5
+ end
6
+ end
7
+
8
+ class SymbolicDuck
9
+ def quack
10
+ end
11
+ end
12
+
13
+ class ClassyDuck
14
+ end
15
+
16
+ describe Object do
17
+
18
+ describe "#full_const_get" do
19
+ it 'returns constant by FQ name in receiver namespace' do
20
+ Object.full_const_get("Extlib").should == Extlib
21
+ Object.full_const_get("Extlib::SimpleSet").should == Extlib::SimpleSet
22
+ end
23
+ end
24
+
25
+ describe "#full_const_set" do
26
+ it 'sets constant value by FQ name in receiver namespace' do
27
+ Object.full_const_set("HactiveSupport::MCU", HactiveSupport::MemoizeConsideredUseless)
28
+
29
+ Object.full_const_get("HactiveSupport::MCU").should == HactiveSupport::MemoizeConsideredUseless
30
+ HactiveSupport.full_const_get("MCU").should == HactiveSupport::MemoizeConsideredUseless
31
+ end
32
+ end
33
+
34
+ describe "#make_module" do
35
+ it 'creates a module from string FQ name' do
36
+ Object.make_module("Milano")
37
+ Object.make_module("Norway::Oslo")
38
+
39
+ defined?(Milano).should == "constant"
40
+ defined?(Norway::Oslo).should == "constant"
41
+ end
42
+ end
43
+
44
+
45
+ describe "#quacks_like?" do
46
+ it 'returns true if duck is a Symbol and receiver responds to it' do
47
+ SymbolicDuck.new.quacks_like?(:quack).should be(true)
48
+ end
49
+
50
+ it 'returns false if duck is a Symbol and receiver DOES NOT respond to it' do
51
+ SymbolicDuck.new.quacks_like?(:wtf).should be(false)
52
+ end
53
+
54
+ it 'returns true if duck is a class and receiver is its instance' do
55
+ receiver = ClassyDuck.new
56
+ receiver.quacks_like?(ClassyDuck).should be(true)
57
+ end
58
+
59
+ it 'returns false if duck is a class and receiver IS NOT its instance' do
60
+ receiver = ClassyDuck.new
61
+ receiver.quacks_like?(SymbolicDuck).should be(false)
62
+ end
63
+
64
+ it 'returns true if duck is an array and at least one of its members quacks like this duck' do
65
+ receiver = ClassyDuck.new
66
+ ary = [ClassyDuck, SymbolicDuck]
67
+
68
+ receiver.quacks_like?(ary).should be(true)
69
+ end
70
+
71
+ it 'returns false if duck is an array and none of its members quacks like this duck' do
72
+ receiver = ClassyDuck.new
73
+ ary = [SymbolicDuck.new, SymbolicDuck]
74
+
75
+ receiver.quacks_like?(ary).should be(false)
76
+ end
77
+ end
78
+
79
+
80
+
81
+ describe "#in?" do
82
+ it 'returns true if object is included in collection' do
83
+ @ary = [1, 2, 3]
84
+ @set = Set.new([2, 3, 5])
85
+
86
+ 1.in?(@ary).should be(true)
87
+ 2.in?(@ary).should be(true)
88
+ 3.in?(@ary).should be(true)
89
+ 4.in?(@ary).should be(false)
90
+
91
+ 1.in?(@set).should be(false)
92
+ 2.in?(@set).should be(true)
93
+ 3.in?(@set).should be(true)
94
+ 4.in?(@set).should be(false)
95
+ 5.in?(@set).should be(true)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,486 @@
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
+ 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
+ end
26
+
27
+ class Overwriter
28
+
29
+ def self.new(*args)
30
+ instance = allocate
31
+ instance.send(:initialize, *args)
32
+ instance.overwritten = true
33
+ instance
34
+ end
35
+
36
+ include Extlib::Pooling
37
+
38
+ attr_accessor :name
39
+
40
+ def initialize(name)
41
+ @name = name
42
+ @overwritten = false
43
+ end
44
+
45
+ def overwritten?
46
+ @overwritten
47
+ end
48
+
49
+ def overwritten=(value)
50
+ @overwritten = value
51
+ end
52
+
53
+ def self.pool_size
54
+ pool_size = if RUBY_PLATFORM =~ /java/
55
+ 20
56
+ else
57
+ 2
58
+ end
59
+ pool_size
60
+ end
61
+
62
+ def dispose
63
+ @name = nil
64
+ end
65
+ end
66
+ end
67
+
68
+ it "should track the initialized pools" do
69
+ bob = Person.new('Bob') # Ensure the pool is "primed"
70
+ bob.name.should == 'Bob'
71
+ bob.instance_variable_get(:@__pool).should_not be_nil
72
+ Person.__pools.size.should == 1
73
+ bob.release
74
+ Person.__pools.size.should == 1
75
+
76
+ Extlib::Pooling::pools.should_not be_empty
77
+ sleep(1.2)
78
+ Extlib::Pooling::pools.should be_empty
79
+ bob.name.should be_nil
80
+ end
81
+
82
+ it "should maintain a size of 1" do
83
+ bob = Person.new('Bob')
84
+ fred = Person.new('Fred')
85
+ ted = Person.new('Ted')
86
+
87
+ Person.__pools.each do |args, pool|
88
+ pool.size.should == 1
89
+ end
90
+
91
+ bob.release
92
+ fred.release
93
+ ted.release
94
+
95
+ Person.__pools.each do |args, pool|
96
+ pool.size.should == 1
97
+ end
98
+ end
99
+
100
+ it "should allow you to overwrite Class#new" do
101
+ bob = Overwriter.new('Bob')
102
+ bob.should be_overwritten
103
+ bob.release
104
+ end
105
+
106
+ it "should raise a ThreadStopError when the pool is exhausted in a single thread" do
107
+ lambda do
108
+ begin
109
+ bob = Person.new('Bob')
110
+ 9.times { Person.new('Bob') }
111
+ ensure
112
+ bob.release
113
+ end
114
+ end.should raise_error(Extlib::Pooling::ThreadStopError)
115
+ end
116
+
117
+ it "should allow multiple threads to access the pool" do
118
+ t1 = Thread.new do
119
+ bob = Person.new('Bob')
120
+ sleep(0.1)
121
+ bob.release
122
+ end
123
+
124
+ lambda do
125
+ bob = Person.new('Bob')
126
+ t1.join
127
+ bob.release
128
+ end.should_not raise_error(Extlib::Pooling::ThreadStopError)
129
+ end
130
+
131
+ it "should allow you to flush a pool" do
132
+ bob = Overwriter.new('Bob')
133
+ Overwriter.new('Bob').release
134
+ bob.release
135
+
136
+ bob.name.should == 'Bob'
137
+
138
+ Overwriter.__pools[['Bob']].size.should == 2
139
+ Overwriter.__pools[['Bob']].flush!
140
+ Overwriter.__pools[['Bob']].size.should == 0
141
+
142
+ bob.name.should be_nil
143
+ end
144
+ end
145
+
146
+ # describe Extlib::Pooling::ResourcePool do
147
+ # before :each do
148
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, :expiration_period => 50)
149
+ # end
150
+ #
151
+ # it "responds to flush!" do
152
+ # @pool.should respond_to(:flush!)
153
+ # end
154
+ #
155
+ # it "responds to aquire" do
156
+ # @pool.should respond_to(:aquire)
157
+ # end
158
+ #
159
+ # it "responds to release" do
160
+ # @pool.should respond_to(:release)
161
+ # end
162
+ #
163
+ # it "responds to :available?" do
164
+ # @pool.should respond_to(:available?)
165
+ # end
166
+ #
167
+ # it "has a size limit" do
168
+ # @pool.size_limit.should == 7
169
+ # end
170
+ #
171
+ # it "has initial size of zero" do
172
+ # @pool.size.should == 0
173
+ # end
174
+ #
175
+ # it "has a set of reserved resources" do
176
+ # @pool.instance_variable_get("@reserved").should be_empty
177
+ # end
178
+ #
179
+ # it "has a set of available resources" do
180
+ # @pool.instance_variable_get("@available").should be_empty
181
+ # end
182
+ #
183
+ # it "knows class of resources (objects) it works with" do
184
+ # @pool.class_of_resources.should == DisposableResource
185
+ # end
186
+ #
187
+ # it "raises exception when given anything but class for resources class" do
188
+ # lambda {
189
+ # @pool = Extlib::Pooling::ResourcePool.new(7, "Hooray!", {})
190
+ # }.should raise_error(ArgumentError, /class/)
191
+ # end
192
+ #
193
+ # it "requires class of resources (objects) it works with to have a dispose instance method" do
194
+ # lambda {
195
+ # @pool = Extlib::Pooling::ResourcePool.new(3, UndisposableResource, {})
196
+ # }.should raise_error(ArgumentError, /dispose/)
197
+ # end
198
+ #
199
+ # it "may take initialization arguments" do
200
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, { :initialization_args => ["paper"] })
201
+ # @pool.instance_variable_get("@initialization_args").should == ["paper"]
202
+ # end
203
+ #
204
+ # it "may take expiration period option" do
205
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, { :expiration_period => 100 })
206
+ # @pool.expiration_period.should == 100
207
+ # end
208
+ #
209
+ # it "has default expiration period of one minute" do
210
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, {})
211
+ # @pool.expiration_period.should == 60
212
+ # end
213
+ #
214
+ # it "spawns a thread to dispose objects haven't been used for a while" do
215
+ # @pool = Extlib::Pooling::ResourcePool.new(7, DisposableResource, {})
216
+ # @pool.instance_variable_get("@pool_expiration_thread").should be_an_instance_of(Thread)
217
+ # end
218
+ # end
219
+ #
220
+ #
221
+ #
222
+ # describe "Aquire from contant size pool" do
223
+ # before :each do
224
+ # DisposableResource.initialize_pool(2)
225
+ # end
226
+ #
227
+ # after :each do
228
+ # DisposableResource.instance_variable_set("@__pool", nil)
229
+ # end
230
+ #
231
+ # it "increased size of the pool" do
232
+ # @time = DisposableResource.pool.aquire
233
+ # DisposableResource.pool.size.should == 1
234
+ # end
235
+ #
236
+ # it "places initialized instance in the reserved set" do
237
+ # @time = DisposableResource.pool.aquire
238
+ # DisposableResource.pool.instance_variable_get("@reserved").size.should == 1
239
+ # end
240
+ #
241
+ # it "raises an exception when pool size limit is hit" do
242
+ # @t1 = DisposableResource.pool.aquire
243
+ # @t2 = DisposableResource.pool.aquire
244
+ #
245
+ # lambda { DisposableResource.pool.aquire }.should raise_error(RuntimeError)
246
+ # end
247
+ #
248
+ # it "returns last released resource" do
249
+ # @t1 = DisposableResource.pool.aquire
250
+ # @t2 = DisposableResource.pool.aquire
251
+ # DisposableResource.pool.release(@t1)
252
+ #
253
+ # DisposableResource.pool.aquire.should == @t1
254
+ # end
255
+ #
256
+ # it "really truly returns last released resource" do
257
+ # @t1 = DisposableResource.pool.aquire
258
+ # DisposableResource.pool.release(@t1)
259
+ #
260
+ # @t2 = DisposableResource.pool.aquire
261
+ # DisposableResource.pool.release(@t2)
262
+ #
263
+ # @t3 = DisposableResource.pool.aquire
264
+ # DisposableResource.pool.release(@t3)
265
+ #
266
+ # DisposableResource.pool.aquire.should == @t1
267
+ # @t1.should == @t3
268
+ # end
269
+ #
270
+ # it "sets allocation timestamp on resource instance" do
271
+ # @t1 = DisposableResource.new
272
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
273
+ # end
274
+ # end
275
+ #
276
+ #
277
+ #
278
+ # describe "Releasing from contant size pool" do
279
+ # before :each do
280
+ # DisposableResource.initialize_pool(2)
281
+ # end
282
+ #
283
+ # after :each do
284
+ # DisposableResource.instance_variable_set("@__pool", nil)
285
+ # end
286
+ #
287
+ # it "decreases size of the pool" do
288
+ # @t1 = DisposableResource.pool.aquire
289
+ # @t2 = DisposableResource.pool.aquire
290
+ # DisposableResource.pool.release(@t1)
291
+ #
292
+ # DisposableResource.pool.size.should == 1
293
+ # end
294
+ #
295
+ # it "raises an exception on attempt to releases object not in pool" do
296
+ # @t1 = DisposableResource.new
297
+ # @t2 = Set.new
298
+ #
299
+ # DisposableResource.pool.release(@t1)
300
+ # lambda { DisposableResource.pool.release(@t2) }.should raise_error(RuntimeError)
301
+ # end
302
+ #
303
+ # it "removes released object from reserved set" do
304
+ # @t1 = DisposableResource.pool.aquire
305
+ #
306
+ # lambda {
307
+ # DisposableResource.pool.release(@t1)
308
+ # }.should change(DisposableResource.pool.instance_variable_get("@reserved"), :size).by(-1)
309
+ # end
310
+ #
311
+ # it "returns released object back to available set" do
312
+ # @t1 = DisposableResource.pool.aquire
313
+ #
314
+ # lambda {
315
+ # DisposableResource.pool.release(@t1)
316
+ # }.should change(DisposableResource.pool.instance_variable_get("@available"), :size).by(1)
317
+ # end
318
+ #
319
+ # it "updates aquire timestamp on already allocated resource instance" do
320
+ # # aquire it once
321
+ # @t1 = DisposableResource.new
322
+ # # wait a bit
323
+ # sleep 3
324
+ #
325
+ # # check old timestamp
326
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 4)
327
+ #
328
+ # # re-aquire
329
+ # DisposableResource.pool.release(@t1)
330
+ # @t1 = DisposableResource.new
331
+ # # see timestamp is updated
332
+ # @t1.instance_variable_get("@__pool_aquire_timestamp").should be_close(Time.now, 2)
333
+ # end
334
+ # end
335
+ #
336
+ #
337
+ #
338
+ # describe Extlib::Pooling::ResourcePool, "#available?" do
339
+ # before :each do
340
+ # DisposableResource.initialize_pool(2)
341
+ # DisposableResource.new
342
+ # end
343
+ #
344
+ # after :each do
345
+ # DisposableResource.instance_variable_set("@__pool", nil)
346
+ # end
347
+ #
348
+ # it "returns true when pool has available instances" do
349
+ # DisposableResource.pool.should be_available
350
+ # end
351
+ #
352
+ # it "returns false when pool is exhausted" do
353
+ # # aquires the last available resource
354
+ # DisposableResource.new
355
+ # DisposableResource.pool.should_not be_available
356
+ # end
357
+ # end
358
+ #
359
+ #
360
+ #
361
+ # describe "Flushing of contant size pool" do
362
+ # before :each do
363
+ # DisposableResource.initialize_pool(2)
364
+ #
365
+ # @t1 = DisposableResource.new
366
+ # @t2 = DisposableResource.new
367
+ #
368
+ # # sanity check
369
+ # DisposableResource.pool.instance_variable_get("@reserved").should_not be_empty
370
+ # end
371
+ #
372
+ # after :each do
373
+ # DisposableResource.instance_variable_set("@__pool", nil)
374
+ # end
375
+ #
376
+ # it "disposes all pooled objects" do
377
+ # [@t1, @t2].each { |instance| instance.should_receive(:dispose) }
378
+ #
379
+ # DisposableResource.pool.flush!
380
+ # end
381
+ #
382
+ # it "empties reserved set" do
383
+ # DisposableResource.pool.flush!
384
+ #
385
+ # DisposableResource.pool.instance_variable_get("@reserved").should be_empty
386
+ # end
387
+ #
388
+ # it "returns all instances to available set" do
389
+ # DisposableResource.pool.flush!
390
+ #
391
+ # DisposableResource.pool.instance_variable_get("@available").size.should == 2
392
+ # end
393
+ # end
394
+ #
395
+ #
396
+ #
397
+ # describe "Poolable resource class" do
398
+ # before :each do
399
+ # DisposableResource.initialize_pool(3, :initialization_args => ["paper"])
400
+ # end
401
+ #
402
+ # after :each do
403
+ # DisposableResource.instance_variable_set("@__pool", nil)
404
+ # end
405
+ #
406
+ # it "aquires new instances from pool" do
407
+ # @instance_one = DisposableResource.new
408
+ #
409
+ # DisposableResource.pool.aquired?(@instance_one).should be(true)
410
+ # end
411
+ #
412
+ # it "flushed existing pool on re-initialization" do
413
+ # DisposableResource.pool.should_receive(:flush!)
414
+ # DisposableResource.initialize_pool(5)
415
+ # end
416
+ #
417
+ # it "replaces pool on re-initialization" do
418
+ # DisposableResource.initialize_pool(5)
419
+ # DisposableResource.pool.size_limit.should == 5
420
+ # end
421
+ #
422
+ # it "passes initialization parameters to newly created resource instances" do
423
+ # DisposableResource.new.name.should == "paper"
424
+ # end
425
+ # end
426
+ #
427
+ #
428
+ #
429
+ # describe "Pooled object", "on initialization" do
430
+ # after :each do
431
+ # DisposableResource.instance_variable_set("@__pool", nil)
432
+ # end
433
+ #
434
+ # it "does not flush pool" do
435
+ # # using pool here initializes the pool first
436
+ # # so we use instance variable directly
437
+ # DisposableResource.instance_variable_get("@__pool").should_not_receive(:flush!)
438
+ # DisposableResource.initialize_pool(23)
439
+ # end
440
+ #
441
+ # it "flushes pool first when re-initialized" do
442
+ # DisposableResource.initialize_pool(5)
443
+ # DisposableResource.pool.should_receive(:flush!)
444
+ # DisposableResource.initialize_pool(23)
445
+ # end
446
+ # end
447
+ #
448
+ #
449
+ #
450
+ # describe Extlib::Pooling::ResourcePool, "#time_to_dispose?" do
451
+ # before :each do
452
+ # DisposableResource.initialize_pool(7, :expiration_period => 2)
453
+ # end
454
+ #
455
+ # after :each do
456
+ # DisposableResource.instance_variable_set("@__pool", nil)
457
+ # end
458
+ #
459
+ # it "returns true when object's last aquisition time is greater than limit" do
460
+ # @t1 = DisposableResource.new
461
+ # DisposableResource.pool.time_to_release?(@t1).should be(false)
462
+ #
463
+ # sleep 3
464
+ # DisposableResource.pool.time_to_release?(@t1).should be(true)
465
+ # end
466
+ # end
467
+ #
468
+ #
469
+ #
470
+ # describe Extlib::Pooling::ResourcePool, "#dispose_outdated" do
471
+ # before :each do
472
+ # DisposableResource.initialize_pool(7, :expiration_period => 2)
473
+ # end
474
+ #
475
+ # after :each do
476
+ # DisposableResource.instance_variable_set("@__pool", nil)
477
+ # end
478
+ #
479
+ # it "releases and thus disposes outdated instances" do
480
+ # @t1 = DisposableResource.new
481
+ # DisposableResource.pool.should_receive(:time_to_release?).with(@t1).and_return(true)
482
+ # DisposableResource.pool.should_receive(:release).with(@t1)
483
+ #
484
+ # DisposableResource.pool.dispose_outdated
485
+ # end
486
+ # end