From b895d3d0393a647d3602783bc53bf68e223e51c9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 6 Jun 2010 05:17:14 +0000 Subject: pass-through body.to_path when wrapping the body Certain configurations of Rainbows! (and Zbatery) are able to use the return value of body.to_path to serve static files more efficiently. This also allows middleware like Rack::Contrib::Sendfile to work properly higher up the stack, too. --- test/test_clogger_to_path.rb | 140 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 test/test_clogger_to_path.rb (limited to 'test') diff --git a/test/test_clogger_to_path.rb b/test/test_clogger_to_path.rb new file mode 100644 index 0000000..4da3103 --- /dev/null +++ b/test/test_clogger_to_path.rb @@ -0,0 +1,140 @@ +# -*- encoding: binary -*- +$stderr.sync = $stdout.sync = true +require "test/unit" +require "date" +require "stringio" +require "rack" +require "clogger" + +class MyBody < Struct.new(:to_path, :closed) + def each(&block) + raise RuntimeError, "each should never get called" + end + + def close + self.closed = true + end +end + +class TestCloggerToPath < Test::Unit::TestCase + + def setup + @req = { + "REQUEST_METHOD" => "GET", + "HTTP_VERSION" => "HTTP/1.0", + "HTTP_USER_AGENT" => 'echo and socat \o/', + "PATH_INFO" => "/", + "QUERY_STRING" => "", + "rack.errors" => $stderr, + "rack.input" => File.open('/dev/null', 'rb'), + "REMOTE_ADDR" => '127.0.0.1', + } + end + + def test_wraps_to_path + logger = StringIO.new + tmp = Tempfile.new('') + b = nil + app = Rack::Builder.new do + tmp.syswrite(' ' * 365) + h = { + 'Content-Length' => '0', + 'Content-Type' => 'text/plain', + } + use Clogger, + :logger => logger, + :reentrant => true, + :format => '$body_bytes_sent $status' + run lambda { |env| [ 200, h, b = MyBody.new(tmp.path) ] } + end.to_app + + status, headers, body = app.call(@req) + assert_instance_of(Clogger::ToPath, body) + assert logger.string.empty? + assert_equal tmp.path, body.to_path + body.close + assert b.closed, "close passed through" + assert_equal "365 200\n", logger.string + end + + def test_wraps_to_path_dev_fd + logger = StringIO.new + tmp = Tempfile.new('') + b = nil + app = Rack::Builder.new do + tmp.syswrite(' ' * 365) + h = { + 'Content-Length' => '0', + 'Content-Type' => 'text/plain', + } + use Clogger, + :logger => logger, + :reentrant => true, + :format => '$body_bytes_sent $status' + run lambda { |env| [ 200, h, b = MyBody.new("/dev/fd/#{tmp.fileno}") ] } + end.to_app + + status, headers, body = app.call(@req) + assert_instance_of(Clogger::ToPath, body) + assert logger.string.empty? + assert_equal "/dev/fd/#{tmp.fileno}", body.to_path + body.close + assert b.closed + assert_equal "365 200\n", logger.string + end + + def test_wraps_to_path_to_io + logger = StringIO.new + tmp = Tempfile.new('') + def tmp.to_io + @to_io_called = super + end + def tmp.to_path + path + end + app = Rack::Builder.new do + tmp.syswrite(' ' * 365) + tmp.sysseek(0) + h = { + 'Content-Length' => '0', + 'Content-Type' => 'text/plain', + } + use Clogger, + :logger => logger, + :reentrant => true, + :format => '$body_bytes_sent $status' + run lambda { |env| [ 200, h, tmp ] } + end.to_app + + status, headers, body = app.call(@req) + assert_instance_of(Clogger::ToPath, body) + body.to_path + assert_kind_of IO, tmp.instance_variable_get(:@to_io_called) + assert logger.string.empty? + assert ! tmp.closed? + body.close + assert tmp.closed? + assert_equal "365 200\n", logger.string + end + + def test_does_not_wrap_to_path + logger = StringIO.new + app = Rack::Builder.new do + h = { + 'Content-Length' => '3', + 'Content-Type' => 'text/plain', + } + use Clogger, + :logger => logger, + :reentrant => true, + :format => '$body_bytes_sent $status' + run lambda { |env| [ 200, h, [ "hi\n" ] ] } + end.to_app + status, headers, body = app.call(@req) + assert_instance_of(Clogger, body) + assert logger.string.empty? + body.close + assert ! logger.string.empty? + end + +end -- cgit v1.2.3-24-ge0c7