test/test_http.rb in atom-tools-0.9.1 vs test/test_http.rb in atom-tools-0.9.2

- old
+ new

@@ -1,14 +1,18 @@ require "test/unit" require "atom/http" require "webrick" -class AtomProtocolTest < Test::Unit::TestCase +class AtomHTTPTest < Test::Unit::TestCase REALM = "test authentication" USER = "test_user" PASS = "aoeuaoeu" + + # for Google AuthSub authentication + TOKEN = "pq7266382__838" + SECRET_DATA = "I kissed a boy once" def setup @http = Atom::HTTP.new @port = rand(1024) + 1024 @@ -16,15 +20,17 @@ :Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL), :AccessLog => [] end def test_parse_wwwauth + # a Basic WWW-Authenticate header = 'realm="SokEvo"' params = @http.send :parse_quoted_wwwauth, header assert_equal "SokEvo", params[:realm] + # Digest is parsed a bit differently header = 'opaque="07UrfUiCYac5BbWJ", algorithm=MD5-sess, qop="auth", stale=TRUE, nonce="MDAx0Mzk", realm="test authentication"' params = @http.send :parse_wwwauth_digest, header assert_equal "test authentication", params[:realm] @@ -34,82 +40,146 @@ assert_equal "MD5-sess", params[:algorithm] assert_equal "07UrfUiCYac5BbWJ", params[:opaque] end def test_GET - @s.mount_proc("/") do |req,res| + mount_one_shot do |req,res| assert_equal("/", req.path) res.content_type = "text/plain" - res.body = "just junk" - - @s.stop + res.body = "Success!" end - one_shot - get_root - assert_equal("200", @res.code) - assert_equal("text/plain", @res.content_type) - assert_equal("just junk", @res.body) + assert_equal "200", @res.code + assert_equal "text/plain", @res.content_type + assert_equal "Success!", @res.body end def test_GET_headers - @s.mount_proc("/") do |req,res| + mount_one_shot do |req,res| assert_equal("tester agent", req["User-Agent"]) + end + + get_root("User-Agent" => "tester agent") + + assert_equal "200", @res.code + end + + def test_redirect + @s.mount_proc("/") do |req,res| + res.status = 302 + res["Location"] = "http://localhost:#{@port}/redirected" + res.body = "ignore me." + end + + @s.mount_proc("/redirected") do |req,res| + res.content_type = "text/plain" + res.body = "Success!" + @s.stop end + one_shot; get_root + + # the redirect should be transparent (to whatever extent it can be) + assert_equal "200", @res.code + assert_equal "Success!", @res.body + end + + def test_redirect_loop + @s.mount_proc("/") do |req,res| + res.status = 302 + res["Location"] = "http://localhost:#{@port}/redirected" + end + + @s.mount_proc("/redirected") do |req,res| + res.status = 302 + res["Location"] = "http://localhost:#{@port}/" + end + one_shot + + assert_raises(Atom::HTTPException) { get_root } - get_root("User-Agent" => "tester agent") + @s.stop + end - assert_equal("200", @res.code) + def test_redirect_non_GET_non_HEAD + @s.mount_proc("/") do |req,res| + assert_equal "POST", req.request_method + res.status = 302 + res["Location"] = "http://localhost:#{@port}/redirected" + end + + @s.mount_proc("/redirected") do |req,res| + assert_equal "POST", req.request_method + assert_equal "important message", req.body + res.content_type = "text/plain" + res.body = "Success!" + end + + one_shot + + @res = @http.post "http://localhost:#{@port}/", "important message" + + assert_equal "302", @res.code + + @http.allow_all_redirects = true + + one_shot + + @res = @http.post "http://localhost:#{@port}/", "important message" + + assert_equal "200", @res.code + assert_equal "Success!", @res.body + + @s.stop end def test_basic_auth - @s.mount_proc("/") do |req,res| + mount_one_shot do |req,res| WEBrick::HTTPAuth.basic_auth(req, res, REALM) do |u,p| u == USER and p == PASS end res.body = SECRET_DATA - @s.stop end - one_shot - - # with no credentials + # no credentials assert_raises(Atom::Unauthorized) { get_root } @http.user = USER @http.pass = "incorrect_password" - # with incorrect credentials + one_shot + + # incorrect credentials assert_raises(Atom::Unauthorized) { get_root } @http.when_auth do |abs_url,realm| assert_equal "http://localhost:#{@port}/", abs_url assert_equal REALM, realm [USER, PASS] end - + one_shot - - get_root - assert_equal "200", @res.code - assert_equal SECRET_DATA, @res.body + + # correct credentials + assert_authenticates end def test_digest_auth - # a dummy userdb + # a dummy userdb (saves me creating a file) userdb = {} + # with a single entry userdb[USER] = PASS + # HTTPAuth::DigestAuth#authenticate uses this def userdb.get_passwd(realm, user, reload) Digest::MD5::hexdigest([user, realm, self[user]].join(":")) end authenticator = WEBrick::HTTPAuth::DigestAuth.new( @@ -130,18 +200,17 @@ @http.user = USER @http.pass = PASS # correct credentials - res = get_root - assert_equal SECRET_DATA, res.body + assert_authenticates @s.stop end def test_wsse_auth - @s.mount_proc("/") do |req,res| + mount_one_shot do |req,res| assert_equal 'WSSE profile="UsernameToken"', req["Authorization"] xwsse = req["X-WSSE"] p = @http.send :parse_quoted_wwwauth, xwsse @@ -157,26 +226,76 @@ password_digest = [Digest::SHA1.digest(pd_string)].pack("m").chomp assert_equal password_digest, p[:PasswordDigest] res.body = SECRET_DATA - @s.stop end - one_shot - @http.always_auth = :wsse @http.user = USER @http.pass = PASS - - get_root + assert_authenticates + end + + def test_authsub_auth + mount_one_shot do |req,res| + assert_equal %{AuthSub token="#{TOKEN}"}, req["Authorization"] + + res.body = SECRET_DATA + end + + @http.always_auth = :authsub + @http.token = TOKEN + + assert_authenticates + end + + def test_https + require 'webrick/https' + + @s = WEBrick::HTTPServer.new( + :Port => (@port + 1), + :DocumentRoot => Dir::pwd + "/htdocs", + :Logger => WEBrick::Log.new($stderr, WEBrick::Log::FATAL), + :AccessLog => [], + :SSLEnable => true, + :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE, + :SSLCertName => [ ["C","CA"], ["O","localhost"], ["CN", "WWW"] ] + ) + + mount_one_shot do |req,res| + res.body = SECRET_DATA + end + + res = @http.get("https://localhost:#{@port + 1}/") + + assert_equal "200", res.code + assert_equal SECRET_DATA, res.body + end + + # mount a block on the test server, shutting the server down after a + # single request + def mount_one_shot &block + @s.mount_proc("/") do |req,res| + block.call req, res + @s.stop + end + + one_shot + end + + # test that we authenticated properly + def assert_authenticates + get_root assert_equal "200", @res.code - assert_equal SECRET_DATA, @res.body + assert_equal SECRET_DATA, @res.body end + # performs a GET on the test server def get_root(*args) @res = @http.get("http://localhost:#{@port}/", *args) end + # sets up the server for a single request def one_shot; Thread.new { @s.start }; end end