<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>test/pipeline_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,11 +1,13 @@
 CHANGELOG
 images/404.png
 images/500.png
-index.html
 lib/sinatra/test/methods.rb
 lib/sinatra/test/spec.rb
 lib/sinatra/test/unit.rb
 lib/sinatra.rb
+LICENSE
+Manifest
+Rakefile
 README.rdoc
 test/app_test.rb
 test/application_test.rb
@@ -42,4 +44,79 @@ test/views/layout_test/layout.haml
 test/views/layout_test/layout.sass
 test/views/no_layout/no_layout.builder
 test/views/no_layout/no_layout.haml
-Manifest
+vendor/rack/AUTHORS
+vendor/rack/bin/rackup
+vendor/rack/contrib/rack_logo.svg
+vendor/rack/COPYING
+vendor/rack/example/lobster.ru
+vendor/rack/example/protectedlobster.rb
+vendor/rack/example/protectedlobster.ru
+vendor/rack/KNOWN-ISSUES
+vendor/rack/lib/rack/adapter/camping.rb
+vendor/rack/lib/rack/auth/abstract/handler.rb
+vendor/rack/lib/rack/auth/abstract/request.rb
+vendor/rack/lib/rack/auth/basic.rb
+vendor/rack/lib/rack/auth/digest/md5.rb
+vendor/rack/lib/rack/auth/digest/nonce.rb
+vendor/rack/lib/rack/auth/digest/params.rb
+vendor/rack/lib/rack/auth/digest/request.rb
+vendor/rack/lib/rack/auth/openid.rb
+vendor/rack/lib/rack/builder.rb
+vendor/rack/lib/rack/cascade.rb
+vendor/rack/lib/rack/commonlogger.rb
+vendor/rack/lib/rack/file.rb
+vendor/rack/lib/rack/handler/cgi.rb
+vendor/rack/lib/rack/handler/fastcgi.rb
+vendor/rack/lib/rack/handler/lsws.rb
+vendor/rack/lib/rack/handler/mongrel.rb
+vendor/rack/lib/rack/handler/scgi.rb
+vendor/rack/lib/rack/handler/webrick.rb
+vendor/rack/lib/rack/lint.rb
+vendor/rack/lib/rack/lobster.rb
+vendor/rack/lib/rack/mock.rb
+vendor/rack/lib/rack/recursive.rb
+vendor/rack/lib/rack/reloader.rb
+vendor/rack/lib/rack/request.rb
+vendor/rack/lib/rack/response.rb
+vendor/rack/lib/rack/session/abstract/id.rb
+vendor/rack/lib/rack/session/cookie.rb
+vendor/rack/lib/rack/session/memcache.rb
+vendor/rack/lib/rack/session/pool.rb
+vendor/rack/lib/rack/showexceptions.rb
+vendor/rack/lib/rack/showstatus.rb
+vendor/rack/lib/rack/static.rb
+vendor/rack/lib/rack/urlmap.rb
+vendor/rack/lib/rack/utils.rb
+vendor/rack/lib/rack.rb
+vendor/rack/Rakefile
+vendor/rack/README
+vendor/rack/test/cgi/lighttpd.conf
+vendor/rack/test/cgi/test
+vendor/rack/test/cgi/test.fcgi
+vendor/rack/test/cgi/test.ru
+vendor/rack/test/spec_rack_auth_basic.rb
+vendor/rack/test/spec_rack_auth_digest.rb
+vendor/rack/test/spec_rack_builder.rb
+vendor/rack/test/spec_rack_camping.rb
+vendor/rack/test/spec_rack_cascade.rb
+vendor/rack/test/spec_rack_cgi.rb
+vendor/rack/test/spec_rack_commonlogger.rb
+vendor/rack/test/spec_rack_fastcgi.rb
+vendor/rack/test/spec_rack_file.rb
+vendor/rack/test/spec_rack_lint.rb
+vendor/rack/test/spec_rack_lobster.rb
+vendor/rack/test/spec_rack_mock.rb
+vendor/rack/test/spec_rack_mongrel.rb
+vendor/rack/test/spec_rack_recursive.rb
+vendor/rack/test/spec_rack_request.rb
+vendor/rack/test/spec_rack_response.rb
+vendor/rack/test/spec_rack_session_cookie.rb
+vendor/rack/test/spec_rack_session_memcache.rb
+vendor/rack/test/spec_rack_session_pool.rb
+vendor/rack/test/spec_rack_showexceptions.rb
+vendor/rack/test/spec_rack_showstatus.rb
+vendor/rack/test/spec_rack_static.rb
+vendor/rack/test/spec_rack_urlmap.rb
+vendor/rack/test/spec_rack_utils.rb
+vendor/rack/test/spec_rack_webrick.rb
+vendor/rack/test/testrequest.rb</diff>
      <filename>Manifest</filename>
    </modified>
    <modified>
      <diff>@@ -88,7 +88,7 @@ If a file exists that maps to the REQUEST_PATH then it is served and the request
 
 = Views (if you need MVC)
 
-All views are looked up in:
+All file-based views are looked up in:
 
   root
     | - views/
@@ -150,12 +150,12 @@ This one is cool:
   
   __END__
   
-  ## layout
+  @@ layout
   X
   = yield
   X
   
-  ## index
+  @@ index
   %div.title Hello world!!!!!
   
 Try it!</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -82,7 +82,7 @@ module Sinatra
   module Version
     MAJOR = '0'
     MINOR = '2'
-    REVISION = '1'
+    REVISION = '3'
     def self.combined
       [MAJOR, MINOR, REVISION].join('.')
     end
@@ -96,19 +96,15 @@ module Sinatra
   def options
     application.options
   end
-  
+
   def application
-    unless @app 
-      @app = Application.new
-      Sinatra::Environment.setup!
-    end
-    @app
+    @app ||= Application.new
   end
-  
+
   def application=(app)
     @app = app
   end
-  
+
   def port
     application.options.port
   end
@@ -116,14 +112,10 @@ module Sinatra
   def env
     application.options.env
   end
-  
-  def build_application
-    app = application
-    app = Rack::Session::Cookie.new(app) if Sinatra.options.sessions == true
-    app = Rack::CommonLogger.new(app) if Sinatra.options.logging == true
-    app
-  end
-  
+
+  # Deprecated: use application instead of build_application.
+  alias :build_application :application
+
   def server
     @server ||= case options.server
     when &quot;mongrel&quot;
@@ -145,11 +137,10 @@ module Sinatra
   end
   
   def run
-    
     begin
       puts &quot;== Sinatra has taken the stage on port #{port} for #{env} with backup by #{server.name}&quot;
       require 'pp'
-      server.run(build_application, :Port =&gt; port) do |server|
+      server.run(application, :Port =&gt; port) do |server|
         trap(:INT) do
           server.stop
           puts &quot;\n== Sinatra has ended his set (crowd applauds)&quot;
@@ -158,9 +149,8 @@ module Sinatra
     rescue Errno::EADDRINUSE =&gt; e
       puts &quot;== Someone is already performing on port #{port}!&quot;
     end
-    
   end
-      
+
   class Event
 
     URI_CHAR = '[^/?:,&amp;#\.]'.freeze unless defined?(URI_CHAR)
@@ -830,17 +820,83 @@ module Sinatra
       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
-    
-    attr_reader :events, :errors, :templates, :filters
-    attr_reader :clearables, :reloading
-    
-    attr_writer :options
-    
+
+    # 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_options set_option enable disable use
+    ]
+
+    # 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?
       root = File.expand_path(File.dirname($0))
-      @@default_options ||= {
+      @default_options = {
         :run =&gt; true,
         :port =&gt; 4567,
         :env =&gt; :development,
@@ -848,19 +904,18 @@ module Sinatra
         :views =&gt; root + '/views',
         :public =&gt; root + '/public',
         :sessions =&gt; false,
-        :logging =&gt; true
+        :logging =&gt; true,
+        :raise_errors =&gt; false
       }
-    end
-    
-    def default_options
-      self.class.default_options
+      load_default_options_from_command_line!
+      @default_options
     end
 
-    
-    ##
-    # Load all options given on the command line
+    # 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 load_options!
+    def self.load_default_options_from_command_line! #:nodoc:
       require 'optparse'
       OptionParser.new do |op|
         op.on('-p port') { |port| default_options[:port] = port }
@@ -870,39 +925,104 @@ module Sinatra
       end.parse!(ARGV.dup.select { |o| o !~ /--name/ })
     end
 
-    # Called immediately after the application is initialized or reloaded to
-    # register default events. Events added here have dibs on requests since
-    # they appear first in the list.
-    def load_default_events!
-      events[:get] &lt;&lt; Static.new
+    # Determine whether the application is in the process of being
+    # reloaded.
+    def reloading?
+      @reloading == true
     end
 
-    def initialize
-      @clearables = [
-        @events = Hash.new { |hash, key| hash[key] = [] },
-        @errors = Hash.new,
-        @filters = Hash.new { |hash, key| hash[key] = [] },
-        @templates = Hash.new
-      ]
-      load_options!
-      load_default_events!
+    # 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
 
-    def define_event(method, path, options = {}, &amp;b)
-      events[method] &lt;&lt; event = Event.new(path, options, &amp;b)
-      event
+    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
-    
-    def define_template(name=:layout, &amp;b)
-      templates[name] = b
+
+    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
-    
-    def define_error(code, options = {}, &amp;b)
-      errors[code] = Error.new(code, &amp;b)
+
+    # 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
-    
-    def define_filter(type, &amp;b)
-      filters[:before] &lt;&lt; b
+
+    # 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
@@ -920,27 +1040,96 @@ module Sinatra
         errors[NotFound].invoke(request)
     end
 
-    def options
-      @options ||= OpenStruct.new(default_options)
+
+    # 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, &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 +type+ is +:before+, 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
+
     def development?
       options.env == :development
     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!
-      @reloading = true
       clearables.each(&amp;:clear)
-      load_default_events!
+      load_default_configuration!
+      @pipeline = nil
+      @reloading = true
       Kernel.load $0
       @reloading = false
-      Environment.setup!
     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 options.mutex
         mutex.synchronize { yield }
@@ -948,16 +1137,74 @@ module Sinatra
         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)
       reload! if development?
+      pipeline.call(env)
+    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)
       result = lookup(request)
-      context = EventContext.new(
-        request, 
-        Rack::Response.new,
-        result.params
-      )
+      context = EventContext.new(request, Rack::Response.new, result.params)
       context.status(result.status)
       begin
         returned = run_safely do
@@ -983,14 +1230,15 @@ module Sinatra
       context.body = body.kind_of?(String) ? [*body] : body
       context.finish
     end
-    
-  end
-  
-  
-  module Environment
-    extend self
-    
-    def setup!
+
+    # Called immediately after the application is initialized or reloaded to
+    # register default events, templates, and error handlers.
+    def load_default_configuration!
+
+      # The static event is always executed first.
+      events[:get] &lt;&lt; Static.new
+
+      # Default configuration for all environments.
       configure do
         error do
           raise request.env['sinatra.error'] if Sinatra.options.raise_errors
@@ -1087,50 +1335,27 @@ end&lt;pre&gt;
         end
       end
     end
-  end
-  
-end
 
-def get(path, options ={}, &amp;b)
-  Sinatra.application.define_event(:get, path, options, &amp;b)
-end
-
-def post(path, options ={}, &amp;b)
-  Sinatra.application.define_event(:post, path, options, &amp;b)
-end
+    private :load_default_configuration!
 
-def put(path, options ={}, &amp;b)
-  Sinatra.application.define_event(:put, path, options, &amp;b)
-end
+  end
 
-def delete(path, options ={}, &amp;b)
-  Sinatra.application.define_event(:delete, path, options, &amp;b)
 end
 
-def before(&amp;b)
-  Sinatra.application.define_filter(:before, &amp;b)
+# 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 error(type = Sinatra::ServerError, options = {}, &amp;b)
-  Sinatra.application.define_error(type, options, &amp;b)
-end
-
-def not_found(options = {}, &amp;b)
-  Sinatra.application.define_error(Sinatra::NotFound, options, &amp;b)
-end
-
-def layout(name = :layout, &amp;b)
-  Sinatra.application.define_template(name, &amp;b)
-end
-
-def template(name, &amp;b)
-  Sinatra.application.define_template(name, &amp;b)
-end
-
 def use_in_file_templates!
   require 'stringio'
   templates = IO.read(caller.first.split(':').first).split('__FILE__').last
@@ -1146,22 +1371,6 @@ def use_in_file_templates!
   end
 end
 
-def configures(*envs, &amp;b)
-  yield if  !Sinatra.application.reloading &amp;&amp; 
-            (envs.include?(Sinatra.application.options.env) ||
-            envs.empty?)
-end
-alias :configure :configures
-
-def set_options(opts)
-  Sinatra::Application.default_options.merge!(opts)
-  Sinatra.application.options = nil
-end
-
-def set_option(key, value)
-  set_options(key =&gt; value)
-end
-
 def mime(ext, type)
   Rack::File::MIME_TYPES[ext.to_s] = type
 end</diff>
      <filename>lib/sinatra.rb</filename>
    </modified>
    <modified>
      <diff>@@ -10,4 +10,4 @@ Sinatra::Application.default_options.merge!(
   :logging =&gt; false
 )
 
-Sinatra.application.options = nil
+Sinatra.application = nil</diff>
      <filename>lib/sinatra/test/unit.rb</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,14 @@ context &quot;Sinatra&quot; do
   setup do
     Sinatra.application = nil
   end
-  
+
+  specify &quot;should put all DSL methods on (main)&quot; do
+    object = Object.new
+    Sinatra::Application::FORWARD_METHODS.each do |method|
+      object.private_methods.should.include(method)
+    end
+  end
+
   specify &quot;should handle result of nil&quot; do
     get '/' do
       nil</diff>
      <filename>test/app_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -97,7 +97,53 @@ context &quot;An app returns&quot; do
   end
   
 end
-  
+
+context &quot;Application#configure blocks&quot; do
+
+  setup do
+    Sinatra.application = nil
+  end
+
+  specify &quot;run when no environment specified&quot; do
+    ref = false
+    configure { ref = true }
+    ref.should.equal true
+  end
+
+  specify &quot;run when matching environment specified&quot; do
+    ref = false
+    configure(:test) { ref = true }
+    ref.should.equal true
+  end
+
+  specify &quot;do not run when no matching environment specified&quot; do
+    configure(:foo) { flunk &quot;block should not have been executed&quot; }
+    configure(:development, :production, :foo) { flunk &quot;block should not have been executed&quot; }
+  end
+
+  specify &quot;accept multiple environments&quot; do
+    ref = false
+    configure(:foo, :test, :bar) { ref = true }
+    ref.should.equal true
+  end
+
+end
+
+context &quot;Default Application Configuration&quot; do
+
+  specify &quot;includes 404 and 500 error handlers&quot; do
+    Sinatra.application.errors.should.include(Sinatra::ServerError)
+    Sinatra.application.errors[Sinatra::ServerError].should.not.be.nil
+    Sinatra.application.errors.should.include(Sinatra::NotFound)
+    Sinatra.application.errors[Sinatra::NotFound].should.not.be.nil
+  end
+
+  specify &quot;includes Static event&quot; do
+    assert Sinatra.application.events[:get].any? { |e| Sinatra::Static === e }
+  end
+
+end
+
 context &quot;Events in an app&quot; do
   
   setup do
@@ -173,3 +219,69 @@ context &quot;Events in an app&quot; do
 end
 
 
+context &quot;Options in an app&quot; do
+
+  setup do
+    Sinatra.application = nil
+    @app = Sinatra::application
+  end
+
+  specify &quot;can be set singly on app&quot; do
+    @app.set :foo, 1234
+    @app.options.foo.should.equal 1234
+  end
+
+  specify &quot;can be set singly from top-level&quot; do
+    set_option :foo, 1234
+    @app.options.foo.should.equal 1234
+  end
+
+  specify &quot;can be set multiply on app&quot; do
+    @app.options.foo.should.be.nil
+    @app.set :foo =&gt; 1234,
+      :bar =&gt; 'hello, world'
+    @app.options.foo.should.equal 1234
+    @app.options.bar.should.equal 'hello, world'
+  end
+
+  specify &quot;can be set multiply from top-level&quot; do
+    @app.options.foo.should.be.nil
+    set_options :foo =&gt; 1234,
+      :bar =&gt; 'hello, world'
+    @app.options.foo.should.equal 1234
+    @app.options.bar.should.equal 'hello, world'
+  end
+
+  specify &quot;can be enabled on app&quot; do
+    @app.options.foo.should.be.nil
+    @app.enable :sessions, :foo, :bar
+    @app.options.sessions.should.equal true
+    @app.options.foo.should.equal true
+    @app.options.bar.should.equal true
+  end
+
+  specify &quot;can be enabled from top-level&quot; do
+    @app.options.foo.should.be.nil
+    enable :sessions, :foo, :bar
+    @app.options.sessions.should.equal true
+    @app.options.foo.should.equal true
+    @app.options.bar.should.equal true
+  end
+
+  specify &quot;can be disabled on app&quot; do
+    @app.options.foo.should.be.nil
+    @app.disable :sessions, :foo, :bar
+    @app.options.sessions.should.equal false
+    @app.options.foo.should.equal false
+    @app.options.bar.should.equal false
+  end
+
+  specify &quot;can be enabled from top-level&quot; do
+    @app.options.foo.should.be.nil
+    disable :sessions, :foo, :bar
+    @app.options.sessions.should.equal false
+    @app.options.foo.should.equal false
+    @app.options.bar.should.equal false
+  end
+
+end</diff>
      <filename>test/application_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,10 @@
 require File.dirname(__FILE__) + '/helper'
 
 context &quot;Sessions&quot; do
-  
-  specify &quot;should be off by default&quot; do
-    Sinatra.application = nil
 
+  setup { Sinatra.application = nil }
+
+  specify &quot;should be off by default&quot; do
     get '/asdf' do
       session[:test] = true
       &quot;asdf&quot;
@@ -18,10 +18,9 @@ context &quot;Sessions&quot; do
     assert ok?
     assert !include?('Set-Cookie')
   end
-  
+
   specify &quot;should be able to store data accross requests&quot; do
-    set_options(:sessions =&gt; true)
-    Sinatra.application = nil
+    set_option :sessions, true
 
     get '/foo' do
       session[:test] = true</diff>
      <filename>test/sessions_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1037fcbe71c76c58af859d0db1eca5f5b5401f90</id>
    </parent>
    <parent>
      <id>d2cfe06c3b177a351f5f16d186620ab2995759c9</id>
    </parent>
  </parents>
  <author>
    <name>Markus Prinz</name>
    <email>markus.prinz@nuclearsquid.com</email>
  </author>
  <url>http://github.com/cschneid/sinatra/commit/b73450982a48eb0bff302d413f036ff911379c9e</url>
  <id>b73450982a48eb0bff302d413f036ff911379c9e</id>
  <committed-date>2008-05-19T00:20:44-07:00</committed-date>
  <authored-date>2008-05-19T00:20:44-07:00</authored-date>
  <message>Merge commit 'bmizerany/master'</message>
  <tree>5a1275c09fd5087f0789a6436ae23ce7c2d4ffd7</tree>
  <committer>
    <name>Markus Prinz</name>
    <email>markus.prinz@nuclearsquid.com</email>
  </committer>
</commit>
