<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>compat/app_test.rb</filename>
    </added>
    <added>
      <filename>compat/application_test.rb</filename>
    </added>
    <added>
      <filename>compat/builder_test.rb</filename>
    </added>
    <added>
      <filename>compat/custom_error_test.rb</filename>
    </added>
    <added>
      <filename>compat/erb_test.rb</filename>
    </added>
    <added>
      <filename>compat/events_test.rb</filename>
    </added>
    <added>
      <filename>compat/filter_test.rb</filename>
    </added>
    <added>
      <filename>compat/haml_test.rb</filename>
    </added>
    <added>
      <filename>compat/helper.rb</filename>
    </added>
    <added>
      <filename>compat/mapped_error_test.rb</filename>
    </added>
    <added>
      <filename>compat/pipeline_test.rb</filename>
    </added>
    <added>
      <filename>compat/public/foo.xml</filename>
    </added>
    <added>
      <filename>compat/sass_test.rb</filename>
    </added>
    <added>
      <filename>compat/sessions_test.rb</filename>
    </added>
    <added>
      <filename>compat/streaming_test.rb</filename>
    </added>
    <added>
      <filename>compat/sym_params_test.rb</filename>
    </added>
    <added>
      <filename>compat/template_test.rb</filename>
    </added>
    <added>
      <filename>compat/use_in_file_templates_test.rb</filename>
    </added>
    <added>
      <filename>compat/views/foo.builder</filename>
    </added>
    <added>
      <filename>compat/views/foo.erb</filename>
    </added>
    <added>
      <filename>compat/views/foo.haml</filename>
    </added>
    <added>
      <filename>compat/views/foo.sass</filename>
    </added>
    <added>
      <filename>compat/views/foo_layout.erb</filename>
    </added>
    <added>
      <filename>compat/views/foo_layout.haml</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/foo.builder</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/foo.erb</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/foo.haml</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/foo.sass</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/layout.builder</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/layout.erb</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/layout.haml</filename>
    </added>
    <added>
      <filename>compat/views/layout_test/layout.sass</filename>
    </added>
    <added>
      <filename>compat/views/no_layout/no_layout.builder</filename>
    </added>
    <added>
      <filename>compat/views/no_layout/no_layout.haml</filename>
    </added>
    <added>
      <filename>lib/sinatra/base.rb</filename>
    </added>
    <added>
      <filename>lib/sinatra/compat.rb</filename>
    </added>
    <added>
      <filename>lib/sinatra/images/404.png</filename>
    </added>
    <added>
      <filename>lib/sinatra/images/500.png</filename>
    </added>
    <added>
      <filename>lib/sinatra/main.rb</filename>
    </added>
    <added>
      <filename>lib/sinatra/rack/methodoverride.rb</filename>
    </added>
    <added>
      <filename>lib/sinatra/test.rb</filename>
    </added>
    <added>
      <filename>test/base_test.rb</filename>
    </added>
    <added>
      <filename>test/data/reload_app_file.rb</filename>
    </added>
    <added>
      <filename>test/helpers_test.rb</filename>
    </added>
    <added>
      <filename>test/middleware_test.rb</filename>
    </added>
    <added>
      <filename>test/options_test.rb</filename>
    </added>
    <added>
      <filename>test/reload_test.rb</filename>
    </added>
    <added>
      <filename>test/request_test.rb</filename>
    </added>
    <added>
      <filename>test/result_test.rb</filename>
    </added>
    <added>
      <filename>test/routing_test.rb</filename>
    </added>
    <added>
      <filename>test/sinatra_test.rb</filename>
    </added>
    <added>
      <filename>test/static_test.rb</filename>
    </added>
    <added>
      <filename>test/templates_test.rb</filename>
    </added>
    <added>
      <filename>test/views/hello.builder</filename>
    </added>
    <added>
      <filename>test/views/hello.erb</filename>
    </added>
    <added>
      <filename>test/views/hello.haml</filename>
    </added>
    <added>
      <filename>test/views/hello.sass</filename>
    </added>
    <added>
      <filename>test/views/hello.test</filename>
    </added>
    <added>
      <filename>test/views/layout2.builder</filename>
    </added>
    <added>
      <filename>test/views/layout2.erb</filename>
    </added>
    <added>
      <filename>test/views/layout2.haml</filename>
    </added>
    <added>
      <filename>test/views/layout2.test</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -36,16 +36,12 @@ Run with &lt;tt&gt;ruby myapp.rb&lt;/tt&gt; and view at &lt;tt&gt;http://localhost:4567&lt;/tt&gt;
 
   end
 
-NOTE: &lt;tt&gt;put&lt;/tt&gt; and &lt;tt&gt;delete&lt;/tt&gt; are also triggered when a
-&lt;tt&gt;_method&lt;/tt&gt; parameter is set to PUT or DELETE and the HTTP request method
-is POST
-
 == Routes
 
 Routes are matched based on the order of declaration. The first route that
 matches the request is invoked.
 
-Simple:
+Basic routes:
 
   get '/hi' do
     ...
@@ -54,19 +50,20 @@ Simple:
 Named parameters:
 
   get '/:name' do
-    # matches /sinatra and the like and sets params[:name]
+    # matches &quot;GET /foo&quot; and &quot;GET /bar&quot;
+    # params[:name] is 'foo' or 'bar'
   end
 
 Splat parameters:
 
   get '/say/*/to/*' do
     # matches /say/hello/to/world
-    params[&quot;splat&quot;] # =&gt; [&quot;hello&quot;, &quot;world&quot;]
+    params[:splat] # =&gt; [&quot;hello&quot;, &quot;world&quot;]
   end
 
   get '/download/*.*' do
     # matches /download/path/to/file.xml
-    params[&quot;splat&quot;] # =&gt; [&quot;path/to/file&quot;, &quot;xml&quot;]
+    params[:splat] # =&gt; [&quot;path/to/file&quot;, &quot;xml&quot;]
   end
 
 User agent matching:
@@ -76,25 +73,29 @@ User agent matching:
   end
 
   get '/foo' do
-    # matches non-songbird browsers
+    # Matches non-songbird browsers
   end
 
-== Static files
+== Static Files
 
 Put all of your static content in the ./public directory
 
   root
     \ public
 
-If a file exists that maps to the REQUEST_PATH then it is served and the
-request ends. Otherwise, Sinatra will look for an event that matches the
-path.
+To use a different static directory:
+
+  set :public, File.dirname(__FILE__) + '/static'
 
 == Views
 
-Views are searched for in a &quot;views&quot; directory in the same location as
+Views are searched for in a ./views directory in the same location as
 your main application.
 
+To use a different views directory:
+
+  set :views, File.dirname(__FILE__) + '/templates'
+
 === Haml Templates
 
   get '/' do
@@ -190,8 +191,7 @@ method:
 
 == Helpers
 
-The top-level &lt;tt&gt;helpers&lt;/tt&gt; method takes a block and extends all
-EventContext instances with the methods defined:
+The top-level &lt;tt&gt;helpers&lt;/tt&gt; method
 
   helpers do
     def bar(name)
@@ -205,27 +205,27 @@ EventContext instances with the methods defined:
 
 == Filters
 
-These are run in Sinatra::EventContext before every event.
+Before filters are evaluated in request context before routing is performed:
 
   before do
-    .. this code will run before each event ..
+    @note = 'Hi!'
+    request.path_info = '/foo/bar/baz'
+  end
+
+  get '/foo/*' do
+    @note #=&gt; 'Hi!'
+    params[:splat] #=&gt; 'bar/baz'
   end
 
+Before filters can modify the request and response; instance variables are
+available to routes.
+
 == Halt!
 
 To immediately stop a request during a before filter or event use:
 
   throw :halt
 
-Set the body to the result of a helper method
-
-  throw :halt, :helper_method
-
-Set the body to the result of a helper method after sending it parameters from
-the local scope
-
-  throw :halt, [:helper_method, foo, bar]
-
 Set the body to a simple string
 
   throw :halt, 'this will be the body'
@@ -234,30 +234,11 @@ Set status then the body
 
   throw :halt, [401, 'go away!']
 
-Set the status then call a helper method with params from local scope
-
-  throw :halt, [401, [:helper_method, foo, bar]]
-
 Run a proc inside the Sinatra::EventContext instance and set the body to the
 result
 
   throw :halt, lambda { puts 'In a proc!'; 'I just wrote to $stdout!' }
 
-Create you own to_result
-
-  class MyResultObject
-    def to_result(event_context, *args)
-      event_context.body = 'This will be the body!
-    end
-  end
-
-  get '/' do
-    throw :halt, MyResultObject.new
-  end
-
-Get the gist?  If you want more fun with this then checkout &lt;tt&gt;to_result&lt;/tt&gt;
-on Array, Symbol, Fixnum, NilClass.
-
 == Configuration and Reloading
 
 Sinatra supports multiple environments and reloading. Reloading happens</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -8,13 +8,19 @@ task :default =&gt; :test
 
 desc 'Run specs with story style output'
 task :spec do
-  sh 'specrb --specdox -Ilib:test test/*_test.rb'
+  pattern = ENV['TEST'] || '.*'
+  sh &quot;specrb --testcase '#{pattern}' --specdox -Ilib:test test/*_test.rb&quot;
 end
 
 desc 'Run specs with unit test style output'
-task :test =&gt; FileList['test/*_test.rb'] do |t|
-  suite = t.prerequisites.map{|f| &quot;-r#{f.chomp('.rb')}&quot;}.join(' ')
-  sh &quot;ruby -Ilib:test #{suite} -e ''&quot;, :verbose =&gt; false
+task :test do |t|
+  sh &quot;specrb -Ilib:test test/*_test.rb&quot;
+end
+
+desc 'Run compatibility specs'
+task :compat do |t|
+  pattern = ENV['TEST'] || '.*'
+  sh &quot;specrb --testcase '#{pattern}' -Ilib:test compat/*_test.rb&quot;
 end
 
 # PACKAGING ============================================================</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,1486 +1,3 @@
-require 'time'
-require 'ostruct'
-require 'uri'
-require 'rack'
-
-if ENV['SWIFT']
- require 'swiftcore/swiftiplied_mongrel'
- puts &quot;Using Swiftiplied Mongrel&quot;
-elsif ENV['EVENT']
-  require 'swiftcore/evented_mongrel'
-  puts &quot;Using Evented Mongrel&quot;
-end
-
-unless defined?(Rack::File::MIME_TYPES)
-  class Rack::File; MIME_TYPES = Rack::Mime::MIME_TYPES; end
-end
-
-module Rack #:nodoc:
-
-  class Request #:nodoc:
-
-    # Set of request method names allowed via the _method parameter hack. By
-    # default, all request methods defined in RFC2616 are included, with the
-    # exception of TRACE and CONNECT.
-    POST_TUNNEL_METHODS_ALLOWED = %w( PUT DELETE OPTIONS HEAD )
-
-    # Return the HTTP request method with support for method tunneling using
-    # the POST _method parameter hack. If the real request method is POST and
-    # a _method param is given and the value is one defined in
-    # +POST_TUNNEL_METHODS_ALLOWED+, return the value of the _method param
-    # instead.
-    def request_method
-      if post_tunnel_method_hack?
-        params['_method'].upcase
-      else
-        @env['REQUEST_METHOD']
-      end
-    end
-
-    def user_agent
-      @env['HTTP_USER_AGENT']
-    end
-
-  private
-
-    # Return truthfully if the request is a valid verb-over-post hack.
-    def post_tunnel_method_hack?
-      @env['REQUEST_METHOD'] == 'POST' &amp;&amp;
-        POST_TUNNEL_METHODS_ALLOWED.include?(self.POST.fetch('_method', '').upcase)
-    end
-  end
-
-  module Utils
-    extend self
-  end
-end
-
-
-module Sinatra
-  extend self
-
-  VERSION = '0.3.2'
-
-  class NotFound &lt; RuntimeError
-    def self.code ; 404 ; end
-  end
-  class ServerError &lt; RuntimeError
-    def self.code ; 500 ; end
-  end
-
-  Result = Struct.new(:block, :params, :status) unless defined?(Result)
-
-  def options
-    application.options
-  end
-
-  def application
-    @app ||= Application.new
-  end
-
-  def application=(app)
-    @app = app
-  end
-
-  def port
-    application.options.port
-  end
-
-  def host
-    application.options.host
-  end
-
-  def env
-    application.options.env
-  end
-
-  # Deprecated: use application instead of build_application.
-  alias :build_application :application
-
-  def server
-    options.server ||= defined?(Rack::Handler::Thin) ? &quot;thin&quot; : &quot;mongrel&quot;
-
-    # Convert the server into the actual handler name
-    handler = options.server.capitalize
-
-    # If the convenience conversion didn't get us anything,
-    # fall back to what the user actually set.
-    handler = options.server unless Rack::Handler.const_defined?(handler)
-
-    @server ||= eval(&quot;Rack::Handler::#{handler}&quot;)
-  end
-
-  def run
-    begin
-      puts &quot;== Sinatra/#{Sinatra::VERSION} has taken the stage on port #{port} for #{env} with backup by #{server.name}&quot;
-      server.run(application, {:Port =&gt; port, :Host =&gt; host}) do |server|
-        trap(:INT) do
-          server.stop
-          puts &quot;\n== Sinatra has ended his set (crowd applauds)&quot;
-        end
-      end
-    rescue Errno::EADDRINUSE =&gt; e
-      puts &quot;== Someone is already performing on port #{port}!&quot;
-    end
-  end
-
-  class Event
-    include Rack::Utils
-
-    URI_CHAR = '[^/?:,&amp;#\.]'.freeze unless defined?(URI_CHAR)
-    PARAM = /(:(#{URI_CHAR}+)|\*)/.freeze unless defined?(PARAM)
-    SPLAT = /(.*?)/
-    attr_reader :path, :block, :param_keys, :pattern, :options
-
-    def initialize(path, options = {}, &amp;b)
-      @path = URI.encode(path)
-      @block = b
-      @param_keys = []
-      @options = options
-      splats = 0
-      regex = @path.to_s.gsub(PARAM) do |match|
-        if match == &quot;*&quot;
-          @param_keys &lt;&lt; &quot;_splat_#{splats}&quot;
-          splats += 1
-          SPLAT.to_s
-        else
-          @param_keys &lt;&lt; $2
-          &quot;(#{URI_CHAR}+)&quot;
-        end
-      end
-
-      @pattern = /^#{regex}$/
-    end
-
-    def invoke(request)
-      params = {}
-      if agent = options[:agent]
-        return unless request.user_agent =~ agent
-        params[:agent] = $~[1..-1]
-      end
-      if host = options[:host]
-        return unless host === request.host
-      end
-      return unless pattern =~ request.path_info.squeeze('/')
-      path_params = param_keys.zip($~.captures.map{|s| unescape(s) if s}).to_hash
-      params.merge!(path_params)
-      splats = params.select { |k, v| k =~ /^_splat_\d+$/ }.sort.map(&amp;:last)
-      unless splats.empty?
-        params.delete_if { |k, v| k =~ /^_splat_\d+$/ }
-        params[&quot;splat&quot;] = splats
-      end
-      Result.new(block, params, 200)
-    end
-
-  end
-
-  class Error
-
-    attr_reader :type, :block, :options
-
-    def initialize(type, options={}, &amp;block)
-      @type = type
-      @block = block
-      @options = options
-    end
-
-    def invoke(request)
-      Result.new(block, options, code)
-    end
-
-    def code
-      if type.respond_to?(:code)
-        type.code
-      else
-        500
-      end
-    end
-
-  end
-
-  class Static
-    include Rack::Utils
-
-    def initialize(app)
-      @app = app
-    end
-
-    def invoke(request)
-      path = @app.options.public + unescape(request.path_info)
-      return unless File.file?(path)
-      block = Proc.new { send_file path, :disposition =&gt; nil }
-      Result.new(block, {}, 200)
-    end
-  end
-
-  # Methods for sending files and streams to the browser instead of rendering.
-  module Streaming
-    DEFAULT_SEND_FILE_OPTIONS = {
-      :type         =&gt; 'application/octet-stream'.freeze,
-      :disposition  =&gt; 'attachment'.freeze,
-      :stream       =&gt; true,
-      :buffer_size  =&gt; 8192
-    }.freeze
-
-    class MissingFile &lt; RuntimeError; end
-
-    class FileStreamer
-      attr_reader :path, :options
-
-      def initialize(path, options)
-        @path, @options = path, options
-      end
-
-      def to_result(cx, *args)
-        self
-      end
-
-      def each
-        size = options[:buffer_size]
-        File.open(path, 'rb') do |file|
-          while buf = file.read(size)
-            yield buf
-          end
-        end
-      end
-    end
-
-  protected
-    # Sends the file by streaming it 8192 bytes at a time. This way the
-    # whole file doesn't need to be read into memory at once.  This makes
-    # it feasible to send even large files.
-    #
-    # Be careful to sanitize the path parameter if it coming from a web
-    # page.  send_file(params[:path]) allows a malicious user to
-    # download any file on your server.
-    #
-    # Options:
-    # * &lt;tt&gt;:filename&lt;/tt&gt; - suggests a filename for the browser to use.
-    #   Defaults to File.basename(path).
-    # * &lt;tt&gt;:type&lt;/tt&gt; - specifies an HTTP content type.
-    #   Defaults to 'application/octet-stream'.
-    # * &lt;tt&gt;:disposition&lt;/tt&gt; - specifies whether the file will be shown
-    #   inline or downloaded. Valid values are 'inline' and 'attachment'
-    #   (default). When set to nil, the Content-Disposition and
-    #   Content-Transfer-Encoding headers are omitted entirely.
-    # * &lt;tt&gt;:stream&lt;/tt&gt; - whether to send the file to the user agent as it
-    #   is read (true) or to read the entire file before sending (false).
-    #   Defaults to true.
-    # * &lt;tt&gt;:buffer_size&lt;/tt&gt; - specifies size (in bytes) of the buffer used
-    #   to stream the file. Defaults to 8192.
-    # * &lt;tt&gt;:status&lt;/tt&gt; - specifies the status code to send with the
-    #   response. Defaults to '200 OK'.
-    # * &lt;tt&gt;:last_modified&lt;/tt&gt; - an optional RFC 2616 formatted date value
-    #   (See Time#httpdate) indicating the last modified time of the file.
-    #   If the request includes an If-Modified-Since header that matches this
-    #   value exactly, a 304 Not Modified response is sent instead of the file.
-    #   Defaults to the file's last modified time.
-    #
-    # The default Content-Type and Content-Disposition headers are
-    # set to download arbitrary binary files in as many browsers as
-    # possible.  IE versions 4, 5, 5.5, and 6 are all known to have
-    # a variety of quirks (especially when downloading over SSL).
-    #
-    # Simple download:
-    #   send_file '/path/to.zip'
-    #
-    # Show a JPEG in the browser:
-    #   send_file '/path/to.jpeg',
-    #     :type =&gt; 'image/jpeg',
-    #     :disposition =&gt; 'inline'
-    #
-    # Show a 404 page in the browser:
-    #   send_file '/path/to/404.html,
-    #     :type =&gt; 'text/html; charset=utf-8',
-    #     :status =&gt; 404
-    #
-    # Read about the other Content-* HTTP headers if you'd like to
-    # provide the user with more information (such as Content-Description).
-    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
-    #
-    # Also be aware that the document may be cached by proxies and browsers.
-    # The Pragma and Cache-Control headers declare how the file may be cached
-    # by intermediaries.  They default to require clients to validate with
-    # the server before releasing cached responses.  See
-    # http://www.mnot.net/cache_docs/ for an overview of web caching and
-    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
-    # for the Cache-Control header spec.
-    def send_file(path, options = {}) #:doc:
-      raise MissingFile, &quot;Cannot read file #{path}&quot; unless File.file?(path) and File.readable?(path)
-
-      options[:length]   ||= File.size(path)
-      options[:filename] ||= File.basename(path)
-      options[:type] ||= Rack::File::MIME_TYPES[File.extname(options[:filename])[1..-1]] || 'text/plain'
-      options[:last_modified] ||= File.mtime(path).httpdate
-      options[:stream] = true unless options.key?(:stream)
-      options[:buffer_size] ||= DEFAULT_SEND_FILE_OPTIONS[:buffer_size]
-      send_file_headers! options
-
-      if options[:stream]
-        throw :halt, [options[:status] || 200, FileStreamer.new(path, options)]
-      else
-        File.open(path, 'rb') { |file| throw :halt, [options[:status] || 200, [file.read]] }
-      end
-    end
-
-    # Send binary data to the user as a file download. May set content type,
-    # apparent file name, and specify whether to show data inline or download
-    # as an attachment.
-    #
-    # Options:
-    # * &lt;tt&gt;:filename&lt;/tt&gt; - Suggests a filename for the browser to use.
-    # * &lt;tt&gt;:type&lt;/tt&gt; - specifies an HTTP content type.
-    #   Defaults to 'application/octet-stream'.
-    # * &lt;tt&gt;:disposition&lt;/tt&gt; - specifies whether the file will be shown inline
-    #   or downloaded. Valid values are 'inline' and 'attachment' (default).
-    # * &lt;tt&gt;:status&lt;/tt&gt; - specifies the status code to send with the response.
-    #   Defaults to '200 OK'.
-    # * &lt;tt&gt;:last_modified&lt;/tt&gt; - an optional RFC 2616 formatted date value (See
-    #   Time#httpdate) indicating the last modified time of the response entity.
-    #   If the request includes an If-Modified-Since header that matches this
-    #   value exactly, a 304 Not Modified response is sent instead of the data.
-    #
-    # Generic data download:
-    #   send_data buffer
-    #
-    # Download a dynamically-generated tarball:
-    #   send_data generate_tgz('dir'), :filename =&gt; 'dir.tgz'
-    #
-    # Display an image Active Record in the browser:
-    #   send_data image.data,
-    #     :type =&gt; image.content_type,
-    #     :disposition =&gt; 'inline'
-    #
-    # See +send_file+ for more information on HTTP Content-* headers and caching.
-    def send_data(data, options = {}) #:doc:
-      send_file_headers! options.merge(:length =&gt; data.size)
-      throw :halt, [options[:status] || 200, [data]]
-    end
-
-  private
-
-    def send_file_headers!(options)
-      options = DEFAULT_SEND_FILE_OPTIONS.merge(options)
-      [:length, :type, :disposition].each do |arg|
-        raise ArgumentError, &quot;:#{arg} option required&quot; unless options.key?(arg)
-      end
-
-      # Send a &quot;304 Not Modified&quot; if the last_modified option is provided and
-      # matches the If-Modified-Since request header value.
-      if last_modified = options[:last_modified]
-        header 'Last-Modified' =&gt; last_modified
-        throw :halt, [ 304, '' ] if last_modified == request.env['HTTP_IF_MODIFIED_SINCE']
-      end
-
-      headers(
-        'Content-Length'            =&gt; options[:length].to_s,
-        'Content-Type'              =&gt; options[:type].strip  # fixes a problem with extra '\r' with some browsers
-      )
-
-      # Omit Content-Disposition and Content-Transfer-Encoding headers if
-      # the :disposition option set to nil.
-      if !options[:disposition].nil?
-        disposition = options[:disposition].dup || 'attachment'
-        disposition &lt;&lt;= %(; filename=&quot;#{options[:filename]}&quot;) if options[:filename]
-        headers 'Content-Disposition' =&gt; disposition, 'Content-Transfer-Encoding' =&gt; 'binary'
-      end
-
-      # Fix a problem with IE 6.0 on opening downloaded files:
-      # If Cache-Control: no-cache is set (which Rails does by default),
-      # IE removes the file it just downloaded from its cache immediately
-      # after it displays the &quot;open/save&quot; dialog, which means that if you
-      # hit &quot;open&quot; the file isn't there anymore when the application that
-      # is called for handling the download is run, so let's workaround that
-      header('Cache-Control' =&gt; 'private') if headers['Cache-Control'] == 'no-cache'
-    end
-  end
-
-
-  # Helper methods for building various aspects of the HTTP response.
-  module ResponseHelpers
-
-    # Immediately halt response execution by redirecting to the resource
-    # specified. The +path+ argument may be an absolute URL or a path
-    # relative to the site root. Additional arguments are passed to the
-    # halt.
-    #
-    # With no integer status code, a '302 Temporary Redirect' response is
-    # sent. To send a permanent redirect, pass an explicit status code of
-    # 301:
-    #
-    #   redirect '/somewhere/else', 301
-    #
-    # NOTE: No attempt is made to rewrite the path based on application
-    # context. The 'Location' response header is set verbatim to the value
-    # provided.
-    def redirect(path, *args)
-      status(302)
-      header 'Location' =&gt; path
-      throw :halt, *args
-    end
-
-    # Access or modify response headers. With no argument, return the
-    # underlying headers Hash. With a Hash argument, add or overwrite
-    # existing response headers with the values provided:
-    #
-    #    headers 'Content-Type' =&gt; &quot;text/html;charset=utf-8&quot;,
-    #      'Last-Modified' =&gt; Time.now.httpdate,
-    #      'X-UA-Compatible' =&gt; 'IE=edge'
-    #
-    # This method also available in singular form (#header).
-    def headers(header = nil)
-      @response.headers.merge!(header) if header
-      @response.headers
-    end
-    alias :header :headers
-
-    # Set the content type of the response body (HTTP 'Content-Type' header).
-    #
-    # The +type+ argument may be an internet media type (e.g., 'text/html',
-    # 'application/xml+atom', 'image/png') or a Symbol key into the
-    # Rack::File::MIME_TYPES table.
-    #
-    # Media type parameters, such as &quot;charset&quot;, may also be specified using the
-    # optional hash argument:
-    #
-    #   get '/foo.html' do
-    #     content_type 'text/html', :charset =&gt; 'utf-8'
-    #     &quot;&lt;h1&gt;Hello World&lt;/h1&gt;&quot;
-    #   end
-    #
-    def content_type(type, params={})
-      type = Rack::File::MIME_TYPES[type.to_s] if type.kind_of?(Symbol)
-      fail &quot;Invalid or undefined media_type: #{type}&quot; if type.nil?
-      if params.any?
-        params = params.collect { |kv| &quot;%s=%s&quot; % kv }.join(', ')
-        type = [ type, params ].join(&quot;;&quot;)
-      end
-      response.header['Content-Type'] = type
-    end
-
-    # Set the last modified time of the resource (HTTP 'Last-Modified' header)
-    # and halt if conditional GET matches. The +time+ argument is a Time,
-    # DateTime, or other object that responds to +to_time+.
-    #
-    # When the current request includes an 'If-Modified-Since' header that
-    # matches the time specified, execution is immediately halted with a
-    # '304 Not Modified' response.
-    #
-    # Calling this method before perfoming heavy processing (e.g., lengthy
-    # database queries, template rendering, complex logic) can dramatically
-    # increase overall throughput with caching clients.
-    def last_modified(time)
-      time = time.to_time if time.respond_to?(:to_time)
-      time = time.httpdate if time.respond_to?(:httpdate)
-      response.header['Last-Modified'] = time
-      throw :halt, 304 if time == request.env['HTTP_IF_MODIFIED_SINCE']
-      time
-    end
-
-    # Set the response entity tag (HTTP 'ETag' header) and halt if conditional
-    # GET matches. The +value+ argument is an identifier that uniquely
-    # identifies the current version of the resource. The +strength+ argument
-    # indicates whether the etag should be used as a :strong (default) or :weak
-    # cache validator.
-    #
-    # When the current request includes an 'If-None-Match' header with a
-    # matching etag, execution is immediately halted. If the request method is
-    # GET or HEAD, a '304 Not Modified' response is sent. For all other request
-    # methods, a '412 Precondition Failed' response is sent.
-    #
-    # Calling this method before perfoming heavy processing (e.g., lengthy
-    # database queries, template rendering, complex logic) can dramatically
-    # increase overall throughput with caching clients.
-    #
-    # ==== See Also
-    # {RFC2616: ETag}[http://w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19],
-    # ResponseHelpers#last_modified
-    def entity_tag(value, strength=:strong)
-      value =
-        case strength
-        when :strong then '&quot;%s&quot;' % value
-        when :weak   then 'W/&quot;%s&quot;' % value
-        else         raise TypeError, &quot;strength must be one of :strong or :weak&quot;
-        end
-      response.header['ETag'] = value
-
-      # Check for If-None-Match request header and halt if match is found.
-      etags = (request.env['HTTP_IF_NONE_MATCH'] || '').split(/\s*,\s*/)
-      if etags.include?(value) || etags.include?('*')
-        # GET/HEAD requests: send Not Modified response
-        throw :halt, 304 if request.get? || request.head?
-        # Other requests: send Precondition Failed response
-        throw :halt, 412
-      end
-    end
-
-    alias :etag :entity_tag
-
-  end
-
-  module RenderingHelpers
-
-    def render(renderer, template, options={})
-      m = method(&quot;render_#{renderer}&quot;)
-      result = m.call(resolve_template(renderer, template, options), options)
-      if layout = determine_layout(renderer, template, options)
-        result = m.call(resolve_template(renderer, layout, options), options) { result }
-      end
-      result
-    end
-
-    def determine_layout(renderer, template, options)
-      return if options[:layout] == false
-      layout_from_options = options[:layout] || :layout
-      resolve_template(renderer, layout_from_options, options, false)
-    end
-
-  private
-
-    def resolve_template(renderer, template, options, scream = true)
-      case template
-      when String
-        template
-      when Proc
-        template.call
-      when Symbol
-        if proc = templates[template]
-          resolve_template(renderer, proc, options, scream)
-        else
-          read_template_file(renderer, template, options, scream)
-        end
-      else
-        nil
-      end
-    end
-
-    def read_template_file(renderer, template, options, scream = true)
-      path = File.join(
-        options[:views_directory] || Sinatra.application.options.views,
-        &quot;#{template}.#{renderer}&quot;
-      )
-      unless File.exists?(path)
-        raise Errno::ENOENT.new(path) if scream
-        nil
-      else
-        File.read(path)
-      end
-    end
-
-    def templates
-      Sinatra.application.templates
-    end
-
-  end
-
-  module Erb
-
-    def erb(content, options={})
-      require 'erb'
-      render(:erb, content, options)
-    end
-
-  private
-
-    def render_erb(content, options = {})
-      locals_opt = options.delete(:locals) || {}
-
-      locals_code = &quot;&quot;
-      locals_hash = {}
-      locals_opt.each do |key, value|
-        locals_code &lt;&lt; &quot;#{key} = locals_hash[:#{key}]\n&quot;
-        locals_hash[:&quot;#{key}&quot;] = value
-      end
-
-      body = ::ERB.new(content).src
-      eval(&quot;#{locals_code}#{body}&quot;, binding)
-    end
-
-  end
-
-  module Haml
-
-    def haml(content, options={})
-      require 'haml'
-      render(:haml, content, options)
-    end
-
-  private
-
-    def render_haml(content, options = {}, &amp;b)
-      haml_options = (options[:options] || {}).
-        merge(Sinatra.options.haml || {})
-      ::Haml::Engine.new(content, haml_options).
-        render(options[:scope] || self, options[:locals] || {}, &amp;b)
-    end
-
-  end
-
-  # Generate valid CSS using Sass (part of Haml)
-  #
-  # Sass templates can be in external files with &lt;tt&gt;.sass&lt;/tt&gt; extension
-  # or can use Sinatra's in_file_templates.  In either case, the file can
-  # be rendered by passing the name of the template to the +sass+ method
-  # as a symbol.
-  #
-  # Unlike Haml, Sass does not support a layout file, so the +sass+ method
-  # will ignore both the default &lt;tt&gt;layout.sass&lt;/tt&gt; file and any parameters
-  # passed in as &lt;tt&gt;:layout&lt;/tt&gt; in the options hash.
-  #
-  # === Sass Template Files
-  #
-  # Sass templates can be stored in separate files with a &lt;tt&gt;.sass&lt;/tt&gt;
-  # extension under the view path.
-  #
-  # Example:
-  #   get '/stylesheet.css' do
-  #     header 'Content-Type' =&gt; 'text/css; charset=utf-8'
-  #     sass :stylesheet
-  #   end
-  #
-  # The &quot;views/stylesheet.sass&quot; file might contain the following:
-  #
-  #  body
-  #    #admin
-  #      :background-color #CCC
-  #    #main
-  #      :background-color #000
-  #  #form
-  #    :border-color #AAA
-  #    :border-width 10px
-  #
-  # And yields the following output:
-  #
-  #   body #admin {
-  #     background-color: #CCC; }
-  #   body #main {
-  #     background-color: #000; }
-  #
-  #   #form {
-  #     border-color: #AAA;
-  #     border-width: 10px; }
-  #
-  #
-  # NOTE: Haml must be installed or a LoadError will be raised the first time an
-  # attempt is made to render a Sass template.
-  #
-  # See http://haml.hamptoncatlin.com/docs/rdoc/classes/Sass.html for comprehensive documentation on Sass.
-  module Sass
-
-    def sass(content, options = {})
-      require 'sass'
-
-      # Sass doesn't support a layout, so we override any possible layout here
-      options[:layout] = false
-
-      render(:sass, content, options)
-    end
-
-  private
-
-    def render_sass(content, options = {})
-      ::Sass::Engine.new(content).render
-    end
-
-  end
-
-  # Generating conservative XML content using Builder templates.
-  #
-  # Builder templates can be inline by passing a block to the builder method,
-  # or in external files with +.builder+ extension by passing the name of the
-  # template to the +builder+ method as a Symbol.
-  #
-  # === Inline Rendering
-  #
-  # If the builder method is given a block, the block is called directly with
-  # an +XmlMarkup+ instance and the result is returned as String:
-  #   get '/who.xml' do
-  #     builder do |xml|
-  #       xml.instruct!
-  #       xml.person do
-  #         xml.name &quot;Francis Albert Sinatra&quot;,
-  #           :aka =&gt; &quot;Frank Sinatra&quot;
-  #         xml.email 'frank@capitolrecords.com'
-  #       end
-  #     end
-  #   end
-  #
-  # Yields the following XML:
-  #   &lt;?xml version='1.0' encoding='UTF-8'?&gt;
-  #   &lt;person&gt;
-  #     &lt;name aka='Frank Sinatra'&gt;Francis Albert Sinatra&lt;/name&gt;
-  #     &lt;email&gt;Frank Sinatra&lt;/email&gt;
-  #   &lt;/person&gt;
-  #
-  # === Builder Template Files
-  #
-  # Builder templates can be stored in separate files with a +.builder+
-  # extension under the view path. An +XmlMarkup+ object named +xml+ is
-  # automatically made available to template.
-  #
-  # Example:
-  #   get '/bio.xml' do
-  #     builder :bio
-  #   end
-  #
-  # The &quot;views/bio.builder&quot; file might contain the following:
-  #   xml.instruct! :xml, :version =&gt; '1.1'
-  #   xml.person do
-  #     xml.name &quot;Francis Albert Sinatra&quot;
-  #     xml.aka &quot;Frank Sinatra&quot;
-  #     xml.aka &quot;Ol' Blue Eyes&quot;
-  #     xml.aka &quot;The Chairman of the Board&quot;
-  #     xml.born 'date' =&gt; '1915-12-12' do
-  #       xml.text! &quot;Hoboken, New Jersey, U.S.A.&quot;
-  #     end
-  #     xml.died 'age' =&gt; 82
-  #   end
-  #
-  # And yields the following output:
-  #   &lt;?xml version='1.1' encoding='UTF-8'?&gt;
-  #   &lt;person&gt;
-  #     &lt;name&gt;Francis Albert Sinatra&lt;/name&gt;
-  #     &lt;aka&gt;Frank Sinatra&lt;/aka&gt;
-  #     &lt;aka&gt;Ol&amp;apos; Blue Eyes&lt;/aka&gt;
-  #     &lt;aka&gt;The Chairman of the Board&lt;/aka&gt;
-  #     &lt;born date='1915-12-12'&gt;Hoboken, New Jersey, U.S.A.&lt;/born&gt;
-  #     &lt;died age='82' /&gt;
-  #   &lt;/person&gt;
-  #
-  # NOTE: Builder must be installed or a LoadError will be raised the first
-  # time an attempt is made to render a builder template.
-  #
-  # See http://builder.rubyforge.org/ for comprehensive documentation on
-  # Builder.
-  module Builder
-
-    def builder(content=nil, options={}, &amp;block)
-      options, content = content, nil if content.is_a?(Hash)
-      content = Proc.new { block } if content.nil?
-      render(:builder, content, options)
-    end
-
-  private
-
-    def render_builder(content, options = {}, &amp;b)
-      require 'builder'
-      xml = ::Builder::XmlMarkup.new(:indent =&gt; 2)
-      case content
-      when String
-        eval(content, binding, '&lt;BUILDER&gt;', 1)
-      when Proc
-        content.call(xml)
-      end
-      xml.target!
-    end
-
-  end
-
-  class EventContext
-    include Rack::Utils
-    include ResponseHelpers
-    include Streaming
-    include RenderingHelpers
-    include Erb
-    include Haml
-    include Builder
-    include Sass
-
-    attr_accessor :request, :response
-
-    attr_accessor :route_params
-
-    def initialize(request, response, route_params)
-      @params = nil
-      @data = nil
-      @request = request
-      @response = response
-      @route_params = route_params
-      @response.body = nil
-    end
-
-    def status(value=nil)
-      response.status = value if value
-      response.status
-    end
-
-    def body(value=nil)
-      response.body = value if value
-      response.body
-    end
-
-    def params
-      @params ||=
-        begin
-          hash = Hash.new {|h,k| h[k.to_s] if Symbol === k}
-          hash.merge! @request.params
-          hash.merge! @route_params
-          hash
-        end
-    end
-
-    def data
-      @data ||= params.keys.first
-    end
-
-    def stop(*args)
-      throw :halt, args
-    end
-
-    def complete(returned)
-      @response.body || returned
-    end
-
-    def session
-      request.env['rack.session'] ||= {}
-    end
-
-    def reset!
-      @params = nil
-      @data = nil
-    end
-
-  private
-
-    def method_missing(name, *args, &amp;b)
-      if @response.respond_to?(name)
-        @response.send(name, *args, &amp;b)
-      else
-        super
-      end
-    end
-
-  end
-
-
-  # The Application class represents the top-level working area of a
-  # Sinatra app. It provides the DSL for defining various aspects of the
-  # application and implements a Rack compatible interface for dispatching
-  # requests.
-  #
-  # Many of the instance methods defined in this class (#get, #post,
-  # #put, #delete, #layout, #before, #error, #not_found, etc.) are
-  # available at top-level scope. When invoked from top-level, the
-  # messages are forwarded to the &quot;default application&quot; (accessible
-  # at Sinatra::application).
-  class Application
-
-    # Hash of event handlers with request method keys and
-    # arrays of potential handlers as values.
-    attr_reader :events
-
-    # Hash of error handlers with error status codes as keys and
-    # handlers as values.
-    attr_reader :errors
-
-    # Hash of template name mappings.
-    attr_reader :templates
-
-    # Hash of filters with event name keys (:before) and arrays of
-    # handlers as values.
-    attr_reader :filters
-
-    # Array of objects to clear during reload. The objects in this array
-    # must respond to :clear.
-    attr_reader :clearables
-
-    # Object including open attribute methods for modifying Application
-    # configuration.
-    attr_reader :options
-
-    # List of methods available from top-level scope. When invoked from
-    # top-level the method is forwarded to the default application
-    # (Sinatra::application).
-    FORWARD_METHODS = %w[
-      get put post delete head template layout before error not_found
-      configures configure set set_options set_option enable disable use
-      development? test? production?
-    ]
-
-    # Create a new Application with a default configuration taken
-    # from the default_options Hash.
-    #
-    # NOTE: A default Application is automatically created the first
-    # time any of Sinatra's DSL related methods is invoked so there
-    # is typically no need to create an instance explicitly. See
-    # Sinatra::application for more information.
-    def initialize
-      @reloading = false
-      @clearables = [
-        @events = Hash.new { |hash, key| hash[key] = [] },
-        @errors = Hash.new,
-        @filters = Hash.new { |hash, key| hash[key] = [] },
-        @templates = Hash.new,
-        @middleware = []
-      ]
-      @options = OpenStruct.new(self.class.default_options)
-      load_default_configuration!
-    end
-
-    # Hash of default application configuration options. When a new
-    # Application is created, the #options object takes its initial values
-    # from here.
-    #
-    # Changes to the default_options Hash effect only Application objects
-    # created after the changes are made. For this reason, modifications to
-    # the default_options Hash typically occur at the very beginning of a
-    # file, before any DSL related functions are invoked.
-    def self.default_options
-      return @default_options unless @default_options.nil?
-      app_file = locate_app_file
-      root = File.expand_path(File.dirname(app_file))
-      @default_options = {
-        :run =&gt; true,
-        :port =&gt; 4567,
-        :host =&gt; '0.0.0.0',
-        :env =&gt; (ENV['RACK_ENV'] || :development).to_sym,
-        :root =&gt; root,
-        :views =&gt; root + '/views',
-        :public =&gt; root + '/public',
-        :sessions =&gt; false,
-        :logging =&gt; true,
-        :app_file =&gt; app_file,
-        :raise_errors =&gt; false
-      }
-      load_default_options_from_command_line!
-      @default_options
-    end
-
-    # Search ARGV for command line arguments and update the
-    # Sinatra::default_options Hash accordingly. This method is
-    # invoked the first time the default_options Hash is accessed.
-    # NOTE:  Ignores --name so unit/spec tests can run individually
-    def self.load_default_options_from_command_line! #:nodoc:
-      # fixes issue with: gem install --test sinatra
-      return if ARGV.empty? || File.basename($0) =~ /gem/
-      require 'optparse'
-      OptionParser.new do |op|
-        op.on('-p port') { |port| default_options[:port] = port }
-        op.on('-e env') { |env| default_options[:env] = env.to_sym }
-        op.on('-x') { default_options[:mutex] = true }
-        op.on('-s server') { |server| default_options[:server] = server }
-      end.parse!(ARGV.dup.select { |o| o !~ /--name/ })
-    end
-
-    # Use heuristics to locate the application file.
-    def self.locate_app_file
-      caller[1..-1].reverse.each do |path|
-        path = path.split(':', 2)[0]
-        next if path =~ /sinatra\.rb$/ || path == '(__DSL__)'
-        return path
-      end
-      $0
-    end
-
-    # Determine whether the application is in the process of being
-    # reloaded.
-    def reloading?
-      @reloading == true
-    end
-
-    # Yield to the block for configuration if the current environment
-    # matches any included in the +envs+ list. Always yield to the block
-    # when no environment is specified.
-    #
-    # NOTE: configuration blocks are not executed during reloads.
-    def configures(*envs, &amp;b)
-      return if reloading?
-      yield self if envs.empty? || envs.include?(options.env)
-    end
-
-    alias :configure :configures
-
-    # When both +option+ and +value+ arguments are provided, set the option
-    # specified. With a single Hash argument, set all options specified in
-    # Hash. Options are available via the Application#options object.
-    #
-    # Setting individual options:
-    #   set :port, 80
-    #   set :env, :production
-    #   set :views, '/path/to/views'
-    #
-    # Setting multiple options:
-    #   set :port  =&gt; 80,
-    #       :env   =&gt; :production,
-    #       :views =&gt; '/path/to/views'
-    #
-    def set(option, value=self)
-      if value == self &amp;&amp; option.kind_of?(Hash)
-        option.each { |key,val| set(key, val) }
-      else
-        options.send(&quot;#{option}=&quot;, value)
-      end
-    end
-
-    alias :set_option :set
-    alias :set_options :set
-
-    # Enable the options specified by setting their values to true. For
-    # example, to enable sessions and logging:
-    #   enable :sessions, :logging
-    def enable(*opts)
-      opts.each { |key| set(key, true) }
-    end
-
-    # Disable the options specified by setting their values to false. For
-    # example, to disable logging and automatic run:
-    #   disable :logging, :run
-    def disable(*opts)
-      opts.each { |key| set(key, false) }
-    end
-
-    # Define an event handler for the given request method and path
-    # spec. The block is executed when a request matches the method
-    # and spec.
-    #
-    # NOTE: The #get, #post, #put, and #delete helper methods should
-    # be used to define events when possible.
-    def event(method, path, options = {}, &amp;b)
-      events[method].push(Event.new(path, options, &amp;b)).last
-    end
-
-    # Define an event handler for GET requests.
-    def get(path, options={}, &amp;b)
-      event(:get, path, options, &amp;b)
-    end
-
-    # Define an event handler for POST requests.
-    def post(path, options={}, &amp;b)
-      event(:post, path, options, &amp;b)
-    end
-
-    # Define an event handler for HEAD requests.
-    def head(path, options={}, &amp;b)
-      event(:head, path, options, &amp;b)
-    end
-
-    # Define an event handler for PUT requests.
-    #
-    # NOTE: PUT events are triggered when the HTTP request method is
-    # PUT and also when the request method is POST and the body includes a
-    # &quot;_method&quot; parameter set to &quot;PUT&quot;.
-    def put(path, options={}, &amp;b)
-      event(:put, path, options, &amp;b)
-    end
-
-    # Define an event handler for DELETE requests.
-    #
-    # NOTE: DELETE events are triggered when the HTTP request method is
-    # DELETE and also when the request method is POST and the body includes a
-    # &quot;_method&quot; parameter set to &quot;DELETE&quot;.
-    def delete(path, options={}, &amp;b)
-      event(:delete, path, options, &amp;b)
-    end
-
-    # Visits and invokes each handler registered for the +request_method+ in
-    # definition order until a Result response is produced. If no handler
-    # responds with a Result, the NotFound error handler is invoked.
-    #
-    # When the request_method is &quot;HEAD&quot; and no valid Result is produced by
-    # the set of handlers registered for HEAD requests, an attempt is made to
-    # invoke the GET handlers to generate the response before resorting to the
-    # default error handler.
-    def lookup(request)
-      method = request.request_method.downcase.to_sym
-      events[method].eject(&amp;[:invoke, request]) ||
-        (events[:get].eject(&amp;[:invoke, request]) if method == :head) ||
-        errors[NotFound].invoke(request)
-    end
-
-    # Define a named template. The template may be referenced from
-    # event handlers by passing the name as a Symbol to rendering
-    # methods. The block is executed each time the template is rendered
-    # and the resulting object is passed to the template handler.
-    #
-    # The following example defines a HAML template named hello and
-    # invokes it from an event handler:
-    #
-    #   template :hello do
-    #     &quot;h1 Hello World!&quot;
-    #   end
-    #
-    #   get '/' do
-    #     haml :hello
-    #   end
-    #
-    def template(name, &amp;b)
-      templates[name] = b
-    end
-
-    # Define a layout template.
-    def layout(name=:layout, &amp;b)
-      template(name, &amp;b)
-    end
-
-    # Define a custom error handler for the exception class +type+. The block
-    # is invoked when the specified exception type is raised from an error
-    # handler and can manipulate the response as needed:
-    #
-    #   error MyCustomError do
-    #     status 500
-    #     'So what happened was...' + request.env['sinatra.error'].message
-    #   end
-    #
-    # The Sinatra::ServerError handler is used by default when an exception
-    # occurs and no matching error handler is found.
-    def error(type=ServerError, options = {}, &amp;b)
-      errors[type] = Error.new(type, options, &amp;b)
-    end
-
-    # Define a custom error handler for '404 Not Found' responses. This is a
-    # shorthand for:
-    #   error NotFound do
-    #     ..
-    #   end
-    def not_found(options={}, &amp;b)
-      error NotFound, options, &amp;b
-    end
-
-    # Define a request filter. When &lt;tt&gt;type&lt;/tt&gt; is &lt;tt&gt;:before&lt;/tt&gt;, execute the
-    # block in the context of each request before matching event handlers.
-    def filter(type, &amp;b)
-      filters[type] &lt;&lt; b
-    end
-
-    # Invoke the block in the context of each request before invoking
-    # matching event handlers.
-    def before(&amp;b)
-      filter :before, &amp;b
-    end
-
-    # True when environment is :development.
-    def development? ; options.env == :development ; end
-
-    # True when environment is :test.
-    def test? ; options.env == :test ; end
-
-    # True when environment is :production.
-    def production? ; options.env == :production ; end
-
-    # Clear all events, templates, filters, and error handlers
-    # and then reload the application source file. This occurs
-    # automatically before each request is processed in development.
-    def reload!
-      clearables.each(&amp;:clear)
-      load_default_configuration!
-      load_development_configuration! if development?
-      @pipeline = nil
-      @reloading = true
-      Kernel.load options.app_file
-      @reloading = false
-    end
-
-    # Determine whether the application is in the process of being
-    # reloaded.
-    def reloading?
-      @reloading == true
-    end
-
-    # Mutex instance used for thread synchronization.
-    def mutex
-      @@mutex ||= Mutex.new
-    end
-
-    # Yield to the block with thread synchronization
-    def run_safely
-      if development? || options.mutex
-        mutex.synchronize { yield }
-      else
-        yield
-      end
-    end
-
-    # Add a piece of Rack middleware to the pipeline leading to the
-    # application.
-    def use(klass, *args, &amp;block)
-      fail &quot;#{klass} must respond to 'new'&quot; unless klass.respond_to?(:new)
-      @pipeline = nil
-      @middleware.push([ klass, args, block ]).last
-    end
-
-  private
-
-    # Rack middleware derived from current state of application options.
-    # These components are plumbed in at the very beginning of the
-    # pipeline.
-    def optional_middleware
-      [
-        ([ Rack::CommonLogger,    [], nil ] if options.logging),
-        ([ Rack::Session::Cookie, [], nil ] if options.sessions)
-      ].compact
-    end
-
-    # Rack middleware explicitly added to the application with #use. These
-    # components are plumbed into the pipeline downstream from
-    # #optional_middle.
-    def explicit_middleware
-      @middleware
-    end
-
-    # All Rack middleware used to construct the pipeline.
-    def middleware
-      optional_middleware + explicit_middleware
-    end
-
-  public
-
-    # An assembled pipeline of Rack middleware that leads eventually to
-    # the Application#invoke method. The pipeline is built upon first
-    # access. Defining new middleware with Application#use or manipulating
-    # application options may cause the pipeline to be rebuilt.
-    def pipeline
-      @pipeline ||=
-        middleware.inject(method(:dispatch)) do |app,(klass,args,block)|
-          klass.new(app, *args, &amp;block)
-        end
-    end
-
-    # Rack compatible request invocation interface.
-    def call(env)
-      run_safely do
-        reload! if development? &amp;&amp; (options.reload != false)
-        pipeline.call(env)
-      end
-    end
-
-    # Request invocation handler - called at the end of the Rack pipeline
-    # for each request.
-    #
-    # 1. Create Rack::Request, Rack::Response helper objects.
-    # 2. Lookup event handler based on request method and path.
-    # 3. Create new EventContext to house event handler evaluation.
-    # 4. Invoke each #before filter in context of EventContext object.
-    # 5. Invoke event handler in context of EventContext object.
-    # 6. Return response to Rack.
-    #
-    # See the Rack specification for detailed information on the
-    # +env+ argument and return value.
-    def dispatch(env)
-      request = Rack::Request.new(env)
-      context = EventContext.new(request, Rack::Response.new([], 200), {})
-      begin
-        returned =
-          catch(:halt) do
-            filters[:before].each { |f| context.instance_eval(&amp;f) }
-            result = lookup(context.request)
-            context.route_params = result.params
-            context.response.status = result.status
-            context.reset!
-            [:complete, context.instance_eval(&amp;result.block)]
-          end
-        body = returned.to_result(context)
-      rescue =&gt; e
-        msg  = &quot;#{e.class.name} - #{e.message}:&quot;
-        msg &lt;&lt; &quot;\n  #{e.backtrace.join(&quot;\n  &quot;)}&quot;
-        request.env['rack.errors'] &lt;&lt; msg
-
-        request.env['sinatra.error'] = e
-        status = e.class.code rescue 500
-        context.status(status)
-        raise if options.raise_errors &amp;&amp; e.class != NotFound
-        result = (errors[e.class] || errors[ServerError]).invoke(request)
-        returned =
-          catch(:halt) do
-            [:complete, context.instance_eval(&amp;result.block)]
-          end
-        body = returned.to_result(context)
-      end
-      body = '' unless body.respond_to?(:each)
-      body = '' if request.env[&quot;REQUEST_METHOD&quot;].upcase == 'HEAD'
-      context.body = body.kind_of?(String) ? [*body] : body
-      context.finish
-    end
-
-  private
-
-    # Called immediately after the application is initialized or reloaded to
-    # register default events, templates, and error handlers.
-    def load_default_configuration!
-      events[:get] &lt;&lt; Static.new(self)
-      configure do
-        error do
-          '&lt;h1&gt;Internal Server Error&lt;/h1&gt;'
-        end
-        not_found { '&lt;h1&gt;Not Found&lt;/h1&gt;'}
-      end
-    end
-
-    # Called before reloading to perform development specific configuration.
-    def load_development_configuration!
-      get '/sinatra_custom_images/:image.png' do
-        content_type :png
-        File.read(File.dirname(__FILE__) + &quot;/../images/#{params[:image]}.png&quot;)
-      end
-
-      not_found do
-        (&lt;&lt;-HTML).gsub(/^ {8}/, '')
-        &lt;!DOCTYPE html&gt;
-        &lt;html&gt;
-          &lt;head&gt;
-            &lt;style type=&quot;text/css&quot;&gt;
-            body {text-align:center;color:#888;font-family:arial;font-size:22px;margin:20px;}
-            #content {margin:0 auto;width:500px;text-align:left}
-            &lt;/style&gt;
-          &lt;/head&gt;
-          &lt;body&gt;
-            &lt;h2&gt;Sinatra doesn't know this diddy.&lt;/h2&gt;
-            &lt;img src='/sinatra_custom_images/404.png'&gt;
-            &lt;div id=&quot;content&quot;&gt;
-              Try this:
-              &lt;pre&gt;#{request.request_method.downcase} &quot;#{request.path_info}&quot; do\n  .. do something ..\nend&lt;pre&gt;
-            &lt;/div&gt;
-          &lt;/body&gt;
-        &lt;/html&gt;
-        HTML
-      end
-
-      error do
-        @error = request.env['sinatra.error']
-        (&lt;&lt;-HTML).gsub(/^ {8}/, '')
-        &lt;!DOCTYPE html&gt;
-        &lt;html&gt;
-          &lt;head&gt;
-            &lt;style type=&quot;text/css&quot; media=&quot;screen&quot;&gt;
-              body {font-family:verdana;color:#333}
-              #content {width:700px;margin-left:20px}
-              #content h1 {width:99%;color:#1D6B8D;font-weight:bold}
-              #stacktrace {margin-top:-20px}
-              #stacktrace pre {font-size:12px;border-left:2px solid #ddd;padding-left:10px}
-              #stacktrace img {margin-top:10px}
-            &lt;/style&gt;
-          &lt;/head&gt;
-          &lt;body&gt;
-            &lt;div id=&quot;content&quot;&gt;
-              &lt;img src=&quot;/sinatra_custom_images/500.png&quot;&gt;
-              &lt;div class=&quot;info&quot;&gt;
-                Params: &lt;pre&gt;#{params.inspect}&lt;/pre&gt;
-              &lt;/div&gt;
-              &lt;div id=&quot;stacktrace&quot;&gt;
-                &lt;h1&gt;#{escape_html(@error.class.name + ' - ' + @error.message.to_s)}&lt;/h1&gt;
-                &lt;pre&gt;&lt;code&gt;#{escape_html(@error.backtrace.join(&quot;\n&quot;))}&lt;/code&gt;&lt;/pre&gt;
-              &lt;/div&gt;
-            &lt;/div&gt;
-          &lt;/body&gt;
-        &lt;/html&gt;
-        HTML
-      end
-    end
-
-  end
-
-end
-
-# Delegate DSLish methods to the currently active Sinatra::Application
-# instance.
-Sinatra::Application::FORWARD_METHODS.each do |method|
-  eval(&lt;&lt;-EOS, binding, '(__DSL__)', 1)
-    def #{method}(*args, &amp;b)
-      Sinatra.application.#{method}(*args, &amp;b)
-    end
-  EOS
-end
-
-def helpers(&amp;b)
-  Sinatra::EventContext.class_eval(&amp;b)
-end
-
-def use_in_file_templates!
-  file = caller.first.sub(/:\d+$/, '')
-  data = IO.read(file).split('__END__').last
-  data.gsub! /\r\n/, &quot;\n&quot;
-  current_template = nil
-  data.each_line do |line|
-    if line =~ /^@@\s?(.*)/
-      current_template = $1.to_sym
-      Sinatra.application.templates[current_template] = ''
-    elsif current_template
-      Sinatra.application.templates[current_template] &lt;&lt; line
-    end
-  end
-end
-
-def mime(ext, type)
-  Rack::File::MIME_TYPES[ext.to_s] = type
-end
-
-### Misc Core Extensions
-
-module Kernel
-  def silence_warnings
-    old_verbose, $VERBOSE = $VERBOSE, nil
-    yield
-  ensure
-    $VERBOSE = old_verbose
-  end
-end
-
-class Symbol
-  def to_proc
-    Proc.new { |*args| args.shift.__send__(self, *args) }
-  end
-end
-
-class Array
-  def to_hash
-    self.inject({}) { |h, (k, v)|  h[k] = v; h }
-  end
-  def to_proc
-    Proc.new { |*args| args.shift.__send__(self[0], *(args + self[1..-1])) }
-  end
-end
-
-module Enumerable
-  def eject(&amp;block)
-    find { |e| result = block[e] and break result }
-  end
-end
-
-### Core Extension results for throw :halt
-
-class Proc
-  def to_result(cx, *args)
-    cx.instance_eval(&amp;self)
-    args.shift.to_result(cx, *args)
-  end
-end
-
-class String
-  def to_result(cx, *args)
-    args.shift.to_result(cx, *args)
-    self
-  end
-end
-
-class Array
-  def to_result(cx, *args)
-    self.shift.to_result(cx, *self)
-  end
-end
-
-class Symbol
-  def to_result(cx, *args)
-    cx.send(self, *args)
-  end
-end
-
-class Fixnum
-  def to_result(cx, *args)
-    cx.status self
-    args.shift.to_result(cx, *args)
-  end
-end
-
-class NilClass
-  def to_result(cx, *args)
-    ''
-  end
-end
-
-at_exit do
-  raise $! if $!
-  Sinatra.run if Sinatra.application.options.run
-end
-
-mime :xml, 'application/xml'
-mime :js,  'application/javascript'
-mime :png, 'image/png'
+require 'sinatra/base'
+require 'sinatra/main'
+require 'sinatra/compat'</diff>
      <filename>lib/sinatra.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,2 @@
-require File.dirname(__FILE__) + '/unit'
+require 'sinatra/test'
 require 'spec/interop/test'
-
-class Test::Unit::TestCase
-
-  def should
-    @response.should
-  end
-
-end</diff>
      <filename>lib/sinatra/test/rspec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,2 @@
-require File.dirname(__FILE__) + '/unit'
 require 'test/spec'
-
-class Test::Unit::TestCase
-
-  def should
-    @response.should
-  end
-
-end
+require 'sinatra/test'</diff>
      <filename>lib/sinatra/test/spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,13 +1,11 @@
 require 'test/unit'
-require File.dirname(__FILE__) + '/methods'
+require 'sinatra/test'
 
-Test::Unit::TestCase.send(:include, Sinatra::Test::Methods)
+Test::Unit::TestCase.send :include, Sinatra::Test
 
-Sinatra::Application.default_options.merge!(
+Sinatra::Default.set(
   :env =&gt; :test,
   :run =&gt; false,
   :raise_errors =&gt; true,
   :logging =&gt; false
 )
-
-Sinatra.application = nil</diff>
      <filename>lib/sinatra/test/unit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,101 +1,68 @@
-require File.dirname(__FILE__) + '/helper'
-
-context &quot;Builder&quot; do
-
-  setup do
-    Sinatra.application = nil
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
+
+describe &quot;Builder Templates&quot; do
+  include Sinatra::Test
+
+  def builder_app(&amp;block)
+    mock_app {
+      set :views, File.dirname(__FILE__) + '/views'
+      get '/', &amp;block
+    }
+    get '/'
   end
 
-  context &quot;without layouts&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;should render&quot; do
-
-      get '/no_layout' do
-        builder 'xml.instruct!'
-      end
-
-      get_it '/no_layout'
-      should.be.ok
-      body.should == %(&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n)
-
-    end
-
-    specify &quot;should render inline block&quot; do
-
-      get '/no_layout_and_inlined' do
-        @name = &quot;Frank &amp; Mary&quot;
-        builder do |xml|
-          xml.couple @name
-        end
-      end
-
-      get_it '/no_layout_and_inlined'
-      should.be.ok
-      body.should == %(&lt;couple&gt;Frank &amp;amp; Mary&lt;/couple&gt;\n)
-
-    end
-
+  it 'renders inline Builder strings' do
+    builder_app { builder 'xml.instruct!' }
+    should.be.ok
+    body.should.equal %{&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;\n}
   end
 
-
-
-  context &quot;Templates (in general)&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;are read from files if Symbols&quot; do
-
-      get '/from_file' do
-        @name = 'Blue'
-        builder :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
+  it 'renders inline blocks' do
+    builder_app {
+      @name = &quot;Frank &amp; Mary&quot;
+      builder do |xml|
+        xml.couple @name
       end
+    }
+    should.be.ok
+    body.should.equal &quot;&lt;couple&gt;Frank &amp;amp; Mary&lt;/couple&gt;\n&quot;
+  end
 
-      get_it '/from_file'
-      should.be.ok
-      body.should.equal %(&lt;exclaim&gt;You rock Blue!&lt;/exclaim&gt;\n)
-
-    end
-
-    specify &quot;use layout.ext by default if available&quot; do
-
-      get '/' do
-        builder :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;&lt;layout&gt;\n&lt;this&gt;is foo!&lt;/this&gt;\n&lt;/layout&gt;\n&quot;
-
-    end
-
-    specify &quot;renders without layout&quot; do
-
-      get '/' do
-        builder :no_layout, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/no_layout&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;&lt;foo&gt;No Layout!&lt;/foo&gt;\n&quot;
-
-    end
-
-    specify &quot;raises error if template not found&quot; do
+  it 'renders .builder files in views path' do
+    builder_app {
+      @name = &quot;Blue&quot;
+      builder :hello
+    }
+    should.be.ok
+    body.should.equal %(&lt;exclaim&gt;You're my boy, Blue!&lt;/exclaim&gt;\n)
+  end
 
-      get '/' do
-        builder :not_found
+  it &quot;renders with inline layouts&quot; do
+    mock_app {
+      layout do
+        %(xml.layout { xml &lt;&lt; yield })
       end
+      get('/') { builder %(xml.em 'Hello World') }
+    }
+    get '/'
+    should.be.ok
+    body.should.equal &quot;&lt;layout&gt;\n&lt;em&gt;Hello World&lt;/em&gt;\n&lt;/layout&gt;\n&quot;
+  end
 
-      lambda { get_it '/' }.should.raise(Errno::ENOENT)
-
-    end
-
+  it &quot;renders with file layouts&quot; do
+    builder_app {
+      builder %(xml.em 'Hello World'), :layout =&gt; :layout2
+    }
+    should.be.ok
+    body.should.equal &quot;&lt;layout&gt;\n&lt;em&gt;Hello World&lt;/em&gt;\n&lt;/layout&gt;\n&quot;
   end
 
+  it &quot;raises error if template not found&quot; do
+    mock_app {
+      get('/') { builder :no_such_template }
+    }
+    lambda { get('/') }.should.raise(Errno::ENOENT)
+  end
 end</diff>
      <filename>test/builder_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,136 +1,55 @@
-require File.dirname(__FILE__) + '/helper'
-
-context &quot;Erb&quot; do
-
-  setup do
-    Sinatra.application = nil
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
+
+describe &quot;ERB Templates&quot; do
+  include Sinatra::Test
+
+  def erb_app(&amp;block)
+    mock_app {
+      set :views, File.dirname(__FILE__) + '/views'
+      get '/', &amp;block
+    }
+    get '/'
   end
 
-  context &quot;without layouts&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;should render&quot; do
-
-      get '/no_layout' do
-        erb '&lt;%= 1 + 1 %&gt;'
-      end
-
-      get_it '/no_layout'
-      should.be.ok
-      body.should == '2'
-
-    end
-
-    specify &quot;should take an options hash with :locals set with a string&quot; do
-      get '/locals' do
-        erb '&lt;%= foo %&gt;', :locals =&gt; {:foo =&gt; &quot;Bar&quot;}
-      end
-
-      get_it '/locals'
-      should.be.ok
-      body.should == 'Bar'
-    end
-
-    specify &quot;should take an options hash with :locals set with a complex object&quot; do
-      get '/locals-complex' do
-        erb '&lt;%= foo[0] %&gt;', :locals =&gt; {:foo =&gt; [&quot;foo&quot;, &quot;bar&quot;, &quot;baz&quot;]}
-      end
-
-      get_it '/locals-complex'
-      should.be.ok
-      body.should == 'foo'
-    end
+  it 'renders inline ERB strings' do
+    erb_app { erb '&lt;%= 1 + 1 %&gt;' }
+    should.be.ok
+    body.should.equal '2'
   end
 
-  context &quot;with layouts&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;can be inline&quot; do
-
-      layout do
-        %Q{This is &lt;%= yield %&gt;!}
-      end
-
-      get '/lay' do
-        erb 'Blake'
-      end
-
-      get_it '/lay'
-      should.be.ok
-      body.should.equal 'This is Blake!'
-
-    end
-
-    specify &quot;can use named layouts&quot; do
-
-      layout :pretty do
-        %Q{&lt;h1&gt;&lt;%= yield %&gt;&lt;/h1&gt;}
-      end
-
-      get '/pretty' do
-        erb 'Foo', :layout =&gt; :pretty
-      end
-
-      get '/not_pretty' do
-        erb 'Bar'
-      end
-
-      get_it '/pretty'
-      body.should.equal '&lt;h1&gt;Foo&lt;/h1&gt;'
-
-      get_it '/not_pretty'
-      body.should.equal 'Bar'
-
-    end
-
-    specify &quot;can be read from a file if they're not inlined&quot; do
-
-      get '/foo' do
-        @title = 'Welcome to the Hello Program'
-        erb 'Blake', :layout =&gt; :foo_layout,
-                     :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
-      end
-
-      get_it '/foo'
-      body.should.equal &quot;Welcome to the Hello Program\nHi Blake\n&quot;
-
-    end
-
+  it 'renders .erb files in views path' do
+    erb_app { erb :hello }
+    should.be.ok
+    body.should.equal &quot;Hello World\n&quot;
   end
 
-  context &quot;Templates (in general)&quot; do
-
-    specify &quot;are read from files if Symbols&quot; do
-
-      get '/from_file' do
-        @name = 'Alena'
-        erb :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
-      end
-
-      get_it '/from_file'
-
-      body.should.equal 'You rock Alena!'
-
-    end
-
-    specify &quot;use layout.ext by default if available&quot; do
-
-      get '/layout_from_file' do
-        erb :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
-
-      get_it '/layout_from_file'
-      should.be.ok
-      body.should.equal &quot;x This is foo! x \n&quot;
+  it 'takes a :locals option' do
+    erb_app {
+      locals = {:foo =&gt; 'Bar'}
+      erb '&lt;%= foo %&gt;', :locals =&gt; locals
+    }
+    should.be.ok
+    body.should.equal 'Bar'
+  end
 
-    end
+  it &quot;renders with inline layouts&quot; do
+    mock_app {
+      layout { 'THIS. IS. &lt;%= yield.upcase %&gt;!' }
+      get('/') { erb 'Sparta' }
+    }
+    get '/'
+    should.be.ok
+    body.should.equal 'THIS. IS. SPARTA!'
+  end
 
+  it &quot;renders with file layouts&quot; do
+    erb_app {
+      erb 'Hello World', :layout =&gt; :layout2
+    }
+    should.be.ok
+    body.should.equal &quot;ERB Layout!\nHello World\n&quot;
   end
 
 end</diff>
      <filename>test/erb_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,30 +1,39 @@
-require File.dirname(__FILE__) + '/helper'
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
 
-context &quot;before filters&quot; do
+describe &quot;Filters&quot; do
+  include Sinatra::Test
 
-  setup do
-    Sinatra.application = nil
-    @app = Sinatra.application
-  end
+  it &quot;executes filters in the order defined&quot; do
+    count = 0
+    mock_app do
+      get('/') { 'Hello World' }
+      before {
+        count.should.be 0
+        count = 1
+      }
+      before {
+        count.should.be 1
+        count = 2
+      }
+    end
 
-  specify &quot;should be executed in the order defined&quot; do
-    invoked = 0x0
-    @app.before { invoked = 0x01 }
-    @app.before { invoked |= 0x02 }
-    @app.get('/') { 'Hello World' }
-    get_it '/'
+    get '/'
     should.be.ok
-    body.should.be == 'Hello World'
-    invoked.should.be == 0x03
+    count.should.be 2
+    body.should.equal 'Hello World'
   end
 
-  specify &quot;should be capable of modifying the request&quot; do
-    @app.get('/foo') { 'foo' }
-    @app.get('/bar') { 'bar' }
-    @app.before { request.path_info = '/bar' }
-    get_it '/foo'
+  it &quot;allows filters to modify the request&quot; do
+    mock_app {
+      get('/foo') { 'foo' }
+      get('/bar') { 'bar' }
+      before { request.path_info = '/bar' }
+    }
+
+    get '/foo'
     should.be.ok
     body.should.be == 'bar'
   end
-
 end</diff>
      <filename>test/filter_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,233 +1,72 @@
-require File.dirname(__FILE__) + '/helper'
-
-context &quot;Haml&quot; do
-
-  setup do
-    Sinatra.application = nil
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
+
+describe &quot;HAML Templates&quot; do
+  include Sinatra::Test
+
+  def haml_app(&amp;block)
+    mock_app {
+      set :views, File.dirname(__FILE__) + '/views'
+      get '/', &amp;block
+    }
+    get '/'
   end
 
-  context &quot;without layouts&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;should render&quot; do
-
-      get '/no_layout' do
-        haml '== #{1+1}'
-      end
-
-      get_it '/no_layout'
-      should.be.ok
-      body.should == &quot;2\n&quot;
-
-    end
+  it 'renders inline HAML strings' do
+    haml_app { haml '%h1 Hiya' }
+    should.be.ok
+    body.should.equal &quot;&lt;h1&gt;Hiya&lt;/h1&gt;\n&quot;
   end
 
-  context &quot;with layouts&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;can be inline&quot; do
-
-      layout do
-        '== This is #{yield}!'
-      end
-
-      get '/lay' do
-        haml 'Blake'
-      end
-
-      get_it '/lay'
-      should.be.ok
-      body.should.equal &quot;This is Blake\n!\n&quot;
-
-    end
-
-    specify &quot;can use named layouts&quot; do
-
-      layout :pretty do
-        '%h1== #{yield}'
-      end
-
-      get '/pretty' do
-        haml 'Foo', :layout =&gt; :pretty
-      end
-
-      get '/not_pretty' do
-        haml 'Bar'
-      end
-
-      get_it '/pretty'
-      body.should.equal &quot;&lt;h1&gt;Foo&lt;/h1&gt;\n&quot;
-
-      get_it '/not_pretty'
-      body.should.equal &quot;Bar\n&quot;
-
-    end
-
-    specify &quot;can be read from a file if they're not inlined&quot; do
-
-      get '/foo' do
-        @title = 'Welcome to the Hello Program'
-        haml 'Blake', :layout =&gt; :foo_layout,
-                      :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
-      end
-
-      get_it '/foo'
-      body.should.equal &quot;Welcome to the Hello Program\nHi Blake\n&quot;
-
-    end
-
-    specify &quot;can be read from file and layout from text&quot; do
-      get '/foo' do
-        haml 'Test', :layout =&gt; '== Foo #{yield}'
-      end
-
-      get_it '/foo'
-
-      body.should.equal &quot;Foo Test\n&quot;
-    end
-
+  it 'renders .haml files in views path' do
+    haml_app { haml :hello }
+    should.be.ok
+    body.should.equal &quot;&lt;h1&gt;Hello From Haml&lt;/h1&gt;\n&quot;
   end
 
-  context &quot;Templates (in general)&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;are read from files if Symbols&quot; do
-
-      get '/from_file' do
-        @name = 'Alena'
-        haml :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
-      end
-
-      get_it '/from_file'
-
-      body.should.equal &quot;You rock Alena!\n&quot;
-
-    end
-
-    specify &quot;use layout.ext by default if available&quot; do
-
-      get '/' do
-        haml :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;x This is foo!\n x\n&quot;
-
-    end
-
-    specify &quot;renders without layout&quot; do
-
-      get '/' do
-        haml :no_layout, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/no_layout&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;&lt;h1&gt;No Layout!&lt;/h1&gt;\n&quot;
-
-    end
-
-    specify &quot;can render with no layout&quot; do
-      layout do
-        &quot;X\n= yield\nX&quot;
-      end
-
-      get '/' do
-        haml 'blake', :layout =&gt; false
-      end
-
-      get_it '/'
-
-      body.should.equal &quot;blake\n&quot;
-    end
-
-    specify &quot;raises error if template not found&quot; do
-      get '/' do
-        haml :not_found
-      end
-
-      lambda { get_it '/' }.should.raise(Errno::ENOENT)
-    end
-
-    specify &quot;use layout.ext by default if available&quot; do
-
-      template :foo do
-        'asdf'
-      end
-
-      get '/' do
-        haml :foo, :layout =&gt; false,
-                   :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;asdf\n&quot;
-
-    end
-
+  it &quot;renders with inline layouts&quot; do
+    mock_app {
+      layout { %q(%h1= 'THIS. IS. ' + yield.upcase) }
+      get('/') { haml '%em Sparta' }
+    }
+    get '/'
+    should.be.ok
+    body.should.equal &quot;&lt;h1&gt;THIS. IS. &lt;EM&gt;SPARTA&lt;/EM&gt;&lt;/h1&gt;\n&quot;
   end
 
-  describe 'Options passed to the HAML interpreter' do
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify 'are empty be default' do
-
-      get '/' do
-        haml 'foo'
-      end
-
-      Haml::Engine.expects(:new).with('foo', {}).returns(stub(:render =&gt; 'foo'))
-
-      get_it '/'
-      should.be.ok
-
-    end
-
-    specify 'can be configured by passing :options to haml' do
-
-      get '/' do
-        haml 'foo', :options =&gt; {:format =&gt; :html4}
-      end
-
-      Haml::Engine.expects(:new).with('foo', {:format =&gt; :html4}).returns(stub(:render =&gt; 'foo'))
-
-      get_it '/'
-      should.be.ok
-
-    end
+  it &quot;renders with file layouts&quot; do
+    haml_app {
+      haml 'Hello World', :layout =&gt; :layout2
+    }
+    should.be.ok
+    body.should.equal &quot;&lt;h1&gt;HAML Layout!&lt;/h1&gt;\n&lt;p&gt;Hello World&lt;/p&gt;\n&quot;
+  end
 
-    specify 'can be configured using set_option :haml' do
+  it &quot;raises error if template not found&quot; do
+    mock_app {
+      get('/') { haml :no_such_template }
+    }
+    lambda { get('/') }.should.raise(Errno::ENOENT)
+  end
 
-      configure do
-        set_option :haml, :format       =&gt; :html4,
-                          :escape_html  =&gt; true
-      end
+  it &quot;passes HAML options to the Haml engine&quot; do
+    haml_app {
+      haml &quot;!!!\n%h1 Hello World&quot;, :options =&gt; {:format =&gt; :html5}
+    }
+    should.be.ok
+    body.should.equal &quot;&lt;!DOCTYPE html&gt;\n&lt;h1&gt;Hello World&lt;/h1&gt;\n&quot;
+  end
 
+  it &quot;passes default HAML options to the Haml engine&quot; do
+    mock_app {
+      set :haml, {:format =&gt; :html5}
       get '/' do
-        haml 'foo'
+        haml &quot;!!!\n%h1 Hello World&quot;
       end
-
-      Haml::Engine.expects(:new).with('foo', {:format =&gt; :html4,
-        :escape_html =&gt; true}).returns(stub(:render =&gt; 'foo'))
-
-      get_it '/'
-      should.be.ok
-
-    end
-
+    }
+    get '/'
+    should.be.ok
+    body.should.equal &quot;&lt;!DOCTYPE html&gt;\n&lt;h1&gt;Hello World&lt;/h1&gt;\n&quot;
   end
-
 end</diff>
      <filename>test/haml_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,72 +1,124 @@
-require File.dirname(__FILE__) + '/helper'
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
 
-class FooError &lt; RuntimeError; end
+describe 'Exception Mappings' do
+  include Sinatra::Test
 
-context &quot;Mapped errors&quot; do
-
-  setup do
-    Sinatra.application = nil
-    Sinatra.application.options.raise_errors = false
+  class FooError &lt; RuntimeError
   end
 
-  specify &quot;are rescued and run in context&quot; do
-
-    error FooError do
-      'MAPPED ERROR!'
-    end
-
-    get '/' do
-      raise FooError
-    end
-
-    get_it '/'
-
-    should.be.server_error
-    body.should.equal 'MAPPED ERROR!'
-
+  it 'invokes handlers registered with ::error when raised' do
+    mock_app {
+      set :raise_errors, false
+      error(FooError) { 'Foo!' }
+      get '/' do
+        raise FooError
+      end
+    }
+    get '/'
+    status.should.equal 500
+    body.should.equal 'Foo!'
   end
 
-  specify &quot;renders empty if no each method on result&quot; do
-
-    error FooError do
-      nil
-    end
-
-    get '/' do
-      raise FooError
-    end
-
-    get_it '/'
-
-    should.be.server_error
-    body.should.be.empty
-
+  it 'uses the Exception handler if no matching handler found' do
+    mock_app {
+      set :raise_errors, false
+      error(Exception) { 'Exception!' }
+      get '/' do
+        raise FooError
+      end
+    }
+    get '/'
+    status.should.equal 500
+    body.should.equal 'Exception!'
   end
 
-  specify &quot;doesn't override status if set&quot; do
-
-    error FooError do
-      status(200)
-    end
+  it &quot;sets env['sinatra.error'] to the rescued exception&quot; do
+    mock_app {
+      set :raise_errors, false
+      error(FooError) {
+        env.should.include 'sinatra.error'
+        env['sinatra.error'].should.be.kind_of FooError
+        'looks good'
+      }
+      get '/' do
+        raise FooError
+      end
+    }
+    get '/'
+    body.should.equal 'looks good'
+  end
 
-    get '/' do
-      raise FooError
-    end
+  it &quot;raises without calling the handler when the raise_errors options is set&quot; do
+    mock_app {
+      set :raise_errors, true
+      error(FooError) { &quot;she's not there.&quot; }
+      get '/' do
+        raise FooError
+      end
+    }
+    lambda { get '/' }.should.raise FooError
+  end
 
-    get_it '/'
+  it &quot;never raises Sinatra::NotFound beyond the application&quot; do
+    mock_app {
+      set :raise_errors, true
+      get '/' do
+        raise Sinatra::NotFound
+      end
+    }
+    lambda { get '/' }.should.not.raise Sinatra::NotFound
+    status.should.equal 404
+  end
+end
 
-    should.be.ok
+describe 'Custom Error Pages' do
+  it 'allows numeric status code mappings to be registered with ::error' do
+    mock_app {
+      set :raise_errors, false
+      error(500) { 'Foo!' }
+      get '/' do
+        [500, {}, 'Internal Foo Error']
+      end
+    }
+    get '/'
+    status.should.equal 500
+    body.should.equal 'Foo!'
+  end
 
+  it 'allows ranges of status code mappings to be registered with :error' do
+    mock_app {
+      set :raise_errors, false
+      error(500..550) { &quot;Error: #{response.status}&quot; }
+      get '/' do
+        [507, {}, 'A very special error']
+      end
+    }
+    get '/'
+    status.should.equal 507
+    body.should.equal 'Error: 507'
   end
 
-  specify &quot;raises errors when the raise_errors option is set&quot; do
-    Sinatra.application.options.raise_errors = true
-    error FooError do
-    end
-    get '/' do
-      raise FooError
-    end
-    assert_raises(FooError) { get_it('/') }
+  class FooError &lt; RuntimeError
   end
 
+  it 'runs after exception mappings and overwrites body' do
+    mock_app {
+      set :raise_errors, false
+      error FooError do
+        response.status = 502
+        'from exception mapping'
+      end
+      error(500) { 'from 500 handler' }
+      error(502) { 'from custom error page' }
+
+      get '/' do
+        raise FooError
+      end
+    }
+    get '/'
+    status.should.equal 502
+    body.should.equal 'from custom error page'
+  end
 end</diff>
      <filename>test/mapped_error_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,57 +1,40 @@
-require File.dirname(__FILE__) + '/helper'
-
-context &quot;Sass&quot; do
-
-  setup do
-    Sinatra.application = nil
+require 'test/spec'
+require 'sinatra/base'
+require 'sinatra/test'
+
+describe &quot;Sass Templates&quot; do
+  include Sinatra::Test
+
+  def sass_app(&amp;block)
+    mock_app {
+      set :views, File.dirname(__FILE__) + '/views'
+      get '/', &amp;block
+    }
+    get '/'
   end
 
-  context &quot;Templates (in general)&quot; do
-
-    setup do
-      Sinatra.application = nil
-    end
-
-    specify &quot;are read from files if Symbols&quot; do
-
-      get '/from_file' do
-        sass :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views&quot;
-      end
-
-      get_it '/from_file'
-      should.be.ok
-      body.should.equal &quot;#sass {\n  background_color: #FFF; }\n&quot;
-
-    end
-
-    specify &quot;raise an error if template not found&quot; do
-      get '/' do
-        sass :not_found
-      end
-
-      lambda { get_it '/' }.should.raise(Errno::ENOENT)
-    end
-
-    specify &quot;ignore default layout file with .sass extension&quot; do
-      get '/' do
-        sass :foo, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
-
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;#sass {\n  background_color: #FFF; }\n&quot;
-    end
-
-    specify &quot;ignore explicitly specified layout file&quot; do
-      get '/' do
-        sass :foo, :layout =&gt; :layout, :views_directory =&gt; File.dirname(__FILE__) + &quot;/views/layout_test&quot;
-      end
+  it 'renders inline Sass strings' do
+    sass_app { sass &quot;#sass\n  :background-color #FFF\n&quot; }
+    should.be.ok
+    body.should.equal &quot;#sass {\n  background-color: #FFF; }\n&quot;
+  end
 
-      get_it '/'
-      should.be.ok
-      body.should.equal &quot;#sass {\n  background_color: #FFF; }\n&quot;
-    end
+  it 'renders .sass files in views path' do
+    sass_app { sass :hello }
+    should.be.ok
+    body.should.equal &quot;#sass {\n  background-color: #FFF; }\n&quot;
+  end
 
+  it 'ignores the layout option' do
+    sass_app { sass :hello, :layout =&gt; :layout2 }
+    should.be.ok
+    body.should.equal &quot;#sass {\n  background-color: #FFF; }\n&quot;
   end
 
+  it &quot;raises error if template not found&quot; do
+    mock_app {
+      get('/') { sass :no_such_template }
+    }
+    lambda { get('/') }.should.raise(Errno::ENOENT)
+  end
 end</diff>
      <filename>test/sass_test.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>images/404.png</filename>
    </removed>
    <removed>
      <filename>images/500.png</filename>
    </removed>
    <removed>
      <filename>lib/sinatra/test/methods.rb</filename>
    </removed>
    <removed>
      <filename>test/app_test.rb</filename>
    </removed>
    <removed>
      <filename>test/application_test.rb</filename>
    </removed>
    <removed>
      <filename>test/custom_error_test.rb</filename>
    </removed>
    <removed>
      <filename>test/event_context_test.rb</filename>
    </removed>
    <removed>
      <filename>test/events_test.rb</filename>
    </removed>
    <removed>
      <filename>test/helper.rb</filename>
    </removed>
    <removed>
      <filename>test/pipeline_test.rb</filename>
    </removed>
    <removed>
      <filename>test/public/foo.xml</filename>
    </removed>
    <removed>
      <filename>test/sessions_test.rb</filename>
    </removed>
    <removed>
      <filename>test/streaming_test.rb</filename>
    </removed>
    <removed>
      <filename>test/sym_params_test.rb</filename>
    </removed>
    <removed>
      <filename>test/template_test.rb</filename>
    </removed>
    <removed>
      <filename>test/use_in_file_templates_test.rb</filename>
    </removed>
    <removed>
      <filename>test/views/foo.builder</filename>
    </removed>
    <removed>
      <filename>test/views/foo.erb</filename>
    </removed>
    <removed>
      <filename>test/views/foo.haml</filename>
    </removed>
    <removed>
      <filename>test/views/foo.sass</filename>
    </removed>
    <removed>
      <filename>test/views/foo_layout.erb</filename>
    </removed>
    <removed>
      <filename>test/views/foo_layout.haml</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/foo.builder</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/foo.erb</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/foo.haml</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/foo.sass</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/layout.builder</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/layout.erb</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/layout.haml</filename>
    </removed>
    <removed>
      <filename>test/views/layout_test/layout.sass</filename>
    </removed>
    <removed>
      <filename>test/views/no_layout/no_layout.builder</filename>
    </removed>
    <removed>
      <filename>test/views/no_layout/no_layout.haml</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>d25e0208800e2fd69522e6b08e909c9c8d746b83</id>
    </parent>
  </parents>
  <author>
    <name>Ryan Tomayko</name>
    <email>rtomayko@gmail.com</email>
  </author>
  <url>http://github.com/rtomayko/sinatra/commit/a734cf38ac0e7ddee437c8d273de50f2a4053339</url>
  <id>a734cf38ac0e7ddee437c8d273de50f2a4053339</id>
  <committed-date>2008-12-20T18:45:28-08:00</committed-date>
  <authored-date>2008-12-13T13:06:02-08:00</authored-date>
  <message>I knew I shoulda taken that left turn at Hoboken

This is a fairly large reworking of Sinatra's innards. Although
most of the internal implementation has been modified, it
provides the same basic feature set and is meant to be compatible
with Sinatra 0.3.2.

* The Event and EventContext classes have been removed. Sinatra
  applications are now defined within the class context of a
  Sinatra::Base subclass; each request is processed within a new
  instance.

* Sinatra::Base can be used as a base class for multiple
  Rack applications within a single process and can be used as
  Rack middleware.

* The routing and result type processing implementation has been
  simplified and enhanced a bit. There's a new route conditions
  system for things like :agent/:host matching and a request
  level #pass method has been added to allow an event handler to
  exit immediately, passing control to the next matching route.

* Regular expressions may now be used in route patterns. Captures
  are available as an array from &quot;params[:captures]&quot;.

* The #body helper method now takes a block. The block is not
  evaluated until an attempt is made to read the body.

* Options are now dynamically generated class attributes on the
  Sinatra::Base subclass (instead of OpenStruct); options are
  inherited by subclasses and may be overridden up the
  inheritance hierarchy. The Base.set manages all option related
  stuff.

* The application file (app_file) detection heuristics are bit
  more sane now. This fixes some bugs with reloading and
  public/views directory detection. All thin / passenger issues
  of these type should be better now.

* Error mappings are now split into to distinct layers: exception
  mappings and custom error pages. Exception mappings are registered
  with 'error(Exception)' and are run only when the app raises an
  exception. Custom error pages are registered with error(status_code)
  and are run any time the response has the status code specified.
  It's also possible to register an error page for a range of status
  codes: 'error(500..599)'.

* The spec and unit testing extensions have been modified to take
  advantage of the ability to have multiple Sinatra applications.
  The Sinatra::Test module must be included within the TestCase
  in order to take advantage of these methods (unless the
  'sinatra/compat' library has been required).

* Rebuilt specs from scratch for better coverage and
  organization. Sinatra 3.2 unit tests have been retained
  under ./compat to ensure a baseline level of compatibility with
  previous versions; use the 'rake compat' task to run these.

A large number of existing Sinatra idioms have been deprecated but
continue to be supported through the 'sinatra/compat' library.

* The &quot;set_option&quot; and &quot;set_options&quot; methods have been deprecated
  due to redundancy; use &quot;set&quot;.

* The &quot;env&quot; option (Sinatra::Base.env) has been renamed to &quot;environment&quot;
  and deprecated because it's too easy to confuse with the request-level
  Rack environment Hash (Sinatra::Base#env).

* The request level &quot;stop&quot; method has been renamed &quot;halt&quot; and
  deprecated. This is for consistency with `throw :halt`.

* The request level &quot;entity_tag&quot; method has been renamed &quot;etag&quot; and
  deprecated. Both versions were previously supported.

* The request level &quot;headers&quot; method has been deprecated. Use
  response['Header-Name'] to access and modify response headers.

* Sinatra.application is deprecated. Use Sinatra::Application instead.

* Setting Sinatra.application = nil to reset an application is
  deprecated. You shouldn't have to reset objects anymore.

* The Sinatra.default_options Hash is deprecated. Modifying this object now
  results in &quot;set(key, value)&quot; invocations on the Sinatra::Base
  subclass.

* The &quot;body.to_result&quot; convention has been deprecated.

* The ServerError exception has been deprecated. Any Exception is now
  considered a ServerError.</message>
  <tree>9e373aedfdc65188ee38f703c73decf8882ffec6</tree>
  <committer>
    <name>Ryan Tomayko</name>
    <email>rtomayko@gmail.com</email>
  </committer>
</commit>
