aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/gems/rack-1.1.0/test
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gems/rack-1.1.0/test')
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_auth_basic.rb73
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_auth_digest.rb226
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_builder.rb84
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_camping.rb51
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_cascade.rb48
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_cgi.rb89
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_chunked.rb62
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_commonlogger.rb61
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_conditionalget.rb41
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_config.rb24
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_content_length.rb43
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_content_type.rb30
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_deflater.rb127
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_directory.rb61
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_etag.rb17
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_fastcgi.rb89
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_file.rb75
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_handler.rb43
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_head.rb30
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_lint.rb528
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_lobster.rb45
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_lock.rb38
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_logger.rb21
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_methodoverride.rb60
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_mock.rb243
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_mongrel.rb189
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_nulllogger.rb13
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_recursive.rb77
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_request.rb545
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_response.rb221
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_rewindable_input.rb118
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_runtime.rb35
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_sendfile.rb86
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_session_cookie.rb73
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_session_memcache.rb273
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_session_pool.rb172
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_showexceptions.rb21
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_showstatus.rb72
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_static.rb37
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_thin.rb91
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_urlmap.rb215
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_utils.rb552
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rack_webrick.rb130
-rw-r--r--vendor/gems/rack-1.1.0/test/spec_rackup.rb154
44 files changed, 5283 insertions, 0 deletions
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_auth_basic.rb b/vendor/gems/rack-1.1.0/test/spec_rack_auth_basic.rb
new file mode 100644
index 000000000..0176efc8b
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_auth_basic.rb
@@ -0,0 +1,73 @@
+require 'test/spec'
+
+require 'rack/auth/basic'
+require 'rack/mock'
+
+context 'Rack::Auth::Basic' do
+
+ def realm
+ 'WallysWorld'
+ end
+
+ def unprotected_app
+ lambda { |env| [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ] }
+ end
+
+ def protected_app
+ app = Rack::Auth::Basic.new(unprotected_app) { |username, password| 'Boss' == username }
+ app.realm = realm
+ app
+ end
+
+ setup do
+ @request = Rack::MockRequest.new(protected_app)
+ end
+
+ def request_with_basic_auth(username, password, &block)
+ request 'HTTP_AUTHORIZATION' => 'Basic ' + ["#{username}:#{password}"].pack("m*"), &block
+ end
+
+ def request(headers = {})
+ yield @request.get('/', headers)
+ end
+
+ def assert_basic_auth_challenge(response)
+ response.should.be.a.client_error
+ response.status.should.equal 401
+ response.should.include 'WWW-Authenticate'
+ response.headers['WWW-Authenticate'].should =~ /Basic realm="#{Regexp.escape(realm)}"/
+ response.body.should.be.empty
+ end
+
+ specify 'should challenge correctly when no credentials are specified' do
+ request do |response|
+ assert_basic_auth_challenge response
+ end
+ end
+
+ specify 'should rechallenge if incorrect credentials are specified' do
+ request_with_basic_auth 'joe', 'password' do |response|
+ assert_basic_auth_challenge response
+ end
+ end
+
+ specify 'should return application output if correct credentials are specified' do
+ request_with_basic_auth 'Boss', 'password' do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Boss'
+ end
+ end
+
+ specify 'should return 400 Bad Request if different auth scheme used' do
+ request 'HTTP_AUTHORIZATION' => 'Digest params' do |response|
+ response.should.be.a.client_error
+ response.status.should.equal 400
+ response.should.not.include 'WWW-Authenticate'
+ end
+ end
+
+ specify 'realm as optional constructor arg' do
+ app = Rack::Auth::Basic.new(unprotected_app, realm) { true }
+ assert_equal realm, app.realm
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_auth_digest.rb b/vendor/gems/rack-1.1.0/test/spec_rack_auth_digest.rb
new file mode 100644
index 000000000..a980acc80
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_auth_digest.rb
@@ -0,0 +1,226 @@
+require 'test/spec'
+
+require 'rack/auth/digest/md5'
+require 'rack/mock'
+
+context 'Rack::Auth::Digest::MD5' do
+
+ def realm
+ 'WallysWorld'
+ end
+
+ def unprotected_app
+ lambda do |env|
+ [ 200, {'Content-Type' => 'text/plain'}, ["Hi #{env['REMOTE_USER']}"] ]
+ end
+ end
+
+ def protected_app
+ app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
+ { 'Alice' => 'correct-password' }[username]
+ end
+ app.realm = realm
+ app.opaque = 'this-should-be-secret'
+ app
+ end
+
+ def protected_app_with_hashed_passwords
+ app = Rack::Auth::Digest::MD5.new(unprotected_app) do |username|
+ username == 'Alice' ? Digest::MD5.hexdigest("Alice:#{realm}:correct-password") : nil
+ end
+ app.realm = realm
+ app.opaque = 'this-should-be-secret'
+ app.passwords_hashed = true
+ app
+ end
+
+ def partially_protected_app
+ Rack::URLMap.new({
+ '/' => unprotected_app,
+ '/protected' => protected_app
+ })
+ end
+
+ def protected_app_with_method_override
+ Rack::MethodOverride.new(protected_app)
+ end
+
+ setup do
+ @request = Rack::MockRequest.new(protected_app)
+ end
+
+ def request(method, path, headers = {}, &block)
+ response = @request.request(method, path, headers)
+ block.call(response) if block
+ return response
+ end
+
+ class MockDigestRequest
+ def initialize(params)
+ @params = params
+ end
+ def method_missing(sym)
+ if @params.has_key? k = sym.to_s
+ return @params[k]
+ end
+ super
+ end
+ def method
+ @params['method']
+ end
+ def response(password)
+ Rack::Auth::Digest::MD5.new(nil).send :digest, self, password
+ end
+ end
+
+ def request_with_digest_auth(method, path, username, password, options = {}, &block)
+ request_options = {}
+ request_options[:input] = options.delete(:input) if options.include? :input
+
+ response = request(method, path, request_options)
+
+ return response unless response.status == 401
+
+ if wait = options.delete(:wait)
+ sleep wait
+ end
+
+ challenge = response['WWW-Authenticate'].split(' ', 2).last
+
+ params = Rack::Auth::Digest::Params.parse(challenge)
+
+ params['username'] = username
+ params['nc'] = '00000001'
+ params['cnonce'] = 'nonsensenonce'
+ params['uri'] = path
+
+ params['method'] = method
+
+ params.update options
+
+ params['response'] = MockDigestRequest.new(params).response(password)
+
+ request(method, path, request_options.merge('HTTP_AUTHORIZATION' => "Digest #{params}"), &block)
+ end
+
+ def assert_digest_auth_challenge(response)
+ response.should.be.a.client_error
+ response.status.should.equal 401
+ response.should.include 'WWW-Authenticate'
+ response.headers['WWW-Authenticate'].should =~ /^Digest /
+ response.body.should.be.empty
+ end
+
+ def assert_bad_request(response)
+ response.should.be.a.client_error
+ response.status.should.equal 400
+ response.should.not.include 'WWW-Authenticate'
+ end
+
+ specify 'should challenge when no credentials are specified' do
+ request 'GET', '/' do |response|
+ assert_digest_auth_challenge response
+ end
+ end
+
+ specify 'should return application output if correct credentials given' do
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Alice'
+ end
+ end
+
+ specify 'should return application output if correct credentials given (hashed passwords)' do
+ @request = Rack::MockRequest.new(protected_app_with_hashed_passwords)
+
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password' do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Alice'
+ end
+ end
+
+ specify 'should rechallenge if incorrect username given' do
+ request_with_digest_auth 'GET', '/', 'Bob', 'correct-password' do |response|
+ assert_digest_auth_challenge response
+ end
+ end
+
+ specify 'should rechallenge if incorrect password given' do
+ request_with_digest_auth 'GET', '/', 'Alice', 'wrong-password' do |response|
+ assert_digest_auth_challenge response
+ end
+ end
+
+ specify 'should rechallenge with stale parameter if nonce is stale' do
+ begin
+ Rack::Auth::Digest::Nonce.time_limit = 1
+
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', :wait => 2 do |response|
+ assert_digest_auth_challenge response
+ response.headers['WWW-Authenticate'].should =~ /\bstale=true\b/
+ end
+ ensure
+ Rack::Auth::Digest::Nonce.time_limit = nil
+ end
+ end
+
+ specify 'should return 400 Bad Request if incorrect qop given' do
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'qop' => 'auth-int' do |response|
+ assert_bad_request response
+ end
+ end
+
+ specify 'should return 400 Bad Request if incorrect uri given' do
+ request_with_digest_auth 'GET', '/', 'Alice', 'correct-password', 'uri' => '/foo' do |response|
+ assert_bad_request response
+ end
+ end
+
+ specify 'should return 400 Bad Request if different auth scheme used' do
+ request 'GET', '/', 'HTTP_AUTHORIZATION' => 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==' do |response|
+ assert_bad_request response
+ end
+ end
+
+ specify 'should not require credentials for unprotected path' do
+ @request = Rack::MockRequest.new(partially_protected_app)
+ request 'GET', '/' do |response|
+ response.should.be.ok
+ end
+ end
+
+ specify 'should challenge when no credentials are specified for protected path' do
+ @request = Rack::MockRequest.new(partially_protected_app)
+ request 'GET', '/protected' do |response|
+ assert_digest_auth_challenge response
+ end
+ end
+
+ specify 'should return application output if correct credentials given for protected path' do
+ @request = Rack::MockRequest.new(partially_protected_app)
+ request_with_digest_auth 'GET', '/protected', 'Alice', 'correct-password' do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Alice'
+ end
+ end
+
+ specify 'should return application output if correct credentials given for POST' do
+ request_with_digest_auth 'POST', '/', 'Alice', 'correct-password' do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Alice'
+ end
+ end
+
+ specify 'should return application output if correct credentials given for PUT (using method override of POST)' do
+ @request = Rack::MockRequest.new(protected_app_with_method_override)
+ request_with_digest_auth 'POST', '/', 'Alice', 'correct-password', :input => "_method=put" do |response|
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Alice'
+ end
+ end
+
+ specify 'realm as optional constructor arg' do
+ app = Rack::Auth::Digest::MD5.new(unprotected_app, realm) { true }
+ assert_equal realm, app.realm
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_builder.rb b/vendor/gems/rack-1.1.0/test/spec_rack_builder.rb
new file mode 100644
index 000000000..3fad9810e
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_builder.rb
@@ -0,0 +1,84 @@
+require 'test/spec'
+
+require 'rack/builder'
+require 'rack/mock'
+require 'rack/showexceptions'
+require 'rack/auth/basic'
+
+context "Rack::Builder" do
+ specify "chains apps by default" do
+ app = Rack::Builder.new do
+ use Rack::ShowExceptions
+ run lambda { |env| raise "bzzzt" }
+ end.to_app
+
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ end
+
+ specify "has implicit #to_app" do
+ app = Rack::Builder.new do
+ use Rack::ShowExceptions
+ run lambda { |env| raise "bzzzt" }
+ end
+
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ end
+
+ specify "supports blocks on use" do
+ app = Rack::Builder.new do
+ use Rack::ShowExceptions
+ use Rack::Auth::Basic do |username, password|
+ 'secret' == password
+ end
+
+ run lambda { |env| [200, {}, ['Hi Boss']] }
+ end
+
+ response = Rack::MockRequest.new(app).get("/")
+ response.should.be.client_error
+ response.status.should.equal 401
+
+ # with auth...
+ response = Rack::MockRequest.new(app).get("/",
+ 'HTTP_AUTHORIZATION' => 'Basic ' + ["joe:secret"].pack("m*"))
+ response.status.should.equal 200
+ response.body.to_s.should.equal 'Hi Boss'
+ end
+
+ specify "has explicit #to_app" do
+ app = Rack::Builder.app do
+ use Rack::ShowExceptions
+ run lambda { |env| raise "bzzzt" }
+ end
+
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ end
+
+ specify "apps are initialized once" do
+ app = Rack::Builder.new do
+ class AppClass
+ def initialize
+ @called = 0
+ end
+ def call(env)
+ raise "bzzzt" if @called > 0
+ @called += 1
+ [200, {'Content-Type' => 'text/plain'}, ['OK']]
+ end
+ end
+
+ use Rack::ShowExceptions
+ run AppClass.new
+ end
+
+ Rack::MockRequest.new(app).get("/").status.should.equal 200
+ Rack::MockRequest.new(app).get("/").should.be.server_error
+ end
+
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_camping.rb b/vendor/gems/rack-1.1.0/test/spec_rack_camping.rb
new file mode 100644
index 000000000..bed117108
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_camping.rb
@@ -0,0 +1,51 @@
+require 'test/spec'
+require 'stringio'
+require 'uri'
+
+begin
+ require 'rack/mock'
+
+ $-w, w = nil, $-w # yuck
+ require 'camping'
+ require 'rack/adapter/camping'
+
+ Camping.goes :CampApp
+ module CampApp
+ module Controllers
+ class HW < R('/')
+ def get
+ @headers["X-Served-By"] = URI("http://rack.rubyforge.org")
+ "Camping works!"
+ end
+
+ def post
+ "Data: #{input.foo}"
+ end
+ end
+ end
+ end
+ $-w = w
+
+ context "Rack::Adapter::Camping" do
+ specify "works with GET" do
+ res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
+ get("/")
+
+ res.should.be.ok
+ res["Content-Type"].should.equal "text/html"
+ res["X-Served-By"].should.equal "http://rack.rubyforge.org"
+
+ res.body.should.equal "Camping works!"
+ end
+
+ specify "works with POST" do
+ res = Rack::MockRequest.new(Rack::Adapter::Camping.new(CampApp)).
+ post("/", :input => "foo=bar")
+
+ res.should.be.ok
+ res.body.should.equal "Data: bar"
+ end
+ end
+rescue LoadError
+ $stderr.puts "Skipping Rack::Adapter::Camping tests (Camping is required). `gem install camping` and try again."
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_cascade.rb b/vendor/gems/rack-1.1.0/test/spec_rack_cascade.rb
new file mode 100644
index 000000000..cf3c29b48
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_cascade.rb
@@ -0,0 +1,48 @@
+require 'test/spec'
+
+require 'rack/cascade'
+require 'rack/mock'
+
+require 'rack/urlmap'
+require 'rack/file'
+
+context "Rack::Cascade" do
+ docroot = File.expand_path(File.dirname(__FILE__))
+ app1 = Rack::File.new(docroot)
+
+ app2 = Rack::URLMap.new("/crash" => lambda { |env| raise "boom" })
+
+ app3 = Rack::URLMap.new("/foo" => lambda { |env|
+ [200, { "Content-Type" => "text/plain"}, [""]]})
+
+ specify "should dispatch onward on 404 by default" do
+ cascade = Rack::Cascade.new([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
+ Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.forbidden
+ end
+
+ specify "should dispatch onward on whatever is passed" do
+ cascade = Rack::Cascade.new([app1, app2, app3], [404, 403])
+ Rack::MockRequest.new(cascade).get("/cgi/../bla").should.be.not_found
+ end
+
+ specify "should return 404 if empty" do
+ Rack::MockRequest.new(Rack::Cascade.new([])).get('/').should.be.not_found
+ end
+
+ specify "should append new app" do
+ cascade = Rack::Cascade.new([], [404, 403])
+ Rack::MockRequest.new(cascade).get('/').should.be.not_found
+ cascade << app2
+ Rack::MockRequest.new(cascade).get('/cgi/test').should.be.not_found
+ Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.not_found
+ cascade << app1
+ Rack::MockRequest.new(cascade).get('/cgi/test').should.be.ok
+ Rack::MockRequest.new(cascade).get('/cgi/../bla').should.be.forbidden
+ Rack::MockRequest.new(cascade).get('/foo').should.be.not_found
+ cascade << app3
+ Rack::MockRequest.new(cascade).get('/foo').should.be.ok
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_cgi.rb b/vendor/gems/rack-1.1.0/test/spec_rack_cgi.rb
new file mode 100644
index 000000000..59500cd7b
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_cgi.rb
@@ -0,0 +1,89 @@
+require 'test/spec'
+require 'testrequest'
+
+context "Rack::Handler::CGI" do
+ include TestRequest::Helpers
+
+ setup do
+ @host = '0.0.0.0'
+ @port = 9203
+ end
+
+ # Keep this first.
+ specify "startup" do
+ $pid = fork {
+ Dir.chdir(File.join(File.dirname(__FILE__), "..", "test", "cgi"))
+ exec "lighttpd -D -f lighttpd.conf"
+ }
+ end
+
+ specify "should respond" do
+ sleep 1
+ lambda {
+ GET("/test")
+ }.should.not.raise
+ end
+
+ specify "should be a lighttpd" do
+ GET("/test")
+ status.should.be 200
+ response["SERVER_SOFTWARE"].should =~ /lighttpd/
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
+ response["SERVER_PORT"].should.equal @port.to_s
+ response["SERVER_NAME"].should =~ @host
+ end
+
+ specify "should have rack headers" do
+ GET("/test")
+ response["rack.version"].should.equal [1,1]
+ response["rack.multithread"].should.be false
+ response["rack.multiprocess"].should.be true
+ response["rack.run_once"].should.be true
+ end
+
+ specify "should have CGI headers on GET" do
+ GET("/test")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal ""
+ response["QUERY_STRING"].should.equal ""
+ response["test.postdata"].should.equal ""
+
+ GET("/test/foo?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal "/foo"
+ response["QUERY_STRING"].should.equal "quux=1"
+ end
+
+ specify "should have CGI headers on POST" do
+ POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
+ status.should.equal 200
+ response["REQUEST_METHOD"].should.equal "POST"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["QUERY_STRING"].should.equal ""
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
+ response["test.postdata"].should.equal "rack-form-data=23"
+ end
+
+ specify "should support HTTP auth" do
+ GET("/test", {:user => "ruth", :passwd => "secret"})
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
+ end
+
+ specify "should set status" do
+ GET("/test?secret")
+ status.should.equal 403
+ response["rack.url_scheme"].should.equal "http"
+ end
+
+ # Keep this last.
+ specify "shutdown" do
+ Process.kill 15, $pid
+ Process.wait($pid).should.equal $pid
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_chunked.rb b/vendor/gems/rack-1.1.0/test/spec_rack_chunked.rb
new file mode 100644
index 000000000..39eea4824
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_chunked.rb
@@ -0,0 +1,62 @@
+require 'rack/mock'
+require 'rack/chunked'
+require 'rack/utils'
+
+context "Rack::Chunked" do
+
+ before do
+ @env = Rack::MockRequest.
+ env_for('/', 'HTTP_VERSION' => '1.1', 'REQUEST_METHOD' => 'GET')
+ end
+
+ specify 'chunks responses with no Content-Length' do
+ app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
+ response = Rack::MockResponse.new(*Rack::Chunked.new(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
+
+ specify 'chunks empty bodies properly' do
+ app = lambda { |env| [200, {}, []] }
+ response = Rack::MockResponse.new(*Rack::Chunked.new(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"
+ end
+
+ specify 'does 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)
+ status.should.equal 200
+ headers.should.not.include 'Transfer-Encoding'
+ headers.should.include 'Content-Length'
+ body.join.should.equal 'Hello World!'
+ end
+
+ specify 'does not modify response when client is HTTP/1.0' do
+ app = lambda { |env| [200, {}, ['Hello', ' ', 'World!']] }
+ @env['HTTP_VERSION'] = 'HTTP/1.0'
+ status, headers, body = Rack::Chunked.new(app).call(@env)
+ status.should.equal 200
+ headers.should.not.include 'Transfer-Encoding'
+ body.join.should.equal 'Hello World!'
+ end
+
+ specify 'does 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)
+ status.should.equal 200
+ headers['Transfer-Encoding'].should.equal 'identity'
+ body.join.should.equal 'Hello World!'
+ end
+
+ [100, 204, 304].each do |status_code|
+ specify "does not modify response when status code is #{status_code}" do
+ app = lambda { |env| [status_code, {}, []] }
+ status, headers, body = Rack::Chunked.new(app).call(@env)
+ status.should.equal status_code
+ headers.should.not.include 'Transfer-Encoding'
+ end
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_commonlogger.rb b/vendor/gems/rack-1.1.0/test/spec_rack_commonlogger.rb
new file mode 100644
index 000000000..46a72e86b
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_commonlogger.rb
@@ -0,0 +1,61 @@
+require 'test/spec'
+require 'stringio'
+
+require 'rack/commonlogger'
+require 'rack/lobster'
+require 'rack/mock'
+
+context "Rack::CommonLogger" do
+ app = lambda { |env|
+ [200,
+ {"Content-Type" => "text/html", "Content-Length" => length.to_s},
+ [obj]]}
+ app_without_length = lambda { |env|
+ [200,
+ {"Content-Type" => "text/html"},
+ []]}
+ app_with_zero_length = lambda { |env|
+ [200,
+ {"Content-Type" => "text/html", "Content-Length" => "0"},
+ []]}
+
+ specify "should log to rack.errors by default" do
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app)).get("/")
+
+ res.errors.should.not.be.empty
+ res.errors.should =~ /"GET \/ " 200 #{length} /
+ end
+
+ specify "should log to anything with +write+" do
+ log = StringIO.new
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app, log)).get("/")
+
+ log.string.should =~ /"GET \/ " 200 #{length} /
+ end
+
+ specify "should log - content length if header is missing" do
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_without_length)).get("/")
+
+ res.errors.should.not.be.empty
+ res.errors.should =~ /"GET \/ " 200 - /
+ end
+
+ specify "should log - content length if header is zero" do
+ res = Rack::MockRequest.new(Rack::CommonLogger.new(app_with_zero_length)).get("/")
+
+ res.errors.should.not.be.empty
+ res.errors.should =~ /"GET \/ " 200 - /
+ end
+
+ def length
+ self.class.length
+ end
+
+ def self.length
+ 123
+ end
+
+ def self.obj
+ "hello world"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_conditionalget.rb b/vendor/gems/rack-1.1.0/test/spec_rack_conditionalget.rb
new file mode 100644
index 000000000..ca34cc922
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_conditionalget.rb
@@ -0,0 +1,41 @@
+require 'test/spec'
+require 'time'
+
+require 'rack/mock'
+require 'rack/conditionalget'
+
+context "Rack::ConditionalGet" do
+ specify "should set a 304 status and truncate body when If-Modified-Since hits" do
+ timestamp = Time.now.httpdate
+ app = Rack::ConditionalGet.new(lambda { |env|
+ [200, {'Last-Modified'=>timestamp}, ['TEST']] })
+
+ response = Rack::MockRequest.new(app).
+ get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
+
+ response.status.should.equal 304
+ response.body.should.be.empty
+ end
+
+ specify "should set a 304 status and truncate body when If-None-Match hits" do
+ app = Rack::ConditionalGet.new(lambda { |env|
+ [200, {'Etag'=>'1234'}, ['TEST']] })
+
+ response = Rack::MockRequest.new(app).
+ get("/", 'HTTP_IF_NONE_MATCH' => '1234')
+
+ response.status.should.equal 304
+ response.body.should.be.empty
+ end
+
+ specify "should not affect non-GET/HEAD requests" do
+ app = Rack::ConditionalGet.new(lambda { |env|
+ [200, {'Etag'=>'1234'}, ['TEST']] })
+
+ response = Rack::MockRequest.new(app).
+ post("/", 'HTTP_IF_NONE_MATCH' => '1234')
+
+ response.status.should.equal 200
+ response.body.should.equal 'TEST'
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_config.rb b/vendor/gems/rack-1.1.0/test/spec_rack_config.rb
new file mode 100644
index 000000000..a508ea4be
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_config.rb
@@ -0,0 +1,24 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/builder'
+require 'rack/content_length'
+require 'rack/config'
+
+context "Rack::Config" do
+
+ specify "should accept a block that modifies the environment" do
+ app = Rack::Builder.new do
+ use Rack::Lint
+ use Rack::ContentLength
+ use Rack::Config do |env|
+ env['greeting'] = 'hello'
+ end
+ run lambda { |env|
+ [200, {'Content-Type' => 'text/plain'}, [env['greeting'] || '']]
+ }
+ end
+ response = Rack::MockRequest.new(app).get('/')
+ response.body.should.equal('hello')
+ end
+
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_content_length.rb b/vendor/gems/rack-1.1.0/test/spec_rack_content_length.rb
new file mode 100644
index 000000000..7db9345f8
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_content_length.rb
@@ -0,0 +1,43 @@
+require 'rack/mock'
+require 'rack/content_length'
+
+context "Rack::ContentLength" do
+ specify "sets Content-Length on String bodies if none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.equal '13'
+ end
+
+ specify "sets Content-Length on Array bodies if none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.equal '13'
+ end
+
+ specify "does not set Content-Length on variable length bodies" do
+ body = lambda { "Hello World!" }
+ def body.each ; yield call ; end
+
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.be.nil
+ end
+
+ specify "does not change Content-Length if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'Content-Length' => '1'}, "Hello, World!"] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.equal '1'
+ end
+
+ specify "does not set Content-Length on 304 responses" do
+ app = lambda { |env| [304, {'Content-Type' => 'text/plain'}, []] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.equal nil
+ end
+
+ specify "does not set Content-Length when Transfer-Encoding is chunked" do
+ app = lambda { |env| [200, {'Transfer-Encoding' => 'chunked'}, []] }
+ response = Rack::ContentLength.new(app).call({})
+ response[1]['Content-Length'].should.equal nil
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_content_type.rb b/vendor/gems/rack-1.1.0/test/spec_rack_content_type.rb
new file mode 100644
index 000000000..9975b94d6
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_content_type.rb
@@ -0,0 +1,30 @@
+require 'rack/mock'
+require 'rack/content_type'
+
+context "Rack::ContentType" do
+ specify "sets Content-Type to default text/html if none is set" do
+ app = lambda { |env| [200, {}, "Hello, World!"] }
+ status, headers, body = Rack::ContentType.new(app).call({})
+ headers['Content-Type'].should.equal 'text/html'
+ end
+
+ specify "sets Content-Type to chosen default if none is set" do
+ app = lambda { |env| [200, {}, "Hello, World!"] }
+ status, headers, body =
+ Rack::ContentType.new(app, 'application/octet-stream').call({})
+ headers['Content-Type'].should.equal 'application/octet-stream'
+ end
+
+ specify "does not change Content-Type if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'foo/bar'}, "Hello, World!"] }
+ status, headers, body = Rack::ContentType.new(app).call({})
+ headers['Content-Type'].should.equal 'foo/bar'
+ end
+
+ specify "case insensitive detection of Content-Type" do
+ app = lambda { |env| [200, {'CONTENT-Type' => 'foo/bar'}, "Hello, World!"] }
+ status, headers, body = Rack::ContentType.new(app).call({})
+ headers.to_a.select { |k,v| k.downcase == "content-type" }.
+ should.equal [["CONTENT-Type","foo/bar"]]
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_deflater.rb b/vendor/gems/rack-1.1.0/test/spec_rack_deflater.rb
new file mode 100644
index 000000000..c9bb31894
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_deflater.rb
@@ -0,0 +1,127 @@
+require 'test/spec'
+
+require 'rack/mock'
+require 'rack/deflater'
+require 'stringio'
+require 'time' # for Time#httpdate
+
+context "Rack::Deflater" do
+ def build_response(status, body, accept_encoding, headers = {})
+ body = [body] if body.respond_to? :to_str
+ app = lambda { |env| [status, {}, body] }
+ request = Rack::MockRequest.env_for("", headers.merge("HTTP_ACCEPT_ENCODING" => accept_encoding))
+ response = Rack::Deflater.new(app).call(request)
+
+ return response
+ end
+
+ specify "should be able to deflate bodies that respond to each" do
+ body = Object.new
+ class << body; def each; yield("foo"); yield("bar"); end; end
+
+ response = build_response(200, body, "deflate")
+
+ response[0].should.equal(200)
+ response[1].should.equal({
+ "Content-Encoding" => "deflate",
+ "Vary" => "Accept-Encoding"
+ })
+ buf = ''
+ response[2].each { |part| buf << part }
+ buf.should.equal("K\313\317OJ,\002\000")
+ end
+
+ # TODO: This is really just a special case of the above...
+ specify "should be able to deflate String bodies" do
+ response = build_response(200, "Hello world!", "deflate")
+
+ response[0].should.equal(200)
+ response[1].should.equal({
+ "Content-Encoding" => "deflate",
+ "Vary" => "Accept-Encoding"
+ })
+ buf = ''
+ response[2].each { |part| buf << part }
+ buf.should.equal("\363H\315\311\311W(\317/\312IQ\004\000")
+ end
+
+ specify "should be able to gzip bodies that respond to each" do
+ body = Object.new
+ class << body; def each; yield("foo"); yield("bar"); end; end
+
+ response = build_response(200, body, "gzip")
+
+ response[0].should.equal(200)
+ response[1].should.equal({
+ "Content-Encoding" => "gzip",
+ "Vary" => "Accept-Encoding",
+ })
+
+ buf = ''
+ response[2].each { |part| buf << part }
+ io = StringIO.new(buf)
+ gz = Zlib::GzipReader.new(io)
+ gz.read.should.equal("foobar")
+ gz.close
+ end
+
+ specify "should be able to fallback to no deflation" do
+ response = build_response(200, "Hello world!", "superzip")
+
+ response[0].should.equal(200)
+ response[1].should.equal({ "Vary" => "Accept-Encoding" })
+ response[2].should.equal(["Hello world!"])
+ end
+
+ specify "should be able to skip when there is no response entity body" do
+ response = build_response(304, [], "gzip")
+
+ response[0].should.equal(304)
+ response[1].should.equal({})
+ response[2].should.equal([])
+ end
+
+ specify "should handle the lack of an acceptable encoding" do
+ response1 = build_response(200, "Hello world!", "identity;q=0", "PATH_INFO" => "/")
+ response1[0].should.equal(406)
+ response1[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "71"})
+ response1[2].should.equal(["An acceptable encoding for the requested resource / could not be found."])
+
+ response2 = build_response(200, "Hello world!", "identity;q=0", "SCRIPT_NAME" => "/foo", "PATH_INFO" => "/bar")
+ response2[0].should.equal(406)
+ response2[1].should.equal({"Content-Type" => "text/plain", "Content-Length" => "78"})
+ response2[2].should.equal(["An acceptable encoding for the requested resource /foo/bar could not be found."])
+ end
+
+ specify "should handle gzip response with Last-Modified header" do
+ last_modified = Time.now.httpdate
+
+ app = lambda { |env| [200, { "Last-Modified" => last_modified }, ["Hello World!"]] }
+ request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
+ response = Rack::Deflater.new(app).call(request)
+
+ response[0].should.equal(200)
+ response[1].should.equal({
+ "Content-Encoding" => "gzip",
+ "Vary" => "Accept-Encoding",
+ "Last-Modified" => last_modified
+ })
+
+ buf = ''
+ response[2].each { |part| buf << part }
+ io = StringIO.new(buf)
+ gz = Zlib::GzipReader.new(io)
+ gz.read.should.equal("Hello World!")
+ gz.close
+ end
+
+ specify "should do nothing when no-transform Cache-Control directive present" do
+ app = lambda { |env| [200, {'Cache-Control' => 'no-transform'}, ['Hello World!']] }
+ request = Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => "gzip")
+ response = Rack::Deflater.new(app).call(request)
+
+ response[0].should.equal(200)
+ response[1].should.not.include "Content-Encoding"
+ response[2].join.should.equal("Hello World!")
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_directory.rb b/vendor/gems/rack-1.1.0/test/spec_rack_directory.rb
new file mode 100644
index 000000000..d255c91da
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_directory.rb
@@ -0,0 +1,61 @@
+require 'test/spec'
+
+require 'rack/directory'
+require 'rack/lint'
+
+require 'rack/mock'
+
+context "Rack::Directory" do
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
+ FILE_CATCH = proc{|env| [200, {'Content-Type'=>'text/plain', "Content-Length" => "7"}, ['passed!']] }
+ app = Rack::Directory.new DOCROOT, FILE_CATCH
+
+ specify "serves directory indices" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/")
+
+ res.should.be.ok
+ res.should =~ /<html><head>/
+ end
+
+ specify "passes to app if file found" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/test")
+
+ res.should.be.ok
+ res.should =~ /passed!/
+ end
+
+ specify "serves uri with URL encoded filenames" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/%63%67%69/") # "/cgi/test"
+
+ res.should.be.ok
+ res.should =~ /<html><head>/
+
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/%74%65%73%74") # "/cgi/test"
+
+ res.should.be.ok
+ res.should =~ /passed!/
+ end
+
+ specify "does not allow directory traversal" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/../test")
+
+ res.should.be.forbidden
+
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/%2E%2E/test")
+
+ res.should.be.forbidden
+ end
+
+ specify "404s if it can't find the file" do
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).
+ get("/cgi/blubb")
+
+ res.should.be.not_found
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_etag.rb b/vendor/gems/rack-1.1.0/test/spec_rack_etag.rb
new file mode 100644
index 000000000..73cd31ac0
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_etag.rb
@@ -0,0 +1,17 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/etag'
+
+context "Rack::ETag" do
+ specify "sets ETag if none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
+ response = Rack::ETag.new(app).call({})
+ response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\""
+ end
+
+ specify "does not change ETag if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] }
+ response = Rack::ETag.new(app).call({})
+ response[1]['ETag'].should.equal "\"abc\""
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_fastcgi.rb b/vendor/gems/rack-1.1.0/test/spec_rack_fastcgi.rb
new file mode 100644
index 000000000..1ae55ace6
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_fastcgi.rb
@@ -0,0 +1,89 @@
+require 'test/spec'
+require 'testrequest'
+
+context "Rack::Handler::FastCGI" do
+ include TestRequest::Helpers
+
+ setup do
+ @host = '0.0.0.0'
+ @port = 9203
+ end
+
+ # Keep this first.
+ specify "startup" do
+ $pid = fork {
+ Dir.chdir(File.join(File.dirname(__FILE__), "..", "test", "cgi"))
+ exec "lighttpd -D -f lighttpd.conf"
+ }
+ end
+
+ specify "should respond" do
+ sleep 1
+ lambda {
+ GET("/test.fcgi")
+ }.should.not.raise
+ end
+
+ specify "should be a lighttpd" do
+ GET("/test.fcgi")
+ status.should.be 200
+ response["SERVER_SOFTWARE"].should =~ /lighttpd/
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
+ response["SERVER_PORT"].should.equal @port.to_s
+ response["SERVER_NAME"].should =~ @host
+ end
+
+ specify "should have rack headers" do
+ GET("/test.fcgi")
+ response["rack.version"].should.equal [1,1]
+ response["rack.multithread"].should.be false
+ response["rack.multiprocess"].should.be true
+ response["rack.run_once"].should.be false
+ end
+
+ specify "should have CGI headers on GET" do
+ GET("/test.fcgi")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test.fcgi"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal ""
+ response["QUERY_STRING"].should.equal ""
+ response["test.postdata"].should.equal ""
+
+ GET("/test.fcgi/foo?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test.fcgi"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal "/foo"
+ response["QUERY_STRING"].should.equal "quux=1"
+ end
+
+ specify "should have CGI headers on POST" do
+ POST("/test.fcgi", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
+ status.should.equal 200
+ response["REQUEST_METHOD"].should.equal "POST"
+ response["SCRIPT_NAME"].should.equal "/test.fcgi"
+ response["REQUEST_PATH"].should.equal "/"
+ response["QUERY_STRING"].should.equal ""
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
+ response["test.postdata"].should.equal "rack-form-data=23"
+ end
+
+ specify "should support HTTP auth" do
+ GET("/test.fcgi", {:user => "ruth", :passwd => "secret"})
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
+ end
+
+ specify "should set status" do
+ GET("/test.fcgi?secret")
+ status.should.equal 403
+ response["rack.url_scheme"].should.equal "http"
+ end
+
+ # Keep this last.
+ specify "shutdown" do
+ Process.kill 15, $pid
+ Process.wait($pid).should.equal $pid
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_file.rb b/vendor/gems/rack-1.1.0/test/spec_rack_file.rb
new file mode 100644
index 000000000..0a2f8ee81
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_file.rb
@@ -0,0 +1,75 @@
+require 'test/spec'
+
+require 'rack/file'
+require 'rack/lint'
+
+require 'rack/mock'
+
+context "Rack::File" do
+ DOCROOT = File.expand_path(File.dirname(__FILE__)) unless defined? DOCROOT
+
+ specify "serves files" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi/test")
+
+ res.should.be.ok
+ res.should =~ /ruby/
+ end
+
+ specify "sets Last-Modified header" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi/test")
+
+ path = File.join(DOCROOT, "/cgi/test")
+
+ res.should.be.ok
+ res["Last-Modified"].should.equal File.mtime(path).httpdate
+ end
+
+ specify "serves files with URL encoded filenames" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi/%74%65%73%74") # "/cgi/test"
+
+ res.should.be.ok
+ res.should =~ /ruby/
+ end
+
+ specify "does not allow directory traversal" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi/../test")
+
+ res.should.be.forbidden
+ end
+
+ specify "does not allow directory traversal with encoded periods" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/%2E%2E/README")
+
+ res.should.be.forbidden
+ end
+
+ specify "404s if it can't find the file" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi/blubb")
+
+ res.should.be.not_found
+ end
+
+ specify "detects SystemCallErrors" do
+ res = Rack::MockRequest.new(Rack::Lint.new(Rack::File.new(DOCROOT))).
+ get("/cgi")
+
+ res.should.be.not_found
+ end
+
+ specify "returns bodies that respond to #to_path" do
+ env = Rack::MockRequest.env_for("/cgi/test")
+ status, headers, body = Rack::File.new(DOCROOT).call(env)
+
+ path = File.join(DOCROOT, "/cgi/test")
+
+ status.should.equal 200
+ body.should.respond_to :to_path
+ body.to_path.should.equal path
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_handler.rb b/vendor/gems/rack-1.1.0/test/spec_rack_handler.rb
new file mode 100644
index 000000000..fcf19b780
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_handler.rb
@@ -0,0 +1,43 @@
+require 'test/spec'
+
+require 'rack/handler'
+
+class Rack::Handler::Lobster; end
+class RockLobster; end
+
+context "Rack::Handler" do
+ specify "has registered default handlers" do
+ Rack::Handler.get('cgi').should.equal Rack::Handler::CGI
+ Rack::Handler.get('fastcgi').should.equal Rack::Handler::FastCGI
+ Rack::Handler.get('mongrel').should.equal Rack::Handler::Mongrel
+ Rack::Handler.get('webrick').should.equal Rack::Handler::WEBrick
+ end
+
+ specify "handler that doesn't exist should raise a NameError" do
+ lambda {
+ Rack::Handler.get('boom')
+ }.should.raise(NameError)
+ end
+
+ specify "should get unregistered, but already required, handler by name" do
+ Rack::Handler.get('Lobster').should.equal Rack::Handler::Lobster
+ end
+
+ specify "should register custom handler" do
+ Rack::Handler.register('rock_lobster', 'RockLobster')
+ Rack::Handler.get('rock_lobster').should.equal RockLobster
+ end
+
+ specify "should not need registration for properly coded handlers even if not already required" do
+ begin
+ $:.push "test/unregistered_handler"
+ Rack::Handler.get('Unregistered').should.equal Rack::Handler::Unregistered
+ lambda {
+ Rack::Handler.get('UnRegistered')
+ }.should.raise(NameError)
+ Rack::Handler.get('UnregisteredLongOne').should.equal Rack::Handler::UnregisteredLongOne
+ ensure
+ $:.delete "test/unregistered_handler"
+ end
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_head.rb b/vendor/gems/rack-1.1.0/test/spec_rack_head.rb
new file mode 100644
index 000000000..48d3f81ff
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_head.rb
@@ -0,0 +1,30 @@
+require 'rack/head'
+require 'rack/mock'
+
+context "Rack::Head" do
+ def test_response(headers = {})
+ app = lambda { |env| [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]] }
+ request = Rack::MockRequest.env_for("/", headers)
+ response = Rack::Head.new(app).call(request)
+
+ return response
+ end
+
+ specify "passes GET, POST, PUT, DELETE, OPTIONS, TRACE requests" do
+ %w[GET POST PUT DELETE OPTIONS TRACE].each do |type|
+ resp = test_response("REQUEST_METHOD" => type)
+
+ resp[0].should.equal(200)
+ resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
+ resp[2].should.equal(["foo"])
+ end
+ end
+
+ specify "removes body from HEAD requests" do
+ resp = test_response("REQUEST_METHOD" => "HEAD")
+
+ resp[0].should.equal(200)
+ resp[1].should.equal({"Content-type" => "test/plain", "Content-length" => "3"})
+ resp[2].should.equal([])
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_lint.rb b/vendor/gems/rack-1.1.0/test/spec_rack_lint.rb
new file mode 100644
index 000000000..bbf75c17a
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_lint.rb
@@ -0,0 +1,528 @@
+require 'test/spec'
+require 'stringio'
+
+require 'rack/lint'
+require 'rack/mock'
+
+context "Rack::Lint" do
+ def env(*args)
+ Rack::MockRequest.env_for("/", *args)
+ end
+
+ specify "passes valid request" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
+ }).call(env({}))
+ }.should.not.raise
+ end
+
+ specify "notices fatal errors" do
+ lambda { Rack::Lint.new(nil).call }.should.raise(Rack::Lint::LintError).
+ message.should.match(/No env given/)
+ end
+
+ specify "notices environment errors" do
+ lambda { Rack::Lint.new(nil).call 5 }.should.raise(Rack::Lint::LintError).
+ message.should.match(/not a Hash/)
+
+ lambda {
+ e = env
+ e.delete("REQUEST_METHOD")
+ Rack::Lint.new(nil).call(e)
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/missing required key REQUEST_METHOD/)
+
+ lambda {
+ e = env
+ e.delete("SERVER_NAME")
+ Rack::Lint.new(nil).call(e)
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/missing required key SERVER_NAME/)
+
+
+ lambda {
+ Rack::Lint.new(nil).call(env("HTTP_CONTENT_TYPE" => "text/plain"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/contains HTTP_CONTENT_TYPE/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("HTTP_CONTENT_LENGTH" => "42"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/contains HTTP_CONTENT_LENGTH/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("FOO" => Object.new))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/non-string value/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.version" => "0.2"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must be an Array/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.url_scheme" => "gopher"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/url_scheme unknown/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.session" => []))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("session [] must respond to store and []=")
+
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.logger" => []))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("logger [] must respond to info")
+
+ lambda {
+ Rack::Lint.new(nil).call(env("REQUEST_METHOD" => "FUCKUP?"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/REQUEST_METHOD/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "howdy"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must start with/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("PATH_INFO" => "../foo"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must start with/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("CONTENT_LENGTH" => "xcii"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/Invalid CONTENT_LENGTH/)
+
+ lambda {
+ e = env
+ e.delete("PATH_INFO")
+ e.delete("SCRIPT_NAME")
+ Rack::Lint.new(nil).call(e)
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/One of .* must be set/)
+
+ lambda {
+ Rack::Lint.new(nil).call(env("SCRIPT_NAME" => "/"))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/cannot be .* make it ''/)
+ end
+
+ specify "notices input errors" do
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.input" => ""))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/does not respond to #gets/)
+
+ lambda {
+ input = Object.new
+ def input.binmode?
+ false
+ end
+ Rack::Lint.new(nil).call(env("rack.input" => input))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/is not opened in binary mode/)
+
+ lambda {
+ input = Object.new
+ def input.external_encoding
+ result = Object.new
+ def result.name
+ "US-ASCII"
+ end
+ result
+ end
+ Rack::Lint.new(nil).call(env("rack.input" => input))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/does not have ASCII-8BIT as its external encoding/)
+ end
+
+ specify "notices error errors" do
+ lambda {
+ Rack::Lint.new(nil).call(env("rack.errors" => ""))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/does not respond to #puts/)
+ end
+
+ specify "notices status errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ ["cc", {}, ""]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must be >=100 seen as integer/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [42, {}, ""]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must be >=100 seen as integer/)
+ end
+
+ specify "notices header errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, Object.new, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("headers object should respond to #each, but doesn't (got Object as headers)")
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {true=>false}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("header key must be a string, was TrueClass")
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Status" => "404"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must not contain Status/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-Type:" => "text/plain"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must not contain :/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-" => "text/plain"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/must not end/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"..%%quark%%.." => "text/plain"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("invalid header name: ..%%quark%%..")
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Foo" => Object.new}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("a header value must be a String, but the value of 'Foo' is a Object")
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Foo" => [1, 2, 3]}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.equal("a header value must be a String, but the value of 'Foo' is a Array")
+
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Foo-Bar" => "text\000plain"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/invalid header/)
+
+ # line ends (010) should be allowed in header values.
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Foo-Bar" => "one\ntwo\nthree", "Content-Length" => "0", "Content-Type" => "text/plain" }, []]
+ }).call(env({}))
+ }.should.not.raise(Rack::Lint::LintError)
+ end
+
+ specify "notices content-type errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/No Content-Type/)
+
+ [100, 101, 204, 304].each do |status|
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [status, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/Content-Type header found/)
+ end
+ end
+
+ specify "notices content-length errors" do
+ [100, 101, 204, 304].each do |status|
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [status, {"Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/Content-Length header found/)
+ end
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-type" => "text/plain", "Content-Length" => "1"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/Content-Length header was 1, but should be 0/)
+ end
+
+ specify "notices body errors" do
+ lambda {
+ status, header, body = Rack::Lint.new(lambda { |env|
+ [200, {"Content-type" => "text/plain","Content-length" => "3"}, [1,2,3]]
+ }).call(env({}))
+ body.each { |part| }
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/yielded non-string/)
+ end
+
+ specify "notices input handling errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].gets("\r\n")
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/gets called with arguments/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(1, 2, 3)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read called with too many arguments/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read("foo")
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read called with non-integer and non-nil length/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(-1)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read called with a negative length/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(nil, nil)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read called with non-String buffer/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(nil, 1)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read called with non-String buffer/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].rewind(0)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/rewind called with arguments/)
+
+ weirdio = Object.new
+ class << weirdio
+ def gets
+ 42
+ end
+
+ def read
+ 23
+ end
+
+ def each
+ yield 23
+ yield 42
+ end
+
+ def rewind
+ raise Errno::ESPIPE, "Errno::ESPIPE"
+ end
+ end
+
+ eof_weirdio = Object.new
+ class << eof_weirdio
+ def gets
+ nil
+ end
+
+ def read(*args)
+ nil
+ end
+
+ def each
+ end
+
+ def rewind
+ end
+ end
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].gets
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env("rack.input" => weirdio))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/gets didn't return a String/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].each { |x| }
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env("rack.input" => weirdio))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/each didn't yield a String/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env("rack.input" => weirdio))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read didn't return nil or a String/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env("rack.input" => eof_weirdio))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/read\(nil\) returned nil on EOF/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].rewind
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env("rack.input" => weirdio))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/rewind raised Errno::ESPIPE/)
+
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].close
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/close must not be called/)
+ end
+
+ specify "notices error handling errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.errors"].write(42)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/write not called with a String/)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.errors"].close
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/close must not be called/)
+ end
+
+ specify "notices HEAD errors" do
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-type" => "test/plain", "Content-length" => "3"}, []]
+ }).call(env({"REQUEST_METHOD" => "HEAD"}))
+ }.should.not.raise
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ [200, {"Content-type" => "test/plain", "Content-length" => "3"}, ["foo"]]
+ }).call(env({"REQUEST_METHOD" => "HEAD"}))
+ }.should.raise(Rack::Lint::LintError).
+ message.should.match(/body was given for HEAD/)
+ end
+
+ specify "passes valid read calls" do
+ hello_str = "hello world"
+ hello_str.force_encoding("ASCII-8BIT") if hello_str.respond_to? :force_encoding
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(0)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(1)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(nil)
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(nil, '')
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+
+ lambda {
+ Rack::Lint.new(lambda { |env|
+ env["rack.input"].read(1, '')
+ [201, {"Content-type" => "text/plain", "Content-length" => "0"}, []]
+ }).call(env({"rack.input" => StringIO.new(hello_str)}))
+ }.should.not.raise(Rack::Lint::LintError)
+ end
+end
+
+context "Rack::Lint::InputWrapper" do
+ specify "delegates :size to underlying IO object" do
+ class IOMock
+ def size
+ 101
+ end
+ end
+
+ wrapper = Rack::Lint::InputWrapper.new(IOMock.new)
+ wrapper.size.should == 101
+ end
+
+ specify "delegates :rewind to underlying IO object" do
+ io = StringIO.new("123")
+ wrapper = Rack::Lint::InputWrapper.new(io)
+ wrapper.read.should.equal "123"
+ wrapper.read.should.equal ""
+ wrapper.rewind
+ wrapper.read.should.equal "123"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_lobster.rb b/vendor/gems/rack-1.1.0/test/spec_rack_lobster.rb
new file mode 100644
index 000000000..7be267a28
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_lobster.rb
@@ -0,0 +1,45 @@
+require 'test/spec'
+
+require 'rack/lobster'
+require 'rack/mock'
+
+context "Rack::Lobster::LambdaLobster" do
+ specify "should be a single lambda" do
+ Rack::Lobster::LambdaLobster.should.be.kind_of Proc
+ end
+
+ specify "should look like a lobster" do
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/")
+ res.should.be.ok
+ res.body.should.include "(,(,,(,,,("
+ res.body.should.include "?flip"
+ end
+
+ specify "should be flippable" do
+ res = Rack::MockRequest.new(Rack::Lobster::LambdaLobster).get("/?flip")
+ res.should.be.ok
+ res.body.should.include "(,,,(,,(,("
+ end
+end
+
+context "Rack::Lobster" do
+ specify "should look like a lobster" do
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/")
+ res.should.be.ok
+ res.body.should.include "(,(,,(,,,("
+ res.body.should.include "?flip"
+ res.body.should.include "crash"
+ end
+
+ specify "should be flippable" do
+ res = Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=left")
+ res.should.be.ok
+ res.body.should.include "(,,,(,,(,("
+ end
+
+ specify "should provide crashing for testing purposes" do
+ lambda {
+ Rack::MockRequest.new(Rack::Lobster.new).get("/?flip=crash")
+ }.should.raise
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_lock.rb b/vendor/gems/rack-1.1.0/test/spec_rack_lock.rb
new file mode 100644
index 000000000..18af2b234
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_lock.rb
@@ -0,0 +1,38 @@
+require 'test/spec'
+
+require 'rack/mock'
+require 'rack/lock'
+
+context "Rack::Lock" do
+ class Lock
+ attr_reader :synchronized
+
+ def initialize
+ @synchronized = false
+ end
+
+ def synchronize
+ @synchronized = true
+ yield
+ end
+ end
+
+ specify "should call synchronize on lock" do
+ lock = Lock.new
+ env = Rack::MockRequest.env_for("/")
+ app = Rack::Lock.new(lambda { |env| }, lock)
+ lock.synchronized.should.equal false
+ app.call(env)
+ lock.synchronized.should.equal true
+ end
+
+ specify "should set multithread flag to false" do
+ app = Rack::Lock.new(lambda { |env| env['rack.multithread'] })
+ app.call(Rack::MockRequest.env_for("/")).should.equal false
+ end
+
+ specify "should reset original multithread flag when exiting lock" do
+ app = Rack::Lock.new(lambda { |env| env })
+ app.call(Rack::MockRequest.env_for("/"))['rack.multithread'].should.equal true
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_logger.rb b/vendor/gems/rack-1.1.0/test/spec_rack_logger.rb
new file mode 100644
index 000000000..d55b9c777
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_logger.rb
@@ -0,0 +1,21 @@
+require 'rack/logger'
+require 'rack/lint'
+require 'stringio'
+
+context "Rack::Logger" do
+ specify "logs to rack.errors" do
+ app = lambda { |env|
+ log = env['rack.logger']
+ log.debug("Created logger")
+ log.info("Program started")
+ log.warn("Nothing to do!")
+
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
+ }
+
+ errors = StringIO.new
+ Rack::Logger.new(app).call({'rack.errors' => errors})
+ errors.string.should.match "INFO -- : Program started"
+ errors.string.should.match "WARN -- : Nothing to do"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_methodoverride.rb b/vendor/gems/rack-1.1.0/test/spec_rack_methodoverride.rb
new file mode 100644
index 000000000..57452394c
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_methodoverride.rb
@@ -0,0 +1,60 @@
+require 'test/spec'
+
+require 'rack/mock'
+require 'rack/methodoverride'
+require 'stringio'
+
+context "Rack::MethodOverride" do
+ specify "should not affect GET requests" do
+ env = Rack::MockRequest.env_for("/?_method=delete", :method => "GET")
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["REQUEST_METHOD"].should.equal "GET"
+ end
+
+ specify "_method parameter should modify REQUEST_METHOD for POST requests" do
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=put")
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["REQUEST_METHOD"].should.equal "PUT"
+ end
+
+ specify "X-HTTP-Method-Override header should modify REQUEST_METHOD for POST requests" do
+ env = Rack::MockRequest.env_for("/",
+ :method => "POST",
+ "HTTP_X_HTTP_METHOD_OVERRIDE" => "PUT"
+ )
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["REQUEST_METHOD"].should.equal "PUT"
+ end
+
+ specify "should not modify REQUEST_METHOD if the method is unknown" do
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "_method=foo")
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["REQUEST_METHOD"].should.equal "POST"
+ end
+
+ specify "should not modify REQUEST_METHOD when _method is nil" do
+ env = Rack::MockRequest.env_for("/", :method => "POST", :input => "foo=bar")
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["REQUEST_METHOD"].should.equal "POST"
+ end
+
+ specify "should store the original REQUEST_METHOD prior to overriding" do
+ env = Rack::MockRequest.env_for("/",
+ :method => "POST",
+ :input => "_method=options")
+ app = Rack::MethodOverride.new(lambda { |env| Rack::Request.new(env) })
+ req = app.call(env)
+
+ req.env["rack.methodoverride.original_method"].should.equal "POST"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_mock.rb b/vendor/gems/rack-1.1.0/test/spec_rack_mock.rb
new file mode 100644
index 000000000..a03bedc21
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_mock.rb
@@ -0,0 +1,243 @@
+require 'yaml'
+require 'rack/mock'
+require 'rack/request'
+require 'rack/response'
+
+app = lambda { |env|
+ req = Rack::Request.new(env)
+
+ env["mock.postdata"] = env["rack.input"].read
+ if req.GET["error"]
+ env["rack.errors"].puts req.GET["error"]
+ env["rack.errors"].flush
+ end
+
+ Rack::Response.new(env.to_yaml,
+ req.GET["status"] || 200,
+ "Content-Type" => "text/yaml").finish
+}
+
+context "Rack::MockRequest" do
+ specify "should return a MockResponse" do
+ res = Rack::MockRequest.new(app).get("")
+ res.should.be.kind_of Rack::MockResponse
+ end
+
+ specify "should be able to only return the environment" do
+ env = Rack::MockRequest.env_for("")
+ env.should.be.kind_of Hash
+ env.should.include "rack.version"
+ end
+
+ specify "should provide sensible defaults" do
+ res = Rack::MockRequest.new(app).request
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "example.org"
+ env["SERVER_PORT"].should.equal "80"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/"
+ env["SCRIPT_NAME"].should.equal ""
+ env["rack.url_scheme"].should.equal "http"
+ env["mock.postdata"].should.be.empty
+ end
+
+ specify "should allow GET/POST/PUT/DELETE" do
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+
+ res = Rack::MockRequest.new(app).post("", :input => "foo")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+
+ res = Rack::MockRequest.new(app).put("", :input => "foo")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "PUT"
+
+ res = Rack::MockRequest.new(app).delete("", :input => "foo")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "DELETE"
+
+ Rack::MockRequest.env_for("/", :method => "OPTIONS")["REQUEST_METHOD"].
+ should.equal "OPTIONS"
+ end
+
+ specify "should set content length" do
+ env = Rack::MockRequest.env_for("/", :input => "foo")
+ env["CONTENT_LENGTH"].should.equal "3"
+ end
+
+ specify "should allow posting" do
+ res = Rack::MockRequest.new(app).get("", :input => "foo")
+ env = YAML.load(res.body)
+ env["mock.postdata"].should.equal "foo"
+
+ res = Rack::MockRequest.new(app).post("", :input => StringIO.new("foo"))
+ env = YAML.load(res.body)
+ env["mock.postdata"].should.equal "foo"
+ end
+
+ specify "should use all parts of an URL" do
+ res = Rack::MockRequest.new(app).
+ get("https://bla.example.org:9292/meh/foo?bar")
+ res.should.be.kind_of Rack::MockResponse
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "bla.example.org"
+ env["SERVER_PORT"].should.equal "9292"
+ env["QUERY_STRING"].should.equal "bar"
+ env["PATH_INFO"].should.equal "/meh/foo"
+ env["rack.url_scheme"].should.equal "https"
+ end
+
+ specify "should set SSL port and HTTP flag on when using https" do
+ res = Rack::MockRequest.new(app).
+ get("https://example.org/foo")
+ res.should.be.kind_of Rack::MockResponse
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "example.org"
+ env["SERVER_PORT"].should.equal "443"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["rack.url_scheme"].should.equal "https"
+ env["HTTPS"].should.equal "on"
+ end
+
+ specify "should prepend slash to uri path" do
+ res = Rack::MockRequest.new(app).
+ get("foo")
+ res.should.be.kind_of Rack::MockResponse
+
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["SERVER_NAME"].should.equal "example.org"
+ env["SERVER_PORT"].should.equal "80"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["rack.url_scheme"].should.equal "http"
+ end
+
+ specify "should properly convert method name to an uppercase string" do
+ res = Rack::MockRequest.new(app).request(:get)
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ end
+
+ specify "should accept params and build query string for GET requests" do
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => {:foo => {:bar => "1"}})
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["QUERY_STRING"].should.match "baz=2"
+ env["QUERY_STRING"].should.match "foo[bar]=1"
+ env["PATH_INFO"].should.equal "/foo"
+ env["mock.postdata"].should.equal ""
+ end
+
+ specify "should accept raw input in params for GET requests" do
+ res = Rack::MockRequest.new(app).get("/foo?baz=2", :params => "foo[bar]=1")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "GET"
+ env["QUERY_STRING"].should.match "baz=2"
+ env["QUERY_STRING"].should.match "foo[bar]=1"
+ env["PATH_INFO"].should.equal "/foo"
+ env["mock.postdata"].should.equal ""
+ end
+
+ specify "should accept params and build url encoded params for POST requests" do
+ res = Rack::MockRequest.new(app).post("/foo", :params => {:foo => {:bar => "1"}})
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
+ env["mock.postdata"].should.equal "foo[bar]=1"
+ end
+
+ specify "should accept raw input in params for POST requests" do
+ res = Rack::MockRequest.new(app).post("/foo", :params => "foo[bar]=1")
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "application/x-www-form-urlencoded"
+ env["mock.postdata"].should.equal "foo[bar]=1"
+ end
+
+ specify "should accept params and build multipart encoded params for POST requests" do
+ files = Rack::Utils::Multipart::UploadedFile.new(File.join(File.dirname(__FILE__), "multipart", "file1.txt"))
+ res = Rack::MockRequest.new(app).post("/foo", :params => { "submit-name" => "Larry", "files" => files })
+ env = YAML.load(res.body)
+ env["REQUEST_METHOD"].should.equal "POST"
+ env["QUERY_STRING"].should.equal ""
+ env["PATH_INFO"].should.equal "/foo"
+ env["CONTENT_TYPE"].should.equal "multipart/form-data; boundary=AaB03x"
+ env["mock.postdata"].length.should.equal 206
+ end
+
+ specify "should behave valid according to the Rack spec" do
+ lambda {
+ res = Rack::MockRequest.new(app).
+ get("https://bla.example.org:9292/meh/foo?bar", :lint => true)
+ }.should.not.raise(Rack::Lint::LintError)
+ end
+end
+
+context "Rack::MockResponse" do
+ specify "should provide access to the HTTP status" do
+ res = Rack::MockRequest.new(app).get("")
+ res.should.be.successful
+ res.should.be.ok
+
+ res = Rack::MockRequest.new(app).get("/?status=404")
+ res.should.not.be.successful
+ res.should.be.client_error
+ res.should.be.not_found
+
+ res = Rack::MockRequest.new(app).get("/?status=501")
+ res.should.not.be.successful
+ res.should.be.server_error
+
+ res = Rack::MockRequest.new(app).get("/?status=307")
+ res.should.be.redirect
+
+ res = Rack::MockRequest.new(app).get("/?status=201", :lint => true)
+ res.should.be.empty
+ end
+
+ specify "should provide access to the HTTP headers" do
+ res = Rack::MockRequest.new(app).get("")
+ res.should.include "Content-Type"
+ res.headers["Content-Type"].should.equal "text/yaml"
+ res.original_headers["Content-Type"].should.equal "text/yaml"
+ res["Content-Type"].should.equal "text/yaml"
+ res.content_type.should.equal "text/yaml"
+ res.content_length.should.be 414 # needs change often.
+ res.location.should.be.nil
+ end
+
+ specify "should provide access to the HTTP body" do
+ res = Rack::MockRequest.new(app).get("")
+ res.body.should =~ /rack/
+ res.should =~ /rack/
+ res.should.match(/rack/)
+ res.should.satisfy { |r| r.match(/rack/) }
+ end
+
+ specify "should provide access to the Rack errors" do
+ res = Rack::MockRequest.new(app).get("/?error=foo", :lint => true)
+ res.should.be.ok
+ res.errors.should.not.be.empty
+ res.errors.should.include "foo"
+ end
+
+ specify "should optionally make Rack errors fatal" do
+ lambda {
+ Rack::MockRequest.new(app).get("/?error=foo", :fatal => true)
+ }.should.raise(Rack::MockRequest::FatalWarning)
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_mongrel.rb b/vendor/gems/rack-1.1.0/test/spec_rack_mongrel.rb
new file mode 100644
index 000000000..4b3868913
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_mongrel.rb
@@ -0,0 +1,189 @@
+require 'test/spec'
+
+begin
+require 'rack/handler/mongrel'
+require 'rack/urlmap'
+require 'rack/lint'
+require 'testrequest'
+require 'timeout'
+
+Thread.abort_on_exception = true
+$tcp_defer_accept_opts = nil
+$tcp_cork_opts = nil
+
+context "Rack::Handler::Mongrel" do
+ include TestRequest::Helpers
+
+ setup do
+ server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
+ server.register('/test',
+ Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new)))
+ server.register('/stream',
+ Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest)))
+ @acc = server.run
+ end
+
+ specify "should respond" do
+ lambda {
+ GET("/test")
+ }.should.not.raise
+ end
+
+ specify "should be a Mongrel" do
+ GET("/test")
+ status.should.be 200
+ response["SERVER_SOFTWARE"].should =~ /Mongrel/
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
+ response["SERVER_PORT"].should.equal "9201"
+ response["SERVER_NAME"].should.equal "0.0.0.0"
+ end
+
+ specify "should have rack headers" do
+ GET("/test")
+ response["rack.version"].should.equal [1,1]
+ response["rack.multithread"].should.be true
+ response["rack.multiprocess"].should.be false
+ response["rack.run_once"].should.be false
+ end
+
+ specify "should have CGI headers on GET" do
+ GET("/test")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/test"
+ response["PATH_INFO"].should.be.equal ""
+ response["QUERY_STRING"].should.equal ""
+ response["test.postdata"].should.equal ""
+
+ GET("/test/foo?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/test/foo"
+ response["PATH_INFO"].should.equal "/foo"
+ response["QUERY_STRING"].should.equal "quux=1"
+ end
+
+ specify "should have CGI headers on POST" do
+ POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
+ status.should.equal 200
+ response["REQUEST_METHOD"].should.equal "POST"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/test"
+ response["QUERY_STRING"].should.equal ""
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
+ response["test.postdata"].should.equal "rack-form-data=23"
+ end
+
+ specify "should support HTTP auth" do
+ GET("/test", {:user => "ruth", :passwd => "secret"})
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
+ end
+
+ specify "should set status" do
+ GET("/test?secret")
+ status.should.equal 403
+ response["rack.url_scheme"].should.equal "http"
+ end
+
+ specify "should provide a .run" do
+ block_ran = false
+ Thread.new {
+ Rack::Handler::Mongrel.run(lambda {}, {:Port => 9211}) { |server|
+ server.should.be.kind_of Mongrel::HttpServer
+ block_ran = true
+ }
+ }
+ sleep 1
+ block_ran.should.be true
+ end
+
+ specify "should provide a .run that maps a hash" do
+ block_ran = false
+ Thread.new {
+ map = {'/'=>lambda{},'/foo'=>lambda{}}
+ Rack::Handler::Mongrel.run(map, :map => true, :Port => 9221) { |server|
+ server.should.be.kind_of Mongrel::HttpServer
+ server.classifier.uris.size.should.be 2
+ server.classifier.uris.should.not.include '/arf'
+ server.classifier.uris.should.include '/'
+ server.classifier.uris.should.include '/foo'
+ block_ran = true
+ }
+ }
+ sleep 1
+ block_ran.should.be true
+ end
+
+ specify "should provide a .run that maps a urlmap" do
+ block_ran = false
+ Thread.new {
+ map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}})
+ Rack::Handler::Mongrel.run(map, {:map => true, :Port => 9231}) { |server|
+ server.should.be.kind_of Mongrel::HttpServer
+ server.classifier.uris.size.should.be 2
+ server.classifier.uris.should.not.include '/arf'
+ server.classifier.uris.should.include '/'
+ server.classifier.uris.should.include '/bar'
+ block_ran = true
+ }
+ }
+ sleep 1
+ block_ran.should.be true
+ end
+
+ specify "should provide a .run that maps a urlmap restricting by host" do
+ block_ran = false
+ Thread.new {
+ map = Rack::URLMap.new({
+ '/' => lambda{},
+ '/foo' => lambda{},
+ '/bar' => lambda{},
+ 'http://localhost/' => lambda{},
+ 'http://localhost/bar' => lambda{},
+ 'http://falsehost/arf' => lambda{},
+ 'http://falsehost/qux' => lambda{}
+ })
+ opt = {:map => true, :Port => 9241, :Host => 'localhost'}
+ Rack::Handler::Mongrel.run(map, opt) { |server|
+ server.should.be.kind_of Mongrel::HttpServer
+ server.classifier.uris.should.include '/'
+ server.classifier.handler_map['/'].size.should.be 2
+ server.classifier.uris.should.include '/foo'
+ server.classifier.handler_map['/foo'].size.should.be 1
+ server.classifier.uris.should.include '/bar'
+ server.classifier.handler_map['/bar'].size.should.be 2
+ server.classifier.uris.should.not.include '/qux'
+ server.classifier.uris.should.not.include '/arf'
+ server.classifier.uris.size.should.be 3
+ block_ran = true
+ }
+ }
+ sleep 1
+ block_ran.should.be true
+ end
+
+ specify "should stream #each part of the response" do
+ body = ''
+ begin
+ Timeout.timeout(1) do
+ Net::HTTP.start(@host, @port) do |http|
+ get = Net::HTTP::Get.new('/stream')
+ http.request(get) do |response|
+ response.read_body { |part| body << part }
+ end
+ end
+ end
+ rescue Timeout::Error
+ end
+ body.should.not.be.empty
+ end
+
+ teardown do
+ @acc.raise Mongrel::StopServer
+ end
+end
+
+rescue LoadError
+ $stderr.puts "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again."
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_nulllogger.rb b/vendor/gems/rack-1.1.0/test/spec_rack_nulllogger.rb
new file mode 100644
index 000000000..b3c2bc9c6
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_nulllogger.rb
@@ -0,0 +1,13 @@
+require 'rack/nulllogger'
+require 'rack/lint'
+require 'rack/mock'
+
+context "Rack::NullLogger" do
+ specify "acks as a nop logger" do
+ app = lambda { |env|
+ env['rack.logger'].warn "b00m"
+ [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
+ }
+ Rack::NullLogger.new(app).call({})
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_recursive.rb b/vendor/gems/rack-1.1.0/test/spec_rack_recursive.rb
new file mode 100644
index 000000000..afc1a0d9a
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_recursive.rb
@@ -0,0 +1,77 @@
+require 'test/spec'
+
+require 'rack/recursive'
+require 'rack/urlmap'
+require 'rack/response'
+require 'rack/mock'
+
+context "Rack::Recursive" do
+ setup do
+
+ @app1 = lambda { |env|
+ res = Rack::Response.new
+ res["X-Path-Info"] = env["PATH_INFO"]
+ res["X-Query-String"] = env["QUERY_STRING"]
+ res.finish do |res|
+ res.write "App1"
+ end
+ }
+
+ @app2 = lambda { |env|
+ Rack::Response.new.finish do |res|
+ res.write "App2"
+ _, _, body = env['rack.recursive.include'].call(env, "/app1")
+ body.each { |b|
+ res.write b
+ }
+ end
+ }
+
+ @app3 = lambda { |env|
+ raise Rack::ForwardRequest.new("/app1")
+ }
+
+ @app4 = lambda { |env|
+ raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh")
+ }
+
+ end
+
+ specify "should allow for subrequests" do
+ res = Rack::MockRequest.new(Rack::Recursive.new(
+ Rack::URLMap.new("/app1" => @app1,
+ "/app2" => @app2))).
+ get("/app2")
+
+ res.should.be.ok
+ res.body.should.equal "App2App1"
+ end
+
+ specify "should raise error on requests not below the app" do
+ app = Rack::URLMap.new("/app1" => @app1,
+ "/app" => Rack::Recursive.new(
+ Rack::URLMap.new("/1" => @app1,
+ "/2" => @app2)))
+
+ lambda {
+ Rack::MockRequest.new(app).get("/app/2")
+ }.should.raise(ArgumentError).
+ message.should =~ /can only include below/
+ end
+
+ specify "should support forwarding" do
+ app = Rack::Recursive.new(Rack::URLMap.new("/app1" => @app1,
+ "/app3" => @app3,
+ "/app4" => @app4))
+
+ res = Rack::MockRequest.new(app).get("/app3")
+ res.should.be.ok
+ res.body.should.equal "App1"
+
+ res = Rack::MockRequest.new(app).get("/app4")
+ res.should.be.ok
+ res.body.should.equal "App1"
+ res["X-Path-Info"].should.equal "/quux"
+ res["X-Query-String"].should.equal "meh"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_request.rb b/vendor/gems/rack-1.1.0/test/spec_rack_request.rb
new file mode 100644
index 000000000..fcdeb4844
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_request.rb
@@ -0,0 +1,545 @@
+require 'test/spec'
+require 'stringio'
+
+require 'rack/request'
+require 'rack/mock'
+
+context "Rack::Request" do
+ specify "wraps the rack variables" do
+ req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
+
+ req.body.should.respond_to? :gets
+ req.scheme.should.equal "http"
+ req.request_method.should.equal "GET"
+
+ req.should.be.get
+ req.should.not.be.post
+ req.should.not.be.put
+ req.should.not.be.delete
+ req.should.not.be.head
+
+ req.script_name.should.equal ""
+ req.path_info.should.equal "/"
+ req.query_string.should.equal ""
+
+ req.host.should.equal "example.com"
+ req.port.should.equal 8080
+
+ req.content_length.should.equal "0"
+ req.content_type.should.be.nil
+ end
+
+ specify "can figure out the correct host" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
+ req.host.should.equal "www2.example.org"
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
+ req.host.should.equal "example.org"
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
+ req.host.should.equal "example.org"
+
+ env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
+ env.delete("SERVER_NAME")
+ req = Rack::Request.new(env)
+ req.host.should.equal "192.168.1.1"
+
+ env = Rack::MockRequest.env_for("/")
+ env.delete("SERVER_NAME")
+ req = Rack::Request.new(env)
+ req.host.should.equal ""
+ end
+
+ specify "can parse the query string" do
+ req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
+ req.query_string.should.equal "foo=bar&quux=bla"
+ req.GET.should.equal "foo" => "bar", "quux" => "bla"
+ req.POST.should.be.empty
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
+ end
+
+ specify "raises if rack.input is missing" do
+ req = Rack::Request.new({})
+ lambda { req.POST }.should.raise(RuntimeError)
+ end
+
+ specify "can parse POST data when method is POST and no Content-Type given" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'POST',
+ :input => "foo=bar&quux=bla")
+ req.content_type.should.be.nil
+ req.media_type.should.be.nil
+ req.query_string.should.equal "foo=quux"
+ req.GET.should.equal "foo" => "quux"
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
+ end
+
+ specify "can parse POST data with explicit content type regardless of method" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
+ :input => "foo=bar&quux=bla")
+ req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar'
+ req.media_type.should.equal 'application/x-www-form-urlencoded'
+ req.media_type_params['foo'].should.equal 'bar'
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
+ end
+
+ specify "does not parse POST data when media type is not form-data" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'POST',
+ "CONTENT_TYPE" => 'text/plain;charset=utf-8',
+ :input => "foo=bar&quux=bla")
+ req.content_type.should.equal 'text/plain;charset=utf-8'
+ req.media_type.should.equal 'text/plain'
+ req.media_type_params['charset'].should.equal 'utf-8'
+ req.POST.should.be.empty
+ req.params.should.equal "foo" => "quux"
+ req.body.read.should.equal "foo=bar&quux=bla"
+ end
+
+ specify "can parse POST data on PUT when media type is form-data" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/?foo=quux",
+ "REQUEST_METHOD" => 'PUT',
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
+ :input => "foo=bar&quux=bla")
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.body.read.should.equal "foo=bar&quux=bla"
+ end
+
+ specify "rewinds input after parsing POST data" do
+ input = StringIO.new("foo=bar&quux=bla")
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
+ :input => input)
+ req.params.should.equal "foo" => "bar", "quux" => "bla"
+ input.read.should.equal "foo=bar&quux=bla"
+ end
+
+ specify "cleans up Safari's ajax POST body" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/",
+ 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ end
+
+ specify "can get value by key from params with #[]" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("?foo=quux")
+ req['foo'].should.equal 'quux'
+ req[:foo].should.equal 'quux'
+ end
+
+ specify "can set value to key on params with #[]=" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("?foo=duh")
+ req['foo'].should.equal 'duh'
+ req[:foo].should.equal 'duh'
+ req.params.should.equal 'foo' => 'duh'
+
+ req['foo'] = 'bar'
+ req.params.should.equal 'foo' => 'bar'
+ req['foo'].should.equal 'bar'
+ req[:foo].should.equal 'bar'
+
+ req[:foo] = 'jaz'
+ req.params.should.equal 'foo' => 'jaz'
+ req['foo'].should.equal 'jaz'
+ req[:foo].should.equal 'jaz'
+ end
+
+ specify "values_at answers values by keys in order given" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
+ req.values_at('foo').should.equal ['baz']
+ req.values_at('foo', 'wun').should.equal ['baz', 'der']
+ req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
+ end
+
+ specify "referrer should be extracted correct" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
+ req.referer.should.equal "/some/path"
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/")
+ req.referer.should.equal "/"
+ end
+
+ specify "user agent should be extracted correct" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
+ req.user_agent.should.equal "Mozilla/4.0 (compatible)"
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/")
+ req.user_agent.should.equal nil
+ end
+
+ specify "can cache, but invalidates the cache" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/?foo=quux",
+ "CONTENT_TYPE" => "application/x-www-form-urlencoded",
+ :input => "foo=bar&quux=bla")
+ req.GET.should.equal "foo" => "quux"
+ req.GET.should.equal "foo" => "quux"
+ req.env["QUERY_STRING"] = "bla=foo"
+ req.GET.should.equal "bla" => "foo"
+ req.GET.should.equal "bla" => "foo"
+
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.POST.should.equal "foo" => "bar", "quux" => "bla"
+ req.env["rack.input"] = StringIO.new("foo=bla&quux=bar")
+ req.POST.should.equal "foo" => "bla", "quux" => "bar"
+ req.POST.should.equal "foo" => "bla", "quux" => "bar"
+ end
+
+ specify "can figure out if called via XHR" do
+ req = Rack::Request.new(Rack::MockRequest.env_for(""))
+ req.should.not.be.xhr
+
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
+ req.should.be.xhr
+ end
+
+ specify "can parse cookies" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
+ req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
+ req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
+ req.env.delete("HTTP_COOKIE")
+ req.cookies.should.equal({})
+ end
+
+ specify "parses cookies according to RFC 2109" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
+ req.cookies.should.equal 'foo' => 'bar'
+ end
+
+ specify "provides setters" do
+ req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
+ req.script_name.should.equal ""
+ req.script_name = "/foo"
+ req.script_name.should.equal "/foo"
+ e["SCRIPT_NAME"].should.equal "/foo"
+
+ req.path_info.should.equal "/"
+ req.path_info = "/foo"
+ req.path_info.should.equal "/foo"
+ e["PATH_INFO"].should.equal "/foo"
+ end
+
+ specify "provides the original env" do
+ req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
+ req.env.should.be e
+ end
+
+ specify "can restore the URL" do
+ Rack::Request.new(Rack::MockRequest.env_for("")).url.
+ should.equal "http://example.org/"
+ Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
+ should.equal "http://example.org/foo/"
+ Rack::Request.new(Rack::MockRequest.env_for("/foo")).url.
+ should.equal "http://example.org/foo"
+ Rack::Request.new(Rack::MockRequest.env_for("?foo")).url.
+ should.equal "http://example.org/?foo"
+ Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url.
+ should.equal "http://example.org:8080/"
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url.
+ should.equal "https://example.org/"
+
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
+ should.equal "https://example.com:8080/foo?foo"
+ end
+
+ specify "can restore the full path" do
+ Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
+ should.equal "/"
+ Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
+ should.equal "/foo/"
+ Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath.
+ should.equal "/foo"
+ Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath.
+ should.equal "/?foo"
+ Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
+ should.equal "/"
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath.
+ should.equal "/"
+
+ Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
+ should.equal "/foo?foo"
+ end
+
+ specify "can handle multiple media type parameters" do
+ req = Rack::Request.new \
+ Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
+ req.should.not.be.form_data
+ req.media_type_params.should.include 'foo'
+ req.media_type_params['foo'].should.equal 'BAR'
+ req.media_type_params.should.include 'baz'
+ req.media_type_params['baz'].should.equal 'bizzle dizzle'
+ req.media_type_params.should.not.include 'BLING'
+ req.media_type_params.should.include 'bling'
+ req.media_type_params['bling'].should.equal 'bam'
+ end
+
+ specify "can parse multipart form data" do
+ # Adapted from RFC 1867.
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="reply"\r
+\r
+yes\r
+--AaB03x\r
+content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
+Content-Type: image/jpeg\r
+Content-Transfer-Encoding: base64\r
+\r
+/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
+--AaB03x--\r
+EOF
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ req.POST.should.include "fileupload"
+ req.POST.should.include "reply"
+
+ req.should.be.form_data
+ req.content_length.should.equal input.size
+ req.media_type.should.equal 'multipart/form-data'
+ req.media_type_params.should.include 'boundary'
+ req.media_type_params['boundary'].should.equal 'AaB03x'
+
+ req.POST["reply"].should.equal "yes"
+
+ f = req.POST["fileupload"]
+ f.should.be.kind_of Hash
+ f[:type].should.equal "image/jpeg"
+ f[:filename].should.equal "dj.jpg"
+ f.should.include :tempfile
+ f[:tempfile].size.should.equal 76
+ end
+
+ specify "can parse big multipart form data" do
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="huge"; filename="huge"\r
+\r
+#{"x"*32768}\r
+--AaB03x\r
+content-disposition: form-data; name="mean"; filename="mean"\r
+\r
+--AaB03xha\r
+--AaB03x--\r
+EOF
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ req.POST["huge"][:tempfile].size.should.equal 32768
+ req.POST["mean"][:tempfile].size.should.equal 10
+ req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
+ end
+
+ specify "can detect invalid multipart form data" do
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="huge"; filename="huge"\r
+EOF
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ lambda { req.POST }.should.raise(EOFError)
+
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="huge"; filename="huge"\r
+\r
+foo\r
+EOF
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ lambda { req.POST }.should.raise(EOFError)
+
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="huge"; filename="huge"\r
+\r
+foo\r
+EOF
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ lambda { req.POST }.should.raise(EOFError)
+ end
+
+ specify "shouldn't try to interpret binary as utf8" do
+ begin
+ original_kcode = $KCODE
+ $KCODE='UTF8'
+
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="fileupload"; filename="junk.a"\r
+content-type: application/octet-stream\r
+\r
+#{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
+--AaB03x--\r
+EOF
+
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ lambda{req.POST}.should.not.raise(EOFError)
+ req.POST["fileupload"][:tempfile].size.should.equal 4
+ ensure
+ $KCODE = original_kcode
+ end
+ end
+
+
+ specify "should work around buggy 1.8.* Tempfile equality" do
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="huge"; filename="huge"\r
+\r
+foo\r
+--AaB03x--
+EOF
+
+ rack_input = Tempfile.new("rackspec")
+ rack_input.write(input)
+ rack_input.rewind
+
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size,
+ :input => rack_input)
+
+ lambda {req.POST}.should.not.raise
+ lambda {req.POST}.should.blaming("input re-processed!").not.raise
+ end
+
+ specify "does conform to the Rack spec" do
+ app = lambda { |env|
+ content = Rack::Request.new(env).POST["file"].inspect
+ size = content.respond_to?(:bytesize) ? content.bytesize : content.size
+ [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
+ }
+
+ input = <<EOF
+--AaB03x\r
+content-disposition: form-data; name="reply"\r
+\r
+yes\r
+--AaB03x\r
+content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
+Content-Type: image/jpeg\r
+Content-Transfer-Encoding: base64\r
+\r
+/9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
+--AaB03x--\r
+EOF
+ input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
+ res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
+ "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
+
+ res.should.be.ok
+ end
+
+ specify "should parse Accept-Encoding correctly" do
+ parser = lambda do |x|
+ Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
+ end
+
+ parser.call(nil).should.equal([])
+
+ parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
+ parser.call("").should.equal([])
+ parser.call("*").should.equal([["*", 1.0]])
+ parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
+ parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
+
+ lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
+ end
+
+ specify 'should provide ip information' do
+ app = lambda { |env|
+ request = Rack::Request.new(env)
+ response = Rack::Response.new
+ response.write request.ip
+ response.finish
+ }
+
+ mock = Rack::MockRequest.new(Rack::Lint.new(app))
+ res = mock.get '/', 'REMOTE_ADDR' => '123.123.123.123'
+ res.body.should.equal '123.123.123.123'
+
+ res = mock.get '/',
+ 'REMOTE_ADDR' => '123.123.123.123',
+ 'HTTP_X_FORWARDED_FOR' => '234.234.234.234'
+
+ res.body.should.equal '234.234.234.234'
+
+ res = mock.get '/',
+ 'REMOTE_ADDR' => '123.123.123.123',
+ 'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212'
+
+ res.body.should.equal '212.212.212.212'
+ end
+
+ class MyRequest < Rack::Request
+ def params
+ {:foo => "bar"}
+ end
+ end
+
+ specify "should allow subclass request to be instantiated after parent request" do
+ env = Rack::MockRequest.env_for("/?foo=bar")
+
+ req1 = Rack::Request.new(env)
+ req1.GET.should.equal "foo" => "bar"
+ req1.params.should.equal "foo" => "bar"
+
+ req2 = MyRequest.new(env)
+ req2.GET.should.equal "foo" => "bar"
+ req2.params.should.equal :foo => "bar"
+ end
+
+ specify "should allow parent request to be instantiated after subclass request" do
+ env = Rack::MockRequest.env_for("/?foo=bar")
+
+ req1 = MyRequest.new(env)
+ req1.GET.should.equal "foo" => "bar"
+ req1.params.should.equal :foo => "bar"
+
+ req2 = Rack::Request.new(env)
+ req2.GET.should.equal "foo" => "bar"
+ req2.params.should.equal "foo" => "bar"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_response.rb b/vendor/gems/rack-1.1.0/test/spec_rack_response.rb
new file mode 100644
index 000000000..7989013da
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_response.rb
@@ -0,0 +1,221 @@
+require 'test/spec'
+require 'set'
+
+require 'rack/response'
+
+context "Rack::Response" do
+ specify "has sensible default values" do
+ response = Rack::Response.new
+ status, header, body = response.finish
+ status.should.equal 200
+ header.should.equal "Content-Type" => "text/html"
+ body.each { |part|
+ part.should.equal ""
+ }
+
+ response = Rack::Response.new
+ status, header, body = *response
+ status.should.equal 200
+ header.should.equal "Content-Type" => "text/html"
+ body.each { |part|
+ part.should.equal ""
+ }
+ end
+
+ specify "can be written to" do
+ response = Rack::Response.new
+
+ status, header, body = response.finish do
+ response.write "foo"
+ response.write "bar"
+ response.write "baz"
+ end
+
+ parts = []
+ body.each { |part| parts << part }
+
+ parts.should.equal ["foo", "bar", "baz"]
+ end
+
+ specify "can set and read headers" do
+ response = Rack::Response.new
+ response["Content-Type"].should.equal "text/html"
+ response["Content-Type"] = "text/plain"
+ response["Content-Type"].should.equal "text/plain"
+ end
+
+ specify "can set cookies" do
+ response = Rack::Response.new
+
+ response.set_cookie "foo", "bar"
+ response["Set-Cookie"].should.equal "foo=bar"
+ response.set_cookie "foo2", "bar2"
+ response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2"]
+ response.set_cookie "foo3", "bar3"
+ response["Set-Cookie"].should.equal ["foo=bar", "foo2=bar2", "foo3=bar3"]
+ end
+
+ specify "formats the Cookie expiration date accordingly to RFC 2109" do
+ response = Rack::Response.new
+
+ response.set_cookie "foo", {:value => "bar", :expires => Time.now+10}
+ response["Set-Cookie"].should.match(
+ /expires=..., \d\d-...-\d\d\d\d \d\d:\d\d:\d\d .../)
+ end
+
+ specify "can set secure cookies" do
+ response = Rack::Response.new
+ response.set_cookie "foo", {:value => "bar", :secure => true}
+ response["Set-Cookie"].should.equal "foo=bar; secure"
+ end
+
+ specify "can set http only cookies" do
+ response = Rack::Response.new
+ response.set_cookie "foo", {:value => "bar", :httponly => true}
+ response["Set-Cookie"].should.equal "foo=bar; HttpOnly"
+ end
+
+ specify "can delete cookies" do
+ response = Rack::Response.new
+ response.set_cookie "foo", "bar"
+ response.set_cookie "foo2", "bar2"
+ response.delete_cookie "foo"
+ response["Set-Cookie"].should.equal ["foo2=bar2",
+ "foo=; expires=Thu, 01-Jan-1970 00:00:00 GMT"]
+ end
+
+ specify "can do redirects" do
+ response = Rack::Response.new
+ response.redirect "/foo"
+ status, header, body = response.finish
+
+ status.should.equal 302
+ header["Location"].should.equal "/foo"
+
+ response = Rack::Response.new
+ response.redirect "/foo", 307
+ status, header, body = response.finish
+
+ status.should.equal 307
+ end
+
+ specify "has a useful constructor" do
+ r = Rack::Response.new("foo")
+ status, header, body = r.finish
+ str = ""; body.each { |part| str << part }
+ str.should.equal "foo"
+
+ r = Rack::Response.new(["foo", "bar"])
+ status, header, body = r.finish
+ str = ""; body.each { |part| str << part }
+ str.should.equal "foobar"
+
+ r = Rack::Response.new(["foo", "bar"].to_set)
+ r.write "foo"
+ status, header, body = r.finish
+ str = ""; body.each { |part| str << part }
+ str.should.equal "foobarfoo"
+
+ r = Rack::Response.new([], 500)
+ r.status.should.equal 500
+
+ r = Rack::Response.new([], "200 OK")
+ r.status.should.equal 200
+ end
+
+ specify "has a constructor that can take a block" do
+ r = Rack::Response.new { |res|
+ res.status = 404
+ res.write "foo"
+ }
+ status, header, body = r.finish
+ str = ""; body.each { |part| str << part }
+ str.should.equal "foo"
+ status.should.equal 404
+ end
+
+ specify "doesn't return invalid responses" do
+ r = Rack::Response.new(["foo", "bar"], 204)
+ status, header, body = r.finish
+ str = ""; body.each { |part| str << part }
+ str.should.be.empty
+ header["Content-Type"].should.equal nil
+
+ lambda {
+ Rack::Response.new(Object.new)
+ }.should.raise(TypeError).
+ message.should =~ /stringable or iterable required/
+ end
+
+ specify "knows if it's empty" do
+ r = Rack::Response.new
+ r.should.be.empty
+ r.write "foo"
+ r.should.not.be.empty
+
+ r = Rack::Response.new
+ r.should.be.empty
+ r.finish
+ r.should.be.empty
+
+ r = Rack::Response.new
+ r.should.be.empty
+ r.finish { }
+ r.should.not.be.empty
+ end
+
+ specify "should provide access to the HTTP status" do
+ res = Rack::Response.new
+ res.status = 200
+ res.should.be.successful
+ res.should.be.ok
+
+ res.status = 404
+ res.should.not.be.successful
+ res.should.be.client_error
+ res.should.be.not_found
+
+ res.status = 501
+ res.should.not.be.successful
+ res.should.be.server_error
+
+ res.status = 307
+ res.should.be.redirect
+ end
+
+ specify "should provide access to the HTTP headers" do
+ res = Rack::Response.new
+ res["Content-Type"] = "text/yaml"
+
+ res.should.include "Content-Type"
+ res.headers["Content-Type"].should.equal "text/yaml"
+ res["Content-Type"].should.equal "text/yaml"
+ res.content_type.should.equal "text/yaml"
+ res.content_length.should.be.nil
+ res.location.should.be.nil
+ end
+
+ specify "does not add or change Content-Length when #finish()ing" do
+ res = Rack::Response.new
+ res.status = 200
+ res.finish
+ res.headers["Content-Length"].should.be.nil
+
+ res = Rack::Response.new
+ res.status = 200
+ res.headers["Content-Length"] = "10"
+ res.finish
+ res.headers["Content-Length"].should.equal "10"
+ end
+
+ specify "updates Content-Length when body appended to using #write" do
+ res = Rack::Response.new
+ res.status = 200
+ res.headers["Content-Length"].should.be.nil
+ res.write "Hi"
+ res.headers["Content-Length"].should.equal "2"
+ res.write " there"
+ res.headers["Content-Length"].should.equal "8"
+ end
+
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_rewindable_input.rb b/vendor/gems/rack-1.1.0/test/spec_rack_rewindable_input.rb
new file mode 100644
index 000000000..78bebfc90
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_rewindable_input.rb
@@ -0,0 +1,118 @@
+require 'test/spec'
+require 'stringio'
+require 'rack/rewindable_input'
+
+shared_context "a rewindable IO object" do
+ setup do
+ @rio = Rack::RewindableInput.new(@io)
+ end
+
+ teardown do
+ @rio.close
+ end
+
+ specify "should be able to handle to read()" do
+ @rio.read.should.equal "hello world"
+ end
+
+ specify "should be able to handle to read(nil)" do
+ @rio.read(nil).should.equal "hello world"
+ end
+
+ specify "should be able to handle to read(length)" do
+ @rio.read(1).should.equal "h"
+ end
+
+ specify "should be able to handle to read(length, buffer)" do
+ buffer = ""
+ result = @rio.read(1, buffer)
+ result.should.equal "h"
+ result.object_id.should.equal buffer.object_id
+ end
+
+ specify "should be able to handle to read(nil, buffer)" do
+ buffer = ""
+ result = @rio.read(nil, buffer)
+ result.should.equal "hello world"
+ result.object_id.should.equal buffer.object_id
+ end
+
+ specify "should rewind to the beginning when #rewind is called" do
+ @rio.read(1)
+ @rio.rewind
+ @rio.read.should.equal "hello world"
+ end
+
+ specify "should be able to handle gets" do
+ @rio.gets.should == "hello world"
+ end
+
+ specify "should be able to handle each" do
+ array = []
+ @rio.each do |data|
+ array << data
+ end
+ array.should.equal(["hello world"])
+ end
+
+ specify "should not buffer into a Tempfile if no data has been read yet" do
+ @rio.instance_variable_get(:@rewindable_io).should.be.nil
+ end
+
+ specify "should buffer into a Tempfile when data has been consumed for the first time" do
+ @rio.read(1)
+ tempfile = @rio.instance_variable_get(:@rewindable_io)
+ tempfile.should.not.be.nil
+ @rio.read(1)
+ tempfile2 = @rio.instance_variable_get(:@rewindable_io)
+ tempfile2.should.equal tempfile
+ end
+
+ specify "should close the underlying tempfile upon calling #close" do
+ @rio.read(1)
+ tempfile = @rio.instance_variable_get(:@rewindable_io)
+ @rio.close
+ tempfile.should.be.closed
+ end
+
+ specify "should be possibel to call #close when no data has been buffered yet" do
+ @rio.close
+ end
+
+ specify "should be possible to call #close multiple times" do
+ @rio.close
+ @rio.close
+ end
+end
+
+context "Rack::RewindableInput" do
+ context "given an IO object that is already rewindable" do
+ setup do
+ @io = StringIO.new("hello world")
+ end
+
+ it_should_behave_like "a rewindable IO object"
+ end
+
+ context "given an IO object that is not rewindable" do
+ setup do
+ @io = StringIO.new("hello world")
+ @io.instance_eval do
+ undef :rewind
+ end
+ end
+
+ it_should_behave_like "a rewindable IO object"
+ end
+
+ context "given an IO object whose rewind method raises Errno::ESPIPE" do
+ setup do
+ @io = StringIO.new("hello world")
+ def @io.rewind
+ raise Errno::ESPIPE, "You can't rewind this!"
+ end
+ end
+
+ it_should_behave_like "a rewindable IO object"
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_runtime.rb b/vendor/gems/rack-1.1.0/test/spec_rack_runtime.rb
new file mode 100644
index 000000000..62d809564
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_runtime.rb
@@ -0,0 +1,35 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/runtime'
+
+context "Rack::Runtime" do
+ specify "sets X-Runtime is none is set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ response = Rack::Runtime.new(app).call({})
+ response[1]['X-Runtime'].should =~ /[\d\.]+/
+ end
+
+ specify "does not set the X-Runtime if it is already set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain', "X-Runtime" => "foobar"}, "Hello, World!"] }
+ response = Rack::Runtime.new(app).call({})
+ response[1]['X-Runtime'].should == "foobar"
+ end
+
+ specify "should allow a suffix to be set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ response = Rack::Runtime.new(app, "Test").call({})
+ response[1]['X-Runtime-Test'].should =~ /[\d\.]+/
+ end
+
+ specify "should allow multiple timers to be set" do
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, "Hello, World!"] }
+ runtime1 = Rack::Runtime.new(app, "App")
+ runtime2 = Rack::Runtime.new(runtime1, "All")
+ response = runtime2.call({})
+
+ response[1]['X-Runtime-App'].should =~ /[\d\.]+/
+ response[1]['X-Runtime-All'].should =~ /[\d\.]+/
+
+ Float(response[1]['X-Runtime-All']).should > Float(response[1]['X-Runtime-App'])
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_sendfile.rb b/vendor/gems/rack-1.1.0/test/spec_rack_sendfile.rb
new file mode 100644
index 000000000..8cfe2017b
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_sendfile.rb
@@ -0,0 +1,86 @@
+require 'test/spec'
+require 'rack/mock'
+require 'rack/sendfile'
+
+context "Rack::File" do
+ specify "should respond to #to_path" do
+ Rack::File.new(Dir.pwd).should.respond_to :to_path
+ end
+end
+
+context "Rack::Sendfile" do
+ def sendfile_body
+ res = ['Hello World']
+ def res.to_path ; "/tmp/hello.txt" ; end
+ res
+ end
+
+ def simple_app(body=sendfile_body)
+ lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
+ end
+
+ def sendfile_app(body=sendfile_body)
+ Rack::Sendfile.new(simple_app(body))
+ end
+
+ setup do
+ @request = Rack::MockRequest.new(sendfile_app)
+ end
+
+ def request(headers={})
+ yield @request.get('/', headers)
+ end
+
+ specify "does nothing when no X-Sendfile-Type header present" do
+ request do |response|
+ response.should.be.ok
+ response.body.should.equal 'Hello World'
+ response.headers.should.not.include 'X-Sendfile'
+ end
+ end
+
+ specify "sets X-Sendfile response header and discards body" do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Sendfile'].should.equal '/tmp/hello.txt'
+ end
+ end
+
+ specify "sets X-Lighttpd-Send-File response header and discards body" do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Lighttpd-Send-File' do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Lighttpd-Send-File'].should.equal '/tmp/hello.txt'
+ end
+ end
+
+ specify "sets X-Accel-Redirect response header and discards body" do
+ headers = {
+ 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect',
+ 'HTTP_X_ACCEL_MAPPING' => '/tmp/=/foo/bar/'
+ }
+ request headers do |response|
+ response.should.be.ok
+ response.body.should.be.empty
+ response.headers['X-Accel-Redirect'].should.equal '/foo/bar/hello.txt'
+ end
+ end
+
+ specify 'writes to rack.error when no X-Accel-Mapping is specified' do
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Accel-Redirect' do |response|
+ response.should.be.ok
+ response.body.should.equal 'Hello World'
+ response.headers.should.not.include 'X-Accel-Redirect'
+ response.errors.should.include 'X-Accel-Mapping'
+ end
+ end
+
+ specify 'does nothing when body does not respond to #to_path' do
+ @request = Rack::MockRequest.new(sendfile_app(['Not a file...']))
+ request 'HTTP_X_SENDFILE_TYPE' => 'X-Sendfile' do |response|
+ response.body.should.equal 'Not a file...'
+ response.headers.should.not.include 'X-Sendfile'
+ end
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_session_cookie.rb b/vendor/gems/rack-1.1.0/test/spec_rack_session_cookie.rb
new file mode 100644
index 000000000..fba3f83bf
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_session_cookie.rb
@@ -0,0 +1,73 @@
+require 'test/spec'
+
+require 'rack/session/cookie'
+require 'rack/mock'
+require 'rack/response'
+
+context "Rack::Session::Cookie" do
+ incrementor = lambda { |env|
+ env["rack.session"]["counter"] ||= 0
+ env["rack.session"]["counter"] += 1
+ Rack::Response.new(env["rack.session"].inspect).to_a
+ }
+
+ specify "creates a new cookie" do
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
+ res["Set-Cookie"].should.match("rack.session=")
+ res.body.should.equal '{"counter"=>1}'
+ end
+
+ specify "loads from a cookie" do
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).get("/")
+ cookie = res["Set-Cookie"]
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
+ get("/", "HTTP_COOKIE" => cookie)
+ res.body.should.equal '{"counter"=>2}'
+ cookie = res["Set-Cookie"]
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
+ get("/", "HTTP_COOKIE" => cookie)
+ res.body.should.equal '{"counter"=>3}'
+ end
+
+ specify "survives broken cookies" do
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor)).
+ get("/", "HTTP_COOKIE" => "rack.session=blarghfasel")
+ res.body.should.equal '{"counter"=>1}'
+ end
+
+ bigcookie = lambda { |env|
+ env["rack.session"]["cookie"] = "big" * 3000
+ Rack::Response.new(env["rack.session"].inspect).to_a
+ }
+
+ specify "barks on too big cookies" do
+ lambda {
+ Rack::MockRequest.new(Rack::Session::Cookie.new(bigcookie)).
+ get("/", :fatal => true)
+ }.should.raise(Rack::MockRequest::FatalWarning)
+ end
+
+ specify "loads from a cookie wih integrity hash" do
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).get("/")
+ cookie = res["Set-Cookie"]
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
+ get("/", "HTTP_COOKIE" => cookie)
+ res.body.should.equal '{"counter"=>2}'
+ cookie = res["Set-Cookie"]
+ res = Rack::MockRequest.new(Rack::Session::Cookie.new(incrementor, :secret => 'test')).
+ get("/", "HTTP_COOKIE" => cookie)
+ res.body.should.equal '{"counter"=>3}'
+ end
+
+ specify "ignores tampered with session cookies" do
+ app = Rack::Session::Cookie.new(incrementor, :secret => 'test')
+ response1 = Rack::MockRequest.new(app).get("/")
+ _, digest = response1["Set-Cookie"].split("--")
+ tampered_with_cookie = "hackerman-was-here" + "--" + digest
+ response2 = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" =>
+ tampered_with_cookie)
+
+ # The tampered-with cookie is ignored, so we get back an identical Set-Cookie
+ response2["Set-Cookie"].should.equal(response1["Set-Cookie"])
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_session_memcache.rb b/vendor/gems/rack-1.1.0/test/spec_rack_session_memcache.rb
new file mode 100644
index 000000000..faac796eb
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_session_memcache.rb
@@ -0,0 +1,273 @@
+require 'test/spec'
+
+begin
+ require 'rack/session/memcache'
+ require 'rack/mock'
+ require 'rack/response'
+ require 'thread'
+
+ context "Rack::Session::Memcache" do
+ session_key = Rack::Session::Memcache::DEFAULT_OPTIONS[:key]
+ session_match = /#{session_key}=([0-9a-fA-F]+);/
+ incrementor = lambda do |env|
+ env["rack.session"]["counter"] ||= 0
+ env["rack.session"]["counter"] += 1
+ Rack::Response.new(env["rack.session"].inspect).to_a
+ end
+ drop_session = proc do |env|
+ env['rack.session.options'][:drop] = true
+ incrementor.call(env)
+ end
+ renew_session = proc do |env|
+ env['rack.session.options'][:renew] = true
+ incrementor.call(env)
+ end
+ defer_session = proc do |env|
+ env['rack.session.options'][:defer] = true
+ incrementor.call(env)
+ end
+
+ specify "faults on no connection" do
+ if RUBY_VERSION < "1.9"
+ lambda do
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
+ end.should.raise
+ else
+ lambda do
+ Rack::Session::Memcache.new incrementor, :memcache_server => 'nosuchserver'
+ end.should.raise ArgumentError
+ end
+ end
+
+ specify "connect to existing server" do
+ test_pool = MemCache.new incrementor, :namespace => 'test:rack:session'
+ end
+
+ specify "creates a new cookie" do
+ pool = Rack::Session::Memcache.new(incrementor)
+ res = Rack::MockRequest.new(pool).get("/")
+ res["Set-Cookie"].should.match("#{session_key}=")
+ res.body.should.equal '{"counter"=>1}'
+ end
+
+ specify "determines session from a cookie" do
+ pool = Rack::Session::Memcache.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ res = req.get("/")
+ cookie = res["Set-Cookie"]
+ req.get("/", "HTTP_COOKIE" => cookie).
+ body.should.equal '{"counter"=>2}'
+ req.get("/", "HTTP_COOKIE" => cookie).
+ body.should.equal '{"counter"=>3}'
+ end
+
+ specify "survives nonexistant cookies" do
+ bad_cookie = "rack.session=blarghfasel"
+ pool = Rack::Session::Memcache.new(incrementor)
+ res = Rack::MockRequest.new(pool).
+ get("/", "HTTP_COOKIE" => bad_cookie)
+ res.body.should.equal '{"counter"=>1}'
+ cookie = res["Set-Cookie"][session_match]
+ cookie.should.not.match(/#{bad_cookie}/)
+ end
+
+ specify "maintains freshness" do
+ pool = Rack::Session::Memcache.new(incrementor, :expire_after => 3)
+ res = Rack::MockRequest.new(pool).get('/')
+ res.body.should.include '"counter"=>1'
+ cookie = res["Set-Cookie"]
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
+ res["Set-Cookie"].should.equal cookie
+ res.body.should.include '"counter"=>2'
+ puts 'Sleeping to expire session' if $DEBUG
+ sleep 4
+ res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
+ res["Set-Cookie"].should.not.equal cookie
+ res.body.should.include '"counter"=>1'
+ end
+
+ specify "deletes cookies with :drop option" do
+ pool = Rack::Session::Memcache.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ drop = Rack::Utils::Context.new(pool, drop_session)
+ dreq = Rack::MockRequest.new(drop)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+ res2["Set-Cookie"].should.equal nil
+ res2.body.should.equal '{"counter"=>3}'
+
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
+ res3["Set-Cookie"][session_match].should.not.equal session
+ res3.body.should.equal '{"counter"=>1}'
+ end
+
+ specify "provides new session id with :renew option" do
+ pool = Rack::Session::Memcache.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ renew = Rack::Utils::Context.new(pool, renew_session)
+ rreq = Rack::MockRequest.new(renew)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
+ new_cookie = res2["Set-Cookie"]
+ new_session = new_cookie[session_match]
+ new_session.should.not.equal session
+ res2.body.should.equal '{"counter"=>3}'
+
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
+ res3["Set-Cookie"][session_match].should.equal new_session
+ res3.body.should.equal '{"counter"=>4}'
+ end
+
+ specify "omits cookie with :defer option" do
+ pool = Rack::Session::Memcache.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ defer = Rack::Utils::Context.new(pool, defer_session)
+ dreq = Rack::MockRequest.new(defer)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+ res2["Set-Cookie"].should.equal nil
+ res2.body.should.equal '{"counter"=>3}'
+
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
+ res3["Set-Cookie"][session_match].should.equal session
+ res3.body.should.equal '{"counter"=>4}'
+ end
+
+ specify "deep hashes are correctly updated" do
+ store = nil
+ hash_check = proc do |env|
+ session = env['rack.session']
+ unless session.include? 'test'
+ session.update :a => :b, :c => { :d => :e },
+ :f => { :g => { :h => :i} }, 'test' => true
+ else
+ session[:f][:g][:h] = :j
+ end
+ [200, {}, session.inspect]
+ end
+ pool = Rack::Session::Memcache.new(hash_check)
+ req = Rack::MockRequest.new(pool)
+
+ res0 = req.get("/")
+ session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
+ ses0 = pool.pool.get(session_id, true)
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ ses1 = pool.pool.get(session_id, true)
+
+ ses1.should.not.equal ses0
+ end
+
+ # anyone know how to do this better?
+ specify "multithread: should cleanly merge sessions" do
+ next unless $DEBUG
+ warn 'Running multithread test for Session::Memcache'
+ pool = Rack::Session::Memcache.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+
+ res = req.get('/')
+ res.body.should.equal '{"counter"=>1}'
+ cookie = res["Set-Cookie"]
+ session_id = cookie[session_match, 1]
+
+ delta_incrementor = lambda do |env|
+ # emulate disconjoinment of threading
+ env['rack.session'] = env['rack.session'].dup
+ Thread.stop
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
+ incrementor.call(env)
+ end
+ tses = Rack::Utils::Context.new pool, delta_incrementor
+ treq = Rack::MockRequest.new(tses)
+ tnum = rand(7).to_i+5
+ r = Array.new(tnum) do
+ Thread.new(treq) do |run|
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
+ end
+ end.reverse.map{|t| t.run.join.value }
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"counter"=>2'
+ end
+
+ session = pool.pool.get(session_id)
+ session.size.should.be tnum+1 # counter
+ session['counter'].should.be 2 # meeeh
+
+ tnum = rand(7).to_i+5
+ r = Array.new(tnum) do |i|
+ delta_time = proc do |env|
+ env['rack.session'][i] = Time.now
+ Thread.stop
+ env['rack.session'] = env['rack.session'].dup
+ env['rack.session'][i] -= Time.now
+ incrementor.call(env)
+ end
+ app = Rack::Utils::Context.new pool, time_delta
+ req = Rack::MockRequest.new app
+ Thread.new(req) do |run|
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
+ end
+ end.reverse.map{|t| t.run.join.value }
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"counter"=>3'
+ end
+
+ session = pool.pool.get(session_id)
+ session.size.should.be tnum+1
+ session['counter'].should.be 3
+
+ drop_counter = proc do |env|
+ env['rack.session'].delete 'counter'
+ env['rack.session']['foo'] = 'bar'
+ [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
+ end
+ tses = Rack::Utils::Context.new pool, drop_counter
+ treq = Rack::MockRequest.new(tses)
+ tnum = rand(7).to_i+5
+ r = Array.new(tnum) do
+ Thread.new(treq) do |run|
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
+ end
+ end.reverse.map{|t| t.run.join.value }
+ r.each do |request|
+ request['Set-Cookie'].should.equal cookie
+ request.body.should.include '"foo"=>"bar"'
+ end
+
+ session = pool.pool.get(session_id)
+ session.size.should.be r.size+1
+ session['counter'].should.be.nil?
+ session['foo'].should.equal 'bar'
+ end
+ end
+rescue RuntimeError
+ $stderr.puts "Skipping Rack::Session::Memcache tests. Start memcached and try again."
+rescue LoadError
+ $stderr.puts "Skipping Rack::Session::Memcache tests (Memcache is required). `gem install memcache-client` and try again."
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_session_pool.rb b/vendor/gems/rack-1.1.0/test/spec_rack_session_pool.rb
new file mode 100644
index 000000000..6be382ec7
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_session_pool.rb
@@ -0,0 +1,172 @@
+require 'test/spec'
+
+require 'rack/session/pool'
+require 'rack/mock'
+require 'rack/response'
+require 'thread'
+
+context "Rack::Session::Pool" do
+ session_key = Rack::Session::Pool::DEFAULT_OPTIONS[:key]
+ session_match = /#{session_key}=[0-9a-fA-F]+;/
+ incrementor = lambda do |env|
+ env["rack.session"]["counter"] ||= 0
+ env["rack.session"]["counter"] += 1
+ Rack::Response.new(env["rack.session"].inspect).to_a
+ end
+ drop_session = proc do |env|
+ env['rack.session.options'][:drop] = true
+ incrementor.call(env)
+ end
+ renew_session = proc do |env|
+ env['rack.session.options'][:renew] = true
+ incrementor.call(env)
+ end
+ defer_session = proc do |env|
+ env['rack.session.options'][:defer] = true
+ incrementor.call(env)
+ end
+
+ specify "creates a new cookie" do
+ pool = Rack::Session::Pool.new(incrementor)
+ res = Rack::MockRequest.new(pool).get("/")
+ res["Set-Cookie"].should.match session_match
+ res.body.should.equal '{"counter"=>1}'
+ end
+
+ specify "determines session from a cookie" do
+ pool = Rack::Session::Pool.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ cookie = req.get("/")["Set-Cookie"]
+ req.get("/", "HTTP_COOKIE" => cookie).
+ body.should.equal '{"counter"=>2}'
+ req.get("/", "HTTP_COOKIE" => cookie).
+ body.should.equal '{"counter"=>3}'
+ end
+
+ specify "survives nonexistant cookies" do
+ pool = Rack::Session::Pool.new(incrementor)
+ res = Rack::MockRequest.new(pool).
+ get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
+ res.body.should.equal '{"counter"=>1}'
+ end
+
+ specify "deletes cookies with :drop option" do
+ pool = Rack::Session::Pool.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ drop = Rack::Utils::Context.new(pool, drop_session)
+ dreq = Rack::MockRequest.new(drop)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+ pool.pool.size.should.be 1
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+ pool.pool.size.should.be 1
+
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+ res2["Set-Cookie"].should.equal nil
+ res2.body.should.equal '{"counter"=>3}'
+ pool.pool.size.should.be 0
+
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
+ res3["Set-Cookie"][session_match].should.not.equal session
+ res3.body.should.equal '{"counter"=>1}'
+ pool.pool.size.should.be 1
+ end
+
+ specify "provides new session id with :renew option" do
+ pool = Rack::Session::Pool.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ renew = Rack::Utils::Context.new(pool, renew_session)
+ rreq = Rack::MockRequest.new(renew)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+ pool.pool.size.should.be 1
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+ pool.pool.size.should.be 1
+
+ res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
+ new_cookie = res2["Set-Cookie"]
+ new_session = new_cookie[session_match]
+ new_session.should.not.equal session
+ res2.body.should.equal '{"counter"=>3}'
+ pool.pool.size.should.be 1
+
+ res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
+ res3["Set-Cookie"][session_match].should.equal new_session
+ res3.body.should.equal '{"counter"=>4}'
+ pool.pool.size.should.be 1
+ end
+
+ specify "omits cookie with :defer option" do
+ pool = Rack::Session::Pool.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+ defer = Rack::Utils::Context.new(pool, defer_session)
+ dreq = Rack::MockRequest.new(defer)
+
+ res0 = req.get("/")
+ session = (cookie = res0["Set-Cookie"])[session_match]
+ res0.body.should.equal '{"counter"=>1}'
+ pool.pool.size.should.be 1
+
+ res1 = req.get("/", "HTTP_COOKIE" => cookie)
+ res1["Set-Cookie"][session_match].should.equal session
+ res1.body.should.equal '{"counter"=>2}'
+ pool.pool.size.should.be 1
+
+ res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
+ res2["Set-Cookie"].should.equal nil
+ res2.body.should.equal '{"counter"=>3}'
+ pool.pool.size.should.be 1
+
+ res3 = req.get("/", "HTTP_COOKIE" => cookie)
+ res3["Set-Cookie"][session_match].should.equal session
+ res3.body.should.equal '{"counter"=>4}'
+ pool.pool.size.should.be 1
+ end
+
+ # anyone know how to do this better?
+ specify "multithread: should merge sessions" do
+ next unless $DEBUG
+ warn 'Running multithread tests for Session::Pool'
+ pool = Rack::Session::Pool.new(incrementor)
+ req = Rack::MockRequest.new(pool)
+
+ res = req.get('/')
+ res.body.should.equal '{"counter"=>1}'
+ cookie = res["Set-Cookie"]
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
+
+ delta_incrementor = lambda do |env|
+ # emulate disconjoinment of threading
+ env['rack.session'] = env['rack.session'].dup
+ Thread.stop
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
+ incrementor.call(env)
+ end
+ tses = Rack::Utils::Context.new pool, delta_incrementor
+ treq = Rack::MockRequest.new(tses)
+ tnum = rand(7).to_i+5
+ r = Array.new(tnum) do
+ Thread.new(treq) do |run|
+ run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
+ end
+ end.reverse.map{|t| t.run.join.value }
+ r.each do |res|
+ res['Set-Cookie'].should.equal cookie
+ res.body.should.include '"counter"=>2'
+ end
+
+ session = pool.pool[sess_id]
+ session.size.should.be tnum+1 # counter
+ session['counter'].should.be 2 # meeeh
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_showexceptions.rb b/vendor/gems/rack-1.1.0/test/spec_rack_showexceptions.rb
new file mode 100644
index 000000000..bdbc12013
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_showexceptions.rb
@@ -0,0 +1,21 @@
+require 'test/spec'
+
+require 'rack/showexceptions'
+require 'rack/mock'
+
+context "Rack::ShowExceptions" do
+ specify "catches exceptions" do
+ res = nil
+ req = Rack::MockRequest.new(Rack::ShowExceptions.new(lambda { |env|
+ raise RuntimeError
+ }))
+ lambda {
+ res = req.get("/")
+ }.should.not.raise
+ res.should.be.a.server_error
+ res.status.should.equal 500
+
+ res.should =~ /RuntimeError/
+ res.should =~ /ShowExceptions/
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_showstatus.rb b/vendor/gems/rack-1.1.0/test/spec_rack_showstatus.rb
new file mode 100644
index 000000000..787001341
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_showstatus.rb
@@ -0,0 +1,72 @@
+require 'test/spec'
+
+require 'rack/showstatus'
+require 'rack/mock'
+
+context "Rack::ShowStatus" do
+ specify "should provide a default status message" do
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
+ }))
+
+ res = req.get("/", :lint => true)
+ res.should.be.not_found
+ res.should.be.not.empty
+
+ res["Content-Type"].should.equal("text/html")
+ res.should =~ /404/
+ res.should =~ /Not Found/
+ end
+
+ specify "should let the app provide additional information" do
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
+ env["rack.showstatus.detail"] = "gone too meta."
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "0"}, []]
+ }))
+
+ res = req.get("/", :lint => true)
+ res.should.be.not_found
+ res.should.be.not.empty
+
+ res["Content-Type"].should.equal("text/html")
+ res.should =~ /404/
+ res.should =~ /Not Found/
+ res.should =~ /too meta/
+ end
+
+ specify "should not replace existing messages" do
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
+ }))
+ res = req.get("/", :lint => true)
+ res.should.be.not_found
+
+ res.body.should == "foo!"
+ end
+
+ specify "should pass on original headers" do
+ headers = {"WWW-Authenticate" => "Basic blah"}
+
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env| [401, headers, []] }))
+ res = req.get("/", :lint => true)
+
+ res["WWW-Authenticate"].should.equal("Basic blah")
+ end
+
+ specify "should replace existing messages if there is detail" do
+ req = Rack::MockRequest.new(Rack::ShowStatus.new(lambda { |env|
+ env["rack.showstatus.detail"] = "gone too meta."
+ [404, {"Content-Type" => "text/plain", "Content-Length" => "4"}, ["foo!"]]
+ }))
+
+ res = req.get("/", :lint => true)
+ res.should.be.not_found
+ res.should.be.not.empty
+
+ res["Content-Type"].should.equal("text/html")
+ res["Content-Length"].should.not.equal("4")
+ res.should =~ /404/
+ res.should =~ /too meta/
+ res.body.should.not =~ /foo/
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_static.rb b/vendor/gems/rack-1.1.0/test/spec_rack_static.rb
new file mode 100644
index 000000000..19d2ecb7e
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_static.rb
@@ -0,0 +1,37 @@
+require 'test/spec'
+
+require 'rack/static'
+require 'rack/mock'
+
+class DummyApp
+ def call(env)
+ [200, {}, ["Hello World"]]
+ end
+end
+
+context "Rack::Static" do
+ root = File.expand_path(File.dirname(__FILE__))
+ OPTIONS = {:urls => ["/cgi"], :root => root}
+
+ setup do
+ @request = Rack::MockRequest.new(Rack::Static.new(DummyApp.new, OPTIONS))
+ end
+
+ specify "serves files" do
+ res = @request.get("/cgi/test")
+ res.should.be.ok
+ res.body.should =~ /ruby/
+ end
+
+ specify "404s if url root is known but it can't find the file" do
+ res = @request.get("/cgi/foo")
+ res.should.be.not_found
+ end
+
+ specify "calls down the chain if url root is not known" do
+ res = @request.get("/something/else")
+ res.should.be.ok
+ res.body.should == "Hello World"
+ end
+
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_thin.rb b/vendor/gems/rack-1.1.0/test/spec_rack_thin.rb
new file mode 100644
index 000000000..324f64986
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_thin.rb
@@ -0,0 +1,91 @@
+require 'test/spec'
+
+begin
+require 'rack/handler/thin'
+require 'testrequest'
+require 'timeout'
+
+context "Rack::Handler::Thin" do
+ include TestRequest::Helpers
+
+ setup do
+ @app = Rack::Lint.new(TestRequest.new)
+ @server = nil
+ Thin::Logging.silent = true
+ @thread = Thread.new do
+ Rack::Handler::Thin.run(@app, :Host => @host='0.0.0.0', :Port => @port=9204) do |server|
+ @server = server
+ end
+ end
+ Thread.pass until @server && @server.running?
+ end
+
+ specify "should respond" do
+ lambda {
+ GET("/")
+ }.should.not.raise
+ end
+
+ specify "should be a Thin" do
+ GET("/")
+ status.should.be 200
+ response["SERVER_SOFTWARE"].should =~ /thin/
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
+ response["SERVER_PORT"].should.equal "9204"
+ response["SERVER_NAME"].should.equal "0.0.0.0"
+ end
+
+ specify "should have rack headers" do
+ GET("/")
+ response["rack.version"].should.equal [0,3]
+ response["rack.multithread"].should.be false
+ response["rack.multiprocess"].should.be false
+ response["rack.run_once"].should.be false
+ end
+
+ specify "should have CGI headers on GET" do
+ GET("/")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.be.equal "/"
+ response["QUERY_STRING"].should.equal ""
+ response["test.postdata"].should.equal ""
+
+ GET("/test/foo?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["REQUEST_PATH"].should.equal "/test/foo"
+ response["PATH_INFO"].should.equal "/test/foo"
+ response["QUERY_STRING"].should.equal "quux=1"
+ end
+
+ specify "should have CGI headers on POST" do
+ POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
+ status.should.equal 200
+ response["REQUEST_METHOD"].should.equal "POST"
+ response["REQUEST_PATH"].should.equal "/"
+ response["QUERY_STRING"].should.equal ""
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
+ response["test.postdata"].should.equal "rack-form-data=23"
+ end
+
+ specify "should support HTTP auth" do
+ GET("/test", {:user => "ruth", :passwd => "secret"})
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
+ end
+
+ specify "should set status" do
+ GET("/test?secret")
+ status.should.equal 403
+ response["rack.url_scheme"].should.equal "http"
+ end
+
+ teardown do
+ @server.stop!
+ @thread.kill
+ end
+end
+
+rescue LoadError
+ $stderr.puts "Skipping Rack::Handler::Thin tests (Thin is required). `gem install thin` and try again."
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_urlmap.rb b/vendor/gems/rack-1.1.0/test/spec_rack_urlmap.rb
new file mode 100644
index 000000000..3d8fe6053
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_urlmap.rb
@@ -0,0 +1,215 @@
+require 'test/spec'
+
+require 'rack/urlmap'
+require 'rack/mock'
+
+context "Rack::URLMap" do
+ specify "dispatches paths correctly" do
+ app = lambda { |env|
+ [200, {
+ 'X-ScriptName' => env['SCRIPT_NAME'],
+ 'X-PathInfo' => env['PATH_INFO'],
+ 'Content-Type' => 'text/plain'
+ }, [""]]
+ }
+ map = Rack::URLMap.new({
+ 'http://foo.org/bar' => app,
+ '/foo' => app,
+ '/foo/bar' => app
+ })
+
+ res = Rack::MockRequest.new(map).get("/")
+ res.should.be.not_found
+
+ res = Rack::MockRequest.new(map).get("/qux")
+ res.should.be.not_found
+
+ res = Rack::MockRequest.new(map).get("/foo")
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo"
+ res["X-PathInfo"].should.equal ""
+
+ res = Rack::MockRequest.new(map).get("/foo/")
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo"
+ res["X-PathInfo"].should.equal "/"
+
+ res = Rack::MockRequest.new(map).get("/foo/bar")
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo/bar"
+ res["X-PathInfo"].should.equal ""
+
+ res = Rack::MockRequest.new(map).get("/foo/bar/")
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo/bar"
+ res["X-PathInfo"].should.equal "/"
+
+ res = Rack::MockRequest.new(map).get("/foo///bar//quux")
+ res.status.should.equal 200
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/foo/bar"
+ res["X-PathInfo"].should.equal "//quux"
+
+ res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/bleh/foo"
+ res["X-PathInfo"].should.equal "/quux"
+
+ res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/bar"
+ res["X-PathInfo"].should.be.empty
+
+ res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
+ res.should.be.ok
+ res["X-ScriptName"].should.equal "/bar"
+ res["X-PathInfo"].should.equal '/'
+ end
+
+
+ specify "dispatches hosts correctly" do
+ map = Rack::URLMap.new("http://foo.org/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "foo.org",
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
+ }, [""]]},
+ "http://subdomain.foo.org/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "subdomain.foo.org",
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
+ }, [""]]},
+ "http://bar.org/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "bar.org",
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
+ }, [""]]},
+ "/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "default.org",
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
+ }, [""]]}
+ )
+
+ res = Rack::MockRequest.new(map).get("/")
+ res.should.be.ok
+ res["X-Position"].should.equal "default.org"
+
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
+ res.should.be.ok
+ res["X-Position"].should.equal "bar.org"
+
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
+ res.should.be.ok
+ res["X-Position"].should.equal "foo.org"
+
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
+ res.should.be.ok
+ res["X-Position"].should.equal "subdomain.foo.org"
+
+ res = Rack::MockRequest.new(map).get("http://foo.org/")
+ res.should.be.ok
+ res["X-Position"].should.equal "default.org"
+
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
+ res.should.be.ok
+ res["X-Position"].should.equal "default.org"
+
+ res = Rack::MockRequest.new(map).get("/",
+ "HTTP_HOST" => "example.org:9292",
+ "SERVER_PORT" => "9292")
+ res.should.be.ok
+ res["X-Position"].should.equal "default.org"
+ end
+
+ specify "should be nestable" do
+ map = Rack::URLMap.new("/foo" =>
+ Rack::URLMap.new("/bar" =>
+ Rack::URLMap.new("/quux" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "/foo/bar/quux",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"],
+ }, [""]]}
+ )))
+
+ res = Rack::MockRequest.new(map).get("/foo/bar")
+ res.should.be.not_found
+
+ res = Rack::MockRequest.new(map).get("/foo/bar/quux")
+ res.should.be.ok
+ res["X-Position"].should.equal "/foo/bar/quux"
+ res["X-PathInfo"].should.equal ""
+ res["X-ScriptName"].should.equal "/foo/bar/quux"
+ end
+
+ specify "should route root apps correctly" do
+ map = Rack::URLMap.new("/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "root",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]},
+ "/foo" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "foo",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]}
+ )
+
+ res = Rack::MockRequest.new(map).get("/foo/bar")
+ res.should.be.ok
+ res["X-Position"].should.equal "foo"
+ res["X-PathInfo"].should.equal "/bar"
+ res["X-ScriptName"].should.equal "/foo"
+
+ res = Rack::MockRequest.new(map).get("/foo")
+ res.should.be.ok
+ res["X-Position"].should.equal "foo"
+ res["X-PathInfo"].should.equal ""
+ res["X-ScriptName"].should.equal "/foo"
+
+ res = Rack::MockRequest.new(map).get("/bar")
+ res.should.be.ok
+ res["X-Position"].should.equal "root"
+ res["X-PathInfo"].should.equal "/bar"
+ res["X-ScriptName"].should.equal ""
+
+ res = Rack::MockRequest.new(map).get("")
+ res.should.be.ok
+ res["X-Position"].should.equal "root"
+ res["X-PathInfo"].should.equal "/"
+ res["X-ScriptName"].should.equal ""
+ end
+
+ specify "should not squeeze slashes" do
+ map = Rack::URLMap.new("/" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "root",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]},
+ "/foo" => lambda { |env|
+ [200,
+ { "Content-Type" => "text/plain",
+ "X-Position" => "foo",
+ "X-PathInfo" => env["PATH_INFO"],
+ "X-ScriptName" => env["SCRIPT_NAME"]
+ }, [""]]}
+ )
+
+ res = Rack::MockRequest.new(map).get("/http://example.org/bar")
+ res.should.be.ok
+ res["X-Position"].should.equal "root"
+ res["X-PathInfo"].should.equal "/http://example.org/bar"
+ res["X-ScriptName"].should.equal ""
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_utils.rb b/vendor/gems/rack-1.1.0/test/spec_rack_utils.rb
new file mode 100644
index 000000000..269a52bdf
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_utils.rb
@@ -0,0 +1,552 @@
+require 'test/spec'
+
+require 'rack/utils'
+require 'rack/lint'
+require 'rack/mock'
+
+context "Rack::Utils" do
+ specify "should escape correctly" do
+ Rack::Utils.escape("fo<o>bar").should.equal "fo%3Co%3Ebar"
+ Rack::Utils.escape("a space").should.equal "a+space"
+ Rack::Utils.escape("q1!2\"'w$5&7/z8)?\\").
+ should.equal "q1%212%22%27w%245%267%2Fz8%29%3F%5C"
+ end
+
+ specify "should escape correctly for multibyte characters" do
+ matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsumoto
+ matz_name.force_encoding("UTF-8") if matz_name.respond_to? :force_encoding
+ Rack::Utils.escape(matz_name).should.equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8'
+ matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8".unpack("a*")[0] # Matsu moto
+ matz_name_sep.force_encoding("UTF-8") if matz_name_sep.respond_to? :force_encoding
+ Rack::Utils.escape(matz_name_sep).should.equal '%E3%81%BE%E3%81%A4+%E3%82%82%E3%81%A8'
+ end
+
+ specify "should unescape correctly" do
+ Rack::Utils.unescape("fo%3Co%3Ebar").should.equal "fo<o>bar"
+ Rack::Utils.unescape("a+space").should.equal "a space"
+ Rack::Utils.unescape("a%20space").should.equal "a space"
+ Rack::Utils.unescape("q1%212%22%27w%245%267%2Fz8%29%3F%5C").
+ should.equal "q1!2\"'w$5&7/z8)?\\"
+ end
+
+ specify "should parse query strings correctly" do
+ Rack::Utils.parse_query("foo=bar").
+ should.equal "foo" => "bar"
+ Rack::Utils.parse_query("foo=\"bar\"").
+ should.equal "foo" => "bar"
+ Rack::Utils.parse_query("foo=bar&foo=quux").
+ should.equal "foo" => ["bar", "quux"]
+ Rack::Utils.parse_query("foo=1&bar=2").
+ should.equal "foo" => "1", "bar" => "2"
+ Rack::Utils.parse_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
+ should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
+ Rack::Utils.parse_query("foo%3Dbaz=bar").should.equal "foo=baz" => "bar"
+ end
+
+ specify "should parse nested query strings correctly" do
+ Rack::Utils.parse_nested_query("foo").
+ should.equal "foo" => nil
+ Rack::Utils.parse_nested_query("foo=").
+ should.equal "foo" => ""
+ Rack::Utils.parse_nested_query("foo=bar").
+ should.equal "foo" => "bar"
+ Rack::Utils.parse_nested_query("foo=\"bar\"").
+ should.equal "foo" => "bar"
+
+ Rack::Utils.parse_nested_query("foo=bar&foo=quux").
+ should.equal "foo" => "quux"
+ Rack::Utils.parse_nested_query("foo&foo=").
+ should.equal "foo" => ""
+ Rack::Utils.parse_nested_query("foo=1&bar=2").
+ should.equal "foo" => "1", "bar" => "2"
+ Rack::Utils.parse_nested_query("&foo=1&&bar=2").
+ should.equal "foo" => "1", "bar" => "2"
+ Rack::Utils.parse_nested_query("foo&bar=").
+ should.equal "foo" => nil, "bar" => ""
+ Rack::Utils.parse_nested_query("foo=bar&baz=").
+ should.equal "foo" => "bar", "baz" => ""
+ Rack::Utils.parse_nested_query("my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F").
+ should.equal "my weird field" => "q1!2\"'w$5&7/z8)?"
+
+ Rack::Utils.parse_nested_query("foo[]").
+ should.equal "foo" => [nil]
+ Rack::Utils.parse_nested_query("foo[]=").
+ should.equal "foo" => [""]
+ Rack::Utils.parse_nested_query("foo[]=bar").
+ should.equal "foo" => ["bar"]
+
+ Rack::Utils.parse_nested_query("foo[]=1&foo[]=2").
+ should.equal "foo" => ["1", "2"]
+ Rack::Utils.parse_nested_query("foo=bar&baz[]=1&baz[]=2&baz[]=3").
+ should.equal "foo" => "bar", "baz" => ["1", "2", "3"]
+ Rack::Utils.parse_nested_query("foo[]=bar&baz[]=1&baz[]=2&baz[]=3").
+ should.equal "foo" => ["bar"], "baz" => ["1", "2", "3"]
+
+ Rack::Utils.parse_nested_query("x[y][z]=1").
+ should.equal "x" => {"y" => {"z" => "1"}}
+ Rack::Utils.parse_nested_query("x[y][z][]=1").
+ should.equal "x" => {"y" => {"z" => ["1"]}}
+ Rack::Utils.parse_nested_query("x[y][z]=1&x[y][z]=2").
+ should.equal "x" => {"y" => {"z" => "2"}}
+ Rack::Utils.parse_nested_query("x[y][z][]=1&x[y][z][]=2").
+ should.equal "x" => {"y" => {"z" => ["1", "2"]}}
+
+ Rack::Utils.parse_nested_query("x[y][][z]=1").
+ should.equal "x" => {"y" => [{"z" => "1"}]}
+ Rack::Utils.parse_nested_query("x[y][][z][]=1").
+ should.equal "x" => {"y" => [{"z" => ["1"]}]}
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=2").
+ should.equal "x" => {"y" => [{"z" => "1", "w" => "2"}]}
+
+ Rack::Utils.parse_nested_query("x[y][][v][w]=1").
+ should.equal "x" => {"y" => [{"v" => {"w" => "1"}}]}
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][v][w]=2").
+ should.equal "x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}
+
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][z]=2").
+ should.equal "x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}
+ Rack::Utils.parse_nested_query("x[y][][z]=1&x[y][][w]=a&x[y][][z]=2&x[y][][w]=3").
+ should.equal "x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}
+
+ lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y]z=2") }.
+ should.raise(TypeError).
+ message.should.equal "expected Hash (got String) for param `y'"
+
+ lambda { Rack::Utils.parse_nested_query("x[y]=1&x[]=1") }.
+ should.raise(TypeError).
+ message.should.equal "expected Array (got Hash) for param `x'"
+
+ lambda { Rack::Utils.parse_nested_query("x[y]=1&x[y][][w]=2") }.
+ should.raise(TypeError).
+ message.should.equal "expected Array (got String) for param `y'"
+ end
+
+ specify "should build query strings correctly" do
+ Rack::Utils.build_query("foo" => "bar").should.equal "foo=bar"
+ Rack::Utils.build_query("foo" => ["bar", "quux"]).
+ should.equal "foo=bar&foo=quux"
+ Rack::Utils.build_query("foo" => "1", "bar" => "2").
+ should.equal "foo=1&bar=2"
+ Rack::Utils.build_query("my weird field" => "q1!2\"'w$5&7/z8)?").
+ should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"
+ end
+
+ specify "should build nested query strings correctly" do
+ Rack::Utils.build_nested_query("foo" => nil).should.equal "foo"
+ Rack::Utils.build_nested_query("foo" => "").should.equal "foo="
+ Rack::Utils.build_nested_query("foo" => "bar").should.equal "foo=bar"
+
+ Rack::Utils.build_nested_query("foo" => "1", "bar" => "2").
+ should.equal "foo=1&bar=2"
+ Rack::Utils.build_nested_query("my weird field" => "q1!2\"'w$5&7/z8)?").
+ should.equal "my+weird+field=q1%212%22%27w%245%267%2Fz8%29%3F"
+
+ Rack::Utils.build_nested_query("foo" => [nil]).
+ should.equal "foo[]"
+ Rack::Utils.build_nested_query("foo" => [""]).
+ should.equal "foo[]="
+ Rack::Utils.build_nested_query("foo" => ["bar"]).
+ should.equal "foo[]=bar"
+
+ # The ordering of the output query string is unpredictable with 1.8's
+ # unordered hash. Test that build_nested_query performs the inverse
+ # function of parse_nested_query.
+ [{"foo" => nil, "bar" => ""},
+ {"foo" => "bar", "baz" => ""},
+ {"foo" => ["1", "2"]},
+ {"foo" => "bar", "baz" => ["1", "2", "3"]},
+ {"foo" => ["bar"], "baz" => ["1", "2", "3"]},
+ {"foo" => ["1", "2"]},
+ {"foo" => "bar", "baz" => ["1", "2", "3"]},
+ {"x" => {"y" => {"z" => "1"}}},
+ {"x" => {"y" => {"z" => ["1"]}}},
+ {"x" => {"y" => {"z" => ["1", "2"]}}},
+ {"x" => {"y" => [{"z" => "1"}]}},
+ {"x" => {"y" => [{"z" => ["1"]}]}},
+ {"x" => {"y" => [{"z" => "1", "w" => "2"}]}},
+ {"x" => {"y" => [{"v" => {"w" => "1"}}]}},
+ {"x" => {"y" => [{"z" => "1", "v" => {"w" => "2"}}]}},
+ {"x" => {"y" => [{"z" => "1"}, {"z" => "2"}]}},
+ {"x" => {"y" => [{"z" => "1", "w" => "a"}, {"z" => "2", "w" => "3"}]}}
+ ].each { |params|
+ qs = Rack::Utils.build_nested_query(params)
+ Rack::Utils.parse_nested_query(qs).should.equal params
+ }
+
+ lambda { Rack::Utils.build_nested_query("foo=bar") }.
+ should.raise(ArgumentError).
+ message.should.equal "value must be a Hash"
+ end
+
+ specify "should figure out which encodings are acceptable" do
+ helper = lambda do |a, b|
+ request = Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => a))
+ Rack::Utils.select_best_encoding(a, b)
+ end
+
+ helper.call(%w(), [["x", 1]]).should.equal(nil)
+ helper.call(%w(identity), [["identity", 0.0]]).should.equal(nil)
+ helper.call(%w(identity), [["*", 0.0]]).should.equal(nil)
+
+ helper.call(%w(identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("identity")
+
+ helper.call(%w(compress gzip identity), [["compress", 1.0], ["gzip", 1.0]]).should.equal("compress")
+ helper.call(%w(compress gzip identity), [["compress", 0.5], ["gzip", 1.0]]).should.equal("gzip")
+
+ helper.call(%w(foo bar identity), []).should.equal("identity")
+ helper.call(%w(foo bar identity), [["*", 1.0]]).should.equal("foo")
+ helper.call(%w(foo bar identity), [["*", 1.0], ["foo", 0.9]]).should.equal("bar")
+
+ helper.call(%w(foo bar identity), [["foo", 0], ["bar", 0]]).should.equal("identity")
+ helper.call(%w(foo bar baz identity), [["*", 0], ["identity", 0.1]]).should.equal("identity")
+ end
+
+ specify "should return the bytesize of String" do
+ Rack::Utils.bytesize("FOO\xE2\x82\xAC").should.equal 6
+ end
+
+ specify "should return status code for integer" do
+ Rack::Utils.status_code(200).should.equal 200
+ end
+
+ specify "should return status code for string" do
+ Rack::Utils.status_code("200").should.equal 200
+ end
+
+ specify "should return status code for symbol" do
+ Rack::Utils.status_code(:ok).should.equal 200
+ end
+end
+
+context "Rack::Utils::HeaderHash" do
+ specify "should retain header case" do
+ h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...")
+ h['ETag'] = 'Boo!'
+ h.to_hash.should.equal "Content-MD5" => "d5ff4e2a0 ...", "ETag" => 'Boo!'
+ end
+
+ specify "should check existence of keys case insensitively" do
+ h = Rack::Utils::HeaderHash.new("Content-MD5" => "d5ff4e2a0 ...")
+ h.should.include 'content-md5'
+ h.should.not.include 'ETag'
+ end
+
+ specify "should merge case-insensitively" do
+ h = Rack::Utils::HeaderHash.new("ETag" => 'HELLO', "content-length" => '123')
+ merged = h.merge("Etag" => 'WORLD', 'Content-Length' => '321', "Foo" => 'BAR')
+ merged.should.equal "Etag"=>'WORLD', "Content-Length"=>'321', "Foo"=>'BAR'
+ end
+
+ specify "should overwrite case insensitively and assume the new key's case" do
+ h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz")
+ h["foo-bar"] = "bizzle"
+ h["FOO-BAR"].should.equal "bizzle"
+ h.length.should.equal 1
+ h.to_hash.should.equal "foo-bar" => "bizzle"
+ end
+
+ specify "should be converted to real Hash" do
+ h = Rack::Utils::HeaderHash.new("foo" => "bar")
+ h.to_hash.should.be.instance_of Hash
+ end
+
+ specify "should convert Array values to Strings when converting to Hash" do
+ h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
+ h.to_hash.should.equal({ "foo" => "bar\nbaz" })
+ end
+
+ specify "should replace hashes correctly" do
+ h = Rack::Utils::HeaderHash.new("Foo-Bar" => "baz")
+ j = {"foo" => "bar"}
+ h.replace(j)
+ h["foo"].should.equal "bar"
+ end
+
+ specify "should be able to delete the given key case-sensitively" do
+ h = Rack::Utils::HeaderHash.new("foo" => "bar")
+ h.delete("foo")
+ h["foo"].should.be.nil
+ h["FOO"].should.be.nil
+ end
+
+ specify "should be able to delete the given key case-insensitively" do
+ h = Rack::Utils::HeaderHash.new("foo" => "bar")
+ h.delete("FOO")
+ h["foo"].should.be.nil
+ h["FOO"].should.be.nil
+ end
+
+ specify "should return the deleted value when #delete is called on an existing key" do
+ h = Rack::Utils::HeaderHash.new("foo" => "bar")
+ h.delete("Foo").should.equal("bar")
+ end
+
+ specify "should return nil when #delete is called on a non-existant key" do
+ h = Rack::Utils::HeaderHash.new("foo" => "bar")
+ h.delete("Hello").should.be.nil
+ end
+
+ specify "should avoid unnecessary object creation if possible" do
+ a = Rack::Utils::HeaderHash.new("foo" => "bar")
+ b = Rack::Utils::HeaderHash.new(a)
+ b.object_id.should.equal(a.object_id)
+ b.should.equal(a)
+ end
+
+ specify "should convert Array values to Strings when responding to #each" do
+ h = Rack::Utils::HeaderHash.new("foo" => ["bar", "baz"])
+ h.each do |k,v|
+ k.should.equal("foo")
+ v.should.equal("bar\nbaz")
+ end
+ end
+
+end
+
+context "Rack::Utils::Context" do
+ class ContextTest
+ attr_reader :app
+ def initialize app; @app=app; end
+ def call env; context env; end
+ def context env, app=@app; app.call(env); end
+ end
+ test_target1 = proc{|e| e.to_s+' world' }
+ test_target2 = proc{|e| e.to_i+2 }
+ test_target3 = proc{|e| nil }
+ test_target4 = proc{|e| [200,{'Content-Type'=>'text/plain', 'Content-Length'=>'0'},['']] }
+ test_app = ContextTest.new test_target4
+
+ specify "should set context correctly" do
+ test_app.app.should.equal test_target4
+ c1 = Rack::Utils::Context.new(test_app, test_target1)
+ c1.for.should.equal test_app
+ c1.app.should.equal test_target1
+ c2 = Rack::Utils::Context.new(test_app, test_target2)
+ c2.for.should.equal test_app
+ c2.app.should.equal test_target2
+ end
+
+ specify "should alter app on recontexting" do
+ c1 = Rack::Utils::Context.new(test_app, test_target1)
+ c2 = c1.recontext(test_target2)
+ c2.for.should.equal test_app
+ c2.app.should.equal test_target2
+ c3 = c2.recontext(test_target3)
+ c3.for.should.equal test_app
+ c3.app.should.equal test_target3
+ end
+
+ specify "should run different apps" do
+ c1 = Rack::Utils::Context.new test_app, test_target1
+ c2 = c1.recontext test_target2
+ c3 = c2.recontext test_target3
+ c4 = c3.recontext test_target4
+ a4 = Rack::Lint.new c4
+ a5 = Rack::Lint.new test_app
+ r1 = c1.call('hello')
+ r1.should.equal 'hello world'
+ r2 = c2.call(2)
+ r2.should.equal 4
+ r3 = c3.call(:misc_symbol)
+ r3.should.be.nil
+ r4 = Rack::MockRequest.new(a4).get('/')
+ r4.status.should.be 200
+ r5 = Rack::MockRequest.new(a5).get('/')
+ r5.status.should.be 200
+ r4.body.should.equal r5.body
+ end
+end
+
+context "Rack::Utils::Multipart" do
+ specify "should return nil if content type is not multipart" do
+ env = Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => 'application/x-www-form-urlencoded')
+ Rack::Utils::Multipart.parse_multipart(env).should.equal nil
+ end
+
+ specify "should parse multipart upload with text file" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:text))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:type].should.equal "text/plain"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"files\"; filename=\"file1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "should parse multipart upload with nested parameters" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:nested))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["foo"]["submit-name"].should.equal "Larry"
+ params["foo"]["files"][:type].should.equal "text/plain"
+ params["foo"]["files"][:filename].should.equal "file1.txt"
+ params["foo"]["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"foo[files]\"; filename=\"file1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n"
+ params["foo"]["files"][:name].should.equal "foo[files]"
+ params["foo"]["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "should parse multipart upload with binary file" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:binary))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:type].should.equal "image/png"
+ params["files"][:filename].should.equal "rack-logo.png"
+ params["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"files\"; filename=\"rack-logo.png\"\r\n" +
+ "Content-Type: image/png\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.length.should.equal 26473
+ end
+
+ specify "should parse multipart upload with empty file" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:empty))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:type].should.equal "text/plain"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"files\"; filename=\"file1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.should.equal ""
+ end
+
+ specify "should parse multipart upload with filename with semicolons" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:semicolon))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["files"][:type].should.equal "text/plain"
+ params["files"][:filename].should.equal "fi;le1.txt"
+ params["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"files\"; filename=\"fi;le1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "should not include file params if no file was selected" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:none))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"].should.equal nil
+ params.keys.should.not.include "files"
+ end
+
+ specify "should parse IE multipart upload and clean up filename" do
+ env = Rack::MockRequest.env_for("/", multipart_fixture(:ie))
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["files"][:type].should.equal "text/plain"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:head].should.equal "Content-Disposition: form-data; " +
+ "name=\"files\"; " +
+ 'filename="C:\Documents and Settings\Administrator\Desktop\file1.txt"' +
+ "\r\nContent-Type: text/plain\r\n"
+ params["files"][:name].should.equal "files"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "rewinds input after parsing upload" do
+ options = multipart_fixture(:text)
+ input = options[:input]
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:filename].should.equal "file1.txt"
+ input.read.length.should.equal 197
+ end
+
+ specify "builds multipart body" do
+ files = Rack::Utils::Multipart::UploadedFile.new(multipart_file("file1.txt"))
+ data = Rack::Utils::Multipart.build_multipart("submit-name" => "Larry", "files" => files)
+
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["submit-name"].should.equal "Larry"
+ params["files"][:filename].should.equal "file1.txt"
+ params["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "builds nested multipart body" do
+ files = Rack::Utils::Multipart::UploadedFile.new(multipart_file("file1.txt"))
+ data = Rack::Utils::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => files}])
+
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+ params["people"][0]["submit-name"].should.equal "Larry"
+ params["people"][0]["files"][:filename].should.equal "file1.txt"
+ params["people"][0]["files"][:tempfile].read.should.equal "contents"
+ end
+
+ specify "can parse fields that end at the end of the buffer" do
+ input = File.read(multipart_file("bad_robots"))
+
+ req = Rack::Request.new Rack::MockRequest.env_for("/",
+ "CONTENT_TYPE" => "multipart/form-data, boundary=1yy3laWhgX31qpiHinh67wJXqKalukEUTvqTzmon",
+ "CONTENT_LENGTH" => input.size,
+ :input => input)
+
+ req.POST['file.path'].should.equal "/var/tmp/uploads/4/0001728414"
+ req.POST['addresses'].should.not.equal nil
+ end
+
+ specify "builds complete params with the chunk size of 16384 slicing exactly on boundary" do
+ data = File.open(multipart_file("fail_16384_nofile")) { |f| f.read }.gsub(/\n/, "\r\n")
+ options = {
+ "CONTENT_TYPE" => "multipart/form-data; boundary=----WebKitFormBoundaryWsY0GnpbI5U7ztzo",
+ "CONTENT_LENGTH" => data.length.to_s,
+ :input => StringIO.new(data)
+ }
+ env = Rack::MockRequest.env_for("/", options)
+ params = Rack::Utils::Multipart.parse_multipart(env)
+
+ params.should.not.equal nil
+ params.keys.should.include "AAAAAAAAAAAAAAAAAAA"
+ params["AAAAAAAAAAAAAAAAAAA"].keys.should.include "PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"].keys.should.include "new"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"].keys.should.include "-2"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"].keys.should.include "ba_unit_id"
+ params["AAAAAAAAAAAAAAAAAAA"]["PLAPLAPLA_MEMMEMMEMM_ATTRATTRER"]["new"]["-2"]["ba_unit_id"].should.equal "1017"
+ end
+
+ specify "should return nil if no UploadedFiles were used" do
+ data = Rack::Utils::Multipart.build_multipart("people" => [{"submit-name" => "Larry", "files" => "contents"}])
+ data.should.equal nil
+ end
+
+ specify "should raise ArgumentError if params is not a Hash" do
+ lambda { Rack::Utils::Multipart.build_multipart("foo=bar") }.
+ should.raise(ArgumentError).
+ message.should.equal "value must be a Hash"
+ end
+
+ private
+ def multipart_fixture(name)
+ file = multipart_file(name)
+ data = File.open(file, 'rb') { |io| io.read }
+
+ type = "multipart/form-data; boundary=AaB03x"
+ length = data.respond_to?(:bytesize) ? data.bytesize : data.size
+
+ { "CONTENT_TYPE" => type,
+ "CONTENT_LENGTH" => length.to_s,
+ :input => StringIO.new(data) }
+ end
+
+ def multipart_file(name)
+ File.join(File.dirname(__FILE__), "multipart", name.to_s)
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rack_webrick.rb b/vendor/gems/rack-1.1.0/test/spec_rack_webrick.rb
new file mode 100644
index 000000000..599425c4f
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rack_webrick.rb
@@ -0,0 +1,130 @@
+require 'test/spec'
+
+require 'rack/handler/webrick'
+require 'rack/lint'
+require 'rack/response'
+require 'testrequest'
+
+Thread.abort_on_exception = true
+
+context "Rack::Handler::WEBrick" do
+ include TestRequest::Helpers
+
+ setup do
+ @server = WEBrick::HTTPServer.new(:Host => @host='0.0.0.0',
+ :Port => @port=9202,
+ :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN),
+ :AccessLog => [])
+ @server.mount "/test", Rack::Handler::WEBrick,
+ Rack::Lint.new(TestRequest.new)
+ Thread.new { @server.start }
+ trap(:INT) { @server.shutdown }
+ end
+
+ specify "should respond" do
+ lambda {
+ GET("/test")
+ }.should.not.raise
+ end
+
+ specify "should be a WEBrick" do
+ GET("/test")
+ status.should.be 200
+ response["SERVER_SOFTWARE"].should =~ /WEBrick/
+ response["HTTP_VERSION"].should.equal "HTTP/1.1"
+ response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
+ response["SERVER_PORT"].should.equal "9202"
+ response["SERVER_NAME"].should.equal "0.0.0.0"
+ end
+
+ specify "should have rack headers" do
+ GET("/test")
+ response["rack.version"].should.equal [1,1]
+ response["rack.multithread"].should.be true
+ response["rack.multiprocess"].should.be false
+ response["rack.run_once"].should.be false
+ end
+
+ specify "should have CGI headers on GET" do
+ GET("/test")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.be.equal ""
+ response["QUERY_STRING"].should.equal ""
+ response["test.postdata"].should.equal ""
+
+ GET("/test/foo?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal "/foo"
+ response["QUERY_STRING"].should.equal "quux=1"
+
+ GET("/test/foo%25encoding?quux=1")
+ response["REQUEST_METHOD"].should.equal "GET"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["PATH_INFO"].should.equal "/foo%25encoding"
+ response["QUERY_STRING"].should.equal "quux=1"
+ end
+
+ specify "should have CGI headers on POST" do
+ POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
+ status.should.equal 200
+ response["REQUEST_METHOD"].should.equal "POST"
+ response["SCRIPT_NAME"].should.equal "/test"
+ response["REQUEST_PATH"].should.equal "/"
+ response["QUERY_STRING"].should.equal ""
+ response["HTTP_X_TEST_HEADER"].should.equal "42"
+ response["test.postdata"].should.equal "rack-form-data=23"
+ end
+
+ specify "should support HTTP auth" do
+ GET("/test", {:user => "ruth", :passwd => "secret"})
+ response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
+ end
+
+ specify "should set status" do
+ GET("/test?secret")
+ status.should.equal 403
+ response["rack.url_scheme"].should.equal "http"
+ end
+
+ specify "should correctly set cookies" do
+ @server.mount "/cookie-test", Rack::Handler::WEBrick,
+ Rack::Lint.new(lambda { |req|
+ res = Rack::Response.new
+ res.set_cookie "one", "1"
+ res.set_cookie "two", "2"
+ res.finish
+ })
+
+ Net::HTTP.start(@host, @port) { |http|
+ res = http.get("/cookie-test")
+ res.code.to_i.should.equal 200
+ res.get_fields("set-cookie").should.equal ["one=1", "two=2"]
+ }
+ end
+
+ specify "should provide a .run" do
+ block_ran = false
+ catch(:done) {
+ Rack::Handler::WEBrick.run(lambda {},
+ {:Port => 9210,
+ :Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN),
+ :AccessLog => []}) { |server|
+ block_ran = true
+ server.should.be.kind_of WEBrick::HTTPServer
+ @s = server
+ throw :done
+ }
+ }
+ block_ran.should.be true
+ @s.shutdown
+ end
+
+ teardown do
+ @server.shutdown
+ end
+end
diff --git a/vendor/gems/rack-1.1.0/test/spec_rackup.rb b/vendor/gems/rack-1.1.0/test/spec_rackup.rb
new file mode 100644
index 000000000..d9926fda0
--- /dev/null
+++ b/vendor/gems/rack-1.1.0/test/spec_rackup.rb
@@ -0,0 +1,154 @@
+require 'test/spec'
+require 'testrequest'
+require 'rack/server'
+require 'open3'
+
+begin
+require "mongrel"
+
+context "rackup" do
+ include TestRequest::Helpers
+
+ def run_rackup(*args)
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ flags = args.first
+ @host = options[:host] || "0.0.0.0"
+ @port = options[:port] || 9292
+
+ Dir.chdir("#{root}/test/rackup") do
+ @in, @rackup, @err = Open3.popen3("#{Gem.ruby} -S #{rackup} #{flags}")
+ end
+
+ return if options[:port] == false
+
+ # Wait until the server is available
+ begin
+ GET("/")
+ rescue
+ sleep 0.05
+ retry
+ end
+ end
+
+ def output
+ @rackup.read
+ end
+
+ after do
+ # This doesn't actually return a response, so we rescue
+ GET "/die" rescue nil
+
+ Dir["#{root}/**/*.pid"].each do |file|
+ File.delete(file)
+ end
+
+ File.delete("#{root}/log_output") if File.exist?("#{root}/log_output")
+ end
+
+ specify "rackup" do
+ run_rackup
+ response["PATH_INFO"].should.equal '/'
+ response["test.$DEBUG"].should.be false
+ response["test.$EVAL"].should.be nil
+ response["test.$VERBOSE"].should.be false
+ response["test.Ping"].should.be nil
+ response["SERVER_SOFTWARE"].should.not =~ /webrick/
+ end
+
+ specify "rackup --help" do
+ run_rackup "--help", :port => false
+ output.should.match /--port/
+ end
+
+ specify "rackup --port" do
+ run_rackup "--port 9000", :port => 9000
+ response["SERVER_PORT"].should.equal "9000"
+ end
+
+ specify "rackup --debug" do
+ run_rackup "--debug"
+ response["test.$DEBUG"].should.be true
+ end
+
+ specify "rackup --eval" do
+ run_rackup %{--eval "BUKKIT = 'BUKKIT'"}
+ response["test.$EVAL"].should.equal "BUKKIT"
+ end
+
+ specify "rackup --warn" do
+ run_rackup %{--warn}
+ response["test.$VERBOSE"].should.be true
+ end
+
+ specify "rackup --include" do
+ run_rackup %{--include /foo/bar}
+ response["test.$LOAD_PATH"].should.include "/foo/bar"
+ end
+
+ specify "rackup --require" do
+ run_rackup %{--require ping}
+ response["test.Ping"].should.equal "constant"
+ end
+
+ specify "rackup --server" do
+ run_rackup %{--server webrick}
+ response["SERVER_SOFTWARE"].should =~ /webrick/i
+ end
+
+ specify "rackup --host" do
+ run_rackup %{--host 127.0.0.1}, :host => "127.0.0.1"
+ response["REMOTE_ADDR"].should.equal "127.0.0.1"
+ end
+
+ specify "rackup --daemonize --pid" do
+ run_rackup %{--daemonize --pid testing.pid}
+ status.should.be 200
+ @rackup.should.be.eof?
+ Dir["#{root}/**/testing.pid"].should.not.be.empty?
+ end
+
+ specify "rackup --pid" do
+ run_rackup %{--pid testing.pid}
+ status.should.be 200
+ Dir["#{root}/**/testing.pid"].should.not.be.empty?
+ end
+
+ specify "rackup --version" do
+ run_rackup %{--version}, :port => false
+ output.should =~ /1.0/
+ end
+
+ specify "rackup --env development includes lint" do
+ run_rackup
+ GET("/broken_lint")
+ status.should.be 500
+ end
+
+ specify "rackup --env deployment does not include lint" do
+ run_rackup %{--env deployment}
+ GET("/broken_lint")
+ status.should.be 200
+ end
+
+ specify "rackup --env none does not include lint" do
+ run_rackup %{--env none}
+ GET("/broken_lint")
+ status.should.be 200
+ end
+
+ specify "rackup --env deployment does log" do
+ run_rackup %{--env deployment}
+ log = File.read(response["test.stderr"])
+ log.should.be.empty?
+ end
+
+ specify "rackup --env none does not log" do
+ run_rackup %{--env none}
+ GET("/")
+ log = File.read(response["test.stderr"])
+ log.should.be.empty?
+ end
+end
+rescue LoadError
+ $stderr.puts "Skipping rackup --server tests (mongrel is required). `gem install thin` and try again."
+end \ No newline at end of file