~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Jelmer Vernooij
  • Date: 2011-05-10 07:46:15 UTC
  • mfrom: (5844 +trunk)
  • mto: This revision was merged to the branch mainline in revision 5845.
  • Revision ID: jelmer@samba.org-20110510074615-eptod049ndjxc4i7
Merge bzr.dev.

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
 
64
89
 
65
90
sample_long_alias="log -r-15..-1 --line"
66
91
sample_config_text = u"""
509
534
    def test_cached(self):
510
535
        my_config = config.IniBasedConfig.from_string(sample_config_text)
511
536
        parser = my_config._get_parser()
512
 
        self.failUnless(my_config._get_parser() is parser)
 
537
        self.assertTrue(my_config._get_parser() is parser)
513
538
 
514
539
    def _dummy_chown(self, path, uid, gid):
515
540
        self.path, self.uid, self.gid = path, uid, gid
831
856
        def c1_write_config_file():
832
857
            before_writing.set()
833
858
            c1_orig()
834
 
            # The lock is held we wait for the main thread to decide when to
 
859
            # The lock is held. We wait for the main thread to decide when to
835
860
            # continue
836
861
            after_writing.wait()
837
862
        c1._write_config_file = c1_write_config_file
864
889
       c1_orig = c1._write_config_file
865
890
       def c1_write_config_file():
866
891
           ready_to_write.set()
867
 
           # The lock is held we wait for the main thread to decide when to
 
892
           # The lock is held. We wait for the main thread to decide when to
868
893
           # continue
869
894
           do_writing.wait()
870
895
           c1_orig()
961
986
            parser = my_config._get_parser()
962
987
        finally:
963
988
            config.ConfigObj = oldparserclass
964
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
989
        self.assertIsInstance(parser, InstrumentedConfigObj)
965
990
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
966
991
                                          'utf-8')])
967
992
 
978
1003
        my_config = config.BranchConfig(branch)
979
1004
        location_config = my_config._get_location_config()
980
1005
        self.assertEqual(branch.base, location_config.location)
981
 
        self.failUnless(location_config is my_config._get_location_config())
 
1006
        self.assertIs(location_config, my_config._get_location_config())
982
1007
 
983
1008
    def test_get_config(self):
984
1009
        """The Branch.get_config method works properly"""
1252
1277
            parser = my_config._get_parser()
1253
1278
        finally:
1254
1279
            config.ConfigObj = oldparserclass
1255
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
1280
        self.assertIsInstance(parser, InstrumentedConfigObj)
1256
1281
        self.assertEqual(parser._calls,
1257
1282
                         [('__init__', config.locations_config_filename(),
1258
1283
                           'utf-8')])
1260
1285
    def test_get_global_config(self):
1261
1286
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
1262
1287
        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())
 
1288
        self.assertIsInstance(global_config, config.GlobalConfig)
 
1289
        self.assertIs(global_config, my_config._get_global_config())
 
1290
 
 
1291
    def assertLocationMatching(self, expected):
 
1292
        self.assertEqual(expected,
 
1293
                         list(self.my_location_config._get_matching_sections()))
1265
1294
 
1266
1295
    def test__get_matching_sections_no_match(self):
1267
1296
        self.get_branch_config('/')
1268
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
1297
        self.assertLocationMatching([])
1269
1298
 
1270
1299
    def test__get_matching_sections_exact(self):
1271
1300
        self.get_branch_config('http://www.example.com')
1272
 
        self.assertEqual([('http://www.example.com', '')],
1273
 
                         self.my_location_config._get_matching_sections())
 
1301
        self.assertLocationMatching([('http://www.example.com', '')])
1274
1302
 
1275
1303
    def test__get_matching_sections_suffix_does_not(self):
1276
1304
        self.get_branch_config('http://www.example.com-com')
1277
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
1305
        self.assertLocationMatching([])
1278
1306
 
1279
1307
    def test__get_matching_sections_subdir_recursive(self):
1280
1308
        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())
 
1309
        self.assertLocationMatching([('http://www.example.com', 'com')])
1283
1310
 
1284
1311
    def test__get_matching_sections_ignoreparent(self):
1285
1312
        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())
 
1313
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
 
1314
                                      '')])
1288
1315
 
1289
1316
    def test__get_matching_sections_ignoreparent_subdir(self):
1290
1317
        self.get_branch_config(
1291
1318
            'http://www.example.com/ignoreparent/childbranch')
1292
 
        self.assertEqual([('http://www.example.com/ignoreparent',
1293
 
                           'childbranch')],
1294
 
                         self.my_location_config._get_matching_sections())
 
1319
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
 
1320
                                      'childbranch')])
1295
1321
 
1296
1322
    def test__get_matching_sections_subdir_trailing_slash(self):
1297
1323
        self.get_branch_config('/b')
1298
 
        self.assertEqual([('/b/', '')],
1299
 
                         self.my_location_config._get_matching_sections())
 
1324
        self.assertLocationMatching([('/b/', '')])
1300
1325
 
1301
1326
    def test__get_matching_sections_subdir_child(self):
1302
1327
        self.get_branch_config('/a/foo')
1303
 
        self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
1304
 
                         self.my_location_config._get_matching_sections())
 
1328
        self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1305
1329
 
1306
1330
    def test__get_matching_sections_subdir_child_child(self):
1307
1331
        self.get_branch_config('/a/foo/bar')
1308
 
        self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
1309
 
                         self.my_location_config._get_matching_sections())
 
1332
        self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1310
1333
 
1311
1334
    def test__get_matching_sections_trailing_slash_with_children(self):
1312
1335
        self.get_branch_config('/a/')
1313
 
        self.assertEqual([('/a/', '')],
1314
 
                         self.my_location_config._get_matching_sections())
 
1336
        self.assertLocationMatching([('/a/', '')])
1315
1337
 
1316
1338
    def test__get_matching_sections_explicit_over_glob(self):
1317
1339
        # XXX: 2006-09-08 jamesh
1319
1341
        # was a config section for '/a/?', it would get precedence
1320
1342
        # over '/a/c'.
1321
1343
        self.get_branch_config('/a/c')
1322
 
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
1323
 
                         self.my_location_config._get_matching_sections())
 
1344
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
1324
1345
 
1325
1346
    def test__get_option_policy_normal(self):
1326
1347
        self.get_branch_config('http://www.example.com')
1817
1838
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1818
1839
 
1819
1840
 
 
1841
class TestSection(tests.TestCase):
 
1842
 
 
1843
    # FIXME: Parametrize so that all sections produced by Stores run these
 
1844
    # tests -- vila 2011-04-01
 
1845
 
 
1846
    def test_get_a_value(self):
 
1847
        a_dict = dict(foo='bar')
 
1848
        section = config.Section('myID', a_dict)
 
1849
        self.assertEquals('bar', section.get('foo'))
 
1850
 
 
1851
    def test_get_unknown_option(self):
 
1852
        a_dict = dict()
 
1853
        section = config.Section(None, a_dict)
 
1854
        self.assertEquals('out of thin air',
 
1855
                          section.get('foo', 'out of thin air'))
 
1856
 
 
1857
    def test_options_is_shared(self):
 
1858
        a_dict = dict()
 
1859
        section = config.Section(None, a_dict)
 
1860
        self.assertIs(a_dict, section.options)
 
1861
 
 
1862
 
 
1863
class TestMutableSection(tests.TestCase):
 
1864
 
 
1865
    # FIXME: Parametrize so that all sections (including os.environ and the
 
1866
    # ones produced by Stores) run these tests -- vila 2011-04-01
 
1867
 
 
1868
    def test_set(self):
 
1869
        a_dict = dict(foo='bar')
 
1870
        section = config.MutableSection('myID', a_dict)
 
1871
        section.set('foo', 'new_value')
 
1872
        self.assertEquals('new_value', section.get('foo'))
 
1873
        # The change appears in the shared section
 
1874
        self.assertEquals('new_value', a_dict.get('foo'))
 
1875
        # We keep track of the change
 
1876
        self.assertTrue('foo' in section.orig)
 
1877
        self.assertEquals('bar', section.orig.get('foo'))
 
1878
 
 
1879
    def test_set_preserve_original_once(self):
 
1880
        a_dict = dict(foo='bar')
 
1881
        section = config.MutableSection('myID', a_dict)
 
1882
        section.set('foo', 'first_value')
 
1883
        section.set('foo', 'second_value')
 
1884
        # We keep track of the original value
 
1885
        self.assertTrue('foo' in section.orig)
 
1886
        self.assertEquals('bar', section.orig.get('foo'))
 
1887
 
 
1888
    def test_remove(self):
 
1889
        a_dict = dict(foo='bar')
 
1890
        section = config.MutableSection('myID', a_dict)
 
1891
        section.remove('foo')
 
1892
        # We get None for unknown options via the default value
 
1893
        self.assertEquals(None, section.get('foo'))
 
1894
        # Or we just get the default value
 
1895
        self.assertEquals('unknown', section.get('foo', 'unknown'))
 
1896
        self.assertFalse('foo' in section.options)
 
1897
        # We keep track of the deletion
 
1898
        self.assertTrue('foo' in section.orig)
 
1899
        self.assertEquals('bar', section.orig.get('foo'))
 
1900
 
 
1901
    def test_remove_new_option(self):
 
1902
        a_dict = dict()
 
1903
        section = config.MutableSection('myID', a_dict)
 
1904
        section.set('foo', 'bar')
 
1905
        section.remove('foo')
 
1906
        self.assertFalse('foo' in section.options)
 
1907
        # The option didn't exist initially so it we need to keep track of it
 
1908
        # with a special value
 
1909
        self.assertTrue('foo' in section.orig)
 
1910
        self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
 
1911
 
 
1912
 
 
1913
class TestStore(tests.TestCaseWithTransport):
 
1914
 
 
1915
    def assertSectionContent(self, expected, section):
 
1916
        """Assert that some options have the proper values in a section."""
 
1917
        expected_name, expected_options = expected
 
1918
        self.assertEquals(expected_name, section.id)
 
1919
        self.assertEquals(
 
1920
            expected_options,
 
1921
            dict([(k, section.get(k)) for k in expected_options.keys()]))
 
1922
 
 
1923
 
 
1924
class TestReadonlyStore(TestStore):
 
1925
 
 
1926
    scenarios = [(key, {'get_store': builder})
 
1927
                 for key, builder in test_store_builder_registry.iteritems()]
 
1928
 
 
1929
    def setUp(self):
 
1930
        super(TestReadonlyStore, self).setUp()
 
1931
        self.branch = self.make_branch('branch')
 
1932
 
 
1933
    def test_building_delays_load(self):
 
1934
        store = self.get_store(self)
 
1935
        self.assertEquals(False, store.is_loaded())
 
1936
        store._load_from_string('')
 
1937
        self.assertEquals(True, store.is_loaded())
 
1938
 
 
1939
    def test_get_no_sections_for_empty(self):
 
1940
        store = self.get_store(self)
 
1941
        store._load_from_string('')
 
1942
        self.assertEquals([], list(store.get_sections()))
 
1943
 
 
1944
    def test_get_default_section(self):
 
1945
        store = self.get_store(self)
 
1946
        store._load_from_string('foo=bar')
 
1947
        sections = list(store.get_sections())
 
1948
        self.assertLength(1, sections)
 
1949
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
1950
 
 
1951
    def test_get_named_section(self):
 
1952
        store = self.get_store(self)
 
1953
        store._load_from_string('[baz]\nfoo=bar')
 
1954
        sections = list(store.get_sections())
 
1955
        self.assertLength(1, sections)
 
1956
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
 
1957
 
 
1958
    def test_load_from_string_fails_for_non_empty_store(self):
 
1959
        store = self.get_store(self)
 
1960
        store._load_from_string('foo=bar')
 
1961
        self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
 
1962
 
 
1963
 
 
1964
class TestMutableStore(TestStore):
 
1965
 
 
1966
    scenarios = [(key, {'store_id': key, 'get_store': builder})
 
1967
                 for key, builder in test_store_builder_registry.iteritems()]
 
1968
 
 
1969
    def setUp(self):
 
1970
        super(TestMutableStore, self).setUp()
 
1971
        self.transport = self.get_transport()
 
1972
        self.branch = self.make_branch('branch')
 
1973
 
 
1974
    def has_store(self, store):
 
1975
        store_basename = urlutils.relative_url(self.transport.external_url(),
 
1976
                                               store.external_url())
 
1977
        return self.transport.has(store_basename)
 
1978
 
 
1979
    def test_save_empty_creates_no_file(self):
 
1980
        if self.store_id == 'branch':
 
1981
            raise tests.TestNotApplicable(
 
1982
                'branch.conf is *always* created when a branch is initialized')
 
1983
        store = self.get_store(self)
 
1984
        store.save()
 
1985
        self.assertEquals(False, self.has_store(store))
 
1986
 
 
1987
    def test_save_emptied_succeeds(self):
 
1988
        store = self.get_store(self)
 
1989
        store._load_from_string('foo=bar\n')
 
1990
        section = store.get_mutable_section(None)
 
1991
        section.remove('foo')
 
1992
        store.save()
 
1993
        self.assertEquals(True, self.has_store(store))
 
1994
        modified_store = self.get_store(self)
 
1995
        sections = list(modified_store.get_sections())
 
1996
        self.assertLength(0, sections)
 
1997
 
 
1998
    def test_save_with_content_succeeds(self):
 
1999
        if self.store_id == 'branch':
 
2000
            raise tests.TestNotApplicable(
 
2001
                'branch.conf is *always* created when a branch is initialized')
 
2002
        store = self.get_store(self)
 
2003
        store._load_from_string('foo=bar\n')
 
2004
        self.assertEquals(False, self.has_store(store))
 
2005
        store.save()
 
2006
        self.assertEquals(True, self.has_store(store))
 
2007
        modified_store = self.get_store(self)
 
2008
        sections = list(modified_store.get_sections())
 
2009
        self.assertLength(1, sections)
 
2010
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2011
 
 
2012
    def test_set_option_in_empty_store(self):
 
2013
        store = self.get_store(self)
 
2014
        section = store.get_mutable_section(None)
 
2015
        section.set('foo', 'bar')
 
2016
        store.save()
 
2017
        modified_store = self.get_store(self)
 
2018
        sections = list(modified_store.get_sections())
 
2019
        self.assertLength(1, sections)
 
2020
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2021
 
 
2022
    def test_set_option_in_default_section(self):
 
2023
        store = self.get_store(self)
 
2024
        store._load_from_string('')
 
2025
        section = store.get_mutable_section(None)
 
2026
        section.set('foo', 'bar')
 
2027
        store.save()
 
2028
        modified_store = self.get_store(self)
 
2029
        sections = list(modified_store.get_sections())
 
2030
        self.assertLength(1, sections)
 
2031
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
 
2032
 
 
2033
    def test_set_option_in_named_section(self):
 
2034
        store = self.get_store(self)
 
2035
        store._load_from_string('')
 
2036
        section = store.get_mutable_section('baz')
 
2037
        section.set('foo', 'bar')
 
2038
        store.save()
 
2039
        modified_store = self.get_store(self)
 
2040
        sections = list(modified_store.get_sections())
 
2041
        self.assertLength(1, sections)
 
2042
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
 
2043
 
 
2044
 
 
2045
class TestIniFileStore(TestStore):
 
2046
 
 
2047
    def test_loading_unknown_file_fails(self):
 
2048
        store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
 
2049
        self.assertRaises(errors.NoSuchFile, store.load)
 
2050
 
 
2051
    def test_invalid_content(self):
 
2052
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
2053
        self.assertEquals(False, store.is_loaded())
 
2054
        exc = self.assertRaises(
 
2055
            errors.ParseConfigError, store._load_from_string,
 
2056
            'this is invalid !')
 
2057
        self.assertEndsWith(exc.filename, 'foo.conf')
 
2058
        # And the load failed
 
2059
        self.assertEquals(False, store.is_loaded())
 
2060
 
 
2061
    def test_get_embedded_sections(self):
 
2062
        # A more complicated example (which also shows that section names and
 
2063
        # option names share the same name space...)
 
2064
        # FIXME: This should be fixed by forbidding dicts as values ?
 
2065
        # -- vila 2011-04-05
 
2066
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
 
2067
        store._load_from_string('''
 
2068
foo=bar
 
2069
l=1,2
 
2070
[DEFAULT]
 
2071
foo_in_DEFAULT=foo_DEFAULT
 
2072
[bar]
 
2073
foo_in_bar=barbar
 
2074
[baz]
 
2075
foo_in_baz=barbaz
 
2076
[[qux]]
 
2077
foo_in_qux=quux
 
2078
''')
 
2079
        sections = list(store.get_sections())
 
2080
        self.assertLength(4, sections)
 
2081
        # The default section has no name.
 
2082
        # List values are provided as lists
 
2083
        self.assertSectionContent((None, {'foo': 'bar', 'l': ['1', '2']}),
 
2084
                                  sections[0])
 
2085
        self.assertSectionContent(
 
2086
            ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
 
2087
        self.assertSectionContent(
 
2088
            ('bar', {'foo_in_bar': 'barbar'}), sections[2])
 
2089
        # sub sections are provided as embedded dicts.
 
2090
        self.assertSectionContent(
 
2091
            ('baz', {'foo_in_baz': 'barbaz', 'qux': {'foo_in_qux': 'quux'}}),
 
2092
            sections[3])
 
2093
 
 
2094
 
 
2095
class TestLockableIniFileStore(TestStore):
 
2096
 
 
2097
    def test_create_store_in_created_dir(self):
 
2098
        t = self.get_transport('dir/subdir')
 
2099
        store = config.LockableIniFileStore(t, 'foo.conf')
 
2100
        store.get_mutable_section(None).set('foo', 'bar')
 
2101
        store.save()
 
2102
 
 
2103
    # FIXME: We should adapt the tests in TestLockableConfig about concurrent
 
2104
    # writes. Since this requires a clearer rewrite, I'll just rely on using
 
2105
    # the same code in LockableIniFileStore (copied from LockableConfig, but
 
2106
    # trivial enough, the main difference is that we add @needs_write_lock on
 
2107
    # save() instead of set_user_option() and remove_user_option()). The intent
 
2108
    # is to ensure that we always get a valid content for the store even when
 
2109
    # concurrent accesses occur, read/write, write/write. It may be worth
 
2110
    # looking into removing the lock dir when it;s not needed anymore and look
 
2111
    # at possible fallouts for concurrent lockers -- vila 20110-04-06
 
2112
 
 
2113
 
 
2114
class TestSectionMatcher(TestStore):
 
2115
 
 
2116
    scenarios = [('location', {'matcher': config.LocationMatcher})]
 
2117
 
 
2118
    def get_store(self, file_name):
 
2119
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
2120
 
 
2121
    def test_no_matches_for_empty_stores(self):
 
2122
        store = self.get_store('foo.conf')
 
2123
        store._load_from_string('')
 
2124
        matcher = self.matcher(store, '/bar')
 
2125
        self.assertEquals([], list(matcher.get_sections()))
 
2126
 
 
2127
    def test_build_doesnt_load_store(self):
 
2128
        store = self.get_store('foo.conf')
 
2129
        matcher = self.matcher(store, '/bar')
 
2130
        self.assertFalse(store.is_loaded())
 
2131
 
 
2132
 
 
2133
class TestLocationSection(tests.TestCase):
 
2134
 
 
2135
    def get_section(self, options, extra_path):
 
2136
        section = config.Section('foo', options)
 
2137
        # We don't care about the length so we use '0'
 
2138
        return config.LocationSection(section, 0, extra_path)
 
2139
 
 
2140
    def test_simple_option(self):
 
2141
        section = self.get_section({'foo': 'bar'}, '')
 
2142
        self.assertEquals('bar', section.get('foo'))
 
2143
 
 
2144
    def test_option_with_extra_path(self):
 
2145
        section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
 
2146
                                   'baz')
 
2147
        self.assertEquals('bar/baz', section.get('foo'))
 
2148
 
 
2149
    def test_invalid_policy(self):
 
2150
        section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
 
2151
                                   'baz')
 
2152
        # invalid policies are ignored
 
2153
        self.assertEquals('bar', section.get('foo'))
 
2154
 
 
2155
 
 
2156
class TestLocationMatcher(TestStore):
 
2157
 
 
2158
    def get_store(self, file_name):
 
2159
        return config.IniFileStore(self.get_readonly_transport(), file_name)
 
2160
 
 
2161
    def test_more_specific_sections_first(self):
 
2162
        store = self.get_store('foo.conf')
 
2163
        store._load_from_string('''
 
2164
[/foo]
 
2165
section=/foo
 
2166
[/foo/bar]
 
2167
section=/foo/bar
 
2168
''')
 
2169
        self.assertEquals(['/foo', '/foo/bar'],
 
2170
                          [section.id for section in store.get_sections()])
 
2171
        matcher = config.LocationMatcher(store, '/foo/bar/baz')
 
2172
        sections = list(matcher.get_sections())
 
2173
        self.assertEquals([3, 2],
 
2174
                          [section.length for section in sections])
 
2175
        self.assertEquals(['/foo/bar', '/foo'],
 
2176
                          [section.id for section in sections])
 
2177
        self.assertEquals(['baz', 'bar/baz'],
 
2178
                          [section.extra_path for section in sections])
 
2179
 
 
2180
 
 
2181
 
 
2182
class TestStackGet(tests.TestCase):
 
2183
 
 
2184
    # FIXME: This should be parametrized for all known Stack or dedicated
 
2185
    # paramerized tests created to avoid bloating -- vila 2011-03-31
 
2186
 
 
2187
    def test_single_config_get(self):
 
2188
        conf = dict(foo='bar')
 
2189
        conf_stack = config.Stack([conf])
 
2190
        self.assertEquals('bar', conf_stack.get('foo'))
 
2191
 
 
2192
    def test_get_first_definition(self):
 
2193
        conf1 = dict(foo='bar')
 
2194
        conf2 = dict(foo='baz')
 
2195
        conf_stack = config.Stack([conf1, conf2])
 
2196
        self.assertEquals('bar', conf_stack.get('foo'))
 
2197
 
 
2198
    def test_get_embedded_definition(self):
 
2199
        conf1 = dict(yy='12')
 
2200
        conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
 
2201
        conf_stack = config.Stack([conf1, conf2])
 
2202
        self.assertEquals('baz', conf_stack.get('foo'))
 
2203
 
 
2204
    def test_get_for_empty_stack(self):
 
2205
        conf_stack = config.Stack([])
 
2206
        self.assertEquals(None, conf_stack.get('foo'))
 
2207
 
 
2208
    def test_get_for_empty_section_callable(self):
 
2209
        conf_stack = config.Stack([lambda : []])
 
2210
        self.assertEquals(None, conf_stack.get('foo'))
 
2211
 
 
2212
    def test_get_for_broken_callable(self):
 
2213
        # Trying to use and invalid callable raises an exception on first use
 
2214
        conf_stack = config.Stack([lambda : object()])
 
2215
        self.assertRaises(TypeError, conf_stack.get, 'foo')
 
2216
 
 
2217
 
 
2218
class TestStackSet(tests.TestCaseWithTransport):
 
2219
 
 
2220
    # FIXME: This should be parametrized for all known Stack or dedicated
 
2221
    # paramerized tests created to avoid bloating -- vila 2011-04-05
 
2222
 
 
2223
    def test_simple_set(self):
 
2224
        store = config.IniFileStore(self.get_transport(), 'test.conf')
 
2225
        store._load_from_string('foo=bar')
 
2226
        conf = config.Stack([store.get_sections], store)
 
2227
        self.assertEquals('bar', conf.get('foo'))
 
2228
        conf.set('foo', 'baz')
 
2229
        # Did we get it back ?
 
2230
        self.assertEquals('baz', conf.get('foo'))
 
2231
 
 
2232
    def test_set_creates_a_new_section(self):
 
2233
        store = config.IniFileStore(self.get_transport(), 'test.conf')
 
2234
        conf = config.Stack([store.get_sections], store)
 
2235
        conf.set('foo', 'baz')
 
2236
        self.assertEquals, 'baz', conf.get('foo')
 
2237
 
 
2238
 
 
2239
class TestStackRemove(tests.TestCaseWithTransport):
 
2240
 
 
2241
    # FIXME: This should be parametrized for all known Stack or dedicated
 
2242
    # paramerized tests created to avoid bloating -- vila 2011-04-06
 
2243
 
 
2244
    def test_remove_existing(self):
 
2245
        store = config.IniFileStore(self.get_transport(), 'test.conf')
 
2246
        store._load_from_string('foo=bar')
 
2247
        conf = config.Stack([store.get_sections], store)
 
2248
        self.assertEquals('bar', conf.get('foo'))
 
2249
        conf.remove('foo')
 
2250
        # Did we get it back ?
 
2251
        self.assertEquals(None, conf.get('foo'))
 
2252
 
 
2253
    def test_remove_unknown(self):
 
2254
        store = config.IniFileStore(self.get_transport(), 'test.conf')
 
2255
        conf = config.Stack([store.get_sections], store)
 
2256
        self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
 
2257
 
 
2258
 
1820
2259
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1821
2260
 
1822
2261
    def setUp(self):
1823
2262
        super(TestConfigGetOptions, self).setUp()
1824
2263
        create_configs(self)
1825
2264
 
1826
 
    # One variable in none of the above
1827
2265
    def test_no_variable(self):
1828
2266
        # Using branch should query branch, locations and bazaar
1829
2267
        self.assertOptions([], self.branch_config)
2469
2907
# test_user_prompted ?
2470
2908
class TestAuthenticationRing(tests.TestCaseWithTransport):
2471
2909
    pass
 
2910
 
 
2911
 
 
2912
class TestAutoUserId(tests.TestCase):
 
2913
    """Test inferring an automatic user name."""
 
2914
 
 
2915
    def test_auto_user_id(self):
 
2916
        """Automatic inference of user name.
 
2917
        
 
2918
        This is a bit hard to test in an isolated way, because it depends on
 
2919
        system functions that go direct to /etc or perhaps somewhere else.
 
2920
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
 
2921
        to be able to choose a user name with no configuration.
 
2922
        """
 
2923
        if sys.platform == 'win32':
 
2924
            raise TestSkipped("User name inference not implemented on win32")
 
2925
        realname, address = config._auto_user_id()
 
2926
        if os.path.exists('/etc/mailname'):
 
2927
            self.assertIsNot(None, realname)
 
2928
            self.assertIsNot(None, address)
 
2929
        else:
 
2930
            self.assertEquals((None, None), (realname, address))
 
2931