1 # -*- encoding: binary -*-
7 $stderr.sync = $stdout.sync = true
9 class TestLinux < Test::Unit::TestCase
10 include Raindrops::Linux
12 TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
19 @to_close.each { |io| io.close unless io.closed? }
23 tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
25 us = UNIXServer.new(tmp.path)
26 stats = unix_listener_stats([tmp.path])
27 assert_equal 1, stats.size
28 assert_equal 0, stats[tmp.path].active
29 assert_equal 0, stats[tmp.path].queued
31 @to_close << UNIXSocket.new(tmp.path)
32 stats = unix_listener_stats([tmp.path])
33 assert_equal 1, stats.size
34 assert_equal 0, stats[tmp.path].active
35 assert_equal 1, stats[tmp.path].queued
37 @to_close << UNIXSocket.new(tmp.path)
38 stats = unix_listener_stats([tmp.path])
39 assert_equal 1, stats.size
40 assert_equal 0, stats[tmp.path].active
41 assert_equal 2, stats[tmp.path].queued
43 @to_close << us.accept
44 stats = unix_listener_stats([tmp.path])
45 assert_equal 1, stats.size
46 assert_equal 1, stats[tmp.path].active
47 assert_equal 1, stats[tmp.path].queued
51 tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
53 us = UNIXServer.new(tmp.path)
54 @to_close << UNIXSocket.new(tmp.path)
55 stats = unix_listener_stats
56 assert_equal 0, stats[tmp.path].active
57 assert_equal 1, stats[tmp.path].queued
59 @to_close << UNIXSocket.new(tmp.path)
60 stats = unix_listener_stats
61 assert_equal 0, stats[tmp.path].active
62 assert_equal 2, stats[tmp.path].queued
64 @to_close << us.accept
65 stats = unix_listener_stats
66 assert_equal 1, stats[tmp.path].active
67 assert_equal 1, stats[tmp.path].queued
70 def test_unix_all_unused
71 tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
73 us = UNIXServer.new(tmp.path)
74 stats = unix_listener_stats
75 assert stats.keys.include?(tmp.path), stats.inspect
77 assert_equal 0, stats[tmp.path].active
78 assert_equal 0, stats[tmp.path].queued
81 def test_unix_resolves_symlinks
82 tmp = Tempfile.new("\xde\xad\xbe\xef") # valid path, really :)
84 us = UNIXServer.new(tmp.path)
87 link = Tempfile.new("somethingelse")
88 File.unlink(link.path) # We need an available name, not an actual file
89 File.symlink(tmp.path, link.path)
91 @to_close << UNIXSocket.new(tmp.path)
92 stats = unix_listener_stats
93 assert_equal 0, stats[tmp.path].active
94 assert_equal 1, stats[tmp.path].queued
96 @to_close << UNIXSocket.new(link.path)
97 stats = unix_listener_stats([link.path])
98 assert_equal 0, stats[link.path].active
99 assert_equal 2, stats[link.path].queued
101 assert_equal stats[link.path].object_id, stats[tmp.path].object_id
103 @to_close << us.accept
104 stats = unix_listener_stats
105 assert_equal 1, stats[tmp.path].active
106 assert_equal 1, stats[tmp.path].queued
110 s = TCPServer.new(TEST_ADDR, 0)
112 addr = "#{TEST_ADDR}:#{port}"
114 stats = tcp_listener_stats(addrs)
115 assert_equal 1, stats.size
116 assert_equal 0, stats[addr].queued
117 assert_equal 0, stats[addr].active
119 @to_close << TCPSocket.new(TEST_ADDR, port)
120 stats = tcp_listener_stats(addrs)
121 assert_equal 1, stats.size
122 assert_equal 1, stats[addr].queued
123 assert_equal 0, stats[addr].active
125 @to_close << s.accept
126 stats = tcp_listener_stats(addrs)
127 assert_equal 1, stats.size
128 assert_equal 0, stats[addr].queued
129 assert_equal 1, stats[addr].active
132 def test_tcp_reuse_sock
133 nlsock = Raindrops::InetDiagSocket.new
134 s = TCPServer.new(TEST_ADDR, 0)
136 addr = "#{TEST_ADDR}:#{port}"
138 stats = tcp_listener_stats(addrs, nlsock)
139 assert_equal 1, stats.size
140 assert_equal 0, stats[addr].queued
141 assert_equal 0, stats[addr].active
143 @to_close << TCPSocket.new(TEST_ADDR, port)
144 stats = tcp_listener_stats(addrs, nlsock)
145 assert_equal 1, stats.size
146 assert_equal 1, stats[addr].queued
147 assert_equal 0, stats[addr].active
149 @to_close << s.accept
150 stats = tcp_listener_stats(addrs, nlsock)
151 assert_equal 1, stats.size
152 assert_equal 0, stats[addr].queued
153 assert_equal 1, stats[addr].active
159 s1 = TCPServer.new(TEST_ADDR, 0)
160 s2 = TCPServer.new(TEST_ADDR, 0)
161 port1, port2 = s1.addr[1], s2.addr[1]
162 addr1, addr2 = "#{TEST_ADDR}:#{port1}", "#{TEST_ADDR}:#{port2}"
163 addrs = [ addr1, addr2 ]
164 stats = tcp_listener_stats(addrs)
165 assert_equal 2, stats.size
166 assert_equal 0, stats[addr1].queued
167 assert_equal 0, stats[addr1].active
168 assert_equal 0, stats[addr2].queued
169 assert_equal 0, stats[addr2].active
171 @to_close << TCPSocket.new(TEST_ADDR, port1)
172 stats = tcp_listener_stats(addrs)
173 assert_equal 2, stats.size
174 assert_equal 1, stats[addr1].queued
175 assert_equal 0, stats[addr1].active
176 assert_equal 0, stats[addr2].queued
177 assert_equal 0, stats[addr2].active
180 stats = tcp_listener_stats(addrs)
181 assert_equal 2, stats.size
182 assert_equal 0, stats[addr1].queued
183 assert_equal 1, stats[addr1].active
184 assert_equal 0, stats[addr2].queued
185 assert_equal 0, stats[addr2].active
187 @to_close << TCPSocket.new(TEST_ADDR, port2)
188 stats = tcp_listener_stats(addrs)
189 assert_equal 2, stats.size
190 assert_equal 0, stats[addr1].queued
191 assert_equal 1, stats[addr1].active
192 assert_equal 1, stats[addr2].queued
193 assert_equal 0, stats[addr2].active
195 @to_close << TCPSocket.new(TEST_ADDR, port2)
196 stats = tcp_listener_stats(addrs)
197 assert_equal 2, stats.size
198 assert_equal 0, stats[addr1].queued
199 assert_equal 1, stats[addr1].active
200 assert_equal 2, stats[addr2].queued
201 assert_equal 0, stats[addr2].active
203 @to_close << s2.accept
204 stats = tcp_listener_stats(addrs)
205 assert_equal 2, stats.size
206 assert_equal 0, stats[addr1].queued
207 assert_equal 1, stats[addr1].active
208 assert_equal 1, stats[addr2].queued
209 assert_equal 1, stats[addr2].active
212 stats = tcp_listener_stats(addrs)
213 assert_equal 0, stats[addr1].queued
214 assert_equal 0, stats[addr1].active
215 assert_equal 1, stats[addr2].queued
216 assert_equal 1, stats[addr2].active
219 # tries to overflow buffers
220 def test_tcp_stress_test
223 s = TCPServer.new(TEST_ADDR, 0)
225 addr = "#{TEST_ADDR}:#{port}"
234 @to_close.concat((1..nr_sock).map { s.accept })
237 rdb.sysread(1) # wait for parent to nuke us
245 @to_close.concat((1..nr_sock).map { TCPSocket.new(TEST_ADDR, port) })
248 rdb.sysread(1) # wait for parent to nuke us
252 assert_equal('.' * (nr_proc * 2), rda.read(nr_proc * 2))
255 stats = tcp_listener_stats(addrs)
256 expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 0] }
257 assert_equal expect, stats
259 @to_close << TCPSocket.new(TEST_ADDR, port)
260 stats = tcp_listener_stats(addrs)
261 expect = { addr => Raindrops::ListenStats[nr_sock * nr_proc, 1] }
262 assert_equal expect, stats
264 if ENV["BENCHMARK"].to_i != 0
266 puts(Benchmark.measure{1000.times { tcp_listener_stats(addrs) }})
269 wrb.syswrite('.' * (nr_proc * 2)) # broadcast a wakeup
270 statuses = Process.waitall
271 statuses.each { |(_,status)| assert status.success?, status.inspect }
272 end if ENV["STRESS"].to_i != 0
273 end if RUBY_PLATFORM =~ /linux/