Rev 2422: Define tests for http proxy basic authentication. They fail. in http://bazaar.launchpad.net/~bzr/bzr/bzr.http.auth

Vincent Ladeuil v.ladeuil+lp at free.fr
Tue Apr 17 11:33:41 BST 2007


At http://bazaar.launchpad.net/~bzr/bzr/bzr.http.auth

------------------------------------------------------------
revno: 2422
revision-id: v.ladeuil+lp at free.fr-20070417103339-3kywr38d0p50czrw
parent: v.ladeuil+lp at free.fr-20070416134120-i8y220zv30spaq0a
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: bzr.http.auth
timestamp: Tue 2007-04-17 12:33:39 +0200
message:
  Define tests for http proxy basic authentication. They fail.
  
  * bzrlib/tests/test_http.py:
  (TestHttpProxyWhiteBox._set_and_capture_env_var): Deleted. YAGNI.
  (TestProxyHttpServer._set_and_capture_env_var): Deleted. YAGNI
  (TestHTTPAuth): Made abstract so it can be reused for proxy.
  (TestHTTPAuth.test_prompt_for_password): New class.
  (TestHTTPAuth.test_prompt_for_password): New class. Failed tests so
  far.
  
  * bzrlib/tests/HTTPTestUtil.py:
  (AbstractBasicAuthRequestHandler): Made abstract from
  BasicAuthRequestHandler so it can be reused for proxy.
  (ProxyBasicAuthRequestHandler): New class.
  (ProxyBasicAuthHTTPServer): New class.
modified:
  bzrlib/tests/HTTPTestUtil.py   HTTPTestUtil.py-20050914180604-247d3aafb7a43343
  bzrlib/tests/test_http.py      testhttp.py-20051018020158-b2eef6e867c514d9
-------------- next part --------------
=== modified file 'bzrlib/tests/HTTPTestUtil.py'
--- a/bzrlib/tests/HTTPTestUtil.py	2007-04-15 15:57:08 +0000
+++ b/bzrlib/tests/HTTPTestUtil.py	2007-04-17 10:33:39 +0000
@@ -309,25 +309,30 @@
        self.old_server = self.get_secondary_server()
 
 
-class BasicAuthRequestHandler(TestingHTTPRequestHandler):
+class AbstractBasicAuthRequestHandler(TestingHTTPRequestHandler):
     """Requires a basic authentication to process requests.
 
     This is intended to be used with a server that always and
     only use basic authentication.
     """
 
+    # The following attribute should be set dy daughter classes
+    _auth_header_sent = None
+    _auth_header_recv = None
+    _auth_error_code = None
+
     def do_GET(self):
         tcs = self.server.test_case_server
         if tcs.auth_scheme == 'basic':
-            auth_header = self.headers.get('Authorization')
+            auth_header = self.headers.get(self._auth_header_recv)
             authorized = False
             if auth_header and auth_header.lower().startswith('basic '):
                 coded_auth = auth_header[len('Basic '):]
                 user, password = coded_auth.decode('base64').split(':')
                 authorized = tcs.authorized(user, password)
             if not authorized:
-                self.send_response(401)
-                self.send_header('www-authenticate',
+                self.send_response(self._auth_error_code)
+                self.send_header(self._auth_header_sent,
                                  'Basic realm="Thou should not pass"')
                 self.end_headers()
                 return
@@ -362,8 +367,43 @@
         return expected_password is not None and password == expected_password
 
 
+class BasicAuthRequestHandler(AbstractBasicAuthRequestHandler,
+                              FakeProxyRequestHandler):
+    """Requires a basic authentication to process requests.
+
+    Note: Each of the inherited request handler overrides
+    different parts of processing in a compatible way, so it is
+    okay to inherit from both.
+    """
+
+    _auth_header_sent = 'WWW-Authenticate'
+    _auth_header_recv = 'Authorization'
+    _auth_error_code = 401
+
+
 class BasicAuthHTTPServer(AuthHTTPServer):
     """An HTTP server requiring basic authentication"""
 
     def __init__(self):
         AuthHTTPServer.__init__(self, BasicAuthRequestHandler, 'basic')
+
+
+class ProxyBasicAuthRequestHandler(AbstractBasicAuthRequestHandler,
+                                   FakeProxyRequestHandler):
+    """Requires a basic authentication to proxy requests.
+
+    Note: Each of the inherited request handler overrides
+    different parts of processing in a compatible way, so it is
+    okay to inherit from both.
+    """
+
+    _auth_header_sent = 'Proxy-Authenticate'
+    _auth_header_recv = 'Proxy-Authorization'
+    _auth_error_code = 407
+
+
+class ProxyBasicAuthHTTPServer(AuthHTTPServer):
+    """An HTTP server requiring basic authentication"""
+
+    def __init__(self):
+        AuthHTTPServer.__init__(self, ProxyBasicAuthRequestHandler, 'basic')

=== modified file 'bzrlib/tests/test_http.py'
--- a/bzrlib/tests/test_http.py	2007-04-15 15:57:08 +0000
+++ b/bzrlib/tests/test_http.py	2007-04-17 10:33:39 +0000
@@ -53,6 +53,7 @@
     HTTPServerRedirecting,
     InvalidStatusRequestHandler,
     NoRangeRequestHandler,
+    ProxyBasicAuthHTTPServer,
     SingleRangeRequestHandler,
     TestCaseWithRedirectedWebserver,
     TestCaseWithTwoWebservers,
@@ -717,13 +718,9 @@
     def tearDown(self):
         self._restore_env()
 
-    def _set_and_capture_env_var(self, name, new_value):
-        """Set an environment variable, and reset it when finished."""
-        self._old_env[name] = osutils.set_or_unset_env(name, new_value)
-
     def _install_env(self, env):
         for name, value in env.iteritems():
-            self._set_and_capture_env_var(name, value)
+            self._old_env[name] = osutils.set_or_unset_env(name, value)
 
     def _restore_env(self):
         for name, value in self._old_env.iteritems():
@@ -786,8 +783,7 @@
                                   ('foo-proxied', 'proxied contents of foo\n')])
         # Let's setup some attributes for tests
         self.server = self.get_readonly_server()
-        # FIXME: We should not rely on 'localhost' being the hostname
-        self.proxy_address = 'localhost:%d' % self.server.port
+        self.proxy_address = '%s:%d' % (self.server.host, self.server.port)
         self.no_proxy_host = self.proxy_address
         # The secondary server is the proxy
         self.proxy = self.get_secondary_server()
@@ -800,13 +796,9 @@
         """
         return HttpServer(FakeProxyRequestHandler)
 
-    def _set_and_capture_env_var(self, name, new_value):
-        """Set an environment variable, and reset it when finished."""
-        self._old_env[name] = osutils.set_or_unset_env(name, new_value)
-
     def _install_env(self, env):
         for name, value in env.iteritems():
-            self._set_and_capture_env_var(name, value)
+            self._old_env[name] = osutils.set_or_unset_env(name, value)
 
     def _restore_env(self):
         for name, value in self._old_env.iteritems():
@@ -1147,21 +1139,24 @@
                           self.get_a, self.old_transport, redirected)
 
 
-class TestHTTPBasicAuth(TestCaseWithWebserver):
-    """Test basic authentication scheme"""
-
-    _transport = HttpTransport_urllib
-    _auth_header = 'Authorization'
-
-    def create_transport_readonly_server(self):
-        return BasicAuthHTTPServer()
+class TestHTTPAuth(object):
+    """Test some authentication scheme specified by daughter class.
+
+    This MUST be used by daughter classes that also inherit from
+    either TestCaseWithWebserver or TestCaseWithTwoWebservers.
+    """
 
     def setUp(self):
-        super(TestHTTPBasicAuth, self).setUp()
+        """Set up the test environment
+
+        Daughter classes should set up their own environment
+        (including self.server) and explicitely call this
+        method. This is needed because we want to reuse the same
+        tests for proxy and no-proxy accesses which have
+        different ways of setting self.server.
+        """
         self.build_tree_contents([('a', 'contents of a\n'),
                                   ('b', 'contents of b\n'),])
-        self.server = self.get_readonly_server()
-
         self.old_factory = ui.ui_factory
         self.addCleanup(self.restoreUIFactory)
 
@@ -1212,3 +1207,53 @@
         t2 = t.clone()
         # And neither against a clone
         self.assertEqual('contents of b\n',t2.get('b').read())
+
+
+class TestHTTPBasicAuth(TestHTTPAuth, TestCaseWithWebserver):
+    """Test basic http authentication scheme"""
+
+    _transport = HttpTransport_urllib
+    _auth_header = 'Authorization'
+
+    def setUp(self):
+        TestCaseWithWebserver.setUp(self)
+        self.server = self.get_readonly_server()
+        TestHTTPAuth.setUp(self)
+
+    def create_transport_readonly_server(self):
+        return BasicAuthHTTPServer()
+
+
+class TestHTTPProxyBasicAuth(TestHTTPAuth, TestCaseWithTwoWebservers):
+    """Test basic http authentication scheme"""
+
+    _transport = HttpTransport_urllib
+    _auth_header = 'Proxy-authorization'
+    _test_class = TestCaseWithWebserver
+
+    def setUp(self):
+        TestCaseWithTwoWebservers.setUp(self)
+        self.server = self.get_readonly_server()
+        self.proxy_url = self.server.get_url()
+        self._old_env = {}
+        self.addCleanup(self._restore_env)
+        self._install_env({'all_proxy': self.proxy_url})
+        TestHTTPAuth.setUp(self)
+        # Override the contents to avoid false positives
+        self.build_tree_contents([('a', 'not proxied contents of a\n'),
+                                  ('b', 'not proxied contents of b\n'),
+                                  ('a-proxied', 'contents of a\n'),
+                                  ('b-proxied', 'contents of b\n'),
+                                  ])
+
+    def create_transport_readonly_server(self):
+        return ProxyBasicAuthHTTPServer()
+
+    def _install_env(self, env):
+        for name, value in env.iteritems():
+            self._old_env[name] = osutils.set_or_unset_env(name, value)
+
+    def _restore_env(self):
+        for name, value in self._old_env.iteritems():
+            osutils.set_or_unset_env(name, value)
+



More information about the bazaar-commits mailing list