Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Use Rack::Lint in all tests #290

Closed
wants to merge 1 commit into from

2 participants

@lgierth

ALL the tests

I recently stumbled upon my fix for #235 again and noticed that I hadn't modified the tests to use Rack::Lint and make sure no regressions will be introduced in the future. I also noticed that hardly any of the tests were using Rack::Lint as a means of verifying spec compliance. Middleware MUST conform to the spec and we can't be sure it does if we don't have tests for it.

This is just a first round with a few updated tests included to gather some feedback, I'll update the other tests if people are positive on this.

@lgierth lgierth Wrap test apps in Rack::Lint (first pass)
Update tests for Auth::Basic, Auth::Digest, Builder, Casecase, Handler::CGI,
Chunked, CommonLogger and ConditionalGet.
22284cb
@raggi raggi closed this
@raggi
Owner

Merged, thanks!

@lgierth

Thanks, I'll update the other tests as well.

@raggi
Owner

@lgierth please note the 1.8/1.9 fix I had to add.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 18, 2011
  1. @lgierth

    Wrap test apps in Rack::Lint (first pass)

    lgierth authored
    Update tests for Auth::Basic, Auth::Digest, Builder, Casecase, Handler::CGI,
    Chunked, CommonLogger and ConditionalGet.
This page is out of date. Refresh to see the latest.
View
2  lib/rack/cascade.rb
@@ -4,7 +4,7 @@ module Rack
# status codes).
class Cascade
- NotFound = [404, {}, []]
+ NotFound = [404, {"Content-Type" => "text/plain"}, []]
attr_reader :apps
View
2  test/cgi/sample_rackup.ru
@@ -2,4 +2,4 @@
require '../testrequest'
-run TestRequest.new
+run Rack::Lint.new(TestRequest.new)
View
2  test/cgi/test.ru
@@ -2,4 +2,4 @@
# -*- ruby -*-
require '../testrequest'
-run TestRequest.new
+run Rack::Lint.new(TestRequest.new)
View
5 test/spec_auth_basic.rb
@@ -1,4 +1,5 @@
require 'rack/auth/basic'
+require 'rack/lint'
require 'rack/mock'
describe Rack::Auth::Basic do
@@ -7,7 +8,9 @@ def realm
end
def unprotected_app
- lambda { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] }
+ Rack::Lint.new lambda { |env|
+ [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ]
+ }
end
def protected_app
View
5 test/spec_auth_digest.rb
@@ -1,4 +1,5 @@
require 'rack/auth/digest/md5'
+require 'rack/lint'
require 'rack/mock'
describe Rack::Auth::Digest::MD5 do
@@ -7,10 +8,10 @@ def realm
end
def unprotected_app
- lambda do |env|
+ Rack::Lint.new lambda { |env|
friend = Rack::Utils.parse_query(env["QUERY_STRING"])["friend"]
[ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}#{friend ? " and #{friend}" : ''}"] ]
- end
+ }
end
def protected_app
View
51 test/spec_builder.rb
@@ -1,4 +1,5 @@
require 'rack/builder'
+require 'rack/lint'
require 'rack/mock'
require 'rack/showexceptions'
require 'rack/urlmap'
@@ -18,38 +19,46 @@ def self.env
end
describe Rack::Builder do
+ def builder(&block)
+ Rack::Lint.new Rack::Builder.new(&block)
+ end
+
+ def builder_to_app(&block)
+ Rack::Lint.new Rack::Builder.new(&block).to_app
+ end
+
it "supports mapping" do
- app = Rack::Builder.new do
+ app = builder_to_app do
map '/' do |outer_env|
- run lambda { |inner_env| [200, {}, ['root']] }
+ run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
end
map '/sub' do
- run lambda { |inner_env| [200, {}, ['sub']] }
+ run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
end
- end.to_app
+ end
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
Rack::MockRequest.new(app).get("/sub").body.to_s.should.equal 'sub'
end
it "doesn't dupe env even when mapping" do
- app = Rack::Builder.new do
+ app = builder_to_app do
use NothingMiddleware
map '/' do |outer_env|
run lambda { |inner_env|
inner_env['new_key'] = 'new_value'
- [200, {}, ['root']]
+ [200, {"Content-Type" => "text/plain"}, ['root']]
}
end
- end.to_app
+ end
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
NothingMiddleware.env['new_key'].should.equal 'new_value'
end
it "chains apps by default" do
- app = Rack::Builder.new do
+ app = builder_to_app do
use Rack::ShowExceptions
run lambda { |env| raise "bzzzt" }
- end.to_app
+ end
Rack::MockRequest.new(app).get("/").should.be.server_error
Rack::MockRequest.new(app).get("/").should.be.server_error
@@ -57,7 +66,7 @@ def self.env
end
it "has implicit #to_app" do
- app = Rack::Builder.new do
+ app = builder do
use Rack::ShowExceptions
run lambda { |env| raise "bzzzt" }
end
@@ -68,13 +77,13 @@ def self.env
end
it "supports blocks on use" do
- app = Rack::Builder.new do
+ app = builder do
use Rack::ShowExceptions
use Rack::Auth::Basic do |username, password|
'secret' == password
end
- run lambda { |env| [200, {}, ['Hi Boss']] }
+ run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
end
response = Rack::MockRequest.new(app).get("/")
@@ -89,7 +98,7 @@ def self.env
end
it "has explicit #to_app" do
- app = Rack::Builder.app do
+ app = builder do
use Rack::ShowExceptions
run lambda { |env| raise "bzzzt" }
end
@@ -100,9 +109,11 @@ def self.env
end
it "can mix map and run for endpoints" do
- app = Rack::Builder.app do
- map('/sub') { run lambda { |inner_env| [200, {}, ['sub']] }}
- run lambda { |inner_env| [200, {}, ['root']] }
+ app = builder do
+ map '/sub' do
+ run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
+ end
+ run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
end
Rack::MockRequest.new(app).get("/").body.to_s.should.equal 'root'
@@ -110,7 +121,7 @@ def self.env
end
it "accepts middleware-only map blocks" do
- app = Rack::Builder.app do
+ app = builder do
map('/foo') { use Rack::ShowExceptions }
run lambda { |env| raise "bzzzt" }
end
@@ -120,7 +131,7 @@ def self.env
end
should "initialize apps once" do
- app = Rack::Builder.new do
+ app = builder do
class AppClass
def initialize
@called = 0
@@ -141,7 +152,7 @@ def call(env)
end
it "allows use after run" do
- app = Rack::Builder.app do
+ app = builder do
run lambda { |env| raise "bzzzt" }
use Rack::ShowExceptions
end
@@ -153,7 +164,7 @@ def call(env)
it 'complains about a missing run' do
proc do
- Rack::Builder.app { use Rack::ShowExceptions }
+ Rack::Lint.new Rack::Builder.app { use Rack::ShowExceptions }
end.should.raise(RuntimeError)
end
View
11 test/spec_cascade.rb
@@ -1,9 +1,14 @@
require 'rack/cascade'
require 'rack/file'
+require 'rack/lint'
require 'rack/urlmap'
require 'rack/mock'
describe Rack::Cascade do
+ def cascade(*args)
+ Rack::Lint.new Rack::Cascade.new(*args)
+ end
+
docroot = File.expand_path(File.dirname(__FILE__))
app1 = Rack::File.new(docroot)
@@ -13,7 +18,7 @@
[200, { "Content-Type" => "text/plain"}, [""]]})
should "dispatch onward on 404 by default" do
- cascade = Rack::Cascade.new([app1, app2, app3])
+ cascade = cascade([app1, app2, app3])
Rack::MockRequest.new(cascade).get("/cgi/test").should.be.ok
Rack::MockRequest.new(cascade).get("/foo").should.be.ok
Rack::MockRequest.new(cascade).get("/toobad").should.be.not_found
@@ -21,12 +26,12 @@
end
should "dispatch onward on whatever is passed" do
- cascade = Rack::Cascade.new([app1, app2, app3], [404, 403])
+ cascade = cascade([app1, app2, app3], [404, 403])
Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
end
should "return 404 if empty" do
- Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found
+ Rack::MockRequest.new(cascade([])).get('/').should.be.not_found
end
should "append new app" do
View
41 test/spec_chunked.rb
@@ -1,23 +1,34 @@
require 'rack/chunked'
+require 'rack/lint'
require 'rack/mock'
describe Rack::Chunked do
+ def chunked(app)
+ proc do |env|
+ app = Rack::Chunked.new(app)
+ Rack::Lint.new(app).call(env).tap do |response|
+ # we want to use body like an array, but it only has #each
+ response[2] = Enumerator.new(response[2]).to_a
+ end
+ end
+ end
+
before do
@env = Rack::MockRequest.
env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
end
should 'chunk responses with no Content-Length' do
- app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
- response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
+ app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
+ response = Rack::MockResponse.new(*chunked(app).call(@env))
response.headers.should.not.include 'Content-Length'
response.headers['Transfer-Encoding'].should.equal 'chunked'
response.body.should.equal "5\r\nHello\r\n1\r\n \r\n6\r\nWorld!\r\n0\r\n\r\n"
end
should 'chunks empty bodies properly' do
- app = lambda { |env| [200, {}, []] }
- response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
+ app = lambda { |env| [200, {"Content-Type" => "text/plain"}, []] }
+ response = Rack::MockResponse.new(*chunked(app).call(@env))
response.headers.should.not.include 'Content-Length'
response.headers['Transfer-Encoding'].should.equal 'chunked'
response.body.should.equal "0\r\n\r\n"
@@ -25,8 +36,8 @@
should 'chunks encoded bodies properly' do
body = ["\uFFFEHello", " ", "World"].map {|t| t.encode("UTF-16LE") }
- app = lambda { |env| [200, {}, body] }
- response = Rack::MockResponse.new(*Rack::Chunked.new(app).call(@env))
+ app = lambda { |env| [200, {"Content-Type" => "text/plain"}, body] }
+ response = Rack::MockResponse.new(*chunked(app).call(@env))
response.headers.should.not.include 'Content-Length'
response.headers['Transfer-Encoding'].should.equal 'chunked'
response.body.encoding.to_s.should == "ASCII-8BIT"
@@ -34,8 +45,10 @@
end if RUBY_VERSION >= "1.9"
should 'not modify response when Content-Length header present' do
- app = lambda { |env| [200, {'Content-Length'=>'12'}, ['Hello', ' ', 'World!']] }
- status, headers, body = Rack::Chunked.new(app).call(@env)
+ app = lambda { |env|
+ [200, {"Content-Type" => "text/plain", 'Content-Length'=>'12'}, ['Hello', ' ', 'World!']]
+ }
+ status, headers, body = chunked(app).call(@env)
status.should.equal 200
headers.should.not.include 'Transfer-Encoding'
headers.should.include 'Content-Length'
@@ -43,17 +56,19 @@
end
should 'not modify response when client is HTTP/1.0' do
- app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
+ app = lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hello', ' ', 'World!']] }
@env['HTTP_VERSION'] = 'HTTP/1.0'
- status, headers, body = Rack::Chunked.new(app).call(@env)
+ status, headers, body = chunked(app).call(@env)
status.should.equal 200
headers.should.not.include 'Transfer-Encoding'
body.join.should.equal 'Hello World!'
end
should 'not modify response when Transfer-Encoding header already present' do
- app = lambda { |env| [200, {'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']] }
- status, headers, body = Rack::Chunked.new(app).call(@env)
+ app = lambda { |env|
+ [200, {"Content-Type" => "text/plain", 'Transfer-Encoding' => 'identity'}, ['Hello', ' ', 'World!']]
+ }
+ status, headers, body = chunked(app).call(@env)
status.should.equal 200
headers['Transfer-Encoding'].should.equal 'identity'
body.join.should.equal 'Hello World!'
@@ -62,7 +77,7 @@
[100, 204, 205, 304].each do |status_code|
should "not modify response when status code is #{status_code}" do
app = lambda { |env| [status_code, {}, []] }
- status, headers, _ = Rack::Chunked.new(app).call(@env)
+ status, headers, _ = chunked(app).call(@env)
status.should.equal status_code
headers.should.not.include 'Transfer-Encoding'
end
View
7 test/spec_commonlogger.rb
@@ -1,19 +1,20 @@
require 'rack/commonlogger'
+require 'rack/lint'
require 'rack/mock'
describe Rack::CommonLogger do
obj = 'foobar'
length = obj.size
- app = lambda { |env|
+ app = Rack::Lint.new lambda { |env|
[200,
{"Content-Type" => "text/html", "Content-Length" => length.to_s},
[obj]]}
- app_without_length = lambda { |env|
+ app_without_length = Rack::Lint.new lambda { |env|
[200,
{"Content-Type" => "text/html"},
[]]}
- app_with_zero_length = lambda { |env|
+ app_with_zero_length = Rack::Lint.new lambda { |env|
[200,
{"Content-Type" => "text/html", "Content-Length" => "0"},
[]]}
View
28 test/spec_conditionalget.rb
@@ -3,9 +3,13 @@
require 'rack/mock'
describe Rack::ConditionalGet do
+ def conditional_get(app)
+ Rack::Lint.new Rack::ConditionalGet.new(app)
+ end
+
should "set a 304 status and truncate body when If-Modified-Since hits" do
timestamp = Time.now.httpdate
- app = Rack::ConditionalGet.new(lambda { |env|
+ app = conditional_get(lambda { |env|
[200, {'Last-Modified'=>timestamp}, ['TEST']] })
response = Rack::MockRequest.new(app).
@@ -16,7 +20,7 @@
end
should "set a 304 status and truncate body when If-Modified-Since hits and is higher than current time" do
- app = Rack::ConditionalGet.new(lambda { |env|
+ app = conditional_get(lambda { |env|
[200, {'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
response = Rack::MockRequest.new(app).
@@ -27,7 +31,7 @@
end
should "set a 304 status and truncate body when If-None-Match hits" do
- app = Rack::ConditionalGet.new(lambda { |env|
+ app = conditional_get(lambda { |env|
[200, {'Etag'=>'1234'}, ['TEST']] })
response = Rack::MockRequest.new(app).
@@ -39,8 +43,8 @@
should "not set a 304 status if If-Modified-Since hits but Etag does not" do
timestamp = Time.now.httpdate
- app = Rack::ConditionalGet.new(lambda { |env|
- [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] })
+ app = conditional_get(lambda { |env|
+ [200, {'Last-Modified'=>timestamp, 'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
@@ -51,7 +55,7 @@
should "set a 304 status and truncate body when both If-None-Match and If-Modified-Since hits" do
timestamp = Time.now.httpdate
- app = Rack::ConditionalGet.new(lambda { |env|
+ app = conditional_get(lambda { |env|
[200, {'Last-Modified'=>timestamp, 'Etag'=>'1234'}, ['TEST']] })
response = Rack::MockRequest.new(app).
@@ -62,8 +66,8 @@
end
should "not affect non-GET/HEAD requests" do
- app = Rack::ConditionalGet.new(lambda { |env|
- [200, {'Etag'=>'1234'}, ['TEST']] })
+ app = conditional_get(lambda { |env|
+ [200, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
response = Rack::MockRequest.new(app).
post("/", 'HTTP_IF_NONE_MATCH' => '1234')
@@ -73,8 +77,8 @@
end
should "not affect non-200 requests" do
- app = Rack::ConditionalGet.new(lambda { |env|
- [302, {'Etag'=>'1234'}, ['TEST']] })
+ app = conditional_get(lambda { |env|
+ [302, {'Etag'=>'1234', 'Content-Type' => 'text/plain'}, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
@@ -85,8 +89,8 @@
should "not affect requests with malformed HTTP_IF_NONE_MATCH" do
bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
- app = Rack::ConditionalGet.new(lambda { |env|
- [200,{'Last-Modified'=>(Time.now - 3600).httpdate}, ['TEST']] })
+ app = conditional_get(lambda { |env|
+ [200,{'Last-Modified'=>(Time.now - 3600).httpdate, 'Content-Type' => 'text/plain'}, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
Something went wrong with that request. Please try again.