1041
1178
self.assertEqual(value, 'value3-top')
1042
1179
value = tree_config.get_option('key3', 'SECTION')
1043
1180
self.assertEqual(value, 'value3-section')
1183
class TestTransportConfig(tests.TestCaseWithTransport):
1185
def test_get_value(self):
1186
"""Test that retreiving a value from a section is possible"""
1187
bzrdir_config = config.TransportConfig(transport.get_transport('.'),
1189
bzrdir_config.set_option('value', 'key', 'SECTION')
1190
bzrdir_config.set_option('value2', 'key2')
1191
bzrdir_config.set_option('value3-top', 'key3')
1192
bzrdir_config.set_option('value3-section', 'key3', 'SECTION')
1193
value = bzrdir_config.get_option('key', 'SECTION')
1194
self.assertEqual(value, 'value')
1195
value = bzrdir_config.get_option('key2')
1196
self.assertEqual(value, 'value2')
1197
self.assertEqual(bzrdir_config.get_option('non-existant'), None)
1198
value = bzrdir_config.get_option('non-existant', 'SECTION')
1199
self.assertEqual(value, None)
1200
value = bzrdir_config.get_option('non-existant', default='default')
1201
self.assertEqual(value, 'default')
1202
self.assertEqual(bzrdir_config.get_option('key2', 'NOSECTION'), None)
1203
value = bzrdir_config.get_option('key2', 'NOSECTION',
1205
self.assertEqual(value, 'default')
1206
value = bzrdir_config.get_option('key3')
1207
self.assertEqual(value, 'value3-top')
1208
value = bzrdir_config.get_option('key3', 'SECTION')
1209
self.assertEqual(value, 'value3-section')
1211
def test_set_unset_default_stack_on(self):
1212
my_dir = self.make_bzrdir('.')
1213
bzrdir_config = config.BzrDirConfig(my_dir)
1214
self.assertIs(None, bzrdir_config.get_default_stack_on())
1215
bzrdir_config.set_default_stack_on('Foo')
1216
self.assertEqual('Foo', bzrdir_config._config.get_option(
1217
'default_stack_on'))
1218
self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
1219
bzrdir_config.set_default_stack_on(None)
1220
self.assertIs(None, bzrdir_config.get_default_stack_on())
1223
class TestAuthenticationConfigFile(tests.TestCase):
1224
"""Test the authentication.conf file matching"""
1226
def _got_user_passwd(self, expected_user, expected_password,
1227
config, *args, **kwargs):
1228
credentials = config.get_credentials(*args, **kwargs)
1229
if credentials is None:
1233
user = credentials['user']
1234
password = credentials['password']
1235
self.assertEquals(expected_user, user)
1236
self.assertEquals(expected_password, password)
1238
def test_empty_config(self):
1239
conf = config.AuthenticationConfig(_file=StringIO())
1240
self.assertEquals({}, conf._get_config())
1241
self._got_user_passwd(None, None, conf, 'http', 'foo.net')
1243
def test_missing_auth_section_header(self):
1244
conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
1245
self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1247
def test_auth_section_header_not_closed(self):
1248
conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
1249
self.assertRaises(errors.ParseConfigError, conf._get_config)
1251
def test_auth_value_not_boolean(self):
1252
conf = config.AuthenticationConfig(_file=StringIO(
1256
verify_certificates=askme # Error: Not a boolean
1258
self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1260
def test_auth_value_not_int(self):
1261
conf = config.AuthenticationConfig(_file=StringIO(
1265
port=port # Error: Not an int
1267
self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1269
def test_unknown_password_encoding(self):
1270
conf = config.AuthenticationConfig(_file=StringIO(
1274
password_encoding=unknown
1276
self.assertRaises(ValueError, conf.get_password,
1277
'ftp', 'foo.net', 'joe')
1279
def test_credentials_for_scheme_host(self):
1280
conf = config.AuthenticationConfig(_file=StringIO(
1281
"""# Identity on foo.net
1286
password=secret-pass
1289
self._got_user_passwd('joe', 'secret-pass', conf, 'ftp', 'foo.net')
1291
self._got_user_passwd(None, None, conf, 'http', 'foo.net')
1293
self._got_user_passwd(None, None, conf, 'ftp', 'bar.net')
1295
def test_credentials_for_host_port(self):
1296
conf = config.AuthenticationConfig(_file=StringIO(
1297
"""# Identity on foo.net
1303
password=secret-pass
1306
self._got_user_passwd('joe', 'secret-pass',
1307
conf, 'ftp', 'foo.net', port=10021)
1309
self._got_user_passwd(None, None, conf, 'ftp', 'foo.net')
1311
def test_for_matching_host(self):
1312
conf = config.AuthenticationConfig(_file=StringIO(
1313
"""# Identity on foo.net
1319
[sourceforge domain]
1326
self._got_user_passwd('georges', 'bendover',
1327
conf, 'bzr', 'foo.bzr.sf.net')
1329
self._got_user_passwd(None, None,
1330
conf, 'bzr', 'bbzr.sf.net')
1332
def test_for_matching_host_None(self):
1333
conf = config.AuthenticationConfig(_file=StringIO(
1334
"""# Identity on foo.net
1344
self._got_user_passwd('joe', 'joepass',
1345
conf, 'bzr', 'quux.net')
1346
# no host but different scheme
1347
self._got_user_passwd('georges', 'bendover',
1348
conf, 'ftp', 'quux.net')
1350
def test_credentials_for_path(self):
1351
conf = config.AuthenticationConfig(_file=StringIO(
1367
self._got_user_passwd(None, None,
1368
conf, 'http', host='bar.org', path='/dir3')
1370
self._got_user_passwd('georges', 'bendover',
1371
conf, 'http', host='bar.org', path='/dir2')
1373
self._got_user_passwd('jim', 'jimpass',
1374
conf, 'http', host='bar.org',path='/dir1/subdir')
1376
def test_credentials_for_user(self):
1377
conf = config.AuthenticationConfig(_file=StringIO(
1386
self._got_user_passwd('jim', 'jimpass',
1387
conf, 'http', 'bar.org')
1389
self._got_user_passwd('jim', 'jimpass',
1390
conf, 'http', 'bar.org', user='jim')
1391
# Don't get a different user if one is specified
1392
self._got_user_passwd(None, None,
1393
conf, 'http', 'bar.org', user='georges')
1395
def test_credentials_for_user_without_password(self):
1396
conf = config.AuthenticationConfig(_file=StringIO(
1403
# Get user but no password
1404
self._got_user_passwd('jim', None,
1405
conf, 'http', 'bar.org')
1407
def test_verify_certificates(self):
1408
conf = config.AuthenticationConfig(_file=StringIO(
1415
verify_certificates=False
1422
credentials = conf.get_credentials('https', 'bar.org')
1423
self.assertEquals(False, credentials.get('verify_certificates'))
1424
credentials = conf.get_credentials('https', 'foo.net')
1425
self.assertEquals(True, credentials.get('verify_certificates'))
1428
class TestAuthenticationStorage(tests.TestCaseInTempDir):
1430
def test_set_credentials(self):
1431
conf = config.AuthenticationConfig()
1432
conf.set_credentials('name', 'host', 'user', 'scheme', 'password',
1433
99, path='/foo', verify_certificates=False, realm='realm')
1434
credentials = conf.get_credentials(host='host', scheme='scheme',
1435
port=99, path='/foo',
1437
CREDENTIALS = {'name': 'name', 'user': 'user', 'password': 'password',
1438
'verify_certificates': False, 'scheme': 'scheme',
1439
'host': 'host', 'port': 99, 'path': '/foo',
1441
self.assertEqual(CREDENTIALS, credentials)
1442
credentials_from_disk = config.AuthenticationConfig().get_credentials(
1443
host='host', scheme='scheme', port=99, path='/foo', realm='realm')
1444
self.assertEqual(CREDENTIALS, credentials_from_disk)
1446
def test_reset_credentials_different_name(self):
1447
conf = config.AuthenticationConfig()
1448
conf.set_credentials('name', 'host', 'user', 'scheme', 'password'),
1449
conf.set_credentials('name2', 'host', 'user2', 'scheme', 'password'),
1450
self.assertIs(None, conf._get_config().get('name'))
1451
credentials = conf.get_credentials(host='host', scheme='scheme')
1452
CREDENTIALS = {'name': 'name2', 'user': 'user2', 'password':
1453
'password', 'verify_certificates': True,
1454
'scheme': 'scheme', 'host': 'host', 'port': None,
1455
'path': None, 'realm': None}
1456
self.assertEqual(CREDENTIALS, credentials)
1459
class TestAuthenticationConfig(tests.TestCase):
1460
"""Test AuthenticationConfig behaviour"""
1462
def _check_default_password_prompt(self, expected_prompt_format, scheme,
1463
host=None, port=None, realm=None,
1467
user, password = 'jim', 'precious'
1468
expected_prompt = expected_prompt_format % {
1469
'scheme': scheme, 'host': host, 'port': port,
1470
'user': user, 'realm': realm}
1472
stdout = tests.StringIOWrapper()
1473
stderr = tests.StringIOWrapper()
1474
ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
1475
stdout=stdout, stderr=stderr)
1476
# We use an empty conf so that the user is always prompted
1477
conf = config.AuthenticationConfig()
1478
self.assertEquals(password,
1479
conf.get_password(scheme, host, user, port=port,
1480
realm=realm, path=path))
1481
self.assertEquals(expected_prompt, stderr.getvalue())
1482
self.assertEquals('', stdout.getvalue())
1484
def _check_default_username_prompt(self, expected_prompt_format, scheme,
1485
host=None, port=None, realm=None,
1490
expected_prompt = expected_prompt_format % {
1491
'scheme': scheme, 'host': host, 'port': port,
1493
stdout = tests.StringIOWrapper()
1494
stderr = tests.StringIOWrapper()
1495
ui.ui_factory = tests.TestUIFactory(stdin=username+ '\n',
1496
stdout=stdout, stderr=stderr)
1497
# We use an empty conf so that the user is always prompted
1498
conf = config.AuthenticationConfig()
1499
self.assertEquals(username, conf.get_user(scheme, host, port=port,
1500
realm=realm, path=path, ask=True))
1501
self.assertEquals(expected_prompt, stderr.getvalue())
1502
self.assertEquals('', stdout.getvalue())
1504
def test_username_defaults_prompts(self):
1505
# HTTP prompts can't be tested here, see test_http.py
1506
self._check_default_username_prompt('FTP %(host)s username: ', 'ftp')
1507
self._check_default_username_prompt(
1508
'FTP %(host)s:%(port)d username: ', 'ftp', port=10020)
1509
self._check_default_username_prompt(
1510
'SSH %(host)s:%(port)d username: ', 'ssh', port=12345)
1512
def test_username_default_no_prompt(self):
1513
conf = config.AuthenticationConfig()
1514
self.assertEquals(None,
1515
conf.get_user('ftp', 'example.com'))
1516
self.assertEquals("explicitdefault",
1517
conf.get_user('ftp', 'example.com', default="explicitdefault"))
1519
def test_password_default_prompts(self):
1520
# HTTP prompts can't be tested here, see test_http.py
1521
self._check_default_password_prompt(
1522
'FTP %(user)s@%(host)s password: ', 'ftp')
1523
self._check_default_password_prompt(
1524
'FTP %(user)s@%(host)s:%(port)d password: ', 'ftp', port=10020)
1525
self._check_default_password_prompt(
1526
'SSH %(user)s@%(host)s:%(port)d password: ', 'ssh', port=12345)
1527
# SMTP port handling is a bit special (it's handled if embedded in the
1529
# FIXME: should we: forbid that, extend it to other schemes, leave
1530
# things as they are that's fine thank you ?
1531
self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
1533
self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
1534
'smtp', host='bar.org:10025')
1535
self._check_default_password_prompt(
1536
'SMTP %(user)s@%(host)s:%(port)d password: ',
1539
def test_ssh_password_emits_warning(self):
1540
conf = config.AuthenticationConfig(_file=StringIO(
1548
entered_password = 'typed-by-hand'
1549
stdout = tests.StringIOWrapper()
1550
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1553
# Since the password defined in the authentication config is ignored,
1554
# the user is prompted
1555
self.assertEquals(entered_password,
1556
conf.get_password('ssh', 'bar.org', user='jim'))
1557
self.assertContainsRe(
1558
self._get_log(keep_log_file=True),
1559
'password ignored in section \[ssh with password\]')
1561
def test_ssh_without_password_doesnt_emit_warning(self):
1562
conf = config.AuthenticationConfig(_file=StringIO(
1569
entered_password = 'typed-by-hand'
1570
stdout = tests.StringIOWrapper()
1571
ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1574
# Since the password defined in the authentication config is ignored,
1575
# the user is prompted
1576
self.assertEquals(entered_password,
1577
conf.get_password('ssh', 'bar.org', user='jim'))
1578
# No warning shoud be emitted since there is no password. We are only
1580
self.assertNotContainsRe(
1581
self._get_log(keep_log_file=True),
1582
'password ignored in section \[ssh with password\]')
1584
def test_uses_fallback_stores(self):
1585
self._old_cs_registry = config.credential_store_registry
1587
config.credential_store_registry = self._old_cs_registry
1588
self.addCleanup(restore)
1589
config.credential_store_registry = config.CredentialStoreRegistry()
1590
store = StubCredentialStore()
1591
store.add_credentials("http", "example.com", "joe", "secret")
1592
config.credential_store_registry.register("stub", store, fallback=True)
1593
conf = config.AuthenticationConfig(_file=StringIO())
1594
creds = conf.get_credentials("http", "example.com")
1595
self.assertEquals("joe", creds["user"])
1596
self.assertEquals("secret", creds["password"])
1599
class StubCredentialStore(config.CredentialStore):
1605
def add_credentials(self, scheme, host, user, password=None):
1606
self._username[(scheme, host)] = user
1607
self._password[(scheme, host)] = password
1609
def get_credentials(self, scheme, host, port=None, user=None,
1610
path=None, realm=None):
1611
key = (scheme, host)
1612
if not key in self._username:
1614
return { "scheme": scheme, "host": host, "port": port,
1615
"user": self._username[key], "password": self._password[key]}
1618
class CountingCredentialStore(config.CredentialStore):
1623
def get_credentials(self, scheme, host, port=None, user=None,
1624
path=None, realm=None):
1629
class TestCredentialStoreRegistry(tests.TestCase):
1631
def _get_cs_registry(self):
1632
return config.credential_store_registry
1634
def test_default_credential_store(self):
1635
r = self._get_cs_registry()
1636
default = r.get_credential_store(None)
1637
self.assertIsInstance(default, config.PlainTextCredentialStore)
1639
def test_unknown_credential_store(self):
1640
r = self._get_cs_registry()
1641
# It's hard to imagine someone creating a credential store named
1642
# 'unknown' so we use that as an never registered key.
1643
self.assertRaises(KeyError, r.get_credential_store, 'unknown')
1645
def test_fallback_none_registered(self):
1646
r = config.CredentialStoreRegistry()
1647
self.assertEquals(None,
1648
r.get_fallback_credentials("http", "example.com"))
1650
def test_register(self):
1651
r = config.CredentialStoreRegistry()
1652
r.register("stub", StubCredentialStore(), fallback=False)
1653
r.register("another", StubCredentialStore(), fallback=True)
1654
self.assertEquals(["another", "stub"], r.keys())
1656
def test_register_lazy(self):
1657
r = config.CredentialStoreRegistry()
1658
r.register_lazy("stub", "bzrlib.tests.test_config",
1659
"StubCredentialStore", fallback=False)
1660
self.assertEquals(["stub"], r.keys())
1661
self.assertIsInstance(r.get_credential_store("stub"),
1662
StubCredentialStore)
1664
def test_is_fallback(self):
1665
r = config.CredentialStoreRegistry()
1666
r.register("stub1", None, fallback=False)
1667
r.register("stub2", None, fallback=True)
1668
self.assertEquals(False, r.is_fallback("stub1"))
1669
self.assertEquals(True, r.is_fallback("stub2"))
1671
def test_no_fallback(self):
1672
r = config.CredentialStoreRegistry()
1673
store = CountingCredentialStore()
1674
r.register("count", store, fallback=False)
1675
self.assertEquals(None,
1676
r.get_fallback_credentials("http", "example.com"))
1677
self.assertEquals(0, store._calls)
1679
def test_fallback_credentials(self):
1680
r = config.CredentialStoreRegistry()
1681
store = StubCredentialStore()
1682
store.add_credentials("http", "example.com",
1683
"somebody", "geheim")
1684
r.register("stub", store, fallback=True)
1685
creds = r.get_fallback_credentials("http", "example.com")
1686
self.assertEquals("somebody", creds["user"])
1687
self.assertEquals("geheim", creds["password"])
1689
def test_fallback_first_wins(self):
1690
r = config.CredentialStoreRegistry()
1691
stub1 = StubCredentialStore()
1692
stub1.add_credentials("http", "example.com",
1693
"somebody", "stub1")
1694
r.register("stub1", stub1, fallback=True)
1695
stub2 = StubCredentialStore()
1696
stub2.add_credentials("http", "example.com",
1697
"somebody", "stub2")
1698
r.register("stub2", stub1, fallback=True)
1699
creds = r.get_fallback_credentials("http", "example.com")
1700
self.assertEquals("somebody", creds["user"])
1701
self.assertEquals("stub1", creds["password"])
1704
class TestPlainTextCredentialStore(tests.TestCase):
1706
def test_decode_password(self):
1707
r = config.credential_store_registry
1708
plain_text = r.get_credential_store()
1709
decoded = plain_text.decode_password(dict(password='secret'))
1710
self.assertEquals('secret', decoded)
1713
# FIXME: Once we have a way to declare authentication to all test servers, we
1714
# can implement generic tests.
1715
# test_user_password_in_url
1716
# test_user_in_url_password_from_config
1717
# test_user_in_url_password_prompted
1718
# test_user_in_config
1719
# test_user_getpass.getuser
1720
# test_user_prompted ?
1721
class TestAuthenticationRing(tests.TestCaseWithTransport):