lib/tap/test/http_test.rb in tap-http-0.2.1 vs lib/tap/test/http_test.rb in tap-http-0.3.0

- old
+ new

@@ -1,150 +1,65 @@ +require 'rack' require 'webrick' -require 'singleton' +require 'thread' require 'tap/test/subset_test' -require 'pp' +require 'stringio' module Tap module Test # HttpTest facilitates testing of HTTP requests by initializing a # Webrick server that echos requests, and providing methods to # validate echoed requests. # module HttpTest - - # Server echos back all requests. - class Server - include Singleton - include WEBrick - - attr_accessor :server_thread, :server + + class MockServer + def initialize(body, status=200, headers={}) + @response = [status, headers, [body]] + end - def initialize - # set the default log level to warn to prevent general access logs, unless otherwise specified - log_level = ENV["WEB_LOG_LEVEL"] ? ENV["WEB_LOG_LEVEL"].upcase : "WARN" - logger = Log.new($stderr, Log.const_get( log_level ) ) - - self.server = HTTPServer.new(:Port => 2000, - :Logger => logger, - :AccessLog => [ - [ logger, AccessLog::COMMON_LOG_FORMAT ], - [ logger, AccessLog::REFERER_LOG_FORMAT ]]) - - server.mount_proc("/") do |req, res| - res.body << req.request_line - res.body << req.raw_header.join('') - - # an extra line must be added to delimit the headers from the body. - if req.body - res.body << "\r\n" - res.body << req.body - end - - res['Content-Type'] = "text/html" - end + def call(env) + @response end - - # Starts the server on a new thread. - def start_web_server - self.server_thread ||= Thread.new { server.start } + end + + class EchoServer + def self.call(env) + body = env['rack.input'].read + headers = {} + env.each_pair {|key, value| headers[key] = [value] unless key =~ /^rack/ } + + [200, headers, [body]] end end def self.included(base) base.send(:include, Tap::Test::SubsetTest) end - # WEB subset of tests. Starts HTTPTest::Server if necessary - # and yields to the block. - def web_test - subset_test("WEB", "w") do - Server.instance.start_web_server - yield - end + def default_config(log_dev=StringIO.new('')) + common_logger = WEBrick::Log.new(log_dev, WEBrick::Log.const_get(:WARN) ) + { + :Port => 2000, + :Logger => common_logger, + :AccessLog => common_logger + } end - REQUEST_ATTRIBUTES = %w{ - request_method http_version - - host port path - script_name path_info - - header cookies query - accept accept_charset - accept_encoding accept_language - - user - addr peeraddr - attributes - keep_alive} - - UNCHECKED_REQUEST_ATTRIBUTES = %w{ - request_line - unparsed_uri - request_uri - request_time - raw_header - query_string} - - # Parses expected and actual as an http request (using Tap::Net.parse_http_request) - # and asserts that all of the REQUEST_ATTRIBUTES are equal. See the parse_http_request - # documentation for some important notes, particularly involving "\r\n" vs "\n" and - # post requests. - def assert_request_equal(expected, actual) - e = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) - e.parse( StringIO.new(expected) ) - - a = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP) - a.parse( StringIO.new(actual) ) - - errors = [] - REQUEST_ATTRIBUTES.each do |attribute| - exp = e.send(attribute) - act = a.send(attribute) - next if exp == act - errors << "<#{PP.singleline_pp(exp, '')}> expected for #{attribute} but was:\n<#{PP.singleline_pp(act, '')}>." + def web_test(app=EchoServer, config=default_config) + subset_test("WEB", "w") do + begin + server = ::WEBrick::HTTPServer.new(config); + server.mount("/", Rack::Handler::WEBrick, app); + Thread.new { server.start } + yield + ensure + server.shutdown + end end - - if errors.empty? - # this rather unecessary assertion is used simply to - # make assert_request_equal cause an assertion. - assert errors.empty? - else - flunk errors.join("\n") - end end - # Convenience method that strips str, strips each line of str, and - # then rejoins them using "\r\n" as is typical of HTTP messages. - # - # strip_align %Q{ - # GET /echo HTTP/1.1 - # Accept: */* - # Host: localhost:2000} - # - # # => "GET /echo HTTP/1.1\r\nAccept: */*\r\nHost: localhost:2000\r\n" - def strip_align(str) - str.strip.split(/\r?\n/).collect do |line| - "#{line.strip}\r\n" - end.compact.join('') - end - - # Turns a hash of parameters into an encoded HTTP query string. - # Multiple values for a given key can be specified by an array. - # - # to_query('key' => 'value', 'array' => ['one', 'two']) # => "array=one&array=two&key=value" - # - # Note: the order of the parameters in the result is determined - # by hash.each_pair and is thus fairly unpredicatable. - def to_query(hash) - query = [] - hash.each_pair do |key,values| - values = values.kind_of?(Array) ? values : [values] - values.each { |value| query << "#{key}=#{value}" } - end - URI.encode(query.join('&')) - end end end end