1146
1135
self.assertRaises(errors.TooManyRedirections, do_catching_redirections,
1147
1136
self.get_a, self.old_transport, redirected)
1139
class TestAuth(object):
1140
"""Test some authentication scheme specified by daughter class.
1142
This MUST be used by daughter classes that also inherit from
1143
either TestCaseWithWebserver or TestCaseWithTwoWebservers.
1147
"""Set up the test environment
1149
Daughter classes should set up their own environment
1150
(including self.server) and explicitely call this
1151
method. This is needed because we want to reuse the same
1152
tests for proxy and no-proxy accesses which have
1153
different ways of setting self.server.
1155
self.build_tree_contents([('a', 'contents of a\n'),
1156
('b', 'contents of b\n'),])
1157
self.old_factory = ui.ui_factory
1158
self.old_stdout = sys.stdout
1159
sys.stdout = StringIOWrapper()
1160
self.addCleanup(self.restoreUIFactory)
1162
def restoreUIFactory(self):
1163
ui.ui_factory = self.old_factory
1164
sys.stdout = self.old_stdout
1166
def get_user_url(self, user=None, password=None):
1167
"""Build an url embedding user and password"""
1168
url = '%s://' % self.server._url_protocol
1169
if user is not None:
1171
if password is not None:
1172
url += ':' + password
1174
url += '%s:%s/' % (self.server.host, self.server.port)
1177
def test_no_user(self):
1178
self.server.add_user('joe', 'foo')
1179
t = self.get_user_transport()
1180
self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
1181
# Only one 'Authentication Required' error should occur
1182
self.assertEqual(1, self.server.auth_required_errors)
1184
def test_empty_pass(self):
1185
self.server.add_user('joe', '')
1186
t = self.get_user_transport('joe', '')
1187
self.assertEqual('contents of a\n', t.get('a').read())
1188
# Only one 'Authentication Required' error should occur
1189
self.assertEqual(1, self.server.auth_required_errors)
1191
def test_user_pass(self):
1192
self.server.add_user('joe', 'foo')
1193
t = self.get_user_transport('joe', 'foo')
1194
self.assertEqual('contents of a\n', t.get('a').read())
1195
# Only one 'Authentication Required' error should occur
1196
self.assertEqual(1, self.server.auth_required_errors)
1198
def test_unknown_user(self):
1199
self.server.add_user('joe', 'foo')
1200
t = self.get_user_transport('bill', 'foo')
1201
self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
1202
# Two 'Authentication Required' errors should occur (the
1203
# initial 'who are you' and 'I don't know you, who are
1205
self.assertEqual(2, self.server.auth_required_errors)
1207
def test_wrong_pass(self):
1208
self.server.add_user('joe', 'foo')
1209
t = self.get_user_transport('joe', 'bar')
1210
self.assertRaises(errors.InvalidHttpResponse, t.get, 'a')
1211
# Two 'Authentication Required' errors should occur (the
1212
# initial 'who are you' and 'this is not you, who are you')
1213
self.assertEqual(2, self.server.auth_required_errors)
1215
def test_prompt_for_password(self):
1216
self.server.add_user('joe', 'foo')
1217
t = self.get_user_transport('joe', None)
1218
ui.ui_factory = TestUIFactory(stdin='foo\n')
1219
self.assertEqual('contents of a\n',t.get('a').read())
1220
# stdin should be empty
1221
self.assertEqual('', ui.ui_factory.stdin.readline())
1222
# And we shouldn't prompt again for a different request
1223
# against the same transport.
1224
self.assertEqual('contents of b\n',t.get('b').read())
1226
# And neither against a clone
1227
self.assertEqual('contents of b\n',t2.get('b').read())
1228
# Only one 'Authentication Required' error should occur
1229
self.assertEqual(1, self.server.auth_required_errors)
1232
class TestHTTPAuth(TestAuth):
1233
"""Test HTTP authentication schemes.
1235
Daughter classes MUST inherit from TestCaseWithWebserver too.
1238
_auth_header = 'Authorization'
1241
TestCaseWithWebserver.setUp(self)
1242
self.server = self.get_readonly_server()
1243
TestAuth.setUp(self)
1245
def get_user_transport(self, user=None, password=None):
1246
return self._transport(self.get_user_url(user, password))
1249
class TestProxyAuth(TestAuth):
1250
"""Test proxy authentication schemes.
1252
Daughter classes MUST also inherit from TestCaseWithWebserver.
1254
_auth_header = 'Proxy-authorization'
1257
TestCaseWithWebserver.setUp(self)
1258
self.server = self.get_readonly_server()
1260
self.addCleanup(self._restore_env)
1261
TestAuth.setUp(self)
1262
# Override the contents to avoid false positives
1263
self.build_tree_contents([('a', 'not proxied contents of a\n'),
1264
('b', 'not proxied contents of b\n'),
1265
('a-proxied', 'contents of a\n'),
1266
('b-proxied', 'contents of b\n'),
1269
def get_user_transport(self, user=None, password=None):
1270
self._install_env({'all_proxy': self.get_user_url(user, password)})
1271
return self._transport(self.server.get_url())
1273
def _install_env(self, env):
1274
for name, value in env.iteritems():
1275
self._old_env[name] = osutils.set_or_unset_env(name, value)
1277
def _restore_env(self):
1278
for name, value in self._old_env.iteritems():
1279
osutils.set_or_unset_env(name, value)
1282
class TestHTTPBasicAuth(TestHTTPAuth, TestCaseWithWebserver):
1283
"""Test http basic authentication scheme"""
1285
_transport = HttpTransport_urllib
1287
def create_transport_readonly_server(self):
1288
return HTTPBasicAuthServer()
1291
class TestHTTPProxyBasicAuth(TestProxyAuth, TestCaseWithWebserver):
1292
"""Test proxy basic authentication scheme"""
1294
_transport = HttpTransport_urllib
1296
def create_transport_readonly_server(self):
1297
return ProxyBasicAuthServer()
1300
class TestDigestAuth(object):
1301
"""Digest Authentication specific tests"""
1303
def test_changing_nonce(self):
1304
self.server.add_user('joe', 'foo')
1305
t = self.get_user_transport('joe', 'foo')
1306
self.assertEqual('contents of a\n', t.get('a').read())
1307
self.assertEqual('contents of b\n', t.get('b').read())
1308
# Only one 'Authentication Required' error should have
1310
self.assertEqual(1, self.server.auth_required_errors)
1311
# The server invalidates the current nonce
1312
self.server.auth_nonce = self.server.auth_nonce + '. No, now!'
1313
self.assertEqual('contents of a\n', t.get('a').read())
1314
# Two 'Authentication Required' errors should occur (the
1315
# initial 'who are you' and a second 'who are you' with the new nonce)
1316
self.assertEqual(2, self.server.auth_required_errors)
1319
class TestHTTPDigestAuth(TestHTTPAuth, TestDigestAuth, TestCaseWithWebserver):
1320
"""Test http digest authentication scheme"""
1322
_transport = HttpTransport_urllib
1324
def create_transport_readonly_server(self):
1325
return HTTPDigestAuthServer()
1328
class TestHTTPProxyDigestAuth(TestProxyAuth, TestDigestAuth,
1329
TestCaseWithWebserver):
1330
"""Test proxy digest authentication scheme"""
1332
_transport = HttpTransport_urllib
1334
def create_transport_readonly_server(self):
1335
return ProxyDigestAuthServer()