# Copyright (C) 2013, Eric Wong and all contributors # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) require_relative 'server_helper' require 'digest/md5' class TestInput < Testcase ENV["N"].to_i > 1 and parallelize_me! include ServerHelper alias setup server_helper_setup alias teardown server_helper_teardown MD5 = lambda do |e| input = e["rack.input"] buf = "" md5 = Digest::MD5.new while input.read(16384, buf) md5 << buf end body = md5.hexdigest h = { "Content-Length" => body.size.to_s, "Content-Type" => 'text/plain' } [ 200, h, [body] ] end def test_input_timeout_lazybuffer stream_input_timeout(:lazy) end def test_input_timeout_nobuffer stream_input_timeout(false) end def stream_input_timeout(ibtype) err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1] cfg.instance_eval do GTL.synchronize do app(:rack, MD5) do listen "#{host}:#{port}" input_buffering ibtype client_timeout 1 end end stderr_path err.path end pid = mkserver(cfg) c = get_tcp_client(host, port) c.write "PUT / HTTP/1.1\r\nContent-Length: 666\r\n\r\n" assert_equal c, c.wait(6) Timeout.timeout(30) { assert_match %r{HTTP/1\.1 408 }, c.read } c.close ensure quit_wait(pid) end def input_server(ru, ibtype) err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1] cfg.instance_eval do GTL.synchronize do app(:rack, ru) { listen "#{host}:#{port}"; input_buffering ibtype } end stderr_path err.path end pid = mkserver(cfg) [ host, port, pid ] end def test_read_negative_lazy; _read_neg(:lazy); end def test_read_negative_nobuffer; _read_neg(false); end def _read_neg(ibtype) ru = lambda do |env| rv = [] input = env["rack.input"] begin input.read(-1) rescue => e rv << e.class.to_s end rv << input.read rv << input.read(1).nil? rv = rv.join(",") h = { "Content-Length" => rv.size.to_s } [ 200, h, [ rv ] ] end host, port, pid = input_server(ru, ibtype) c = get_tcp_client(host, port) c.write "PUT / HTTP/1.0\r\nContent-Length: 5\r\n\r\nhello" assert_equal c, c.wait(30) head, body = c.read.split(/\r\n\r\n/) assert_match %r{ 200 OK}, head exc, full, final = body.split(/,/) assert_equal "hello", full assert_equal "ArgumentError", exc assert_equal true.to_s, final c.close ensure quit_wait(pid) end def test_gets_lazy; _gets(:lazy); end def test_gets_nobuffer; _gets(false); end def _gets(ibtype) in_join = lambda do |input| rv = [] while line = input.gets rv << line end rv.join(",") end ru = lambda do |env| rv = in_join.call(env["rack.input"]) h = { "Content-Length" => rv.size.to_s } [ 200, h, [ rv ] ] end host, port, pid = input_server(ru, ibtype) c = get_tcp_client(host, port) buf = "a\nb\n\n" c.write "PUT / HTTP/1.0\r\nContent-Length: 5\r\n\r\n#{buf}" assert_equal c, c.wait(30) head, body = c.read.split(/\r\n\r\n/) assert_match %r{ 200 OK}, head expect = in_join.call(StringIO.new(buf)) assert_equal expect, body c.close ensure quit_wait(pid) end end