summaryrefslogtreecommitdiff
path: root/jni/ruby/test/webrick
diff options
context:
space:
mode:
Diffstat (limited to 'jni/ruby/test/webrick')
-rw-r--r--jni/ruby/test/webrick/.htaccess1
-rw-r--r--jni/ruby/test/webrick/test_cgi.rb151
-rw-r--r--jni/ruby/test/webrick/test_cookie.rb131
-rw-r--r--jni/ruby/test/webrick/test_filehandler.rb309
-rw-r--r--jni/ruby/test/webrick/test_htmlutils.rb20
-rw-r--r--jni/ruby/test/webrick/test_httpauth.rb198
-rw-r--r--jni/ruby/test/webrick/test_httpproxy.rb284
-rw-r--r--jni/ruby/test/webrick/test_httprequest.rb411
-rw-r--r--jni/ruby/test/webrick/test_httpresponse.rb149
-rw-r--r--jni/ruby/test/webrick/test_httpserver.rb412
-rw-r--r--jni/ruby/test/webrick/test_httputils.rb100
-rw-r--r--jni/ruby/test/webrick/test_httpversion.rb40
-rw-r--r--jni/ruby/test/webrick/test_server.rb131
-rw-r--r--jni/ruby/test/webrick/test_utils.rb64
-rw-r--r--jni/ruby/test/webrick/utils.rb70
-rw-r--r--jni/ruby/test/webrick/webrick.cgi36
-rw-r--r--jni/ruby/test/webrick/webrick_long_filename.cgi36
17 files changed, 2543 insertions, 0 deletions
diff --git a/jni/ruby/test/webrick/.htaccess b/jni/ruby/test/webrick/.htaccess
new file mode 100644
index 0000000..69d4659
--- /dev/null
+++ b/jni/ruby/test/webrick/.htaccess
@@ -0,0 +1 @@
+this file should not be published.
diff --git a/jni/ruby/test/webrick/test_cgi.rb b/jni/ruby/test/webrick/test_cgi.rb
new file mode 100644
index 0000000..5507dfe
--- /dev/null
+++ b/jni/ruby/test/webrick/test_cgi.rb
@@ -0,0 +1,151 @@
+# coding: US-ASCII
+require_relative "utils"
+require "webrick"
+require "test/unit"
+
+class TestWEBrickCGI < Test::Unit::TestCase
+ CRLF = "\r\n"
+
+ def start_cgi_server(log_tester=TestWEBrick::DefaultLogTester, &block)
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :DirectoryIndex => ["webrick.cgi"],
+ :RequestCallback => Proc.new{|req, res|
+ def req.meta_vars
+ meta = super
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
+ return meta
+ end
+ },
+ }
+ if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
+ config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
+ end
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ block.call(server, addr, port, log)
+ }
+ end
+
+ def test_cgi
+ start_cgi_server{|server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi/path/info")
+ http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
+ http.request(req){|res| assert_equal("/???", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
+ # Path info of res.body is passed via ENV.
+ # ENV[] returns different value on Windows depending on locale.
+ unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/ &&
+ Encoding.find("locale") != Encoding.find("filesystem")
+ http.request(req){|res|
+ assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
+ end
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
+
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1;a=2;b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1&a=2&b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ ary = res.body.lines.to_a
+ assert_match(%r{/$}, ary[0], log.call)
+ assert_match(%r{/webrick.cgi$}, ary[1], log.call)
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
+ http.request(req){|res|
+ assert_equal(
+ "CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
+ res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ cookie = %{$Version="1"; }
+ cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
+ cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
+ cookie << %{Shipping="FedEx"; $Path="/acme"}
+ req["Cookie"] = cookie
+ http.request(req){|res|
+ assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
+ res["Set-Cookie"], log.call)
+ assert_equal("Customer=WILE_E_COYOTE\n" +
+ "Part_Number=Rocket_Launcher_0001\n" +
+ "Shipping=FedEx\n", res.body, log.call)
+ }
+ }
+ end
+
+ def test_bad_request
+ log_tester = lambda {|log, access_log|
+ assert_match(/BadRequest/, log.join)
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ sock = TCPSocket.new(addr, port)
+ begin
+ sock << "POST /webrick.cgi HTTP/1.0" << CRLF
+ sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
+ sock << "Content-Length: 1024" << CRLF
+ sock << CRLF
+ sock << "a=1&a=2&b=x"
+ sock.close_write
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
+ ensure
+ sock.close
+ end
+ }
+ end
+
+ CtrlSeq = [0x7f, *(1..31)].pack("C*").gsub(/\s+/, '')
+ CtrlPat = /#{Regexp.quote(CtrlSeq)}/o
+ DumpPat = /#{Regexp.quote(CtrlSeq.dump[1...-1])}/o
+
+ def test_bad_uri
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/ERROR bad URI/, log[0])
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ res = TCPSocket.open(addr, port) {|sock|
+ sock << "GET /#{CtrlSeq}#{CRLF}#{CRLF}"
+ sock.close_write
+ sock.read
+ }
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
+ s = log.call.each_line.grep(/ERROR bad URI/)[0]
+ assert_match(DumpPat, s)
+ assert_not_match(CtrlPat, s)
+ }
+ end
+
+ def test_bad_header
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/ERROR bad header/, log[0])
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ res = TCPSocket.open(addr, port) {|sock|
+ sock << "GET / HTTP/1.0#{CRLF}#{CtrlSeq}#{CRLF}#{CRLF}"
+ sock.close_write
+ sock.read
+ }
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
+ s = log.call.each_line.grep(/ERROR bad header/)[0]
+ assert_match(DumpPat, s)
+ assert_not_match(CtrlPat, s)
+ }
+ end
+end
diff --git a/jni/ruby/test/webrick/test_cookie.rb b/jni/ruby/test/webrick/test_cookie.rb
new file mode 100644
index 0000000..1652f39
--- /dev/null
+++ b/jni/ruby/test/webrick/test_cookie.rb
@@ -0,0 +1,131 @@
+require "test/unit"
+require "webrick/cookie"
+
+class TestWEBrickCookie < Test::Unit::TestCase
+ def test_new
+ cookie = WEBrick::Cookie.new("foo","bar")
+ assert_equal("foo", cookie.name)
+ assert_equal("bar", cookie.value)
+ assert_equal("foo=bar", cookie.to_s)
+ end
+
+ def test_time
+ cookie = WEBrick::Cookie.new("foo","bar")
+ t = 1000000000
+ cookie.max_age = t
+ assert_match(t.to_s, cookie.to_s)
+
+ cookie = WEBrick::Cookie.new("foo","bar")
+ t = Time.at(1000000000)
+ cookie.expires = t
+ assert_equal(Time, cookie.expires.class)
+ assert_equal(t, cookie.expires)
+ ts = t.httpdate
+ cookie.expires = ts
+ assert_equal(Time, cookie.expires.class)
+ assert_equal(t, cookie.expires)
+ assert_match(ts, cookie.to_s)
+ end
+
+ def test_parse
+ data = ""
+ data << '$Version="1"; '
+ data << 'Customer="WILE_E_COYOTE"; $Path="/acme"; '
+ data << 'Part_Number="Rocket_Launcher_0001"; $Path="/acme"; '
+ data << 'Shipping="FedEx"; $Path="/acme"'
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(3, cookies.size)
+ assert_equal(1, cookies[0].version)
+ assert_equal("Customer", cookies[0].name)
+ assert_equal("WILE_E_COYOTE", cookies[0].value)
+ assert_equal("/acme", cookies[0].path)
+ assert_equal(1, cookies[1].version)
+ assert_equal("Part_Number", cookies[1].name)
+ assert_equal("Rocket_Launcher_0001", cookies[1].value)
+ assert_equal(1, cookies[2].version)
+ assert_equal("Shipping", cookies[2].name)
+ assert_equal("FedEx", cookies[2].value)
+
+ data = "hoge=moge; __div__session=9865ecfd514be7f7"
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(0, cookies[0].version)
+ assert_equal("hoge", cookies[0].name)
+ assert_equal("moge", cookies[0].value)
+ assert_equal("__div__session", cookies[1].name)
+ assert_equal("9865ecfd514be7f7", cookies[1].value)
+ end
+
+ def test_parse_no_whitespace
+ data = [
+ '$Version="1"; ',
+ 'Customer="WILE_E_COYOTE";$Path="/acme";', # no SP between cookie-string
+ 'Part_Number="Rocket_Launcher_0001";$Path="/acme";', # no SP between cookie-string
+ 'Shipping="FedEx";$Path="/acme"'
+ ].join
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(1, cookies.size)
+ end
+
+ def test_parse_too_much_whitespaces
+ # According to RFC6265,
+ # cookie-string = cookie-pair *( ";" SP cookie-pair )
+ # So single 0x20 is needed after ';'. We allow multiple spaces here for
+ # compatibility with older WEBrick versions.
+ data = [
+ '$Version="1"; ',
+ 'Customer="WILE_E_COYOTE";$Path="/acme"; ', # no SP between cookie-string
+ 'Part_Number="Rocket_Launcher_0001";$Path="/acme"; ', # no SP between cookie-string
+ 'Shipping="FedEx";$Path="/acme"'
+ ].join
+ cookies = WEBrick::Cookie.parse(data)
+ assert_equal(3, cookies.size)
+ end
+
+ def test_parse_set_cookie
+ data = %(Customer="WILE_E_COYOTE"; Version="1"; Path="/acme")
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
+ assert_equal("Customer", cookie.name)
+ assert_equal("WILE_E_COYOTE", cookie.value)
+ assert_equal(1, cookie.version)
+ assert_equal("/acme", cookie.path)
+
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
+ cookie = WEBrick::Cookie.parse_set_cookie(data)
+ assert_equal("Shipping", cookie.name)
+ assert_equal("FedEx", cookie.value)
+ assert_equal(1, cookie.version)
+ assert_equal("/acme", cookie.path)
+ assert_equal(true, cookie.secure)
+ end
+
+ def test_parse_set_cookies
+ data = %(Shipping="FedEx"; Version="1"; Path="/acme"; Secure)
+ data << %(, CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT; path=/; Secure)
+ data << %(, name="Aaron"; Version="1"; path="/acme")
+ cookies = WEBrick::Cookie.parse_set_cookies(data)
+ assert_equal(3, cookies.length)
+
+ fed_ex = cookies.find { |c| c.name == 'Shipping' }
+ assert_not_nil(fed_ex)
+ assert_equal("Shipping", fed_ex.name)
+ assert_equal("FedEx", fed_ex.value)
+ assert_equal(1, fed_ex.version)
+ assert_equal("/acme", fed_ex.path)
+ assert_equal(true, fed_ex.secure)
+
+ name = cookies.find { |c| c.name == 'name' }
+ assert_not_nil(name)
+ assert_equal("name", name.name)
+ assert_equal("Aaron", name.value)
+ assert_equal(1, name.version)
+ assert_equal("/acme", name.path)
+
+ customer = cookies.find { |c| c.name == 'CUSTOMER' }
+ assert_not_nil(customer)
+ assert_equal("CUSTOMER", customer.name)
+ assert_equal("WILE_E_COYOTE", customer.value)
+ assert_equal(0, customer.version)
+ assert_equal("/", customer.path)
+ assert_equal(Time.utc(1999, 11, 9, 23, 12, 40), customer.expires)
+ end
+end
diff --git a/jni/ruby/test/webrick/test_filehandler.rb b/jni/ruby/test/webrick/test_filehandler.rb
new file mode 100644
index 0000000..f984efb
--- /dev/null
+++ b/jni/ruby/test/webrick/test_filehandler.rb
@@ -0,0 +1,309 @@
+require "test/unit"
+require_relative "utils.rb"
+require "webrick"
+require "stringio"
+
+class WEBrick::TestFileHandler < Test::Unit::TestCase
+ def default_file_handler(filename)
+ klass = WEBrick::HTTPServlet::DefaultFileHandler
+ klass.new(WEBrick::Config::HTTP, filename)
+ end
+
+ def windows?
+ File.directory?("\\")
+ end
+
+ def get_res_body(res)
+ body = res.body
+ if defined? body.read
+ begin
+ body.read
+ ensure
+ body.close
+ end
+ else
+ body
+ end
+ end
+
+ def make_range_request(range_spec)
+ msg = <<-END_OF_REQUEST
+ GET / HTTP/1.0
+ Range: #{range_spec}
+
+ END_OF_REQUEST
+ return StringIO.new(msg.gsub(/^ {6}/, ""))
+ end
+
+ def make_range_response(file, range_spec)
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(make_range_request(range_spec))
+ res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
+ size = File.size(file)
+ handler = default_file_handler(file)
+ handler.make_partial_content(req, res, file, size)
+ return res
+ end
+
+ def test_make_partial_content
+ filename = __FILE__
+ filesize = File.size(filename)
+
+ res = make_range_response(filename, "bytes=#{filesize-100}-")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=-100")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-99")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=100-199")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-0")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(1, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=-1")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(1, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-0, -2")
+ assert_match(%r{^multipart/byteranges}, res["content-type"])
+ end
+
+ def test_filehandler
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ filesize = File.size(__FILE__)
+ this_data = File.open(__FILE__, "rb") {|f| f.read}
+ range = nil
+ bug2593 = '[ruby-dev:40030]'
+
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
+ assert_match(/HREF="#{this_file}"/, res.body, log.call)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_equal(File.read(__FILE__), res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
+ assert_equal(this_data[-100..-1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
+ assert_equal(this_data[-100..-1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(0..99, range, log.call)
+ assert_equal(this_data[0..99], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(100..199, range, log.call)
+ assert_equal(this_data[100..199], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(0..0, range, log.call)
+ assert_equal(this_data[0..0], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-1)..(filesize-1), range, log.call)
+ assert_equal(this_data[-1, 1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("multipart/byteranges", res.content_type, log.call)
+ }
+
+ end
+ end
+
+ def test_non_disclosure_name
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*' not found\./ =~ s }
+ log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
+ assert_equal([], log)
+ }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ doc_root_opts = server[:DocumentRootOptions]
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
+ assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("404", res.code, log.call)
+ }
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
+ http.request(req){|res|
+ assert_equal("404", res.code, log.call)
+ }
+ end
+ end
+
+ def test_directory_traversal
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR bad URI/ =~ s }
+ log = log.reject {|s| /ERROR `.*' not found\./ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/../../")
+ http.request(req){|res| assert_equal("400", res.code, log.call) }
+ req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
+ http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
+ http.request(req){|res| assert_equal("404", res.code, log.call) }
+ end
+ end
+
+ def test_unwise_in_path
+ if windows?
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/..%5c..")
+ http.request(req){|res| assert_equal("301", res.code, log.call) }
+ end
+ end
+ end
+
+ def test_short_filename
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*' not found\./ =~ s }
+ log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ if windows?
+ fname = nil
+ Dir.chdir(config[:DocumentRoot]) do
+ fname = `dir /x webrick_long_filename.cgi`.match(/\s(w.+?cgi)\s/i)[1].downcase
+ end
+ else
+ fname = "webric~1.cgi"
+ end
+ req = Net::HTTP::Get.new("/#{fname}/test")
+ http.request(req) do |res|
+ if windows?
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ else
+ assert_equal("404", res.code, log.call)
+ end
+ end
+
+ req = Net::HTTP::Get.new("/.htaccess")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/htacce~1")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/HTACCE~1")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ end
+ end
+
+ def test_script_disclosure
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ :RequestCallback => Proc.new{|req, res|
+ def req.meta_vars
+ meta = super
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
+ return meta
+ end
+ },
+ }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*' not found\./ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/webrick.cgi/test")
+ http.request(req) do |res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ end
+
+ resok = windows?
+ response_assertion = Proc.new do |res|
+ if resok
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ else
+ assert_equal("404", res.code, log.call)
+ end
+ end
+ req = Net::HTTP::Get.new("/webrick.cgi%20/test")
+ http.request(req, &response_assertion)
+ req = Net::HTTP::Get.new("/webrick.cgi./test")
+ http.request(req, &response_assertion)
+ resok &&= File.exist?(__FILE__+"::$DATA")
+ req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
+ http.request(req, &response_assertion)
+ end
+ end
+end
diff --git a/jni/ruby/test/webrick/test_htmlutils.rb b/jni/ruby/test/webrick/test_htmlutils.rb
new file mode 100644
index 0000000..1fe49ee
--- /dev/null
+++ b/jni/ruby/test/webrick/test_htmlutils.rb
@@ -0,0 +1,20 @@
+require "test/unit"
+require "webrick/htmlutils"
+
+class TestWEBrickHTMLUtils < Test::Unit::TestCase
+ include WEBrick::HTMLUtils
+
+ def test_escape
+ assert_equal("foo", escape("foo"))
+ assert_equal("foo bar", escape("foo bar"))
+ assert_equal("foo&amp;bar", escape("foo&bar"))
+ assert_equal("foo&quot;bar", escape("foo\"bar"))
+ assert_equal("foo&gt;bar", escape("foo>bar"))
+ assert_equal("foo&lt;bar", escape("foo<bar"))
+ assert_equal("\u{3053 3093 306B 3061 306F}", escape("\u{3053 3093 306B 3061 306F}"))
+ bug8425 = '[Bug #8425] [ruby-core:55052]'
+ assert_nothing_raised(ArgumentError, Encoding::CompatibilityError, bug8425) {
+ assert_equal("\u{3053 3093 306B}\xff&lt;", escape("\u{3053 3093 306B}\xff<"))
+ }
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httpauth.rb b/jni/ruby/test/webrick/test_httpauth.rb
new file mode 100644
index 0000000..27c37f3
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httpauth.rb
@@ -0,0 +1,198 @@
+require "test/unit"
+require "net/http"
+require "tempfile"
+require "webrick"
+require "webrick/httpauth/basicauth"
+require_relative "utils"
+
+class TestWEBrickHTTPAuth < Test::Unit::TestCase
+ def test_basic_auth
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, log[0])
+ }
+ TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
+ realm = "WEBrick's realm"
+ path = "/basic_auth"
+
+ server.mount_proc(path){|req, res|
+ WEBrick::HTTPAuth.basic_auth(req, res, realm){|user, pass|
+ user == "webrick" && pass == "supersecretpassword"
+ }
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("webrick", "supersecretpassword")
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+ g.basic_auth("webrick", "not super")
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
+ }
+ end
+
+ def test_basic_auth2
+ log_tester = lambda {|log, access_log|
+ log.reject! {|line| /\A\s*\z/ =~ line }
+ pats = [
+ /ERROR Basic WEBrick's realm: webrick: password unmatch\./,
+ /ERROR WEBrick::HTTPStatus::Unauthorized/
+ ]
+ pats.each {|pat|
+ assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}")
+ log.reject! {|line| pat =~ line }
+ }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
+ realm = "WEBrick's realm"
+ path = "/basic_auth2"
+
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.close
+ tmp_pass = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+ tmp_pass.flush
+
+ htpasswd = WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ users = []
+ htpasswd.each{|user, pass| users << user }
+ assert_equal(2, users.size, log.call)
+ assert(users.member?("webrick"), log.call)
+ assert(users.member?("foo"), log.call)
+
+ server.mount_proc(path){|req, res|
+ auth = WEBrick::HTTPAuth::BasicAuth.new(
+ :Realm => realm, :UserDB => htpasswd,
+ :Logger => server.logger
+ )
+ auth.authenticate(req, res)
+ res.body = "hoge"
+ }
+ http = Net::HTTP.new(addr, port)
+ g = Net::HTTP::Get.new(path)
+ g.basic_auth("webrick", "supersecretpassword")
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+ g.basic_auth("webrick", "not super")
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
+ }
+ }
+ end
+
+ def test_basic_auth3
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.puts("webrick:{SHA}GJYFRpBbdchp595jlh3Bhfmgp8k=")
+ tmpfile.flush
+ assert_raise(NotImplementedError){
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ }
+ }
+
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.puts("webrick:$apr1$IOVMD/..$rmnOSPXr0.wwrLPZHBQZy0")
+ tmpfile.flush
+ assert_raise(NotImplementedError){
+ WEBrick::HTTPAuth::Htpasswd.new(tmpfile.path)
+ }
+ }
+ end
+
+ DIGESTRES_ = /
+ ([a-zA-Z\-]+)
+ [ \t]*(?:\r\n[ \t]*)*
+ =
+ [ \t]*(?:\r\n[ \t]*)*
+ (?:
+ "((?:[^"]+|\\[\x00-\x7F])*)" |
+ ([!\#$%&'*+\-.0-9A-Z^_`a-z|~]+)
+ )/x
+
+ def test_digest_auth
+ log_tester = lambda {|log, access_log|
+ log.reject! {|line| /\A\s*\z/ =~ line }
+ pats = [
+ /ERROR Digest WEBrick's realm: no credentials in the request\./,
+ /ERROR WEBrick::HTTPStatus::Unauthorized/,
+ /ERROR Digest WEBrick's realm: webrick: digest unmatch\./
+ ]
+ pats.each {|pat|
+ assert(!log.grep(pat).empty?, "webrick log doesn't have expected error: #{pat.inspect}")
+ log.reject! {|line| pat =~ line }
+ }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver({}, log_tester) {|server, addr, port, log|
+ realm = "WEBrick's realm"
+ path = "/digest_auth"
+
+ Tempfile.create("test_webrick_auth") {|tmpfile|
+ tmpfile.close
+ tmp_pass = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
+ tmp_pass.set_passwd(realm, "webrick", "supersecretpassword")
+ tmp_pass.set_passwd(realm, "foo", "supersecretpassword")
+ tmp_pass.flush
+
+ htdigest = WEBrick::HTTPAuth::Htdigest.new(tmpfile.path)
+ users = []
+ htdigest.each{|user, pass| users << user }
+ assert_equal(2, users.size, log.call)
+ assert(users.member?("webrick"), log.call)
+ assert(users.member?("foo"), log.call)
+
+ auth = WEBrick::HTTPAuth::DigestAuth.new(
+ :Realm => realm, :UserDB => htdigest,
+ :Algorithm => 'MD5',
+ :Logger => server.logger
+ )
+ server.mount_proc(path){|req, res|
+ auth.authenticate(req, res)
+ res.body = "hoge"
+ }
+
+ Net::HTTP.start(addr, port) do |http|
+ g = Net::HTTP::Get.new(path)
+ params = {}
+ http.request(g) do |res|
+ assert_equal('401', res.code, log.call)
+ res["www-authenticate"].scan(DIGESTRES_) do |key, quoted, token|
+ params[key.downcase] = token || quoted.delete('\\')
+ end
+ params['uri'] = "http://#{addr}:#{port}#{path}"
+ end
+
+ g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+
+ params['algorithm'].downcase! #4936
+ g['Authorization'] = credentials_for_request('webrick', "supersecretpassword", params)
+ http.request(g){|res| assert_equal("hoge", res.body, log.call)}
+
+ g['Authorization'] = credentials_for_request('webrick', "not super", params)
+ http.request(g){|res| assert_not_equal("hoge", res.body, log.call)}
+ end
+ }
+ }
+ end
+
+ private
+ def credentials_for_request(user, password, params)
+ cnonce = "hoge"
+ nonce_count = 1
+ ha1 = "#{user}:#{params['realm']}:#{password}"
+ ha2 = "GET:#{params['uri']}"
+ request_digest =
+ "#{Digest::MD5.hexdigest(ha1)}:" \
+ "#{params['nonce']}:#{'%08x' % nonce_count}:#{cnonce}:#{params['qop']}:" \
+ "#{Digest::MD5.hexdigest(ha2)}"
+ "Digest username=\"#{user}\"" \
+ ", realm=\"#{params['realm']}\"" \
+ ", nonce=\"#{params['nonce']}\"" \
+ ", uri=\"#{params['uri']}\"" \
+ ", qop=#{params['qop']}" \
+ ", nc=#{'%08x' % nonce_count}" \
+ ", cnonce=\"#{cnonce}\"" \
+ ", response=\"#{Digest::MD5.hexdigest(request_digest)}\"" \
+ ", opaque=\"#{params['opaque']}\"" \
+ ", algorithm=#{params['algorithm']}"
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httpproxy.rb b/jni/ruby/test/webrick/test_httpproxy.rb
new file mode 100644
index 0000000..501bb4c
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httpproxy.rb
@@ -0,0 +1,284 @@
+require "test/unit"
+require "net/http"
+require "webrick"
+require "webrick/httpproxy"
+begin
+ require "webrick/ssl"
+ require "net/https"
+ require File.expand_path("../openssl/utils.rb", File.dirname(__FILE__))
+rescue LoadError
+ # test_connect will be skipped
+end
+require File.expand_path("utils.rb", File.dirname(__FILE__))
+
+class TestWEBrickHTTPProxy < Test::Unit::TestCase
+ def test_fake_proxy
+ assert_nil(WEBrick::FakeProxyURI.scheme)
+ assert_nil(WEBrick::FakeProxyURI.host)
+ assert_nil(WEBrick::FakeProxyURI.port)
+ assert_nil(WEBrick::FakeProxyURI.path)
+ assert_nil(WEBrick::FakeProxyURI.userinfo)
+ assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
+ end
+
+ def test_proxy
+ # Testing GET or POST to the proxy server
+ # Note that the proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy ---+
+ # GET / POST GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
+ }
+ assert_equal(1, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_nil(res.body, log.call)
+ }
+ assert_equal(2, proxy_handler_called, log.call)
+ assert_equal(4, request_handler_called, log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
+ }
+ assert_equal(3, proxy_handler_called, log.call)
+ assert_equal(6, request_handler_called, log.call)
+ }
+ end
+
+ def test_no_proxy
+ # Testing GET or POST to the proxy server without proxy request.
+ #
+ # client -------> proxy
+ # GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(1, request_handler_called, log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_nil(res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(3, request_handler_called, log.call)
+ }
+ end
+
+ def make_certificate(key, cn)
+ subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
+ exts = [
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
+ ]
+ cert = OpenSSL::TestUtils.issue_cert(
+ subject, key, 1, Time.now, Time.now + 3600, exts,
+ nil, nil, OpenSSL::Digest::SHA1.new
+ )
+ return cert
+ end if defined?(OpenSSL::TestUtils)
+
+ def test_connect
+ # Testing CONNECT to proxy server
+ #
+ # client -----------> proxy -----------> https
+ # 1. CONNECT establish TCP
+ # 2. ---- establish SSL session --->
+ # 3. ------- GET or POST ---------->
+ #
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :RequestCallback => Proc.new{|req, res|
+ assert_equal("CONNECT", req.request_method)
+ },
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
+ s_server.mount_proc("/"){|req, res|
+ res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req = Net::HTTP::Get.new("/")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req){|res|
+ assert_equal("SSL GET / ", res.body, s_log.call + log.call)
+ }
+
+ req = Net::HTTP::Post.new("/")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("SSL POST / post-data", res.body, s_log.call + log.call)
+ }
+ }
+ }
+ end if defined?(OpenSSL::TestUtils)
+
+ def test_upstream_proxy
+ # Testing GET or POST through the upstream proxy server
+ # Note that the upstream proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy -------> proxy ---+
+ # GET / POST GET / POST GET / POST
+ #
+ up_proxy_handler_called = up_request_handler_called = 0
+ proxy_handler_called = request_handler_called = 0
+ up_config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
+ :RequestCallback => Proc.new{|req, res| up_request_handler_called += 1}
+ }
+ TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
+ up_server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyURI => URI.parse("http://localhost:#{up_port}"),
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1},
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ http = Net::HTTP.new(up_addr, up_port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ skip res.message unless res.code == '200'
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_equal("GET / ", res.body)
+ }
+ assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, up_request_handler_called, up_log.call + log.call)
+ assert_equal(1, proxy_handler_called, up_log.call + log.call)
+ assert_equal(1, request_handler_called, up_log.call + log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_nil(res.body, up_log.call + log.call)
+ }
+ assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(4, up_request_handler_called, up_log.call + log.call)
+ assert_equal(2, proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, request_handler_called, up_log.call + log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_equal("POST / post-data", res.body, up_log.call + log.call)
+ }
+ assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(6, up_request_handler_called, up_log.call + log.call)
+ assert_equal(3, proxy_handler_called, up_log.call + log.call)
+ assert_equal(3, request_handler_called, up_log.call + log.call)
+
+ if defined?(OpenSSL::TestUtils)
+ # Testing CONNECT to the upstream proxy server
+ #
+ # client -------> proxy -------> proxy -------> https
+ # 1. CONNECT CONNECT establish TCP
+ # 2. -------- establish SSL session ------>
+ # 3. ---------- GET or POST -------------->
+ #
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
+ s_server.mount_proc("/"){|req2, res|
+ res.body = "SSL #{req2.request_method} #{req2.path} #{req2.body}"
+ }
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req2 = Net::HTTP::Get.new("/")
+ http.request(req2){|res|
+ assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
+ }
+
+ req2 = Net::HTTP::Post.new("/")
+ req2.body = "post-data"
+ http.request(req2){|res|
+ assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
+ }
+ }
+ end
+ }
+ }
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httprequest.rb b/jni/ruby/test/webrick/test_httprequest.rb
new file mode 100644
index 0000000..3a7e675
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httprequest.rb
@@ -0,0 +1,411 @@
+require "webrick"
+require "stringio"
+require "test/unit"
+
+class TestWEBrickHTTPRequest < Test::Unit::TestCase
+ def test_simple_request
+ msg = <<-_end_of_message_
+GET /
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert(req.meta_vars) # fails if @header was not initialized and iteration is attempted on the nil reference
+ end
+
+ def test_parse_09
+ msg = <<-_end_of_message_
+ GET /
+ foobar # HTTP/0.9 request don't have header nor entity body.
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("0.9"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_10
+ msg = <<-_end_of_message_
+ GET / HTTP/1.0
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("1.0"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_11
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/path", req.unparsed_uri)
+ assert_equal("", req.script_name)
+ assert_equal("/path", req.path_info)
+ assert_equal(WEBrick::HTTPVersion.new("1.1"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(true, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_request_uri_too_large
+ msg = <<-_end_of_message_
+ GET /#{"a"*2084} HTTP/1.1
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ assert_raise(WEBrick::HTTPStatus::RequestURITooLarge){
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ }
+ end
+
+ def test_parse_headers
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Connection: close
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+ Accept-Encoding: compress;q=0.5
+ Accept-Encoding: gzip;q=1.0, identity; q=0.4, *;q=0
+ Accept-Language: en;q=0.5, *; q=0
+ Accept-Language: ja
+ Content-Type: text/plain
+ Content-Length: 7
+ X-Empty-Header:
+
+ foobar
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(
+ URI.parse("http://test.ruby-lang.org:8080/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(8080, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(
+ %w(text/html;level=1 text/html */* text/html;level=2 text/*),
+ req.accept)
+ assert_equal(%w(gzip compress identity *), req.accept_encoding)
+ assert_equal(%w(ja en *), req.accept_language)
+ assert_equal(7, req.content_length)
+ assert_equal("text/plain", req.content_type)
+ assert_equal("foobar\n", req.body)
+ assert_equal("", req["x-empty-header"])
+ assert_equal(nil, req["x-no-header"])
+ assert(req.query.empty?)
+ end
+
+ def test_parse_header2()
+ msg = <<-_end_of_message_
+ POST /foo/bar/../baz?q=a HTTP/1.0
+ Content-Length: 9
+ User-Agent:
+ FOO BAR
+ BAZ
+
+ hogehoge
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("POST", req.request_method)
+ assert_equal("/foo/baz", req.path)
+ assert_equal("", req.script_name)
+ assert_equal("/foo/baz", req.path_info)
+ assert_equal("9", req['content-length'])
+ assert_equal("FOO BAR BAZ", req['user-agent'])
+ assert_equal("hogehoge\n", req.body)
+ end
+
+ def test_parse_headers3
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://test.ruby-lang.org/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1:8080/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(8080, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]:8080/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(8080, req.port)
+ end
+
+ def test_parse_get_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ GET /path?#{param} HTTP/1.1
+ Host: test.ruby-lang.org:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_parse_post_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: #{param.size}
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_chunked
+ crlf = "\x0d\x0a"
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: chunked
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ open(__FILE__){|io|
+ while chunk = io.read(100)
+ msg << chunk.size.to_s(16) << crlf
+ msg << chunk << crlf
+ end
+ }
+ msg << "0" << crlf
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal(File.read(__FILE__), req.body)
+ end
+
+ def test_forwarded
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(80, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com:8080
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(8080, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(443, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10
+ X-Forwarded-Host: forward1.example.com:1234, forward2.example.com:5678
+ X-Forwarded-Server: server1.example.com, server2.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server1.example.com", req.server_name)
+ assert_equal("https://forward1.example.com:1234/foo", req.request_uri.to_s)
+ assert_equal("forward1.example.com", req.host)
+ assert_equal(1234, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+ end
+
+ def test_continue_sent
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+ Expect: 100-continue
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert req['expect']
+ l = msg.size
+ req.continue
+ assert_not_equal l, msg.size
+ assert_match(/HTTP\/1.1 100 continue\r\n\r\n\z/, msg)
+ assert !req['expect']
+ end
+
+ def test_continue_not_sent
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert !req['expect']
+ l = msg.size
+ req.continue
+ assert_equal l, msg.size
+ end
+
+ def test_bad_messages
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::LengthRequired){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: 100000
+
+ body is too short.
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::BadRequest){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: foobar
+
+ body is too short.
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::NotImplemented){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httpresponse.rb b/jni/ruby/test/webrick/test_httpresponse.rb
new file mode 100644
index 0000000..c916ed5
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httpresponse.rb
@@ -0,0 +1,149 @@
+require "webrick"
+require "minitest/autorun"
+require "stringio"
+
+module WEBrick
+ class TestHTTPResponse < MiniTest::Unit::TestCase
+ class FakeLogger
+ attr_reader :messages
+
+ def initialize
+ @messages = []
+ end
+
+ def warn msg
+ @messages << msg
+ end
+ end
+
+ attr_reader :config, :logger, :res
+
+ def setup
+ super
+ @logger = FakeLogger.new
+ @config = Config::HTTP
+ @config[:Logger] = logger
+ @res = HTTPResponse.new config
+ @res.keep_alive = true
+ end
+
+ def test_304_does_not_log_warning
+ res.status = 304
+ res.setup_header
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_204_does_not_log_warning
+ res.status = 204
+ res.setup_header
+
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_1xx_does_not_log_warnings
+ res.status = 105
+ res.setup_header
+
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_io
+ IO.pipe {|body_r, body_w|
+ body_w.write 'hello'
+ body_w.close
+
+ @res.body = body_r
+
+ IO.pipe {|r, w|
+
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string
+ @res.body = 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_io
+ @res.body = StringIO.new 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_io_chunked
+ @res.chunked = true
+
+ IO.pipe {|body_r, body_w|
+
+ body_w.write 'hello'
+ body_w.close
+
+ @res.body = body_r
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_chunked
+ @res.chunked = true
+
+ @res.body = 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_io_chunked
+ @res.chunked = true
+
+ @res.body = StringIO.new 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httpserver.rb b/jni/ruby/test/webrick/test_httpserver.rb
new file mode 100644
index 0000000..5cd4ba5
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httpserver.rb
@@ -0,0 +1,412 @@
+require "test/unit"
+require "net/http"
+require "webrick"
+require_relative "utils"
+
+class TestWEBrickHTTPServer < Test::Unit::TestCase
+ empty_log = Object.new
+ def empty_log.<<(str)
+ assert_equal('', str)
+ self
+ end
+ NoLog = WEBrick::Log.new(empty_log, WEBrick::BasicLog::WARN)
+
+ def test_mount
+ httpd = WEBrick::HTTPServer.new(
+ :Logger => NoLog,
+ :DoNotListen=>true
+ )
+ httpd.mount("/", :Root)
+ httpd.mount("/foo", :Foo)
+ httpd.mount("/foo/bar", :Bar, :bar1)
+ httpd.mount("/foo/bar/baz", :Baz, :baz1, :baz2)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/sub", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/sub/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/sub")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("/sub", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar")
+ assert_equal(:Bar, serv)
+ assert_equal([:bar1], opts)
+ assert_equal("/foo/bar", script_name)
+ assert_equal("", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar/baz")
+ assert_equal(:Baz, serv)
+ assert_equal([:baz1, :baz2], opts)
+ assert_equal("/foo/bar/baz", script_name)
+ assert_equal("", path_info)
+ end
+
+ class Req
+ attr_reader :port, :host
+ def initialize(addr, port, host)
+ @addr, @port, @host = addr, port, host
+ end
+ def addr
+ [0,0,0,@addr]
+ end
+ end
+
+ def httpd(addr, port, host, ali)
+ config ={
+ :Logger => NoLog,
+ :DoNotListen => true,
+ :BindAddress => addr,
+ :Port => port,
+ :ServerName => host,
+ :ServerAlias => ali,
+ }
+ return WEBrick::HTTPServer.new(config)
+ end
+
+ def assert_eql?(v1, v2)
+ assert_equal(v1.object_id, v2.object_id)
+ end
+
+ def test_lookup_server
+ addr1 = "192.168.100.1"
+ addr2 = "192.168.100.2"
+ addrz = "192.168.100.254"
+ local = "127.0.0.1"
+ port1 = 80
+ port2 = 8080
+ port3 = 10080
+ portz = 32767
+ name1 = "www.example.com"
+ name2 = "www2.example.com"
+ name3 = "www3.example.com"
+ namea = "www.example.co.jp"
+ nameb = "www.example.jp"
+ namec = "www2.example.co.jp"
+ named = "www2.example.jp"
+ namez = "foobar.example.com"
+ alias1 = [namea, nameb]
+ alias2 = [namec, named]
+
+ host1 = httpd(nil, port1, name1, nil)
+ hosts = [
+ host2 = httpd(addr1, port1, name1, nil),
+ host3 = httpd(addr1, port1, name2, alias1),
+ host4 = httpd(addr1, port2, name1, nil),
+ host5 = httpd(addr1, port2, name2, alias1),
+ httpd(addr1, port2, name3, alias2),
+ host7 = httpd(addr2, nil, name1, nil),
+ host8 = httpd(addr2, nil, name2, alias1),
+ httpd(addr2, nil, name3, alias2),
+ host10 = httpd(local, nil, nil, nil),
+ host11 = httpd(nil, port3, nil, nil),
+ ].sort_by{ rand }
+ hosts.each{|h| host1.virtual_host(h) }
+
+ # connect to addr1
+ assert_eql?(host2, host1.lookup_server(Req.new(addr1, port1, name1)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, name2)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, namea)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port1, namez)))
+ assert_eql?(host4, host1.lookup_server(Req.new(addr1, port2, name1)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, name2)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, namea)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namez)))
+
+ # connect to addr2
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port1, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port1, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port2, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port2, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port3, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr2, port3, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, portz, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, portz, namez)))
+
+ # connect to addrz
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namez)))
+
+ # connect to localhost
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namez)))
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ requested0 = requested1 = 0
+ config = {
+ :ServerName => "localhost",
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ :RequestCallback => Proc.new{|req, res| requested0 += 1 },
+ }
+ log_tester = lambda {|log, access_log|
+ assert(log.find {|s| %r{ERROR `/' not found\.} =~ s })
+ assert_equal([], log.reject {|s| %r{ERROR `/' not found\.} =~ s })
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ vhost_config = {
+ :ServerName => "myhostname",
+ :BindAddress => addr,
+ :Port => port,
+ :DoNotListen => true,
+ :Logger => NoLog,
+ :AccessLog => [],
+ :RequestCallback => Proc.new{|req, res| requested1 += 1 },
+ }
+ server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
+
+ Thread.pass while server.status != :Running
+ assert_equal(1, started, log.call)
+ assert_equal(0, stopped, log.call)
+ assert_equal(0, accepted, log.call)
+
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req["Host"] = "myhostname:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ req["Host"] = "localhost:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ assert_equal(6, accepted, log.call)
+ assert_equal(3, requested0, log.call)
+ assert_equal(3, requested1, log.call)
+ }
+ assert_equal(started, 1)
+ assert_equal(stopped, 1)
+ end
+
+ # This class is needed by test_response_io_with_chunked_set method
+ class EventManagerForChunkedResponseTest
+ def initialize
+ @listeners = []
+ end
+ def add_listener( &block )
+ @listeners << block
+ end
+ def raise_str_event( str )
+ @listeners.each{ |e| e.call( :str, str ) }
+ end
+ def raise_close_event()
+ @listeners.each{ |e| e.call( :cls ) }
+ end
+ end
+ def test_response_io_with_chunked_set
+ evt_man = EventManagerForChunkedResponseTest.new
+ t = Thread.new do
+ begin
+ config = {
+ :ServerName => "localhost"
+ }
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ body_strs = [ 'aaaaaa', 'bb', 'cccc' ]
+ server.mount_proc( "/", ->( req, res ){
+ # Test for setting chunked...
+ res.chunked = true
+ r,w = IO.pipe
+ evt_man.add_listener do |type,str|
+ type == :cls ? ( w.close ) : ( w << str )
+ end
+ res.body = r
+ } )
+ Thread.pass while server.status != :Running
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ http.request(req) do |res|
+ i = 0
+ evt_man.raise_str_event( body_strs[i] )
+ res.read_body do |s|
+ assert_equal( body_strs[i], s )
+ i += 1
+ if i < body_strs.length
+ evt_man.raise_str_event( body_strs[i] )
+ else
+ evt_man.raise_close_event()
+ end
+ end
+ assert_equal( body_strs.length, i )
+ end
+ end
+ rescue => err
+ flunk( 'exception raised in thread: ' + err.to_s )
+ end
+ end
+ if t.join( 3 ).nil?
+ evt_man.raise_close_event()
+ flunk( 'timeout' )
+ if t.join( 1 ).nil?
+ Thread.kill t
+ end
+ end
+ end
+
+ def test_response_io_without_chunked_set
+ config = {
+ :ServerName => "localhost"
+ }
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/WARN Could not determine content-length of response body./, log[0])
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ server.mount_proc("/", lambda { |req, res|
+ r,w = IO.pipe
+ # Test for not setting chunked...
+ # res.chunked = true
+ res.body = r
+ w << "foo"
+ w.close
+ })
+ Thread.pass while server.status != :Running
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req['Connection'] = 'Keep-Alive'
+ begin
+ timeout(2) do
+ http.request(req){|res| assert_equal("foo", res.body) }
+ end
+ rescue Timeout::Error
+ flunk('corrupted reponse')
+ end
+ }
+ end
+
+ def test_request_handler_callback_is_deprecated
+ requested = 0
+ config = {
+ :ServerName => "localhost",
+ :RequestHandler => Proc.new{|req, res| requested += 1 },
+ }
+ log_tester = lambda {|log, access_log|
+ assert_equal(2, log.length)
+ assert_match(/WARN :RequestHandler is deprecated, please use :RequestCallback/, log[0])
+ assert_match(%r{ERROR `/' not found\.}, log[1])
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ Thread.pass while server.status != :Running
+
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req["Host"] = "localhost:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ assert_match(%r{:RequestHandler is deprecated, please use :RequestCallback$}, log.call, log.call)
+ }
+ assert_equal(1, requested)
+ end
+
+ def test_shutdown_with_busy_keepalive_connection
+ requested = 0
+ config = {
+ :ServerName => "localhost",
+ }
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
+ server.mount_proc("/", lambda {|req, res| res.body = "heffalump" })
+ Thread.pass while server.status != :Running
+
+ Net::HTTP.start(addr, port) do |http|
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res| assert_equal('Keep-Alive', res['Connection'], log.call) }
+ server.shutdown
+ begin
+ 10.times {|n| http.request(req); requested += 1 }
+ rescue
+ # Errno::ECONNREFUSED or similar
+ end
+ end
+ }
+ assert_equal(0, requested, "Server responded to #{requested} requests after shutdown")
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httputils.rb b/jni/ruby/test/webrick/test_httputils.rb
new file mode 100644
index 0000000..2753cbe
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httputils.rb
@@ -0,0 +1,100 @@
+require "test/unit"
+require "webrick/httputils"
+
+class TestWEBrickHTTPUtils < Test::Unit::TestCase
+ include WEBrick::HTTPUtils
+
+ def test_normilize_path
+ assert_equal("/foo", normalize_path("/foo"))
+ assert_equal("/foo/bar/", normalize_path("/foo/bar/"))
+
+ assert_equal("/", normalize_path("/foo/../"))
+ assert_equal("/", normalize_path("/foo/.."))
+ assert_equal("/", normalize_path("/foo/bar/../../"))
+ assert_equal("/", normalize_path("/foo/bar/../.."))
+ assert_equal("/", normalize_path("/foo/bar/../.."))
+ assert_equal("/baz", normalize_path("/foo/bar/../../baz"))
+ assert_equal("/baz", normalize_path("/foo/../bar/../baz"))
+ assert_equal("/baz/", normalize_path("/foo/../bar/../baz/"))
+ assert_equal("/...", normalize_path("/bar/../..."))
+ assert_equal("/.../", normalize_path("/bar/../.../"))
+
+ assert_equal("/foo/", normalize_path("/foo/./"))
+ assert_equal("/foo/", normalize_path("/foo/."))
+ assert_equal("/foo/", normalize_path("/foo/././"))
+ assert_equal("/foo/", normalize_path("/foo/./."))
+ assert_equal("/foo/bar", normalize_path("/foo/./bar"))
+ assert_equal("/foo/bar/", normalize_path("/foo/./bar/."))
+ assert_equal("/foo/bar/", normalize_path("/./././foo/./bar/."))
+
+ assert_equal("/foo/bar/", normalize_path("//foo///.//bar/.///.//"))
+ assert_equal("/", normalize_path("//foo///..///bar/.///..//.//"))
+
+ assert_raise(RuntimeError){ normalize_path("foo/bar") }
+ assert_raise(RuntimeError){ normalize_path("..") }
+ assert_raise(RuntimeError){ normalize_path("/..") }
+ assert_raise(RuntimeError){ normalize_path("/./..") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
+ assert_raise(RuntimeError){ normalize_path("/./../..") }
+ assert_raise(RuntimeError){ normalize_path("/./../../") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
+ assert_raise(RuntimeError){ normalize_path("/../..") }
+ assert_raise(RuntimeError){ normalize_path("/../../") }
+ assert_raise(RuntimeError){ normalize_path("/../../..") }
+ assert_raise(RuntimeError){ normalize_path("/../../../") }
+ assert_raise(RuntimeError){ normalize_path("/../foo/../") }
+ assert_raise(RuntimeError){ normalize_path("/../foo/../../") }
+ assert_raise(RuntimeError){ normalize_path("/foo/bar/../../../../") }
+ assert_raise(RuntimeError){ normalize_path("/foo/../bar/../../") }
+ assert_raise(RuntimeError){ normalize_path("/./../bar/") }
+ assert_raise(RuntimeError){ normalize_path("/./../") }
+ end
+
+ def test_split_header_value
+ assert_equal(['foo', 'bar'], split_header_value('foo, bar'))
+ assert_equal(['"foo"', 'bar'], split_header_value('"foo", bar'))
+ assert_equal(['foo', '"bar"'], split_header_value('foo, "bar"'))
+ assert_equal(['*'], split_header_value('*'))
+ assert_equal(['W/"xyzzy"', 'W/"r2d2xxxx"', 'W/"c3piozzzz"'],
+ split_header_value('W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"'))
+ end
+
+ def test_escape
+ assert_equal("/foo/bar", escape("/foo/bar"))
+ assert_equal("/~foo/bar", escape("/~foo/bar"))
+ assert_equal("/~foo%20bar", escape("/~foo bar"))
+ assert_equal("/~foo%20bar", escape("/~foo bar"))
+ assert_equal("/~foo%09bar", escape("/~foo\tbar"))
+ assert_equal("/~foo+bar", escape("/~foo+bar"))
+ bug8425 = '[Bug #8425] [ruby-core:55052]'
+ assert_nothing_raised(ArgumentError, Encoding::CompatibilityError, bug8425) {
+ assert_equal("%E3%83%AB%E3%83%93%E3%83%BC%E3%81%95%E3%82%93", escape("\u{30EB 30D3 30FC 3055 3093}"))
+ }
+ end
+
+ def test_escape_form
+ assert_equal("%2Ffoo%2Fbar", escape_form("/foo/bar"))
+ assert_equal("%2F~foo%2Fbar", escape_form("/~foo/bar"))
+ assert_equal("%2F~foo+bar", escape_form("/~foo bar"))
+ assert_equal("%2F~foo+%2B+bar", escape_form("/~foo + bar"))
+ end
+
+ def test_unescape
+ assert_equal("/foo/bar", unescape("%2ffoo%2fbar"))
+ assert_equal("/~foo/bar", unescape("/%7efoo/bar"))
+ assert_equal("/~foo/bar", unescape("%2f%7efoo%2fbar"))
+ assert_equal("/~foo+bar", unescape("/%7efoo+bar"))
+ end
+
+ def test_unescape_form
+ assert_equal("//foo/bar", unescape_form("/%2Ffoo/bar"))
+ assert_equal("//foo/bar baz", unescape_form("/%2Ffoo/bar+baz"))
+ assert_equal("/~foo/bar baz", unescape_form("/%7Efoo/bar+baz"))
+ end
+
+ def test_escape_path
+ assert_equal("/foo/bar", escape_path("/foo/bar"))
+ assert_equal("/foo/bar/", escape_path("/foo/bar/"))
+ assert_equal("/%25foo/bar/", escape_path("/%foo/bar/"))
+ end
+end
diff --git a/jni/ruby/test/webrick/test_httpversion.rb b/jni/ruby/test/webrick/test_httpversion.rb
new file mode 100644
index 0000000..81a871a
--- /dev/null
+++ b/jni/ruby/test/webrick/test_httpversion.rb
@@ -0,0 +1,40 @@
+require "test/unit"
+require "webrick/httpversion"
+
+class TestWEBrickHTTPVersion < Test::Unit::TestCase
+ def setup
+ @v09 = WEBrick::HTTPVersion.new("0.9")
+ @v10 = WEBrick::HTTPVersion.new("1.0")
+ @v11 = WEBrick::HTTPVersion.new("1.001")
+ end
+
+ def test_to_s()
+ assert_equal("0.9", @v09.to_s)
+ assert_equal("1.0", @v10.to_s)
+ assert_equal("1.1", @v11.to_s)
+ end
+
+ def test_major()
+ assert_equal(0, @v09.major)
+ assert_equal(1, @v10.major)
+ assert_equal(1, @v11.major)
+ end
+
+ def test_minor()
+ assert_equal(9, @v09.minor)
+ assert_equal(0, @v10.minor)
+ assert_equal(1, @v11.minor)
+ end
+
+ def test_compar()
+ assert_equal(0, @v09 <=> "0.9")
+ assert_equal(0, @v09 <=> "0.09")
+
+ assert_equal(-1, @v09 <=> @v10)
+ assert_equal(-1, @v09 <=> "1.00")
+
+ assert_equal(1, @v11 <=> @v09)
+ assert_equal(1, @v11 <=> "1.0")
+ assert_equal(1, @v11 <=> "0.9")
+ end
+end
diff --git a/jni/ruby/test/webrick/test_server.rb b/jni/ruby/test/webrick/test_server.rb
new file mode 100644
index 0000000..043d439
--- /dev/null
+++ b/jni/ruby/test/webrick/test_server.rb
@@ -0,0 +1,131 @@
+require "test/unit"
+require "tempfile"
+require "webrick"
+require_relative "utils"
+
+class TestWEBrickServer < Test::Unit::TestCase
+ class Echo < WEBrick::GenericServer
+ def run(sock)
+ while line = sock.gets
+ sock << line
+ end
+ end
+ end
+
+ def test_server
+ TestWEBrick.start_server(Echo){|server, addr, port, log|
+ TCPSocket.open(addr, port){|sock|
+ sock.puts("foo"); assert_equal("foo\n", sock.gets, log.call)
+ sock.puts("bar"); assert_equal("bar\n", sock.gets, log.call)
+ sock.puts("baz"); assert_equal("baz\n", sock.gets, log.call)
+ sock.puts("qux"); assert_equal("qux\n", sock.gets, log.call)
+ }
+ }
+ end
+
+ def test_start_exception
+ stopped = 0
+
+ log = []
+ logger = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
+
+ assert_raises(SignalException) do
+ listener = Object.new
+ def listener.to_io # IO.select invokes #to_io.
+ raise SignalException, 'SIGTERM' # simulate signal in main thread
+ end
+ def listener.shutdown
+ end
+ def listener.close
+ end
+
+ server = WEBrick::HTTPServer.new({
+ :BindAddress => "127.0.0.1", :Port => 0,
+ :StopCallback => Proc.new{ stopped += 1 },
+ :Logger => logger,
+ })
+ server.listeners[0].close
+ server.listeners[0] = listener
+
+ server.start
+ end
+
+ assert_equal(1, stopped)
+ assert_equal(1, log.length)
+ assert_match(/FATAL SignalException: SIGTERM/, log[0])
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ config = {
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ }
+ TestWEBrick.start_server(Echo, config){|server, addr, port, log|
+ true while server.status != :Running
+ assert_equal(1, started, log.call)
+ assert_equal(0, stopped, log.call)
+ assert_equal(0, accepted, log.call)
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ assert_equal(3, accepted, log.call)
+ }
+ assert_equal(1, started)
+ assert_equal(1, stopped)
+ end
+
+ def test_daemon
+ begin
+ r, w = IO.pipe
+ pid1 = Process.fork{
+ r.close
+ WEBrick::Daemon.start
+ w.puts(Process.pid)
+ sleep 10
+ }
+ pid2 = r.gets.to_i
+ assert(Process.kill(:KILL, pid2))
+ assert_not_equal(pid1, pid2)
+ rescue NotImplementedError
+ # snip this test
+ ensure
+ Process.wait(pid1) if pid1
+ r.close
+ w.close
+ end
+ end
+
+ def test_restart
+ address = '127.0.0.1'
+ port = 0
+ log = []
+ config = {
+ :BindAddress => address,
+ :Port => port,
+ :Logger => WEBrick::Log.new(log, WEBrick::BasicLog::WARN),
+ }
+ server = Echo.new(config)
+ client_proc = lambda {|str|
+ begin
+ ret = server.listeners.first.connect_address.connect {|s|
+ s.write(str)
+ s.close_write
+ s.read
+ }
+ assert_equal(str, ret)
+ ensure
+ server.shutdown
+ end
+ }
+ server_thread = Thread.new { server.start }
+ client_thread = Thread.new { client_proc.call("a") }
+ assert_join_threads([client_thread, server_thread])
+ server.listen(address, port)
+ server_thread = Thread.new { server.start }
+ client_thread = Thread.new { client_proc.call("b") }
+ assert_join_threads([client_thread, server_thread])
+ assert_equal([], log)
+ end
+end
diff --git a/jni/ruby/test/webrick/test_utils.rb b/jni/ruby/test/webrick/test_utils.rb
new file mode 100644
index 0000000..e63e0eb
--- /dev/null
+++ b/jni/ruby/test/webrick/test_utils.rb
@@ -0,0 +1,64 @@
+require "test/unit"
+require "webrick/utils"
+
+class TestWEBrickUtils < Test::Unit::TestCase
+ def assert_expired(flag, m)
+ if m == WEBrick::Utils
+ handler = WEBrick::Utils::TimeoutHandler.instance
+ assert_equal(flag, handler.instance_eval{ @timeout_info.empty? })
+ end
+ end
+
+ def do_test_timeout(m)
+ ex = Class.new(StandardError)
+
+ assert_equal(:foo, m.timeout(10){ :foo })
+ assert_expired(true, m)
+
+ i = 0
+ assert_raise(Timeout::Error){
+ m.timeout(2){
+ assert_raise(Timeout::Error){ m.timeout(1){ i += 1; sleep } }
+ assert_expired(false, m)
+ i += 1
+ sleep
+ }
+ }
+ assert_equal(2, i)
+ assert_expired(true, m)
+
+ assert_raise(Timeout::Error){ m.timeout(0.1){ sleep } }
+ assert_expired(true, m)
+
+ assert_raise(ex){ m.timeout(0.1, ex){ sleep } }
+ assert_expired(true, m)
+
+ i = 0
+ assert_raise(ex){
+ m.timeout(10){
+ m.timeout(1, ex){ i += 1; sleep }
+ }
+ sleep
+ }
+ assert_equal(1, i)
+ assert_expired(true, m)
+
+ i = 0
+ assert_raise(Timeout::Error){
+ m.timeout(1){
+ m.timeout(10, ex){ i += 1; sleep }
+ }
+ sleep
+ }
+ assert_equal(1, i)
+ assert_expired(true, m)
+ end
+
+ def test_webrick_timeout
+ do_test_timeout(WEBrick::Utils)
+ end
+
+ #def test_timeout
+ # do_test_timeout(Timeout)
+ #end
+end
diff --git a/jni/ruby/test/webrick/utils.rb b/jni/ruby/test/webrick/utils.rb
new file mode 100644
index 0000000..71559a5
--- /dev/null
+++ b/jni/ruby/test/webrick/utils.rb
@@ -0,0 +1,70 @@
+require "webrick"
+begin
+ require "webrick/https"
+rescue LoadError
+end
+require "webrick/httpproxy"
+
+module TestWEBrick
+ NullWriter = Object.new
+ def NullWriter.<<(msg)
+ puts msg if $DEBUG
+ return self
+ end
+
+ class WEBrick::HTTPServlet::CGIHandler
+ remove_const :Ruby
+ Ruby = EnvUtil.rubybin
+ remove_const :CGIRunner
+ CGIRunner = "\"#{Ruby}\" \"#{WEBrick::Config::LIBDIR}/httpservlet/cgi_runner.rb\"" # :nodoc:
+ end
+
+ RubyBin = "\"#{EnvUtil.rubybin}\""
+ RubyBin << " --disable-gems"
+ RubyBin << " \"-I#{File.expand_path("../..", File.dirname(__FILE__))}/lib\""
+ RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/common\""
+ RubyBin << " \"-I#{File.dirname(EnvUtil.rubybin)}/.ext/#{RUBY_PLATFORM}\""
+
+ include Test::Unit::Assertions
+ extend Test::Unit::Assertions
+
+ module_function
+
+ DefaultLogTester = lambda {|log, access_log| assert_equal([], log) }
+
+ def start_server(klass, config={}, log_tester=DefaultLogTester, &block)
+ log_ary = []
+ access_log_ary = []
+ log = proc { "webrick log start:\n" + (log_ary+access_log_ary).join.gsub(/^/, " ").chomp + "\nwebrick log end" }
+ server = klass.new({
+ :BindAddress => "127.0.0.1", :Port => 0,
+ :ServerType => Thread,
+ :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN),
+ :AccessLog => [[access_log_ary, ""]]
+ }.update(config))
+ server_thread = server.start
+ server_thread2 = Thread.new {
+ server_thread.join
+ if log_tester
+ log_tester.call(log_ary, access_log_ary)
+ end
+ }
+ addr = server.listeners[0].addr
+ client_thread = Thread.new {
+ begin
+ block.yield([server, addr[3], addr[1], log])
+ ensure
+ server.shutdown
+ end
+ }
+ assert_join_threads([client_thread, server_thread2])
+ end
+
+ def start_httpserver(config={}, log_tester=DefaultLogTester, &block)
+ start_server(WEBrick::HTTPServer, config, log_tester, &block)
+ end
+
+ def start_httpproxy(config={}, log_tester=DefaultLogTester, &block)
+ start_server(WEBrick::HTTPProxyServer, config, log_tester, &block)
+ end
+end
diff --git a/jni/ruby/test/webrick/webrick.cgi b/jni/ruby/test/webrick/webrick.cgi
new file mode 100644
index 0000000..43c1af8
--- /dev/null
+++ b/jni/ruby/test/webrick/webrick.cgi
@@ -0,0 +1,36 @@
+#!ruby
+require "webrick/cgi"
+
+class TestApp < WEBrick::CGI
+ def do_GET(req, res)
+ res["content-type"] = "text/plain"
+ if (p = req.path_info) && p.length > 0
+ res.body = p
+ elsif (q = req.query).size > 0
+ res.body = q.keys.sort.collect{|key|
+ q[key].list.sort.collect{|v|
+ "#{key}=#{v}"
+ }.join(", ")
+ }.join(", ")
+ elsif %r{/$} =~ req.request_uri.to_s
+ res.body = ""
+ res.body << req.request_uri.to_s << "\n"
+ res.body << req.script_name
+ elsif !req.cookies.empty?
+ res.body = req.cookies.inject(""){|result, cookie|
+ result << "%s=%s\n" % [cookie.name, cookie.value]
+ }
+ res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE")
+ res.cookies << WEBrick::Cookie.new("Shipping", "FedEx")
+ else
+ res.body = req.script_name
+ end
+ end
+
+ def do_POST(req, res)
+ do_GET(req, res)
+ end
+end
+
+cgi = TestApp.new
+cgi.start
diff --git a/jni/ruby/test/webrick/webrick_long_filename.cgi b/jni/ruby/test/webrick/webrick_long_filename.cgi
new file mode 100644
index 0000000..43c1af8
--- /dev/null
+++ b/jni/ruby/test/webrick/webrick_long_filename.cgi
@@ -0,0 +1,36 @@
+#!ruby
+require "webrick/cgi"
+
+class TestApp < WEBrick::CGI
+ def do_GET(req, res)
+ res["content-type"] = "text/plain"
+ if (p = req.path_info) && p.length > 0
+ res.body = p
+ elsif (q = req.query).size > 0
+ res.body = q.keys.sort.collect{|key|
+ q[key].list.sort.collect{|v|
+ "#{key}=#{v}"
+ }.join(", ")
+ }.join(", ")
+ elsif %r{/$} =~ req.request_uri.to_s
+ res.body = ""
+ res.body << req.request_uri.to_s << "\n"
+ res.body << req.script_name
+ elsif !req.cookies.empty?
+ res.body = req.cookies.inject(""){|result, cookie|
+ result << "%s=%s\n" % [cookie.name, cookie.value]
+ }
+ res.cookies << WEBrick::Cookie.new("Customer", "WILE_E_COYOTE")
+ res.cookies << WEBrick::Cookie.new("Shipping", "FedEx")
+ else
+ res.body = req.script_name
+ end
+ end
+
+ def do_POST(req, res)
+ do_GET(req, res)
+ end
+end
+
+cgi = TestApp.new
+cgi.start