hot_tub 0.0.4 → 0.1.0

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.
@@ -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