puma 2.11.1 → 2.11.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

@@ -1,38 +0,0 @@
1
- require 'puma/io_buffer'
2
- require 'test/unit'
3
-
4
- class TestIOBuffer < Test::Unit::TestCase
5
- attr_accessor :iobuf
6
- def setup
7
- self.iobuf = Puma::IOBuffer.new
8
- end
9
-
10
- def test_initial_size
11
- assert_equal 0, iobuf.used
12
- assert iobuf.capacity > 0
13
- end
14
-
15
- def test_append_op
16
- iobuf << "abc"
17
- assert_equal "abc", iobuf.to_s
18
- iobuf << "123"
19
- assert_equal "abc123", iobuf.to_s
20
- assert_equal 6, iobuf.used
21
- end
22
-
23
- def test_append
24
- expected = "mary had a little lamb"
25
- iobuf.append("mary", " ", "had ", "a little", " lamb")
26
- assert_equal expected, iobuf.to_s
27
- assert_equal expected.length, iobuf.used
28
- end
29
-
30
- def test_reset
31
- iobuf << "content"
32
- assert_equal "content", iobuf.to_s
33
- iobuf.reset
34
- assert_equal 0, iobuf.used
35
- assert_equal "", iobuf.to_s
36
- end
37
-
38
- end
@@ -1,29 +0,0 @@
1
- require 'test/unit'
2
- require 'puma'
3
- require 'puma/minissl'
4
-
5
- class TestMiniSSL < Test::Unit::TestCase
6
-
7
- if defined?(JRUBY_VERSION)
8
- def test_raises_with_invalid_keystore_file
9
- ctx = Puma::MiniSSL::Context.new
10
-
11
- exception = assert_raise(ArgumentError) { ctx.keystore = "/no/such/keystore" }
12
- assert_equal("No such keystore file '/no/such/keystore'", exception.message)
13
- end
14
- else
15
- def test_raises_with_invalid_key_file
16
- ctx = Puma::MiniSSL::Context.new
17
-
18
- exception = assert_raise(ArgumentError) { ctx.key = "/no/such/key" }
19
- assert_equal("No such key file '/no/such/key'", exception.message)
20
- end
21
-
22
- def test_raises_with_invalid_cert_file
23
- ctx = Puma::MiniSSL::Context.new
24
-
25
- exception = assert_raise(ArgumentError) { ctx.cert = "/no/such/cert" }
26
- assert_equal("No such cert file '/no/such/cert'", exception.message)
27
- end
28
- end
29
- end
@@ -1,31 +0,0 @@
1
- require 'puma/null_io'
2
- require 'test/unit'
3
-
4
- class TestNullIO < Test::Unit::TestCase
5
- attr_accessor :nio
6
- def setup
7
- self.nio = Puma::NullIO.new
8
- end
9
-
10
- def test_read_with_no_arguments
11
- assert_equal "", nio.read
12
- end
13
-
14
- def test_read_with_nil_length
15
- assert_equal "", nio.read(nil)
16
- end
17
-
18
- def test_read_with_zero_length
19
- assert_equal "", nio.read(0)
20
- end
21
-
22
- def test_read_with_positive_integer_length
23
- assert_nil nio.read(1)
24
- end
25
-
26
- def test_read_with_length_and_buffer
27
- buf = ""
28
- assert_nil nio.read(1,buf)
29
- assert_equal "", buf
30
- end
31
- end
@@ -1,238 +0,0 @@
1
- require 'puma'
2
- require 'test/unit'
3
- require 'timeout'
4
-
5
- class TestPersistent < Test::Unit::TestCase
6
- def setup
7
- @valid_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
8
- @close_request = "GET / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\n"
9
- @http10_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
10
- @keep_request = "GET / HTTP/1.0\r\nHost: test.com\r\nContent-Type: text/plain\r\nConnection: Keep-Alive\r\n\r\n"
11
-
12
- @valid_post = "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello"
13
- @valid_no_body = "GET / HTTP/1.1\r\nHost: test.com\r\nX-Status: 204\r\nContent-Type: text/plain\r\n\r\n"
14
-
15
- @headers = { "X-Header" => "Works" }
16
- @body = ["Hello"]
17
- @inputs = []
18
-
19
- @simple = lambda do |env|
20
- @inputs << env['rack.input']
21
- status = Integer(env['HTTP_X_STATUS'] || 200)
22
- [status, @headers, @body]
23
- end
24
-
25
- @host = "127.0.0.1"
26
- @port = 9988
27
-
28
- @server = Puma::Server.new @simple
29
- @server.add_tcp_listener "127.0.0.1", 9988
30
- @server.max_threads = 1
31
- @server.run
32
-
33
- @client = TCPSocket.new "127.0.0.1", 9988
34
- end
35
-
36
- def teardown
37
- @client.close
38
- @server.stop(true)
39
- end
40
-
41
- def lines(count, s=@client)
42
- str = ""
43
- timeout(5) do
44
- count.times { str << s.gets }
45
- end
46
- str
47
- end
48
-
49
- def test_one_with_content_length
50
- @client << @valid_request
51
- sz = @body[0].size.to_s
52
-
53
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
54
- assert_equal "Hello", @client.read(5)
55
- end
56
-
57
- def test_two_back_to_back
58
- @client << @valid_request
59
- sz = @body[0].size.to_s
60
-
61
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
62
- assert_equal "Hello", @client.read(5)
63
-
64
- @client << @valid_request
65
- sz = @body[0].size.to_s
66
-
67
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
68
- assert_equal "Hello", @client.read(5)
69
- end
70
-
71
- def test_post_then_get
72
- @client << @valid_post
73
- sz = @body[0].size.to_s
74
-
75
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
76
- assert_equal "Hello", @client.read(5)
77
-
78
- @client << @valid_request
79
- sz = @body[0].size.to_s
80
-
81
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
82
- assert_equal "Hello", @client.read(5)
83
- end
84
-
85
- def test_no_body_then_get
86
- @client << @valid_no_body
87
- assert_equal "HTTP/1.1 204 No Content\r\nX-Header: Works\r\n\r\n", lines(3)
88
-
89
- @client << @valid_request
90
- sz = @body[0].size.to_s
91
-
92
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
93
- assert_equal "Hello", @client.read(5)
94
- end
95
-
96
- def test_chunked
97
- @body << "Chunked"
98
-
99
- @client << @valid_request
100
-
101
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n7\r\nChunked\r\n0\r\n\r\n", lines(10)
102
- end
103
-
104
- def test_no_chunked_in_http10
105
- @body << "Chunked"
106
-
107
- @client << @http10_request
108
-
109
- assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\n\r\n", lines(4)
110
- assert_equal "HelloChunked", @client.read
111
- end
112
-
113
- def test_hex
114
- str = "This is longer and will be in hex"
115
- @body << str
116
-
117
- @client << @valid_request
118
-
119
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nHello\r\n#{str.size.to_s(16)}\r\n#{str}\r\n0\r\n\r\n", lines(10)
120
-
121
- end
122
-
123
- def test_client11_close
124
- @client << @close_request
125
- sz = @body[0].size.to_s
126
-
127
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
128
- assert_equal "Hello", @client.read(5)
129
- end
130
-
131
- def test_client10_close
132
- @client << @http10_request
133
- sz = @body[0].size.to_s
134
-
135
- assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: close\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
136
- assert_equal "Hello", @client.read(5)
137
- end
138
-
139
- def test_one_with_keep_alive_header
140
- @client << @keep_request
141
- sz = @body[0].size.to_s
142
-
143
- assert_equal "HTTP/1.0 200 OK\r\nX-Header: Works\r\nConnection: Keep-Alive\r\nContent-Length: #{sz}\r\n\r\n", lines(5)
144
- assert_equal "Hello", @client.read(5)
145
- end
146
-
147
- def test_persistent_timeout
148
- @server.persistent_timeout = 2
149
- @client << @valid_request
150
- sz = @body[0].size.to_s
151
-
152
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
153
- assert_equal "Hello", @client.read(5)
154
-
155
- sleep 3
156
-
157
- assert_raises EOFError do
158
- @client.read_nonblock(1)
159
- end
160
- end
161
-
162
- def test_app_sets_content_length
163
- @body = ["hello", " world"]
164
- @headers['Content-Length'] = "11"
165
-
166
- @client << @valid_request
167
-
168
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: 11\r\n\r\n",
169
- lines(4)
170
- assert_equal "hello world", @client.read(11)
171
- end
172
-
173
- def test_allow_app_to_chunk_itself
174
- @headers = {'Transfer-Encoding' => "chunked" }
175
-
176
- @body = ["5\r\nhello\r\n0\r\n\r\n"]
177
-
178
- @client << @valid_request
179
-
180
- assert_equal "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n", lines(7)
181
- end
182
-
183
-
184
- def test_two_requests_in_one_chunk
185
- @server.persistent_timeout = 3
186
-
187
- req = @valid_request.to_s
188
- req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
189
-
190
- @client << req
191
-
192
- sz = @body[0].size.to_s
193
-
194
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
195
- assert_equal "Hello", @client.read(5)
196
-
197
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
198
- assert_equal "Hello", @client.read(5)
199
- end
200
-
201
- def test_second_request_not_in_first_req_body
202
- @server.persistent_timeout = 3
203
-
204
- req = @valid_request.to_s
205
- req << "GET /second HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\n\r\n"
206
-
207
- @client << req
208
-
209
- sz = @body[0].size.to_s
210
-
211
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
212
- assert_equal "Hello", @client.read(5)
213
-
214
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4)
215
- assert_equal "Hello", @client.read(5)
216
-
217
- assert_kind_of Puma::NullIO, @inputs[0]
218
- assert_kind_of Puma::NullIO, @inputs[1]
219
- end
220
-
221
- def test_keepalive_doesnt_starve_clients
222
- sz = @body[0].size.to_s
223
-
224
- @client << @valid_request
225
-
226
- c2 = TCPSocket.new @host, @port
227
- c2 << @valid_request
228
-
229
- out = IO.select([c2], nil, nil, 1)
230
-
231
- assert out, "select returned nil"
232
- assert_equal c2, out.first.first
233
-
234
- assert_equal "HTTP/1.1 200 OK\r\nX-Header: Works\r\nContent-Length: #{sz}\r\n\r\n", lines(4, c2)
235
- assert_equal "Hello", c2.read(5)
236
- end
237
-
238
- end
@@ -1,288 +0,0 @@
1
- require "rbconfig"
2
- require 'test/unit'
3
- require 'socket'
4
- require 'openssl'
5
-
6
- require 'puma/minissl'
7
- require 'puma/server'
8
-
9
- require 'net/https'
10
-
11
- class TestPumaServer < Test::Unit::TestCase
12
-
13
- def setup
14
- @port = 3212
15
- @host = "127.0.0.1"
16
-
17
- @app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
18
-
19
- @events = Puma::Events.new STDOUT, STDERR
20
- @server = Puma::Server.new @app, @events
21
- end
22
-
23
- def teardown
24
- @server.stop(true)
25
- end
26
-
27
- def test_proper_stringio_body
28
- data = nil
29
-
30
- @server.app = proc do |env|
31
- data = env['rack.input'].read
32
- [200, {}, ["ok"]]
33
- end
34
-
35
- @server.add_tcp_listener @host, @port
36
- @server.run
37
-
38
- fifteen = "1" * 15
39
-
40
- sock = TCPSocket.new @host, @port
41
- sock << "PUT / HTTP/1.0\r\nContent-Length: 30\r\n\r\n#{fifteen}"
42
- sleep 0.1 # important so that the previous data is sent as a packet
43
- sock << fifteen
44
-
45
- sock.read
46
-
47
- assert_equal "#{fifteen}#{fifteen}", data
48
- end
49
-
50
- def test_puma_socket
51
- body = "HTTP/1.1 750 Upgraded to Awesome\r\nDone: Yep!\r\n"
52
- @server.app = proc do |env|
53
- io = env['puma.socket']
54
-
55
- io.write body
56
-
57
- io.close
58
-
59
- [-1, {}, []]
60
- end
61
-
62
- @server.add_tcp_listener @host, @port
63
- @server.run
64
-
65
- sock = TCPSocket.new @host, @port
66
- sock << "PUT / HTTP/1.0\r\n\r\nHello"
67
-
68
- assert_equal body, sock.read
69
- end
70
-
71
- def test_very_large_return
72
- giant = "x" * 2056610
73
-
74
- @server.app = proc do |env|
75
- [200, {}, [giant]]
76
- end
77
-
78
- @server.add_tcp_listener @host, @port
79
- @server.run
80
-
81
- sock = TCPSocket.new @host, @port
82
- sock << "GET / HTTP/1.0\r\n\r\n"
83
-
84
- while true
85
- line = sock.gets
86
- break if line == "\r\n"
87
- end
88
-
89
- out = sock.read
90
-
91
- assert_equal giant.bytesize, out.bytesize
92
- end
93
-
94
- def test_respect_x_forwarded_proto
95
- @server.app = proc do |env|
96
- [200, {}, [env['SERVER_PORT']]]
97
- end
98
-
99
- @server.add_tcp_listener @host, @port
100
- @server.run
101
-
102
- req = Net::HTTP::Get.new("/")
103
- req['HOST'] = "example.com"
104
- req['X_FORWARDED_PROTO'] = "https"
105
-
106
- res = Net::HTTP.start @host, @port do |http|
107
- http.request(req)
108
- end
109
-
110
- assert_equal "443", res.body
111
- end
112
-
113
- def test_default_server_port
114
- @server.app = proc do |env|
115
- [200, {}, [env['SERVER_PORT']]]
116
- end
117
-
118
- @server.add_tcp_listener @host, @port
119
- @server.run
120
-
121
- req = Net::HTTP::Get.new("/")
122
- req['HOST'] = "example.com"
123
-
124
- res = Net::HTTP.start @host, @port do |http|
125
- http.request(req)
126
- end
127
-
128
- assert_equal "80", res.body
129
- end
130
-
131
- def test_HEAD_has_no_body
132
- @server.app = proc { |env| [200, {"Foo" => "Bar"}, ["hello"]] }
133
-
134
- @server.add_tcp_listener @host, @port
135
- @server.run
136
-
137
- sock = TCPSocket.new @host, @port
138
- sock << "HEAD / HTTP/1.0\r\n\r\n"
139
-
140
- data = sock.read
141
-
142
- assert_equal "HTTP/1.0 200 OK\r\nFoo: Bar\r\nContent-Length: 5\r\n\r\n", data
143
- end
144
-
145
- def test_GET_with_empty_body_has_sane_chunking
146
- @server.app = proc { |env| [200, {}, [""]] }
147
-
148
- @server.add_tcp_listener @host, @port
149
- @server.run
150
-
151
- sock = TCPSocket.new @host, @port
152
- sock << "HEAD / HTTP/1.0\r\n\r\n"
153
-
154
- data = sock.read
155
-
156
- assert_equal "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n", data
157
- end
158
-
159
- def test_GET_with_no_body_has_sane_chunking
160
- @server.app = proc { |env| [200, {}, []] }
161
-
162
- @server.add_tcp_listener @host, @port
163
- @server.run
164
-
165
- sock = TCPSocket.new @host, @port
166
- sock << "HEAD / HTTP/1.0\r\n\r\n"
167
-
168
- data = sock.read
169
-
170
- assert_equal "HTTP/1.0 200 OK\r\n\r\n", data
171
- end
172
-
173
- def test_doesnt_print_backtrace_in_production
174
- @events = Puma::Events.strings
175
- @server = Puma::Server.new @app, @events
176
-
177
- @server.app = proc { |e| raise "don't leak me bro" }
178
- @server.leak_stack_on_error = false
179
- @server.add_tcp_listener @host, @port
180
- @server.run
181
-
182
- sock = TCPSocket.new @host, @port
183
- sock << "GET / HTTP/1.0\r\n\r\n"
184
-
185
- data = sock.read
186
-
187
- assert_not_match(/don't leak me bro/, data)
188
- assert_match(/HTTP\/1.0 500 Internal Server Error/, data)
189
- end
190
-
191
- def test_prints_custom_error
192
- @events = Puma::Events.strings
193
- re = lambda { |err| [302, {'Content-Type' => 'text', 'Location' => 'foo.html'}, ['302 found']] }
194
- @server = Puma::Server.new @app, @events, {lowlevel_error_handler: re}
195
-
196
- @server.app = proc { |e| raise "don't leak me bro" }
197
- @server.add_tcp_listener @host, @port
198
- @server.run
199
-
200
- sock = TCPSocket.new @host, @port
201
- sock << "GET / HTTP/1.0\r\n\r\n"
202
-
203
- data = sock.read
204
- assert_match(/HTTP\/1.0 302 Found/, data)
205
- end
206
-
207
- def test_custom_http_codes_10
208
- @server.app = proc { |env| [449, {}, [""]] }
209
-
210
- @server.add_tcp_listener @host, @port
211
- @server.run
212
-
213
- sock = TCPSocket.new @host, @port
214
-
215
- sock << "GET / HTTP/1.0\r\n\r\n"
216
-
217
- data = sock.read
218
-
219
- assert_equal "HTTP/1.0 449 CUSTOM\r\nConnection: close\r\nContent-Length: 0\r\n\r\n", data
220
- end
221
-
222
- def test_custom_http_codes_11
223
- @server.app = proc { |env| [449, {}, [""]] }
224
-
225
- @server.add_tcp_listener @host, @port
226
- @server.run
227
-
228
- sock = TCPSocket.new @host, @port
229
- sock << "GET / HTTP/1.1\r\n\r\n"
230
-
231
- data = sock.read
232
-
233
- assert_equal "HTTP/1.1 449 CUSTOM\r\nContent-Length: 0\r\n\r\n", data
234
- end
235
-
236
- def test_HEAD_returns_content_headers
237
- @server.app = proc { |env| [200, {"Content-Type" => "application/pdf",
238
- "Content-Length" => "4242"}, []] }
239
-
240
- @server.add_tcp_listener @host, @port
241
- @server.run
242
-
243
- sock = TCPSocket.new @host, @port
244
-
245
- sock << "HEAD / HTTP/1.0\r\n\r\n"
246
-
247
- data = sock.read
248
-
249
- assert_equal "HTTP/1.0 200 OK\r\nContent-Type: application/pdf\r\nContent-Length: 4242\r\n\r\n", data
250
- end
251
-
252
- def test_status_hook_fires_when_server_changes_states
253
-
254
- states = []
255
-
256
- @events.register(:state) { |s| states << s }
257
-
258
- @server.app = proc { |env| [200, {}, [""]] }
259
-
260
- @server.add_tcp_listener @host, @port
261
- @server.run
262
-
263
- sock = TCPSocket.new @host, @port
264
- sock << "HEAD / HTTP/1.0\r\n\r\n"
265
-
266
- sock.read
267
-
268
- assert_equal [:booting, :running], states
269
-
270
- @server.stop(true)
271
-
272
- assert_equal [:booting, :running, :stop, :done], states
273
- end
274
-
275
- def test_timeout_in_data_phase
276
- @server.first_data_timeout = 2
277
- @server.add_tcp_listener @host, @port
278
- @server.run
279
-
280
- client = TCPSocket.new @host, @port
281
-
282
- client << "POST / HTTP/1.1\r\nHost: test.com\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\n"
283
-
284
- data = client.gets
285
-
286
- assert_equal "HTTP/1.1 408 Request Timeout\r\n", data
287
- end
288
- end