~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

NEWS section template into a separate file

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
#   Authors: Robert Collins <robert.collins@canonical.com>
 
1
# Copyright (C) 2005, 2006, 2008, 2009 Canonical Ltd
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
13
12
#
14
13
# You should have received a copy of the GNU General Public License
15
14
# along with this program; if not, write to the Free Software
16
 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
16
 
18
17
"""Tests for finding and reading the bzr config file[s]."""
19
18
# import system imports here
150
149
        self._transport = self.control_files = \
151
150
            FakeControlFilesAndTransport(user_id=user_id)
152
151
 
 
152
    def _get_config(self):
 
153
        return config.TransportConfig(self._transport, 'branch.conf')
 
154
 
153
155
    def lock_write(self):
154
156
        pass
155
157
 
318
320
    def setUp(self):
319
321
        super(TestConfigPath, self).setUp()
320
322
        os.environ['HOME'] = '/home/bogus'
 
323
        os.environ['XDG_CACHE_DIR'] = ''
321
324
        if sys.platform == 'win32':
322
325
            os.environ['BZR_HOME'] = \
323
326
                r'C:\Documents and Settings\bogus\Application Data'
345
348
        self.assertEqual(config.authentication_config_filename(),
346
349
                         self.bzr_home + '/authentication.conf')
347
350
 
 
351
    def test_xdg_cache_dir(self):
 
352
        self.assertEqual(config.xdg_cache_dir(),
 
353
            '/home/bogus/.cache')
 
354
 
348
355
 
349
356
class TestIniConfig(tests.TestCase):
350
357
 
364
371
        parser = my_config._get_parser(file=config_file)
365
372
        self.failUnless(my_config._get_parser() is parser)
366
373
 
 
374
    def test_get_user_option_as_bool(self):
 
375
        config_file = StringIO("""
 
376
a_true_bool = true
 
377
a_false_bool = 0
 
378
an_invalid_bool = maybe
 
379
a_list = hmm, who knows ? # This interpreted as a list !
 
380
""".encode('utf-8'))
 
381
        my_config = config.IniBasedConfig(None)
 
382
        parser = my_config._get_parser(file=config_file)
 
383
        get_option = my_config.get_user_option_as_bool
 
384
        self.assertEqual(True, get_option('a_true_bool'))
 
385
        self.assertEqual(False, get_option('a_false_bool'))
 
386
        self.assertIs(None, get_option('an_invalid_bool'))
 
387
        self.assertIs(None, get_option('not_defined_in_this_config'))
367
388
 
368
389
class TestGetConfig(tests.TestCase):
369
390
 
425
446
        locations = config.locations_config_filename()
426
447
        config.ensure_config_dir_exists()
427
448
        local_url = urlutils.local_path_to_url('branch')
428
 
        open(locations, 'wb').write('[%s]\nnickname = foobar' 
 
449
        open(locations, 'wb').write('[%s]\nnickname = foobar'
429
450
                                    % (local_url,))
430
451
        self.assertEqual('foobar', branch.nick)
431
452
 
436
457
 
437
458
        locations = config.locations_config_filename()
438
459
        config.ensure_config_dir_exists()
439
 
        open(locations, 'wb').write('[%s/branch]\nnickname = barry' 
 
460
        open(locations, 'wb').write('[%s/branch]\nnickname = barry'
440
461
                                    % (osutils.getcwd().encode('utf8'),))
441
462
        self.assertEqual('barry', branch.nick)
442
463
 
951
972
        self.assertIs(self.my_config.get_user_option('foo'), None)
952
973
        self.my_config.set_user_option('foo', 'bar')
953
974
        self.assertEqual(
954
 
            self.my_config.branch.control_files.files['branch.conf'],
955
 
            'foo = bar\n')
 
975
            self.my_config.branch.control_files.files['branch.conf'].strip(),
 
976
            'foo = bar')
956
977
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
957
978
        self.my_config.set_user_option('foo', 'baz',
958
979
                                       store=config.STORE_LOCATION)
1205
1226
        value = bzrdir_config.get_option('key3', 'SECTION')
1206
1227
        self.assertEqual(value, 'value3-section')
1207
1228
 
 
1229
    def test_set_unset_default_stack_on(self):
 
1230
        my_dir = self.make_bzrdir('.')
 
1231
        bzrdir_config = config.BzrDirConfig(my_dir)
 
1232
        self.assertIs(None, bzrdir_config.get_default_stack_on())
 
1233
        bzrdir_config.set_default_stack_on('Foo')
 
1234
        self.assertEqual('Foo', bzrdir_config._config.get_option(
 
1235
                         'default_stack_on'))
 
1236
        self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
 
1237
        bzrdir_config.set_default_stack_on(None)
 
1238
        self.assertIs(None, bzrdir_config.get_default_stack_on())
 
1239
 
1208
1240
 
1209
1241
class TestAuthenticationConfigFile(tests.TestCase):
1210
1242
    """Test the authentication.conf file matching"""
1252
1284
"""))
1253
1285
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1254
1286
 
 
1287
    def test_unknown_password_encoding(self):
 
1288
        conf = config.AuthenticationConfig(_file=StringIO(
 
1289
                """[broken]
 
1290
scheme=ftp
 
1291
user=joe
 
1292
password_encoding=unknown
 
1293
"""))
 
1294
        self.assertRaises(ValueError, conf.get_password,
 
1295
                          'ftp', 'foo.net', 'joe')
 
1296
 
1255
1297
    def test_credentials_for_scheme_host(self):
1256
1298
        conf = config.AuthenticationConfig(_file=StringIO(
1257
1299
                """# Identity on foo.net
1401
1443
        self.assertEquals(True, credentials.get('verify_certificates'))
1402
1444
 
1403
1445
 
 
1446
class TestAuthenticationStorage(tests.TestCaseInTempDir):
 
1447
 
 
1448
    def test_set_credentials(self):
 
1449
        conf = config.AuthenticationConfig()
 
1450
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password',
 
1451
        99, path='/foo', verify_certificates=False, realm='realm')
 
1452
        credentials = conf.get_credentials(host='host', scheme='scheme',
 
1453
                                           port=99, path='/foo',
 
1454
                                           realm='realm')
 
1455
        CREDENTIALS = {'name': 'name', 'user': 'user', 'password': 'password',
 
1456
                       'verify_certificates': False, 'scheme': 'scheme', 
 
1457
                       'host': 'host', 'port': 99, 'path': '/foo', 
 
1458
                       'realm': 'realm'}
 
1459
        self.assertEqual(CREDENTIALS, credentials)
 
1460
        credentials_from_disk = config.AuthenticationConfig().get_credentials(
 
1461
            host='host', scheme='scheme', port=99, path='/foo', realm='realm')
 
1462
        self.assertEqual(CREDENTIALS, credentials_from_disk)
 
1463
 
 
1464
    def test_reset_credentials_different_name(self):
 
1465
        conf = config.AuthenticationConfig()
 
1466
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password'),
 
1467
        conf.set_credentials('name2', 'host', 'user2', 'scheme', 'password'),
 
1468
        self.assertIs(None, conf._get_config().get('name'))
 
1469
        credentials = conf.get_credentials(host='host', scheme='scheme')
 
1470
        CREDENTIALS = {'name': 'name2', 'user': 'user2', 'password':
 
1471
                       'password', 'verify_certificates': True, 
 
1472
                       'scheme': 'scheme', 'host': 'host', 'port': None, 
 
1473
                       'path': None, 'realm': None}
 
1474
        self.assertEqual(CREDENTIALS, credentials)
 
1475
 
 
1476
 
1404
1477
class TestAuthenticationConfig(tests.TestCase):
1405
1478
    """Test AuthenticationConfig behaviour"""
1406
1479
 
1407
 
    def _check_default_prompt(self, expected_prompt_format, scheme,
1408
 
                              host=None, port=None, realm=None, path=None):
 
1480
    def _check_default_password_prompt(self, expected_prompt_format, scheme,
 
1481
                                       host=None, port=None, realm=None,
 
1482
                                       path=None):
1409
1483
        if host is None:
1410
1484
            host = 'bar.org'
1411
1485
        user, password = 'jim', 'precious'
1414
1488
            'user': user, 'realm': realm}
1415
1489
 
1416
1490
        stdout = tests.StringIOWrapper()
 
1491
        stderr = tests.StringIOWrapper()
1417
1492
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
1418
 
                                            stdout=stdout)
 
1493
                                            stdout=stdout, stderr=stderr)
1419
1494
        # We use an empty conf so that the user is always prompted
1420
1495
        conf = config.AuthenticationConfig()
1421
1496
        self.assertEquals(password,
1422
1497
                          conf.get_password(scheme, host, user, port=port,
1423
1498
                                            realm=realm, path=path))
1424
 
        self.assertEquals(stdout.getvalue(), expected_prompt)
1425
 
 
1426
 
    def test_default_prompts(self):
1427
 
        # HTTP prompts can't be tested here, see test_http.py
1428
 
        self._check_default_prompt('FTP %(user)s@%(host)s password: ', 'ftp')
1429
 
        self._check_default_prompt('FTP %(user)s@%(host)s:%(port)d password: ',
1430
 
                                   'ftp', port=10020)
1431
 
 
1432
 
        self._check_default_prompt('SSH %(user)s@%(host)s:%(port)d password: ',
1433
 
                                   'ssh', port=12345)
 
1499
        self.assertEquals(expected_prompt, stderr.getvalue())
 
1500
        self.assertEquals('', stdout.getvalue())
 
1501
 
 
1502
    def _check_default_username_prompt(self, expected_prompt_format, scheme,
 
1503
                                       host=None, port=None, realm=None,
 
1504
                                       path=None):
 
1505
        if host is None:
 
1506
            host = 'bar.org'
 
1507
        username = 'jim'
 
1508
        expected_prompt = expected_prompt_format % {
 
1509
            'scheme': scheme, 'host': host, 'port': port,
 
1510
            'realm': realm}
 
1511
        stdout = tests.StringIOWrapper()
 
1512
        stderr = tests.StringIOWrapper()
 
1513
        ui.ui_factory = tests.TestUIFactory(stdin=username+ '\n',
 
1514
                                            stdout=stdout, stderr=stderr)
 
1515
        # We use an empty conf so that the user is always prompted
 
1516
        conf = config.AuthenticationConfig()
 
1517
        self.assertEquals(username, conf.get_user(scheme, host, port=port,
 
1518
                          realm=realm, path=path, ask=True))
 
1519
        self.assertEquals(expected_prompt, stderr.getvalue())
 
1520
        self.assertEquals('', stdout.getvalue())
 
1521
 
 
1522
    def test_username_defaults_prompts(self):
 
1523
        # HTTP prompts can't be tested here, see test_http.py
 
1524
        self._check_default_username_prompt('FTP %(host)s username: ', 'ftp')
 
1525
        self._check_default_username_prompt(
 
1526
            'FTP %(host)s:%(port)d username: ', 'ftp', port=10020)
 
1527
        self._check_default_username_prompt(
 
1528
            'SSH %(host)s:%(port)d username: ', 'ssh', port=12345)
 
1529
 
 
1530
    def test_username_default_no_prompt(self):
 
1531
        conf = config.AuthenticationConfig()
 
1532
        self.assertEquals(None,
 
1533
            conf.get_user('ftp', 'example.com'))
 
1534
        self.assertEquals("explicitdefault",
 
1535
            conf.get_user('ftp', 'example.com', default="explicitdefault"))
 
1536
 
 
1537
    def test_password_default_prompts(self):
 
1538
        # HTTP prompts can't be tested here, see test_http.py
 
1539
        self._check_default_password_prompt(
 
1540
            'FTP %(user)s@%(host)s password: ', 'ftp')
 
1541
        self._check_default_password_prompt(
 
1542
            'FTP %(user)s@%(host)s:%(port)d password: ', 'ftp', port=10020)
 
1543
        self._check_default_password_prompt(
 
1544
            'SSH %(user)s@%(host)s:%(port)d password: ', 'ssh', port=12345)
1434
1545
        # SMTP port handling is a bit special (it's handled if embedded in the
1435
1546
        # host too)
1436
1547
        # FIXME: should we: forbid that, extend it to other schemes, leave
1437
1548
        # things as they are that's fine thank you ?
1438
 
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
1439
 
                                   'smtp')
1440
 
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
1441
 
                                   'smtp', host='bar.org:10025')
1442
 
        self._check_default_prompt(
 
1549
        self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
 
1550
                                            'smtp')
 
1551
        self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
 
1552
                                            'smtp', host='bar.org:10025')
 
1553
        self._check_default_password_prompt(
1443
1554
            'SMTP %(user)s@%(host)s:%(port)d password: ',
1444
1555
            'smtp', port=10025)
1445
1556
 
1454
1565
"""))
1455
1566
        entered_password = 'typed-by-hand'
1456
1567
        stdout = tests.StringIOWrapper()
 
1568
        stderr = tests.StringIOWrapper()
1457
1569
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1458
 
                                            stdout=stdout)
 
1570
                                            stdout=stdout, stderr=stderr)
1459
1571
 
1460
1572
        # Since the password defined in the authentication config is ignored,
1461
1573
        # the user is prompted
1475
1587
"""))
1476
1588
        entered_password = 'typed-by-hand'
1477
1589
        stdout = tests.StringIOWrapper()
 
1590
        stderr = tests.StringIOWrapper()
1478
1591
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1479
 
                                            stdout=stdout)
 
1592
                                            stdout=stdout,
 
1593
                                            stderr=stderr)
1480
1594
 
1481
1595
        # Since the password defined in the authentication config is ignored,
1482
1596
        # the user is prompted
1488
1602
            self._get_log(keep_log_file=True),
1489
1603
            'password ignored in section \[ssh with password\]')
1490
1604
 
 
1605
    def test_uses_fallback_stores(self):
 
1606
        self._old_cs_registry = config.credential_store_registry
 
1607
        def restore():
 
1608
            config.credential_store_registry = self._old_cs_registry
 
1609
        self.addCleanup(restore)
 
1610
        config.credential_store_registry = config.CredentialStoreRegistry()
 
1611
        store = StubCredentialStore()
 
1612
        store.add_credentials("http", "example.com", "joe", "secret")
 
1613
        config.credential_store_registry.register("stub", store, fallback=True)
 
1614
        conf = config.AuthenticationConfig(_file=StringIO())
 
1615
        creds = conf.get_credentials("http", "example.com")
 
1616
        self.assertEquals("joe", creds["user"])
 
1617
        self.assertEquals("secret", creds["password"])
 
1618
 
 
1619
 
 
1620
class StubCredentialStore(config.CredentialStore):
 
1621
 
 
1622
    def __init__(self):
 
1623
        self._username = {}
 
1624
        self._password = {}
 
1625
 
 
1626
    def add_credentials(self, scheme, host, user, password=None):
 
1627
        self._username[(scheme, host)] = user
 
1628
        self._password[(scheme, host)] = password
 
1629
 
 
1630
    def get_credentials(self, scheme, host, port=None, user=None,
 
1631
        path=None, realm=None):
 
1632
        key = (scheme, host)
 
1633
        if not key in self._username:
 
1634
            return None
 
1635
        return { "scheme": scheme, "host": host, "port": port,
 
1636
                "user": self._username[key], "password": self._password[key]}
 
1637
 
 
1638
 
 
1639
class CountingCredentialStore(config.CredentialStore):
 
1640
 
 
1641
    def __init__(self):
 
1642
        self._calls = 0
 
1643
 
 
1644
    def get_credentials(self, scheme, host, port=None, user=None,
 
1645
        path=None, realm=None):
 
1646
        self._calls += 1
 
1647
        return None
 
1648
 
 
1649
 
 
1650
class TestCredentialStoreRegistry(tests.TestCase):
 
1651
 
 
1652
    def _get_cs_registry(self):
 
1653
        return config.credential_store_registry
 
1654
 
 
1655
    def test_default_credential_store(self):
 
1656
        r = self._get_cs_registry()
 
1657
        default = r.get_credential_store(None)
 
1658
        self.assertIsInstance(default, config.PlainTextCredentialStore)
 
1659
 
 
1660
    def test_unknown_credential_store(self):
 
1661
        r = self._get_cs_registry()
 
1662
        # It's hard to imagine someone creating a credential store named
 
1663
        # 'unknown' so we use that as an never registered key.
 
1664
        self.assertRaises(KeyError, r.get_credential_store, 'unknown')
 
1665
 
 
1666
    def test_fallback_none_registered(self):
 
1667
        r = config.CredentialStoreRegistry()
 
1668
        self.assertEquals(None,
 
1669
                          r.get_fallback_credentials("http", "example.com"))
 
1670
 
 
1671
    def test_register(self):
 
1672
        r = config.CredentialStoreRegistry()
 
1673
        r.register("stub", StubCredentialStore(), fallback=False)
 
1674
        r.register("another", StubCredentialStore(), fallback=True)
 
1675
        self.assertEquals(["another", "stub"], r.keys())
 
1676
 
 
1677
    def test_register_lazy(self):
 
1678
        r = config.CredentialStoreRegistry()
 
1679
        r.register_lazy("stub", "bzrlib.tests.test_config",
 
1680
                        "StubCredentialStore", fallback=False)
 
1681
        self.assertEquals(["stub"], r.keys())
 
1682
        self.assertIsInstance(r.get_credential_store("stub"),
 
1683
                              StubCredentialStore)
 
1684
 
 
1685
    def test_is_fallback(self):
 
1686
        r = config.CredentialStoreRegistry()
 
1687
        r.register("stub1", None, fallback=False)
 
1688
        r.register("stub2", None, fallback=True)
 
1689
        self.assertEquals(False, r.is_fallback("stub1"))
 
1690
        self.assertEquals(True, r.is_fallback("stub2"))
 
1691
 
 
1692
    def test_no_fallback(self):
 
1693
        r = config.CredentialStoreRegistry()
 
1694
        store = CountingCredentialStore()
 
1695
        r.register("count", store, fallback=False)
 
1696
        self.assertEquals(None,
 
1697
                          r.get_fallback_credentials("http", "example.com"))
 
1698
        self.assertEquals(0, store._calls)
 
1699
 
 
1700
    def test_fallback_credentials(self):
 
1701
        r = config.CredentialStoreRegistry()
 
1702
        store = StubCredentialStore()
 
1703
        store.add_credentials("http", "example.com",
 
1704
                              "somebody", "geheim")
 
1705
        r.register("stub", store, fallback=True)
 
1706
        creds = r.get_fallback_credentials("http", "example.com")
 
1707
        self.assertEquals("somebody", creds["user"])
 
1708
        self.assertEquals("geheim", creds["password"])
 
1709
 
 
1710
    def test_fallback_first_wins(self):
 
1711
        r = config.CredentialStoreRegistry()
 
1712
        stub1 = StubCredentialStore()
 
1713
        stub1.add_credentials("http", "example.com",
 
1714
                              "somebody", "stub1")
 
1715
        r.register("stub1", stub1, fallback=True)
 
1716
        stub2 = StubCredentialStore()
 
1717
        stub2.add_credentials("http", "example.com",
 
1718
                              "somebody", "stub2")
 
1719
        r.register("stub2", stub1, fallback=True)
 
1720
        creds = r.get_fallback_credentials("http", "example.com")
 
1721
        self.assertEquals("somebody", creds["user"])
 
1722
        self.assertEquals("stub1", creds["password"])
 
1723
 
 
1724
 
 
1725
class TestPlainTextCredentialStore(tests.TestCase):
 
1726
 
 
1727
    def test_decode_password(self):
 
1728
        r = config.credential_store_registry
 
1729
        plain_text = r.get_credential_store()
 
1730
        decoded = plain_text.decode_password(dict(password='secret'))
 
1731
        self.assertEquals('secret', decoded)
 
1732
 
1491
1733
 
1492
1734
# FIXME: Once we have a way to declare authentication to all test servers, we
1493
1735
# can implement generic tests.