hot_tub 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
1
  module HotTub
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/pool_spec.rb ADDED
@@ -0,0 +1,241 @@
1
+ require 'spec_helper'
2
+ unless HotTub.jruby?
3
+ require "em-synchrony"
4
+ require "em-synchrony/em-http"
5
+ end
6
+ describe HotTub::Pool do
7
+
8
+ context 'default settings' do
9
+ before(:each) do
10
+ @pool = HotTub::Pool.new()
11
+ end
12
+
13
+ it "should have :size of 5" do
14
+ @pool.instance_variable_get(:@size).should eql(5)
15
+ end
16
+
17
+ it "should have :blocking_timeout of 0.5" do
18
+ @pool.instance_variable_get(:@blocking_timeout).should eql(10)
19
+ end
20
+
21
+ it "should have default :client" do
22
+ @pool.instance_variable_get(:@client_block).call.should be_a(HTTPClient)
23
+ end
24
+
25
+ it "should be true" do
26
+ @pool.instance_variable_get(:@never_block).should be_true
27
+ end
28
+ end
29
+
30
+ context 'custom settings' do
31
+ before(:each) do
32
+ @pool = HotTub::Pool.new(:size => 10, :blocking_timeout => 1.0, :never_block => false) { MocClient.new }
33
+ end
34
+
35
+ it "should have :size of 5" do
36
+ @pool.instance_variable_get(:@size).should eql(10)
37
+ end
38
+
39
+ it "should have :blocking_timeout of 0.5" do
40
+ @pool.instance_variable_get(:@blocking_timeout).should eql(1.0)
41
+ end
42
+
43
+ it "should have defult :client" do
44
+ @pool.instance_variable_get(:@client_block).call.should be_a(MocClient)
45
+ end
46
+
47
+ it "should be true" do
48
+ @pool.instance_variable_get(:@never_block).should be_false
49
+ end
50
+ end
51
+
52
+ describe '#run' do
53
+ before(:each) do
54
+ @pool = HotTub::Pool.new
55
+ end
56
+
57
+ it "should remove connection from pool when doing work" do
58
+ @pool.run do |connection|
59
+ @connection = connection
60
+ @fetched = @pool.instance_variable_get(:@pool).select{|c| c.object_id == @connection.object_id}.length.should eql(0) # not in pool because its doing work
61
+ end
62
+ end
63
+
64
+ it "should return the connection after use" do
65
+ @pool.run do |connection|
66
+ @connection = connection
67
+ end
68
+ # returned to pool after work was done
69
+ @pool.instance_variable_get(:@pool).select{|c| c.object_id == @connection.object_id}.length.should eql(1)
70
+ end
71
+
72
+ it "should work" do
73
+ status = 0
74
+ @pool.run{|clnt| status = clnt.head('https://www.google.com').status}
75
+ status.should eql(200)
76
+ end
77
+
78
+ context "block given" do
79
+ it "should call the supplied block" do
80
+ status = nil
81
+ @pool.run { |con| status = con.get('https://google.com').status}
82
+ status.should_not be_nil
83
+ end
84
+ end
85
+
86
+ context 'block not given' do
87
+ it "should raise ArgumentError" do
88
+ lambda { @pool.run }.should raise_error(ArgumentError)
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#close_all' do
94
+ before(:each) do
95
+ @pool = HotTub::Pool.new(:size => 5)
96
+ 5.times do
97
+ @pool.send(:add)
98
+ end
99
+ end
100
+ it "should reset pool" do
101
+ @pool.current_size.should eql(5)
102
+ @pool.instance_variable_get(:@clients).length.should eql(5)
103
+ @pool.instance_variable_get(:@pool).length.should eql(5)
104
+ @pool.close_all
105
+ @pool.instance_variable_get(:@clients).length.should eql(0)
106
+ @pool.instance_variable_get(:@pool).length.should eql(0)
107
+ @pool.current_size.should eql(0)
108
+ end
109
+ end
110
+
111
+ context 'private methods' do
112
+ before(:each) do
113
+ @url = "http://www.testurl123.com/"
114
+ @pool = HotTub::Pool.new()
115
+ end
116
+
117
+ describe '#client' do
118
+ it "should raise HotTub::BlockingTimeout if an available is not found in time"do
119
+ @pool.instance_variable_set(:@never_block,false)
120
+ @pool.instance_variable_set(:@blocking_timeout,0.1)
121
+ @pool.stub(:pop).and_return(nil)
122
+ lambda { puts @pool.send(:client) }.should raise_error(HotTub::BlockingTimeout)
123
+ end
124
+
125
+ it "should return an instance of the driver" do
126
+ @pool.send(:client).should be_instance_of(HTTPClient)
127
+ end
128
+ end
129
+
130
+ describe 'add?' do
131
+ it "should be true if @pool_data[:length] is less than desired pool size and
132
+ the pool is empty?"do
133
+ @pool.instance_variable_set(:@pool,[])
134
+ @pool.send(:add?).should be_true
135
+ end
136
+
137
+ it "should be false pool has reached pool_size" do
138
+ @pool.instance_variable_set(:@pool_data,{:current_size => 5})
139
+ @pool.instance_variable_set(:@pool,["connection","connection","connection","connection","connection"])
140
+ @pool.send(:add?).should be_false
141
+ end
142
+ end
143
+
144
+ describe '#add' do
145
+ it "should add connections for supplied url"do
146
+ @pool.send(:add)
147
+ @pool.instance_variable_get(:@pool).should_not be_nil
148
+ end
149
+ end
150
+ end
151
+
152
+ context 'thread safety' do
153
+ it "should work" do
154
+ url = "https://www.google.com/"
155
+ pool = HotTub::Pool.new({:size => 20})
156
+ failed = false
157
+ lambda {
158
+ threads = []
159
+ 20.times.each do
160
+ threads << Thread.new do
161
+ pool.run{|connection| failed = true unless connection.head(url).status == 200}
162
+ end
163
+ end
164
+ sleep(0.01)
165
+ threads.each do |t|
166
+ t.join
167
+ end
168
+ }.should_not raise_error
169
+ pool.instance_variable_get(:@pool).length.should eql(20) # make sure work got done
170
+ failed.should be_false # Make sure our requests woked
171
+ end
172
+ end
173
+
174
+ context "other http client" do
175
+ before(:each) do
176
+ @url = "https://www.google.com"
177
+ @pool = HotTub::Pool.new(:clean => lambda {|clnt| clnt.clean}) {MocClient.new(@url)}
178
+ end
179
+
180
+ it "should clean connections" do
181
+ @pool.run do |clnt|
182
+ clnt.cleaned?.should be_true
183
+ end
184
+ end
185
+ end
186
+
187
+ unless HotTub.jruby?
188
+ context 'EM:HTTPRequest' do
189
+ before(:each) do
190
+ @url = "https://www.google.com"
191
+ end
192
+
193
+ it "should work" do
194
+ EM.synchrony do
195
+ status = []
196
+ c = HotTub::Pool.new {EM::HttpRequest.new(@url)}
197
+ c.run { |conn| status << conn.head(:keepalive => true).response_header.status}
198
+ c.run { |conn| status << conn.ahead(:keepalive => true).response_header.status}
199
+ c.run { |conn| status << conn.head(:keepalive => true).response_header.status}
200
+ status.should eql([200,0,200])
201
+ EM.stop
202
+ end
203
+ end
204
+
205
+ context 'fibers' do
206
+ it "should work" do
207
+ EM.synchrony do
208
+ url = "https://www.google.com/"
209
+ pool = HotTub::Pool.new({:size => 5}) {EM::HttpRequest.new(@url)}
210
+ failed = false
211
+ fibers = []
212
+ lambda {
213
+ 10.times.each do
214
+ fibers << Fiber.new do
215
+ pool.run{|connection| failed = true unless connection.head(:keepalive => true).response_header.status == 200}
216
+ end
217
+ end
218
+ fibers.each do |f|
219
+ f.resume
220
+ end
221
+ loop do
222
+ done = true
223
+ fibers.each do |f|
224
+ done = false if f.alive?
225
+ end
226
+ if done
227
+ break
228
+ else
229
+ EM::Synchrony.sleep(0.01)
230
+ end
231
+ end
232
+ }.should_not raise_error
233
+ pool.instance_variable_get(:@pool).length.should eql(5) #make sure work got done
234
+ failed.should be_false # Make sure our requests worked
235
+ EM.stop
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end
241
+ end
data/spec/session_spec.rb CHANGED
@@ -1,108 +1,97 @@
1
1
  require 'spec_helper'
2
- class MocClient < HotTub::Client
3
- def initialize(url,options={})
4
- end
5
-
6
- def get
7
- sleep(0.05)
8
- end
9
- end
10
-
2
+ require 'hot_tub/session'
3
+ require 'uri'
11
4
  describe HotTub::Session do
12
5
 
13
- before(:each) do
14
- @url = "http://www.testurl123.com/"
15
- @tub = HotTub::Session.new(MocClient.new(@url))
6
+ it "should raise error if block is not supplied" do
7
+ lambda {HotTub::Session.new}.should raise_error(ArgumentError)
16
8
  end
17
9
 
18
- context 'default configuration' do
19
-
20
- it "should have @pool_size of 5" do
21
- @tub.instance_variable_get(:@options)[:size].should eql(5)
10
+ context 'default settings' do
11
+ before(:each) do
12
+ @url = "http://www.testurl123.com/"
13
+ @tub = HotTub::Session.new { |url| MocClient.new(url) }
14
+ @options = @tub.instance_variable_get(:@options)
22
15
  end
23
-
24
- it "should have @pool_timeout of 0" do
25
- @tub.instance_variable_get(:@options)[:blocking_timeout].should eql(0.5)
16
+
17
+ it "should have :size of 5" do
18
+ @options[:size].should eql(5)
26
19
  end
27
- end
28
-
29
- describe '#add_client?' do
30
- it "should be true if @pool_data[:length] is less than desired pool size and
31
- the pool is empty?"do
32
- @tub.instance_variable_set(:@pool_data,{:current_size => 1})
33
- @tub.send(:add_client?).should be_true
20
+
21
+ it "should have :blocking_timeout of 10 seconds" do
22
+ @options[:blocking_timeout].should eql(10)
34
23
  end
35
-
36
- it "should be false pool has reached pool_size" do
37
- @tub.instance_variable_set(:@pool_data,{:current_size => 5})
38
- @tub.instance_variable_set(:@pool,
39
- ["connection","connection","connection","connection","connection"])
40
- @tub.send(:add_client?).should be_false
24
+
25
+ it "should default never_block to true" do
26
+ @options[:never_block].should be_true
41
27
  end
42
28
  end
43
-
44
- describe '#add_client' do
45
- it "should add connections for supplied url"do
46
- @tub.send(:add_client)
47
- @tub.instance_variable_get(:@pool).should_not be_nil
29
+
30
+ context 'passed options' do
31
+ before(:each) do
32
+ @url = "http://www.testurl123.com/"
33
+ @tub = HotTub::Session.new({:size => 21, :never_block => false}) { |url| MocClient.new(url) }
34
+ @options = @tub.instance_variable_get(:@options)
48
35
  end
49
- end
50
-
51
- describe '#fetch' do
52
- it "should raise Timeout::Error if an available is not found in time"do
53
- @tub.stub(:pool).and_return([])
54
- lambda { @tub.send(:fetch)}.should raise_error(Timeout::Error)
36
+
37
+ it "should have @pool_size of 21" do
38
+ @options[:size].should eql(21)
55
39
  end
56
-
57
- it "should not raise Timeout::Error if an available is not found in time"do
58
- @tub.instance_variable_get(:@options)[:never_block] = true
59
- @tub.stub(:pool).and_return([])
60
- lambda { @tub.send(:fetch)}.should_not raise_error(Timeout::Error)
40
+
41
+ it "should have never_block be false" do
42
+ @options[:never_block].should be_false
43
+ end
44
+ end
45
+
46
+ describe '#sessions' do
47
+ before(:each) do
48
+ @url = "https://www.google.com"
49
+ @uri = URI(@url)
50
+ @tub = HotTub::Session.new({:size => 21, :never_block => false}) { |url| MocClient.new(url) }
61
51
  end
62
52
 
63
- it "should return an instance of the driver" do
64
- @tub.send(:fetch).should be_instance_of(MocClient)
53
+ it "should add a new pool for the url" do
54
+ @tub.sessions(@url)
55
+ sessions = @tub.instance_variable_get(:@sessions)
56
+ sessions.length.should eql(1)
57
+ sessions.first[1].should be_a(HotTub::Pool)
65
58
  end
66
- end
67
-
68
- describe '#run' do
69
- it "should fetch a connection and run the supplied block" do
70
- @fetched = nil
71
-
72
- @tub.run do |connection|
73
- @fetched = connection.class.name
59
+
60
+ context "passed URL string" do
61
+ it "should set key with URI scheme-domain" do
62
+ @tub.sessions(@url)
63
+ sessions = @tub.instance_variable_get(:@sessions)
64
+ sessions["#{@uri.scheme}-#{@uri.host}"].should be_a(HotTub::Pool)
74
65
  end
75
- @fetched.should eql("MocClient")
76
66
  end
77
-
78
- it "should return the connection after use" do
79
- @tub.run do |connection|
80
- @connection = connection
81
- @fetched = @tub.instance_variable_get(:@pool).include?(connection)
67
+
68
+ context "passed URI" do
69
+ it "should set key with URI scheme-domain" do
70
+ @tub.sessions(@uri)
71
+ sessions = @tub.instance_variable_get(:@sessions)
72
+ sessions["#{@uri.scheme}-#{@uri.host}"].should be_a(HotTub::Pool)
73
+ end
74
+ end
75
+
76
+ context "invalid argument" do
77
+ it "should raise an ArgumentError" do
78
+ lambda { @tub.sessions(nil) }.should raise_error(ArgumentError)
79
+
80
+ end
81
+ it "should raise URI::InvalidURIError with bad url" do
82
+ lambda { @tub.sessions("bad url") }.should raise_error(URI::InvalidURIError)
82
83
  end
83
- @fetched.should be_false # not in pool because its doing work
84
-
85
- # returned to pool after work was done
86
- @tub.instance_variable_get(:@pool).include?(@connection).should be_true
87
84
  end
88
85
  end
89
-
90
- context 'thread safety' do
86
+ describe '#run' do
91
87
  it "should work" do
92
- threads = []
93
- 20.times.each do
94
- threads << Thread.new do
95
- @tub.run{|connection| connection.get}
96
- end
97
- end
98
-
99
- sleep(0.5)
100
-
101
- threads.each do |t|
102
- t.join
88
+ @url = "https://www.google.com"
89
+ @tub = HotTub::Session.new({:size => 21, :never_block => false}) { |url| HTTPClient.new }
90
+ status = 0
91
+ @tub.run(@url) do |conn|
92
+ status = conn.head(@url).status
103
93
  end
104
-
105
- @tub.instance_variable_get(:@pool).length.should eql(5)
94
+ status.should eql(200)
106
95
  end
107
96
  end
108
97
  end
data/spec/spec_helper.rb CHANGED
@@ -7,6 +7,34 @@ require 'logger'
7
7
  # in ./support/ and its subdirectories.
8
8
  #Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
9
  HotTub.logger.level = Logger::ERROR
10
+
10
11
  RSpec.configure do |config|
11
12
 
12
- end
13
+ end
14
+
15
+ class MocClient
16
+ def initialize(url=nil,options={})
17
+ @close = false
18
+ @clean = false
19
+ end
20
+
21
+ def get
22
+ sleep(0.05)
23
+ end
24
+
25
+ def close
26
+ @close = true
27
+ end
28
+
29
+ def closed?
30
+ @close == true
31
+ end
32
+
33
+ def clean
34
+ @clean = true
35
+ end
36
+
37
+ def cleaned?
38
+ @clean == true
39
+ end
40
+ end