/
test_integration_single.rb
207 lines (149 loc) · 5.57 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
require_relative "helper"
require_relative "helpers/integration"
class TestIntegrationSingle < TestIntegration
parallelize_me! if ::Puma.mri?
def workers ; 0 ; end
def test_hot_restart_does_not_drop_connections_threads
hot_restart_does_not_drop_connections num_threads: 5, total_requests: 1_000
end
def test_hot_restart_does_not_drop_connections
hot_restart_does_not_drop_connections
end
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
# 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_if :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_if :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_if :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
skip_if :jruby # seems to intermittently lockup JRuby CI
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
def test_application_logs_are_flushed_on_write
@control_tcp_port = UniquePort.call
cli_server "--control-url tcp://#{HOST}:#{@control_tcp_port} --control-token #{TOKEN} test/rackup/write_to_stdout.ru"
read_body connect
cli_pumactl 'stop'
assert_equal "hello\n", @server.gets
assert_includes @server.read, 'Goodbye!'
@server.close unless @server.closed?
@server = nil
end
# listener is closed 'externally' while Puma is in the IO.select statement
def test_closed_listener
skip_unless_signal_exist? :TERM
skip_if :darwin # been flaky with Ruby 2.2, 2.3, 2.4
cli_server "test/rackup/close_listeners.ru", merge_err: true
read_body connect
begin
Timeout.timeout(5) do
begin
Process.kill :SIGTERM, @pid
rescue Errno::ESRCH
end
begin
Process.wait2 @pid
rescue Errno::ECHILD
end
end
rescue Timeout::Error
Process.kill :SIGKILL, @pid
assert false, "Process froze"
end
assert true
end
end