summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2022-05-10 11:06:01 -0700
committerJeremy Evans <code@jeremyevans.net>2022-05-25 08:33:11 -0700
commit214023ea7745018125fcad43edc9ff8b6cfb209a (patch)
tree184d7181028714ba513661938590cfee13788002
parentf7e05d530ca306d2d730671765d88587c75b4741 (diff)
downloadrack-214023ea7745018125fcad43edc9ff8b6cfb209a.tar.gz
Add remaining tests for 100% branch coverage
Coverage after this commit: 3273 relevant lines, 3273 lines covered and 0 lines missed. ( 100.0% ) 1083 total branches, 1083 branches covered and 0 branches missed. ( 100.0% )
-rw-r--r--test/multipart/content_type_and_unknown_charset6
-rw-r--r--test/spec_auth_digest.rb5
-rw-r--r--test/spec_chunked.rb16
-rw-r--r--test/spec_common_logger.rb4
-rw-r--r--test/spec_conditional_get.rb27
-rw-r--r--test/spec_directory.rb24
-rw-r--r--test/spec_etag.rb6
-rw-r--r--test/spec_files.rb14
-rwxr-xr-xtest/spec_headers.rb1
-rw-r--r--test/spec_mock.rb11
-rw-r--r--test/spec_multipart.rb24
-rw-r--r--test/spec_rewindable_input.rb19
-rw-r--r--test/spec_sendfile.rb13
-rw-r--r--test/spec_static.rb8
-rw-r--r--test/spec_tempfile_reaper.rb16
-rw-r--r--test/spec_urlmap.rb5
16 files changed, 191 insertions, 8 deletions
diff --git a/test/multipart/content_type_and_unknown_charset b/test/multipart/content_type_and_unknown_charset
new file mode 100644
index 00000000..cf9c14c7
--- /dev/null
+++ b/test/multipart/content_type_and_unknown_charset
@@ -0,0 +1,6 @@
+--AaB03x
+content-disposition: form-data; name="text"
+content-type: text/plain; charset=foo; bar=baz
+
+contents
+--AaB03x--
diff --git a/test/spec_auth_digest.rb b/test/spec_auth_digest.rb
index e428375c..95df9c1b 100644
--- a/test/spec_auth_digest.rb
+++ b/test/spec_auth_digest.rb
@@ -273,6 +273,7 @@ describe Rack::Auth::Digest::MD5 do
req.respond_to?(:nonce).must_equal true
req.respond_to?(:a).must_equal true
req.a.must_equal 'b'
+ proc{req.missing}.must_raise NoMethodError
lambda { req.a(2) }.must_raise ArgumentError
end
@@ -280,4 +281,8 @@ describe Rack::Auth::Digest::MD5 do
Rack::Auth::Digest::Nonce.new.fresh?.must_equal true
Rack::Auth::Digest::Nonce.new.stale?.must_equal false
end
+
+ it 'Params.new can be called without a block' do
+ Rack::Auth::Digest::Params.new.must_be_instance_of(Rack::Auth::Digest::Params)
+ end
end
diff --git a/test/spec_chunked.rb b/test/spec_chunked.rb
index ec3e4fb2..933a0817 100644
--- a/test/spec_chunked.rb
+++ b/test/spec_chunked.rb
@@ -52,6 +52,22 @@ describe Rack::Chunked do
response.body.must_equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
end
+ it 'avoid empty chunks' do
+ app = lambda { |env| [200, { "content-type" => "text/plain" }, ['Hello', '', 'World!']] }
+ response = Rack::MockResponse.new(*chunked(app).call(@env))
+ response.headers.wont_include 'content-length'
+ response.headers['transfer-encoding'].must_equal 'chunked'
+ response.body.must_equal "5\r\nHello\r\n6\r\nWorld!\r\n0\r\n\r\n"
+ end
+
+ it 'handles unclosable bodies' do
+ app = lambda { |env| [200, { "content-type" => "text/plain" }, ['Hello', '', 'World!']] }
+ response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
+ response.headers.wont_include 'content-length'
+ response.headers['transfer-encoding'].must_equal 'chunked'
+ response.body.must_equal "5\r\nHello\r\n6\r\nWorld!\r\n0\r\n\r\n"
+ end
+
it 'chunks empty bodies properly' do
app = lambda { |env| [200, { "content-type" => "text/plain" }, []] }
response = Rack::MockResponse.new(*chunked(app).call(@env))
diff --git a/test/spec_common_logger.rb b/test/spec_common_logger.rb
index 09995dda..56495e6c 100644
--- a/test/spec_common_logger.rb
+++ b/test/spec_common_logger.rb
@@ -91,10 +91,10 @@ describe Rack::CommonLogger do
it "log in common log format" do
log = StringIO.new
with_mock_time do
- Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
+ Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/", 'QUERY_STRING' => 'foo=bar')
end
- md = /- - - \[([^\]]+)\] "(\w+) \/ HTTP\/1\.1" (\d{3}) \d+ ([\d\.]+)/.match(log.string)
+ md = /- - - \[([^\]]+)\] "(\w+) \/\?foo=bar HTTP\/1\.1" (\d{3}) \d+ ([\d\.]+)/.match(log.string)
md.wont_equal nil
time, method, status, duration = *md.captures
time.must_equal Time.at(0).strftime("%d/%b/%Y:%H:%M:%S %z")
diff --git a/test/spec_conditional_get.rb b/test/spec_conditional_get.rb
index 36da7412..8811bb27 100644
--- a/test/spec_conditional_get.rb
+++ b/test/spec_conditional_get.rb
@@ -37,6 +37,22 @@ describe Rack::ConditionalGet do
response.body.must_be :empty?
end
+ it "closes bodies" do
+ body = Object.new
+ def body.each; yield 'TEST' end
+ closed = false
+ body.define_singleton_method(:close){closed = true}
+ app = conditional_get(lambda { |env|
+ [200, { 'last-modified' => (Time.now - 3600).httpdate }, body] })
+
+ response = Rack::MockRequest.new(app).
+ get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
+
+ response.status.must_equal 304
+ response.body.must_be :empty?
+ closed.must_equal true
+ end
+
it "set a 304 status and truncate body when if-none-match hits" do
app = conditional_get(lambda { |env|
[200, { 'etag' => '1234' }, ['TEST']] })
@@ -59,6 +75,17 @@ describe Rack::ConditionalGet do
response.body.must_be :empty?
end
+ it "not set a 304 status if last-modified is too short" do
+ app = conditional_get(lambda { |env|
+ [200, { 'last-modified' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
+
+ response = Rack::MockRequest.new(app).
+ get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
+
+ response.status.must_equal 200
+ response.body.must_equal 'TEST'
+ end
+
it "not set a 304 status if if-modified-since hits but etag does not" do
timestamp = Time.now.httpdate
app = conditional_get(lambda { |env|
diff --git a/test/spec_directory.rb b/test/spec_directory.rb
index d7e90333..4e5db0e8 100644
--- a/test/spec_directory.rb
+++ b/test/spec_directory.rb
@@ -40,12 +40,34 @@ describe Rack::Directory do
end
end
+ it "serve root directory index" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/")
+
+ res.must_be :ok?
+ assert_includes(res.body, '<html><head>')
+ assert_includes(res.body, "href='cgi")
+ end
+
it "serve directory indices" do
res = Rack::MockRequest.new(Rack::Lint.new(app)).
get("/cgi/")
res.must_be :ok?
- assert_match(res, /<html><head>/)
+ assert_includes(res.body, '<html><head>')
+ assert_includes(res.body, "rackup_stub.rb")
+ end
+
+ it "return 404 for pipes" do
+ begin
+ File.mkfifo('test/cgi/fifo')
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/fifo")
+
+ res.status.must_equal 404
+ ensure
+ File.delete('test/cgi/fifo')
+ end
end
it "serve directory indices with bad symlinks" do
diff --git a/test/spec_etag.rb b/test/spec_etag.rb
index ecd9383f..35fab258 100644
--- a/test/spec_etag.rb
+++ b/test/spec_etag.rb
@@ -76,6 +76,12 @@ describe Rack::ETag do
response[1]['etag'].must_be_nil
end
+ it "set handle empty body parts" do
+ app = lambda { |env| [200, { 'content-type' => 'text/plain' }, ["Hello", "", ", World!"]] }
+ response = etag(app).call(request)
+ response[1]['etag'].must_equal "W/\"dffd6021bb2bd5b0af676290809ec3a5\""
+ end
+
it "not set etag if last-modified is set" do
app = lambda { |env| [200, { 'content-type' => 'text/plain', 'last-modified' => Time.now.httpdate }, ["Hello, World!"]] }
response = etag(app).call(request)
diff --git a/test/spec_files.rb b/test/spec_files.rb
index f74e5195..b65a7cfd 100644
--- a/test/spec_files.rb
+++ b/test/spec_files.rb
@@ -192,6 +192,20 @@ describe Rack::Files do
res.body.must_equal "IS FILE! ***"
end
+ it "handle case where file is truncated during request" do
+ env = Rack::MockRequest.env_for("/cgi/test")
+ env["HTTP_RANGE"] = "bytes=0-3300"
+ files = Class.new(Rack::Files) do
+ def filesize(_); 10000 end
+ end.new(DOCROOT)
+
+ res = Rack::MockResponse.new(*files.call(env))
+
+ res.status.must_equal 206
+ res["content-length"].must_equal "209"
+ res["content-range"].must_equal "bytes 0-3300/10000"
+ end
+
it "return correct multiple byte ranges in body" do
env = Rack::MockRequest.env_for("/cgi/test")
env["HTTP_RANGE"] = "bytes=22-33, 60-80"
diff --git a/test/spec_headers.rb b/test/spec_headers.rb
index cabf00ff..dcd6296b 100755
--- a/test/spec_headers.rb
+++ b/test/spec_headers.rb
@@ -468,6 +468,7 @@ class RackHeadersTest < Minitest::Spec
def test_slice
assert_equal(Rack::Headers['Ab'=>'1', 'cD'=>'2', '3'=>'4'], @fh.slice('aB', 'Cd', '3'))
assert_equal(Rack::Headers['AB'=>'1', 'CD'=>'2'], @fh.slice('Ab', 'CD'))
+ assert_equal(Rack::Headers[], @fh.slice('ad'))
assert_equal('1', @fh.slice('AB', 'cd')['Ab'])
end
diff --git a/test/spec_mock.rb b/test/spec_mock.rb
index 48dfde06..4bc57b18 100644
--- a/test/spec_mock.rb
+++ b/test/spec_mock.rb
@@ -49,6 +49,13 @@ describe Rack::MockRequest do
env.must_include "rack.version"
end
+ it "should handle a non-GET request with both :input and :params" do
+ env = Rack::MockRequest.env_for("/", method: :post, input: nil, params: {})
+ env["PATH_INFO"].must_equal "/"
+ env.must_be_kind_of Hash
+ env['rack.input'].read.must_equal ''
+ end
+
it "return an environment with a path" do
env = Rack::MockRequest.env_for("http://www.example.com/parse?location[]=1&location[]=2&age_group[]=2")
env["QUERY_STRING"].must_equal "location[]=1&location[]=2&age_group[]=2"
@@ -429,6 +436,10 @@ describe Rack::MockResponse do
res.body.must_equal 'hi'
end
+ it "ignores plain strings passed as errors" do
+ Rack::MockResponse.new(200, {}, [], 'e').errors.must_be_nil
+ end
+
it "optionally make Rack errors fatal" do
lambda {
Rack::MockRequest.new(app).get("/?error=foo", fatal: true)
diff --git a/test/spec_multipart.rb b/test/spec_multipart.rb
index 8e4a0c4c..12065aa1 100644
--- a/test/spec_multipart.rb
+++ b/test/spec_multipart.rb
@@ -527,6 +527,15 @@ content-type: image/jpeg\r
files[:tempfile].read.must_equal "contents"
end
+ it "raises RuntimeError for invalid file path" do
+ proc{Rack::Multipart::UploadedFile.new('non-existant')}.must_raise RuntimeError
+ end
+
+ it "supports uploading files in binary mode" do
+ Rack::Multipart::UploadedFile.new(multipart_file("file1.txt")).wont_be :binmode?
+ Rack::Multipart::UploadedFile.new(multipart_file("file1.txt"), binary: true).must_be :binmode?
+ end
+
it "builds multipart body" do
files = Rack::Multipart::UploadedFile.new(multipart_file("file1.txt"))
data = Rack::Multipart.build_multipart("submit-name" => "Larry", "files" => files)
@@ -660,6 +669,21 @@ content-type: image/jpeg\r
end
end
+ it "treat a multipart limit of 0 as no limit" do
+ begin
+ previous_limit = Rack::Utils.multipart_part_limit
+ Rack::Utils.multipart_part_limit = 0
+
+ env = Rack::MockRequest.env_for '/', multipart_fixture(:three_files_three_fields)
+ params = Rack::Multipart.parse_multipart(env)
+ params['reply'].must_equal 'yes'
+ params['to'].must_equal 'people'
+ params['from'].must_equal 'others'
+ ensure
+ Rack::Utils.multipart_part_limit = previous_limit
+ end
+ end
+
it "reach a multipart limit" do
begin
previous_limit = Rack::Utils.multipart_part_limit
diff --git a/test/spec_rewindable_input.rb b/test/spec_rewindable_input.rb
index e672bcbb..603afbda 100644
--- a/test/spec_rewindable_input.rb
+++ b/test/spec_rewindable_input.rb
@@ -13,10 +13,6 @@ module RewindableTest
@rio = Rack::RewindableInput.new(@io)
end
- class << self # HACK to get this running w/ as few changes as possible
- alias_method :should, :it
- end
-
it "be able to handle to read()" do
@rio.read.must_equal "hello world"
end
@@ -44,17 +40,23 @@ module RewindableTest
end
it "rewind to the beginning when #rewind is called" do
- @rio.read(1)
+ @rio.rewind
+ @rio.read(1).must_equal 'h'
@rio.rewind
@rio.read.must_equal "hello world"
end
it "be able to handle gets" do
@rio.gets.must_equal "hello world"
+ @rio.rewind
+ @rio.gets.must_equal "hello world"
end
it "be able to handle size" do
@rio.size.must_equal "hello world".size
+ @rio.size.must_equal "hello world".size
+ @rio.rewind
+ @rio.gets.must_equal "hello world"
end
it "be able to handle each" do
@@ -63,6 +65,13 @@ module RewindableTest
array << data
end
array.must_equal ["hello world"]
+
+ @rio.rewind
+ array = []
+ @rio.each do |data|
+ array << data
+ end
+ array.must_equal ["hello world"]
end
it "not buffer into a Tempfile if no data has been read yet" do
diff --git a/test/spec_sendfile.rb b/test/spec_sendfile.rb
index ee6f222a..c0ef5e5d 100644
--- a/test/spec_sendfile.rb
+++ b/test/spec_sendfile.rb
@@ -67,6 +67,19 @@ describe Rack::Sendfile do
end
end
+ it "closes body when x-sendfile used" do
+ body = sendfile_body
+ closed = false
+ body.define_singleton_method(:close){closed = true}
+ request({'HTTP_X_SENDFILE_TYPE' => 'x-sendfile'}, body) do |response|
+ response.must_be :ok?
+ response.body.must_be :empty?
+ response.headers['content-length'].must_equal '0'
+ response.headers['x-sendfile'].must_equal File.join(Dir.tmpdir, "rack_sendfile")
+ end
+ closed.must_equal true
+ end
+
it "sets x-lighttpd-send-file response header and discards body" do
request 'HTTP_X_SENDFILE_TYPE' => 'x-lighttpd-send-file' do |response|
response.must_be :ok?
diff --git a/test/spec_static.rb b/test/spec_static.rb
index e102ded6..9cc33a42 100644
--- a/test/spec_static.rb
+++ b/test/spec_static.rb
@@ -151,6 +151,14 @@ describe Rack::Static do
res.headers['content-type'].must_be_nil
end
+ it "return 304 if gzipped file isn't modified since last serve" do
+ path = File.join(DOCROOT, "/cgi/test")
+ res = @gzip_request.get("/cgi/test", 'HTTP_IF_MODIFIED_SINCE' => File.mtime(path+'.gz').httpdate, 'HTTP_ACCEPT_ENCODING' => 'deflate, gzip')
+
+ res.status.must_equal 304
+ res.body.must_be :empty?
+ end
+
it "supports serving fixed cache-control (legacy option)" do
opts = OPTIONS.merge(cache_control: 'public')
request = Rack::MockRequest.new(static(DummyApp.new, opts))
diff --git a/test/spec_tempfile_reaper.rb b/test/spec_tempfile_reaper.rb
index ce5d2c76..7e5c6790 100644
--- a/test/spec_tempfile_reaper.rb
+++ b/test/spec_tempfile_reaper.rb
@@ -84,4 +84,20 @@ describe Rack::TempfileReaper do
tempfile1.closed.must_equal true
tempfile2.closed.must_equal true
end
+
+ it 'handle missing rack.tempfiles on normal response' do
+ app = lambda do |env|
+ env.delete('rack.tempfiles')
+ [200, {}, ['Hello, World!']]
+ end
+ call(app)[2].close
+ end
+
+ it 'handle missing rack.tempfiles on error' do
+ app = lambda do |env|
+ env.delete('rack.tempfiles')
+ raise 'Foo'
+ end
+ proc{call(app)}.must_raise RuntimeError
+ end
end
diff --git a/test/spec_urlmap.rb b/test/spec_urlmap.rb
index 855e4541..e11c4e6d 100644
--- a/test/spec_urlmap.rb
+++ b/test/spec_urlmap.rb
@@ -44,6 +44,11 @@ describe Rack::URLMap do
res["x-scriptname"].must_equal "/foo/bar"
res["x-pathinfo"].must_equal ""
+ res = Rack::MockRequest.new(map).get("/foo/bard")
+ res.must_be :ok?
+ res["x-scriptname"].must_equal "/foo"
+ res["x-pathinfo"].must_equal "/bard"
+
res = Rack::MockRequest.new(map).get("/foo/bar/")
res.must_be :ok?
res["x-scriptname"].must_equal "/foo/bar"