~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

resolve conflicts against trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
    mergetools,
37
37
    ui,
38
38
    urlutils,
 
39
    registry,
39
40
    tests,
40
41
    trace,
41
42
    transport,
42
43
    )
43
44
from bzrlib.tests import (
44
45
    features,
 
46
    TestSkipped,
45
47
    scenarios,
46
48
    )
47
49
from bzrlib.util.configobj import configobj
61
63
 
62
64
load_tests = scenarios.load_tests_apply_scenarios
63
65
 
 
66
# We need adapters that can build a config store in a test context. Test
 
67
# classes, based on TestCaseWithTransport, can use the registry to parametrize
 
68
# themselves. The builder will receive a test instance and should return a
 
69
# ready-to-use store.  Plugins that defines new stores can also register
 
70
# themselves here to be tested against the tests defined below.
 
71
 
 
72
# FIXME: plugins should *not* need to import test_config to register their
 
73
# helpers (or selftest -s xxx will be broken), the following registry should be
 
74
# moved to bzrlib.config instead so that selftest -s bt.test_config also runs
 
75
# the plugin specific tests (selftest -s bp.xxx won't, that would be against
 
76
# the spirit of '-s') -- vila 20110503
 
77
test_store_builder_registry = registry.Registry()
 
78
test_store_builder_registry.register(
 
79
    'configobj', lambda test: config.IniFileStore(test.get_transport(),
 
80
                                                  'configobj.conf'))
 
81
test_store_builder_registry.register(
 
82
    'bazaar', lambda test: config.GlobalStore())
 
83
test_store_builder_registry.register(
 
84
    'location', lambda test: config.LocationStore())
 
85
test_store_builder_registry.register(
 
86
    'branch', lambda test: config.BranchStore(test.branch))
 
87
 
 
88
# FIXME: Same remark as above for the following registry -- vila 20110503
 
89
test_stack_builder_registry = registry.Registry()
 
90
test_stack_builder_registry.register(
 
91
    'bazaar', lambda test: config.GlobalStack())
 
92
test_stack_builder_registry.register(
 
93
    'location', lambda test: config.LocationStack('.'))
 
94
test_stack_builder_registry.register(
 
95
    'branch', lambda test: config.BranchStack(test.branch))
 
96
 
64
97
 
65
98
sample_long_alias="log -r-15..-1 --line"
66
99
sample_config_text = u"""
509
542
    def test_cached(self):
510
543
        my_config = config.IniBasedConfig.from_string(sample_config_text)
511
544
        parser = my_config._get_parser()
512
 
        self.failUnless(my_config._get_parser() is parser)
 
545
        self.assertTrue(my_config._get_parser() is parser)
513
546
 
514
547
    def _dummy_chown(self, path, uid, gid):
515
548
        self.path, self.uid, self.gid = path, uid, gid
831
864
        def c1_write_config_file():
832
865
            before_writing.set()
833
866
            c1_orig()
834
 
            # The lock is held we wait for the main thread to decide when to
 
867
            # The lock is held. We wait for the main thread to decide when to
835
868
            # continue
836
869
            after_writing.wait()
837
870
        c1._write_config_file = c1_write_config_file
864
897
       c1_orig = c1._write_config_file
865
898
       def c1_write_config_file():
866
899
           ready_to_write.set()
867
 
           # The lock is held we wait for the main thread to decide when to
 
900
           # The lock is held. We wait for the main thread to decide when to
868
901
           # continue
869
902
           do_writing.wait()
870
903
           c1_orig()
961
994
            parser = my_config._get_parser()
962
995
        finally:
963
996
            config.ConfigObj = oldparserclass
964
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
997
        self.assertIsInstance(parser, InstrumentedConfigObj)
965
998
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
966
999
                                          'utf-8')])
967
1000
 
978
1011
        my_config = config.BranchConfig(branch)
979
1012
        location_config = my_config._get_location_config()
980
1013
        self.assertEqual(branch.base, location_config.location)
981
 
        self.failUnless(location_config is my_config._get_location_config())
 
1014
        self.assertIs(location_config, my_config._get_location_config())
982
1015
 
983
1016
    def test_get_config(self):
984
1017
        """The Branch.get_config method works properly"""
1252
1285
            parser = my_config._get_parser()
1253
1286
        finally:
1254
1287
            config.ConfigObj = oldparserclass
1255
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
1288
        self.assertIsInstance(parser, InstrumentedConfigObj)
1256
1289
        self.assertEqual(parser._calls,
1257
1290
                         [('__init__', config.locations_config_filename(),
1258
1291
                           'utf-8')])
1260
1293
    def test_get_global_config(self):
1261
1294
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
1262
1295
        global_config = my_config._get_global_config()
1263
 
        self.failUnless(isinstance(global_config, config.GlobalConfig))
1264
 
        self.failUnless(global_config is my_config._get_global_config())
 
1296
        self.assertIsInstance(global_config, config.GlobalConfig)
 
1297
        self.assertIs(global_config, my_config._get_global_config())
 
1298
 
 
1299
    def assertLocationMatching(self, expected):
 
1300
        self.assertEqual(expected,
 
1301
                         list(self.my_location_config._get_matching_sections()))
1265
1302
 
1266
1303
    def test__get_matching_sections_no_match(self):
1267
1304
        self.get_branch_config('/')
1268
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
1305
        self.assertLocationMatching([])
1269
1306
 
1270
1307
    def test__get_matching_sections_exact(self):
1271
1308
        self.get_branch_config('http://www.example.com')
1272
 
        self.assertEqual([('http://www.example.com', '')],
1273
 
                         self.my_location_config._get_matching_sections())
 
1309
        self.assertLocationMatching([('http://www.example.com', '')])
1274
1310
 
1275
1311
    def test__get_matching_sections_suffix_does_not(self):
1276
1312
        self.get_branch_config('http://www.example.com-com')
1277
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
1313
        self.assertLocationMatching([])
1278
1314
 
1279
1315
    def test__get_matching_sections_subdir_recursive(self):
1280
1316
        self.get_branch_config('http://www.example.com/com')
1281
 
        self.assertEqual([('http://www.example.com', 'com')],
1282
 
                         self.my_location_config._get_matching_sections())
 
1317
        self.assertLocationMatching([('http://www.example.com', 'com')])
1283
1318
 
1284
1319
    def test__get_matching_sections_ignoreparent(self):
1285
1320
        self.get_branch_config('http://www.example.com/ignoreparent')
1286
 
        self.assertEqual([('http://www.example.com/ignoreparent', '')],
1287
 
                         self.my_location_config._get_matching_sections())
 
1321
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
 
1322
                                      '')])
1288
1323
 
1289
1324
    def test__get_matching_sections_ignoreparent_subdir(self):
1290
1325
        self.get_branch_config(
1291
1326
            'http://www.example.com/ignoreparent/childbranch')
1292
 
        self.assertEqual([('http://www.example.com/ignoreparent',
1293
 
                           'childbranch')],
1294
 
                         self.my_location_config._get_matching_sections())
 
1327
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
 
1328
                                      'childbranch')])
1295
1329
 
1296
1330
    def test__get_matching_sections_subdir_trailing_slash(self):
1297
1331
        self.get_branch_config('/b')
1298
 
        self.assertEqual([('/b/', '')],
1299
 
                         self.my_location_config._get_matching_sections())
 
1332
        self.assertLocationMatching([('/b/', '')])
1300
1333
 
1301
1334
    def test__get_matching_sections_subdir_child(self):
1302
1335
        self.get_branch_config('/a/foo')
1303
 
        self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
1304
 
                         self.my_location_config._get_matching_sections())
 
1336
        self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1305
1337
 
1306
1338
    def test__get_matching_sections_subdir_child_child(self):
1307
1339
        self.get_branch_config('/a/foo/bar')
1308
 
        self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
1309
 
                         self.my_location_config._get_matching_sections())
 
1340
        self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1310
1341
 
1311
1342
    def test__get_matching_sections_trailing_slash_with_children(self):
1312
1343
        self.get_branch_config('/a/')
1313
 
        self.assertEqual([('/a/', '')],
1314
 
                         self.my_location_config._get_matching_sections())
 
1344
        self.assertLocationMatching([('/a/', '')])
1315
1345
 
1316
1346
    def test__get_matching_sections_explicit_over_glob(self):
1317
1347
        # XXX: 2006-09-08 jamesh
1319
1349
        # was a config section for '/a/?', it would get precedence
1320
1350
        # over '/a/c'.
1321
1351
        self.get_branch_config('/a/c')
1322
 
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
1323
 
                         self.my_location_config._get_matching_sections())
 
1352
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
1324
1353
 
1325
1354
    def test__get_option_policy_normal(self):
1326
1355
        self.get_branch_config('http://www.example.com')
1817
1846
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1818
1847
 
1819
1848
 
 
1849
class TestSection(tests.TestCase):
 
1850
 
 
1851
    # FIXME: Parametrize so that all sections produced by Stores run these
 
1852
    # tests -- vila 2011-04-01
 
1853
 
 
1854
    def test_get_a_value(self):
 
1855
        a_dict = dict(foo='bar')
 
1856
        section = config.Section('myID', a_dict)
 
1857
        self.assertEquals('bar', section.get('foo'))
 
1858
 
 
1859
    def test_get_unknown_option(self):
 
1860
        a_dict = dict()
 
1861
        section = config.Section(None, a_dict)
 
1862
        self.assertEquals('out of thin air',
 
1863
                          section.get('foo', 'out of thin air'))
 
1864
 
 
1865
    def test_options_is_shared(self):
 
1866
        a_dict = dict()
 
1867
        section = config.Section(None, a_dict)
 
1868
        self.assertIs(a_dict, section.options)
 
1869
 
 
1870
 
 
1871
class TestMutableSection(tests.TestCase):
 
1872
 
 
1873
    # FIXME: Parametrize so that all sections (including os.environ and the
 
1874
    # ones produced by Stores) run these tests -- vila 2011-04-01
 
1875
 
 
1876
    def test_set(self):
 
1877
        a_dict = dict(foo='bar')
 
1878
        section = config.MutableSection('myID', a_dict)
 
1879
        section.set('foo', 'new_value')
 
1880
        self.assertEquals('new_value', section.get('foo'))
 
1881
        # The change appears in the shared section
 
1882
        self.assertEquals('new_value', a_dict.get('foo'))
 
1883
        # We keep track of the change
 
1884
        self.assertTrue('foo' in section.orig)
 
1885
        self.assertEquals('bar', section.orig.get('foo'))
 
1886
 
 
1887
    def test_set_preserve_original_once(self):
 
1888
        a_dict = dict(foo='bar')
 
1889
        section = config.MutableSection('myID', a_dict)
 
1890
        section.set('foo', 'first_value')
 
1891
        section.set('foo', 'second_value')
 
1892
        # We keep track of the original value
 
1893
        self.assertTrue('foo' in section.orig)
 
1894
        self.assertEquals('bar', section.orig.get('foo'))
 
1895
 
 
1896
    def test_remove(self):
 
1897
        a_dict = dict(foo='bar')
 
1898
        section = config.MutableSection('myID', a_dict)
 
1899
        section.remove('foo')
 
1900
        # We get None for unknown options via the default value
 
1901
        self.assertEquals(None, section.get('foo'))
 
1902
        # Or we just get the default value
 
1903
        self.assertEquals('unknown', section.get('foo', 'unknown'))
 
1904
        self.assertFalse('foo' in section.options)
 
1905
        # We keep track of the deletion
 
1906
        self.assertTrue('foo' in section.orig)
 
1907
        self.assertEquals('bar', section.orig.get('foo'))
 
1908
 
 
1909
    def test_remove_new_option(self):
 
1910
        a_dict = dict()
 
1911
        section = config.MutableSection('myID', a_dict)
 
1912
        section.set('foo', 'bar')
 
1913
        section.remove('foo')
 
1914
        self.assertFalse('foo' in section.options)
 
1915
        # The option didn't exist initially so it we need to keep track of it
 
1916
        # with a special value
 
1917
        self.assertTrue('foo' in section.orig)
 
1918
        self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
 
1919
 
 
1920
 
 
1921
class TestStore(tests.TestCaseWithTransport):
 
1922
 
 
1923
    def assertSectionContent(self, expected, section):
 
1924
        """Assert that some options have the proper values in a section."""
 
1925
        expected_name, expected_options = expected
 
1926
        self.assertEquals(expected_name, section.id)
 
1927
        self.assertEquals(
 
1928
            expected_options,
 
1929
            dict([(k, section.get(k)) for k in expected_options.keys()]))
 
1930
 
 
1931
 
 
1932
class TestReadonlyStore(TestStore):
 
1933
 
 
1934
    scenarios = [(key, {'get_store': builder})
 
1935
                 for key, builder in test_store_builder_registry.iteritems()]
 
1936
 
 
1937
    def setUp(self):
 
1938
        super(TestReadonlyStore, self).setUp()
 
1939
        self.branch = self.make_branch('branch')
 
1940
 
 
1941
    def test_building_delays_load(self):
 
1942
        store = self.get_store(self)
 
1943
        self.assertEquals(False, store.is_loaded())
 
1944
        store._load_from_string('')
 
1945
        self.assertEquals(True, store.is_loaded())
 
1946
 
 
1947
    def test_get_no_sections_for_empty(self):
 
1948
        store = self.get_store(self)
 
1949
        store._load_from_string('')
 
1950
        self.assertEquals([], list(store.get_sections()))
 
1951
 
 
1952
    def test_get_default_section(self):
 
1953
        store = self.get_store(self)
 
1954
        store._load_from_string('foo=bar')
 
1955
        sections = list(store.get_sections())
 
1956
        self.assertLength(1, sections)
 
1957
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
1958
 
 
1959
    def test_get_named_section(self):
 
1960
        store = self.get_store(self)
 
1961
        store._load_from_string('[baz]\nfoo=bar')
 
1962
        sections = list(store.get_sections())
 
1963
        self.assertLength(1, sections)
 
1964
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
 
1965
 
 
1966
    def test_load_from_string_fails_for_non_empty_store(self):
 
1967
        store = self.get_store(self)
 
1968
        store._load_from_string('foo=bar')
 
1969
        self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
 
1970
 
 
1971
 
 
1972
class TestMutableStore(TestStore):
 
1973
 
 
1974
    scenarios = [(key, {'store_id': key, 'get_store': builder})
 
1975
                 for key, builder in test_store_builder_registry.iteritems()]
 
1976
 
 
1977
    def setUp(self):
 
1978
        super(TestMutableStore, self).setUp()
 
1979
        self.transport = self.get_transport()
 
1980
        self.branch = self.make_branch('branch')
 
1981
 
 
1982
    def has_store(self, store):
 
1983
        store_basename = urlutils.relative_url(self.transport.external_url(),
 
1984
                                               store.external_url())
 
1985
        return self.transport.has(store_basename)
 
1986
 
 
1987
    def test_save_empty_creates_no_file(self):
 
1988
        if self.store_id == 'branch':
 
1989
            raise tests.TestNotApplicable(
 
1990
                'branch.conf is *always* created when a branch is initialized')
 
1991
        store = self.get_store(self)
 
1992
        store.save()
 
1993
        self.assertEquals(False, self.has_store(store))
 
1994
 
 
1995
    def test_save_emptied_succeeds(self):
 
1996
        store = self.get_store(self)
 
1997
        store._load_from_string('foo=bar\n')
 
1998
        section = store.get_mutable_section(None)
 
1999
        section.remove('foo')
 
2000
        store.save()
 
2001
        self.assertEquals(True, self.has_store(store))
 
2002
        modified_store = self.get_store(self)
 
2003
        sections = list(modified_store.get_sections())
 
2004
        self.assertLength(0, sections)
 
2005
 
 
2006
    def test_save_with_content_succeeds(self):
 
2007
        if self.store_id == 'branch':
 
2008
            raise tests.TestNotApplicable(
 
2009
                'branch.conf is *always* created when a branch is initialized')
 
2010
        store = self.get_store(self)
 
2011
        store._load_from_string('foo=bar\n')
 
2012
        self.assertEquals(False, self.has_store(store))
 
2013
        store.save()
 
2014
        self.assertEquals(True, self.has_store(store))
 
2015
        modified_store = self.get_store(self)
 
2016
        sections = list(modified_store.get_sections())
 
2017
        self.assertLength(1, sections)
 
2018
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2019
 
 
2020
    def test_set_option_in_empty_store(self):
 
2021
        store = self.get_store(self)
 
2022
        section = store.get_mutable_section(None)
 
2023
        section.set('foo', 'bar')
 
2024
        store.save()
 
2025
        modified_store = self.get_store(self)
 
2026
        sections = list(modified_store.get_sections())
 
2027
        self.assertLength(1, sections)
 
2028
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2029
 
 
2030
    def test_set_option_in_default_section(self):
 
2031
        store = self.get_store(self)
 
2032
        store._load_from_string('')
 
2033
        section = store.get_mutable_section(None)
 
2034
        section.set('foo', 'bar')
 
2035
        store.save()
 
2036
        modified_store = self.get_store(self)
 
2037
        sections = list(modified_store.get_sections())
 
2038
        self.assertLength(1, sections)
 
2039
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2040
 
 
2041
    def test_set_option_in_named_section(self):
 
2042
        store = self.get_store(self)
 
2043
        store._load_from_string('')
 
2044
        section = store.get_mutable_section('baz')
 
2045
        section.set('foo', 'bar')
 
2046
        store.save()
 
2047
        modified_store = self.get_store(self)
 
2048
        sections = list(modified_store.get_sections())
 
2049
        self.assertLength(1, sections)
 
2050
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
 
2051
 
 
2052
 
 
2053
class TestIniFileStore(TestStore):
 
2054
 
 
2055
    def test_loading_unknown_file_fails(self):
 
2056
        store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
 
2057
        self.assertRaises(errors.NoSuchFile, store.load)
 
2058
 
 
2059
    def test_invalid_content(self):
 
2060
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
2061
        self.assertEquals(False, store.is_loaded())
 
2062
        exc = self.assertRaises(
 
2063
            errors.ParseConfigError, store._load_from_string,
 
2064
            'this is invalid !')
 
2065
        self.assertEndsWith(exc.filename, 'foo.conf')
 
2066
        # And the load failed
 
2067
        self.assertEquals(False, store.is_loaded())
 
2068
 
 
2069
    def test_get_embedded_sections(self):
 
2070
        # A more complicated example (which also shows that section names and
 
2071
        # option names share the same name space...)
 
2072
        # FIXME: This should be fixed by forbidding dicts as values ?
 
2073
        # -- vila 2011-04-05
 
2074
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
2075
        store._load_from_string('''
 
2076
foo=bar
 
2077
l=1,2
 
2078
[DEFAULT]
 
2079
foo_in_DEFAULT=foo_DEFAULT
 
2080
[bar]
 
2081
foo_in_bar=barbar
 
2082
[baz]
 
2083
foo_in_baz=barbaz
 
2084
[[qux]]
 
2085
foo_in_qux=quux
 
2086
''')
 
2087
        sections = list(store.get_sections())
 
2088
        self.assertLength(4, sections)
 
2089
        # The default section has no name.
 
2090
        # List values are provided as lists
 
2091
        self.assertSectionContent((None, {'foo': 'bar', 'l': ['1', '2']}),
 
2092
                                  sections[0])
 
2093
        self.assertSectionContent(
 
2094
            ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
 
2095
        self.assertSectionContent(
 
2096
            ('bar', {'foo_in_bar': 'barbar'}), sections[2])
 
2097
        # sub sections are provided as embedded dicts.
 
2098
        self.assertSectionContent(
 
2099
            ('baz', {'foo_in_baz': 'barbaz', 'qux': {'foo_in_qux': 'quux'}}),
 
2100
            sections[3])
 
2101
 
 
2102
 
 
2103
class TestLockableIniFileStore(TestStore):
 
2104
 
 
2105
    def test_create_store_in_created_dir(self):
 
2106
        t = self.get_transport('dir/subdir')
 
2107
        store = config.LockableIniFileStore(t, 'foo.conf')
 
2108
        store.get_mutable_section(None).set('foo', 'bar')
 
2109
        store.save()
 
2110
 
 
2111
    # FIXME: We should adapt the tests in TestLockableConfig about concurrent
 
2112
    # writes. Since this requires a clearer rewrite, I'll just rely on using
 
2113
    # the same code in LockableIniFileStore (copied from LockableConfig, but
 
2114
    # trivial enough, the main difference is that we add @needs_write_lock on
 
2115
    # save() instead of set_user_option() and remove_user_option()). The intent
 
2116
    # is to ensure that we always get a valid content for the store even when
 
2117
    # concurrent accesses occur, read/write, write/write. It may be worth
 
2118
    # looking into removing the lock dir when it;s not needed anymore and look
 
2119
    # at possible fallouts for concurrent lockers -- vila 20110-04-06
 
2120
 
 
2121
 
 
2122
class TestSectionMatcher(TestStore):
 
2123
 
 
2124
    scenarios = [('location', {'matcher': config.LocationMatcher})]
 
2125
 
 
2126
    def get_store(self, file_name):
 
2127
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
2128
 
 
2129
    def test_no_matches_for_empty_stores(self):
 
2130
        store = self.get_store('foo.conf')
 
2131
        store._load_from_string('')
 
2132
        matcher = self.matcher(store, '/bar')
 
2133
        self.assertEquals([], list(matcher.get_sections()))
 
2134
 
 
2135
    def test_build_doesnt_load_store(self):
 
2136
        store = self.get_store('foo.conf')
 
2137
        matcher = self.matcher(store, '/bar')
 
2138
        self.assertFalse(store.is_loaded())
 
2139
 
 
2140
 
 
2141
class TestLocationSection(tests.TestCase):
 
2142
 
 
2143
    def get_section(self, options, extra_path):
 
2144
        section = config.Section('foo', options)
 
2145
        # We don't care about the length so we use '0'
 
2146
        return config.LocationSection(section, 0, extra_path)
 
2147
 
 
2148
    def test_simple_option(self):
 
2149
        section = self.get_section({'foo': 'bar'}, '')
 
2150
        self.assertEquals('bar', section.get('foo'))
 
2151
 
 
2152
    def test_option_with_extra_path(self):
 
2153
        section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
 
2154
                                   'baz')
 
2155
        self.assertEquals('bar/baz', section.get('foo'))
 
2156
 
 
2157
    def test_invalid_policy(self):
 
2158
        section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
 
2159
                                   'baz')
 
2160
        # invalid policies are ignored
 
2161
        self.assertEquals('bar', section.get('foo'))
 
2162
 
 
2163
 
 
2164
class TestLocationMatcher(TestStore):
 
2165
 
 
2166
    def get_store(self, file_name):
 
2167
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
2168
 
 
2169
    def test_more_specific_sections_first(self):
 
2170
        store = self.get_store('foo.conf')
 
2171
        store._load_from_string('''
 
2172
[/foo]
 
2173
section=/foo
 
2174
[/foo/bar]
 
2175
section=/foo/bar
 
2176
''')
 
2177
        self.assertEquals(['/foo', '/foo/bar'],
 
2178
                          [section.id for section in store.get_sections()])
 
2179
        matcher = config.LocationMatcher(store, '/foo/bar/baz')
 
2180
        sections = list(matcher.get_sections())
 
2181
        self.assertEquals([3, 2],
 
2182
                          [section.length for section in sections])
 
2183
        self.assertEquals(['/foo/bar', '/foo'],
 
2184
                          [section.id for section in sections])
 
2185
        self.assertEquals(['baz', 'bar/baz'],
 
2186
                          [section.extra_path for section in sections])
 
2187
 
 
2188
    def test_appendpath_in_no_name_section(self):
 
2189
        # It's a bit weird to allow appendpath in a no-name section, but
 
2190
        # someone may found a use for it
 
2191
        store = self.get_store('foo.conf')
 
2192
        store._load_from_string('''
 
2193
foo=bar
 
2194
foo:policy = appendpath
 
2195
''')
 
2196
        matcher = config.LocationMatcher(store, 'dir/subdir')
 
2197
        sections = list(matcher.get_sections())
 
2198
        self.assertLength(1, sections)
 
2199
        self.assertEquals('bar/dir/subdir', sections[0].get('foo'))
 
2200
 
 
2201
    def test_file_urls_are_normalized(self):
 
2202
        store = self.get_store('foo.conf')
 
2203
        if sys.platform == 'win32':
 
2204
            expected_url = 'file:///C:/dir/subdir'
 
2205
            expected_location = 'C:/dir/subdir'
 
2206
        else:
 
2207
            expected_url = 'file:///dir/subdir'
 
2208
            expected_location = '/dir/subdir'
 
2209
        matcher = config.LocationMatcher(store, expected_url)
 
2210
        self.assertEquals(expected_location, matcher.location)
 
2211
 
 
2212
 
 
2213
class TestStackGet(tests.TestCase):
 
2214
 
 
2215
    # FIXME: This should be parametrized for all known Stack or dedicated
 
2216
    # paramerized tests created to avoid bloating -- vila 2011-03-31
 
2217
 
 
2218
    def test_single_config_get(self):
 
2219
        conf = dict(foo='bar')
 
2220
        conf_stack = config.Stack([conf])
 
2221
        self.assertEquals('bar', conf_stack.get('foo'))
 
2222
 
 
2223
    def test_get_first_definition(self):
 
2224
        conf1 = dict(foo='bar')
 
2225
        conf2 = dict(foo='baz')
 
2226
        conf_stack = config.Stack([conf1, conf2])
 
2227
        self.assertEquals('bar', conf_stack.get('foo'))
 
2228
 
 
2229
    def test_get_embedded_definition(self):
 
2230
        conf1 = dict(yy='12')
 
2231
        conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
 
2232
        conf_stack = config.Stack([conf1, conf2])
 
2233
        self.assertEquals('baz', conf_stack.get('foo'))
 
2234
 
 
2235
    def test_get_for_empty_stack(self):
 
2236
        conf_stack = config.Stack([])
 
2237
        self.assertEquals(None, conf_stack.get('foo'))
 
2238
 
 
2239
    def test_get_for_empty_section_callable(self):
 
2240
        conf_stack = config.Stack([lambda : []])
 
2241
        self.assertEquals(None, conf_stack.get('foo'))
 
2242
 
 
2243
    def test_get_for_broken_callable(self):
 
2244
        # Trying to use and invalid callable raises an exception on first use
 
2245
        conf_stack = config.Stack([lambda : object()])
 
2246
        self.assertRaises(TypeError, conf_stack.get, 'foo')
 
2247
 
 
2248
 
 
2249
class TestStackWithTransport(tests.TestCaseWithTransport):
 
2250
 
 
2251
    def setUp(self):
 
2252
        super(TestStackWithTransport, self).setUp()
 
2253
        # FIXME: A more elaborate builder for the stack would avoid building a
 
2254
        # branch even for tests that don't need it.
 
2255
        self.branch = self.make_branch('branch')
 
2256
 
 
2257
 
 
2258
class TestStackSet(TestStackWithTransport):
 
2259
 
 
2260
    scenarios = [(key, {'get_stack': builder})
 
2261
                 for key, builder in test_stack_builder_registry.iteritems()]
 
2262
 
 
2263
    def test_simple_set(self):
 
2264
        conf = self.get_stack(self)
 
2265
        conf.store._load_from_string('foo=bar')
 
2266
        self.assertEquals('bar', conf.get('foo'))
 
2267
        conf.set('foo', 'baz')
 
2268
        # Did we get it back ?
 
2269
        self.assertEquals('baz', conf.get('foo'))
 
2270
 
 
2271
    def test_set_creates_a_new_section(self):
 
2272
        conf = self.get_stack(self)
 
2273
        conf.set('foo', 'baz')
 
2274
        self.assertEquals, 'baz', conf.get('foo')
 
2275
 
 
2276
 
 
2277
class TestStackRemove(TestStackWithTransport):
 
2278
 
 
2279
    scenarios = [(key, {'get_stack': builder})
 
2280
                 for key, builder in test_stack_builder_registry.iteritems()]
 
2281
 
 
2282
    def test_remove_existing(self):
 
2283
        conf = self.get_stack(self)
 
2284
        conf.store._load_from_string('foo=bar')
 
2285
        self.assertEquals('bar', conf.get('foo'))
 
2286
        conf.remove('foo')
 
2287
        # Did we get it back ?
 
2288
        self.assertEquals(None, conf.get('foo'))
 
2289
 
 
2290
    def test_remove_unknown(self):
 
2291
        conf = self.get_stack(self)
 
2292
        self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
 
2293
 
 
2294
 
 
2295
class TestConcreteStacks(TestStackWithTransport):
 
2296
 
 
2297
    scenarios = [(key, {'get_stack': builder})
 
2298
                 for key, builder in test_stack_builder_registry.iteritems()]
 
2299
 
 
2300
    def test_build_stack(self):
 
2301
        stack = self.get_stack(self)
 
2302
 
 
2303
 
1820
2304
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1821
2305
 
1822
2306
    def setUp(self):
1823
2307
        super(TestConfigGetOptions, self).setUp()
1824
2308
        create_configs(self)
1825
2309
 
1826
 
    # One variable in none of the above
1827
2310
    def test_no_variable(self):
1828
2311
        # Using branch should query branch, locations and bazaar
1829
2312
        self.assertOptions([], self.branch_config)
2469
2952
# test_user_prompted ?
2470
2953
class TestAuthenticationRing(tests.TestCaseWithTransport):
2471
2954
    pass
 
2955
 
 
2956
 
 
2957
class TestAutoUserId(tests.TestCase):
 
2958
    """Test inferring an automatic user name."""
 
2959
 
 
2960
    def test_auto_user_id(self):
 
2961
        """Automatic inference of user name.
 
2962
        
 
2963
        This is a bit hard to test in an isolated way, because it depends on
 
2964
        system functions that go direct to /etc or perhaps somewhere else.
 
2965
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
 
2966
        to be able to choose a user name with no configuration.
 
2967
        """
 
2968
        if sys.platform == 'win32':
 
2969
            raise TestSkipped("User name inference not implemented on win32")
 
2970
        realname, address = config._auto_user_id()
 
2971
        if os.path.exists('/etc/mailname'):
 
2972
            self.assertIsNot(None, realname)
 
2973
            self.assertIsNot(None, address)
 
2974
        else:
 
2975
            self.assertEquals((None, None), (realname, address))
 
2976