diff options
Diffstat (limited to 'test/test_session.rb')
-rw-r--r-- | test/test_session.rb | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/test/test_session.rb b/test/test_session.rb new file mode 100644 index 0000000..aef7d70 --- /dev/null +++ b/test/test_session.rb @@ -0,0 +1,342 @@ +# -*- encoding: binary -*- +require 'test/unit' +require 'pp' +require 'socket' +require 'kcar' + +class TestSession < Test::Unit::TestCase + def setup + @s, @c = UNIXSocket.pair + end + + def test_http_one_zero + pid = fork do + @s << "HTTP/1.0 200 OK\r\n\r\nHI" + @s.close + end + @s.close + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "200 OK" + assert headers.empty? + tmp = [] + assert ! body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal [ "HI" ], tmp + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert @c.closed? + end + + def test_http_keepalive + pid = fork do + @s << "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHI" + end + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "200 OK" + assert_equal({"Content-Length" => "2" }, headers) + tmp = [] + assert body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal [ "HI" ], tmp + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert ! @c.closed? + + pid = fork do + @s << "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n" + @s << "Connection: close\r\n\r\nBYE" + end + status, headers, body = @session.read + assert_equal status, "200 OK" + assert_equal({ "Content-Length" => "3", "Connection" => "close" }, headers) + tmp = [] + assert ! body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal [ "BYE" ], tmp + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert @c.closed? + end + + def test_http_keepalive_chunky + @session = Kcar::Session.new(@c) + pid = fork do + @s << "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n" + @s << "5\r\nabcde\r\n" + @s << "0\r\n\r\nHTTP/1.1 " # partial response + end + status, headers, body = @session.read + assert_equal status, "200 OK" + assert_equal({"Transfer-Encoding" => "chunked" }, headers) + tmp = [] + assert body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal [ "abcde" ], tmp + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert ! @c.closed? + assert_equal "HTTP/1.1 ", @session.buf + + pid = fork do + @s << "200 OK\r\nContent-Length: 3\r\n" + @s << "Connection: close\r\n\r\nBYE" + end + status, headers, body = @session.read + assert_equal status, "200 OK" + assert_equal({ "Content-Length" => "3", "Connection" => "close" }, headers) + tmp = [] + assert ! body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal [ "BYE" ], tmp + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert @c.closed? + end + + def test_http_no_body_keepalive + pid = fork { @s << "HTTP/1.1 100 Continue\r\n\r\n" } + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "100 Continue" + assert_equal({}, headers) + tmp = [] + assert body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert tmp.empty? + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert ! @c.closed? + + pid = fork { @s << "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nhello" } + @s.close + status, headers, body = @session.read + assert_equal status, "200 OK" + assert_equal({'Connection' => 'close'}, headers) + tmp = [] + assert ! body.parser.keepalive? + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal(%w(hello), tmp) + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert @c.closed? + end + + def test_trailers + pid = fork do + @s << "HTTP/1.1 200 OK\r\nTrailer: Foo\r\n" + @s << "Transfer-Encoding: chunked\r\n\r\n" + end + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { + "Trailer" => "Foo", + "Transfer-Encoding" => "chunked", + } + assert_equal(expect, headers) + assert body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "5\r\nhello\r\n0\r\nFoo: bar\r\n\r\n" } + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal %w(hello), tmp + expect['Foo'] = 'bar' + assert_equal(expect, headers) + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert ! @c.closed? + end + + def test_trailers_pass_through + pid = fork do + @s << "HTTP/1.1 200 OK\r\nTrailer: Foo\r\n" + @s << "Transfer-Encoding: chunked\r\n\r\n" + end + @session = Kcar::Session.new(@c, false) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { + "Trailer" => "Foo", + "Transfer-Encoding" => "chunked", + } + assert_equal(expect, headers) + assert body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "5\r\nhello\r\n0\r\nFoo: bar\r\n\r\n" } + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal ["5\r\n", "hello\r\n", "0\r\n", "Foo: bar\r\n\r\n"], tmp + expect['Foo'] = 'bar' + assert_equal(expect, headers) + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert ! @c.closed? + end + + def test_pass_through_one_oh + pid = fork do + @s << "HTTP/1.0 200 OK\r\n" + @s << "Content-Type: text/plain\r\n\r\n" + end + @session = Kcar::Session.new(@c, false) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { "Content-Type" => "text/plain", } + assert_equal(expect, headers) + assert ! body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "hello" } + @s.close + assert_nothing_raised { body.each { |chunk| tmp << chunk.dup } } + assert_equal %w(hello), tmp + assert_equal(expect, headers) + _, status = Process.waitpid2(pid) + assert status.success? + body.close + assert @c.closed? + end + + def test_trailers_burpy + pid = fork do + @s << "HTTP/1.1 200 OK\r\nTrailer: Foo\r\n" + @s << "Transfer-Encoding: chunked\r\n\r\n" + end + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { + "Trailer" => "Foo", + "Transfer-Encoding" => "chunked", + } + assert_equal(expect, headers) + assert body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "5\r\nhello\r\n0\r\nFoo: bar" } + rd, wr = IO.pipe + crlf_pid = fork do + wr.close + @s << rd.sysread(4) + end + rd.close + assert_nothing_raised do + first = true + body.each do |chunk| + tmp << chunk.dup + if first + first = false + wr.syswrite "\r\n\r\n" + end + end + end + assert_equal %w(hello), tmp + _, status = Process.waitpid2(pid) + assert status.success? + _, status = Process.waitpid2(crlf_pid) + assert status.success? + expect['Foo'] = 'bar' + assert_equal(expect, headers) + body.close + assert ! @c.closed? + end + + def test_pass_through_trailers_burpy + pid = fork do + @s << "HTTP/1.1 200 OK\r\nTrailer: Foo\r\n" + @s << "Transfer-Encoding: chunked\r\n\r\n" + end + @session = Kcar::Session.new(@c, false) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { + "Trailer" => "Foo", + "Transfer-Encoding" => "chunked", + } + assert_equal(expect, headers) + assert body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "5\r\nhello\r\n0\r\nFoo: bar" } + rd, wr = IO.pipe + crlf_pid = fork do + wr.close + @s << rd.sysread(4) + end + rd.close + assert_nothing_raised do + first = true + body.each do |chunk| + tmp << chunk.dup + if first + first = false + wr.syswrite "\r\n\r\n" + end + end + end + assert_equal ["5\r\n", "hello\r\n", "0\r\n", "Foo: bar\r\n\r\n"], tmp + _, status = Process.waitpid2(pid) + assert status.success? + _, status = Process.waitpid2(crlf_pid) + assert status.success? + expect['Foo'] = 'bar' + assert_equal(expect, headers) + body.close + assert ! @c.closed? + end + + def test_identity_burpy + pid = fork { @s << "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n" } + @session = Kcar::Session.new(@c) + status, headers, body = @session.read + assert_equal status, "200 OK" + expect = { "Content-Length" => '5' } + assert_equal(expect, headers) + assert body.parser.keepalive? + _, status = Process.waitpid2(pid) + assert status.success? + tmp = [] + pid = fork { @s << "h" } + rd, wr = IO.pipe + crlf_pid = fork do + wr.close + @s << rd.sysread(4) + end + rd.close + assert_nothing_raised do + first = true + body.each do |chunk| + tmp << chunk.dup + if first + first = false + wr.syswrite "ello" + end + end + end + assert_equal %w(h ello), tmp + _, status = Process.waitpid2(pid) + assert status.success? + _, status = Process.waitpid2(crlf_pid) + assert status.success? + assert_equal(expect, headers) + body.close + assert ! @c.closed? + end + +end |