-
Notifications
You must be signed in to change notification settings - Fork 548
/
abstract_server_collection_spec.rb
247 lines (216 loc) · 6.4 KB
/
abstract_server_collection_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
require 'phusion_passenger/abstract_server'
require 'phusion_passenger/abstract_server_collection'
module PhusionPassenger
describe AbstractServerCollection do
before :each do
@collection = AbstractServerCollection.new
end
after :each do
@collection.cleanup
end
specify "#lookup_or_add adds the server returned by its block" do
@collection.synchronize do
@collection.lookup_or_add('foo') do
AbstractServer.new
end
@collection.should have_key('foo')
end
end
specify "#lookup_or_add does not execute the block if the key exists" do
@collection.synchronize do
@collection.lookup_or_add('foo') do
AbstractServer.new
end
@collection.lookup_or_add('foo') do
violated
end
end
end
specify "#lookup_or_add returns the found server" do
@collection.synchronize do
server = AbstractServer.new
@collection.lookup_or_add('foo') { server }
result = @collection.lookup_or_add('foo') { AbstractServer.new }
result.should == server
end
end
specify "#lookup_or_add returns the value of the block if server is not already in the collection" do
@collection.synchronize do
server = AbstractServer.new
result = @collection.lookup_or_add('foo') do
server
end
result.should == server
end
end
specify "#delete deletes the server with the given key" do
@collection.synchronize do
@collection.lookup_or_add('foo') do
AbstractServer.new
end
@collection.delete('foo')
@collection.should_not have_key('foo')
end
end
specify "#delete stops the server if it's started" do
@collection.synchronize do
server = AbstractServer.new
@collection.lookup_or_add('foo') do
server.start
server
end
@collection.delete('foo')
server.should_not be_started
end
end
specify "#clear deletes everything" do
@collection.synchronize do
@collection.lookup_or_add('foo') do
AbstractServer.new
end
@collection.lookup_or_add('bar') do
AbstractServer.new
end
@collection.clear
@collection.should_not have_key('foo')
@collection.should_not have_key('bar')
end
end
specify "#cleanup deletes everything" do
@collection.synchronize do
@collection.lookup_or_add('foo') do
AbstractServer.new
end
@collection.lookup_or_add('bar') do
AbstractServer.new
end
end
@collection.cleanup
@collection.synchronize do
@collection.should_not have_key('foo')
@collection.should_not have_key('bar')
end
end
specify "#cleanup stops all servers" do
servers = []
3.times do
server = AbstractServer.new
server.start
servers << server
end
@collection.synchronize do
@collection.lookup_or_add('foo') { servers[0] }
@collection.lookup_or_add('bar') { servers[1] }
@collection.lookup_or_add('baz') { servers[2] }
end
@collection.cleanup
servers.each do |server|
server.should_not be_started
end
end
specify "idle servers are cleaned up periodically" do
foo = AbstractServer.new
foo.max_idle_time = 0.05
bar = AbstractServer.new
bar.max_idle_time = 2
@collection.synchronize do
@collection.lookup_or_add('foo') { foo }
@collection.lookup_or_add('bar') { bar }
end
sleep 0.3
@collection.synchronize do
@collection.should_not have_key('foo')
@collection.should have_key('bar')
end
end
specify "servers with max_idle_time of 0 are never cleaned up" do
@collection.synchronize do
@collection.lookup_or_add('foo') { AbstractServer.new }
end
original_cleaning_time = @collection.next_cleaning_time
@collection.check_idle_servers!
# Wait until the cleaner thread has run.
while original_cleaning_time == @collection.next_cleaning_time
sleep 0.01
end
@collection.synchronize do
@collection.should have_key('foo')
end
end
specify "upon adding a new server to an empty collection, the next cleaning will " <<
"be scheduled at that server's next cleaning time" do
server = AbstractServer.new
server.max_idle_time = 10
@collection.synchronize do
@collection.lookup_or_add('foo') { server }
end
@collection.next_cleaning_time.should == server.next_cleaning_time
end
specify "upon adding a new server to a nonempty collection, and that server's next cleaning " <<
"time is not the smallest of all servers' cleaning times, then the next cleaning schedule " <<
"will not change" do
server1 = AbstractServer.new
server1.max_idle_time = 10
@collection.synchronize do
@collection.lookup_or_add('foo') { server1 }
end
server2 = AbstractServer.new
server2.max_idle_time = 11
@collection.synchronize do
@collection.lookup_or_add('bar') { server2 }
end
@collection.next_cleaning_time.should == server1.next_cleaning_time
end
specify "upon deleting server from a nonempty collection, and the deleted server's next cleaning " <<
"time IS the smallest of all servers' cleaning times, then the next cleaning schedule " <<
"will be changed to the smallest cleaning time of all servers" do
server1 = AbstractServer.new
server1.max_idle_time = 10
@collection.synchronize do
@collection.lookup_or_add('foo') { server1 }
end
server2 = AbstractServer.new
server2.max_idle_time = 11
@collection.synchronize do
@collection.lookup_or_add('bar') { server2 }
end
@collection.synchronize do
@collection.delete('foo')
end
@collection.next_cleaning_time.should == server2.next_cleaning_time
end
specify "upon deleting server from a nonempty collection, and the deleted server's next cleaning " <<
"time IS NOT the smallest of all servers' cleaning times, then the next cleaning schedule " <<
"will not change" do
server1 = AbstractServer.new
server1.max_idle_time = 10
@collection.synchronize do
@collection.lookup_or_add('foo') { server1 }
end
server2 = AbstractServer.new
server2.max_idle_time = 11
@collection.synchronize do
@collection.lookup_or_add('bar') { server2 }
end
@collection.synchronize do
@collection.delete('bar')
end
@collection.next_cleaning_time.should == server1.next_cleaning_time
end
specify "bug check" do
block = lambda do
@collection.synchronize do
@collection.clear
@collection.lookup_or_add('foo') do
s = AbstractServer.new
s.max_idle_time = 0.05
s
end
@collection.lookup_or_add('bar') { AbstractServer.new }
end
end
block.should_not raise_error
end
end
end # module PhusionPassenger