/
test_integration_single.rb
208 lines (153 loc) · 5.65 KB
/
test_integration_single.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
require_relative "helper"
require_relative "helpers/integration"
class TestIntegrationSingle < TestIntegration
parallelize_me!
def test_usr2_restart
skip_unless_signal_exist? :USR2
_, new_reply = restart_server_and_listen("-q test/rackup/hello.ru")
assert_equal "Hello World", new_reply
end
def test_hot_restart_does_not_drop_connections
skip_unless_signal_exist? :USR2
replies = Hash.new 0
num_requests = 500
refused = thread_run_refused unix: false
message = 'A' * 2**14
cli_server "-q test/rackup/hello.ru"
client_thread = Thread.new do
num_requests.times do
begin
socket = TCPSocket.new(HOST, @tcp_port)
@ios_to_close << socket
socket << "POST / HTTP/1.1\r\nContent-Length: #{message.bytesize}\r\n\r\n#{message}"
true until socket.gets == "\r\n"
body = read_body(socket, 20)
if body == "Hello World"
replies[:success] += 1
else
replies[:unexpected_response] += 1
end
rescue Errno::ECONNRESET
# connection was accepted but then closed
# client would see an empty response
replies[:reset] += 1
rescue *refused
replies[:refused] += 1
end
end
end
run = true
restart_thread = Thread.new do
while run
Process.kill :USR2, @pid
wait_for_server_to_boot
sleep 1
end
end
client_thread.join
run = false
restart_thread.join
assert_equal 0, replies[:unexpected_response], "Unexpected response"
assert_equal 0, replies[:reset], "Expected no reset errors"
assert_equal 0, replies[:refused], "Expected no refused connections"
assert_equal num_requests, replies[:success]
end
# It does not share environments between multiple generations, which would break Dotenv
def test_usr2_restart_restores_environment
# jruby has a bug where setting `nil` into the ENV or `delete` do not change the
# next workers ENV
skip_on :jruby
skip_unless_signal_exist? :USR2
initial_reply, new_reply = restart_server_and_listen("-q test/rackup/hello-env.ru")
assert_includes initial_reply, "Hello RAND"
assert_includes new_reply, "Hello RAND"
refute_equal initial_reply, new_reply
end
def test_term_exit_code
skip_unless_signal_exist? :TERM
skip_on :jruby # JVM does not return correct exit code for TERM
cli_server "test/rackup/hello.ru"
_, status = stop_server
assert_equal 15, status
end
def test_term_suppress
skip_unless_signal_exist? :TERM
cli_server "-C test/config/suppress_exception.rb test/rackup/hello.ru"
_, status = stop_server
assert_equal 0, status
end
def test_prefer_rackup_file_specified_by_cli
skip_unless_signal_exist? :TERM
cli_server "-C test/config/with_rackup_from_dsl.rb test/rackup/hello.ru"
reply = read_body(connect)
stop_server
assert_match("Hello World", reply)
end
def test_term_not_accepts_new_connections
skip_unless_signal_exist? :TERM
skip_on :jruby
cli_server 'test/rackup/sleep.ru'
_stdin, curl_stdout, _stderr, curl_wait_thread = Open3.popen3({ 'LC_ALL' => 'C' }, "curl http://#{HOST}:#{@tcp_port}/sleep10")
sleep 1 # ensure curl send a request
Process.kill :TERM, @pid
true while @server.gets !~ /Gracefully stopping/ # wait for server to begin graceful shutdown
# Invoke a request which must be rejected
_stdin, _stdout, rejected_curl_stderr, rejected_curl_wait_thread = Open3.popen3("curl #{HOST}:#{@tcp_port}")
assert nil != Process.getpgid(@server.pid) # ensure server is still running
assert nil != Process.getpgid(curl_wait_thread[:pid]) # ensure first curl invocation still in progress
curl_wait_thread.join
rejected_curl_wait_thread.join
assert_match(/Slept 10/, curl_stdout.read)
assert_match(/Connection refused/, rejected_curl_stderr.read)
Process.wait(@server.pid)
@server.close unless @server.closed?
@server = nil # prevent `#teardown` from killing already killed server
end
def test_int_refuse
skip_unless_signal_exist? :INT
cli_server 'test/rackup/hello.ru'
begin
sock = TCPSocket.new(HOST, @tcp_port)
sock.close
rescue => ex
fail("Port didn't open properly: #{ex.message}")
end
Process.kill :INT, @pid
Process.wait @pid
assert_raises(Errno::ECONNREFUSED) { TCPSocket.new(HOST, @tcp_port) }
end
def test_siginfo_thread_print
skip_unless_signal_exist? :INFO
cli_server 'test/rackup/hello.ru'
output = []
t = Thread.new { output << @server.readlines }
Process.kill :INFO, @pid
Process.kill :INT , @pid
t.join
assert_match "Thread: TID", output.join
end
def test_write_to_log
skip_unless_signal_exist? :TERM
suppress_output = '> /dev/null 2>&1'
cli_server '-C test/config/t1_conf.rb test/rackup/hello.ru'
system "curl http://localhost:#{@tcp_port}/ #{suppress_output}"
stop_server
log = File.read('t1-stdout')
File.unlink 't1-stdout' if File.file? 't1-stdout'
File.unlink 't1-pid' if File.file? 't1-pid'
assert_match(%r!GET / HTTP/1\.1!, log)
end
def test_puma_started_log_writing
skip_unless_signal_exist? :TERM
suppress_output = '> /dev/null 2>&1'
cli_server '-C test/config/t2_conf.rb test/rackup/hello.ru'
system "curl http://localhost:#{@tcp_port}/ #{suppress_output}"
out=`#{BASE} bin/pumactl -F test/config/t2_conf.rb status`
stop_server
log = File.read('t2-stdout')
File.unlink 't2-stdout' if File.file? 't2-stdout'
assert_match(%r!GET / HTTP/1\.1!, log)
assert(!File.file?("t2-pid"))
assert_equal("Puma is started\n", out)
end
end