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())
1299
def assertLocationMatching(self, expected):
1300
self.assertEqual(expected,
1301
list(self.my_location_config._get_matching_sections()))
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([])
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', '')])
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([])
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')])
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',
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',
1294
self.my_location_config._get_matching_sections())
1327
self.assertLocationMatching([('http://www.example.com/ignoreparent',
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/', '')])
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')])
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')])
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/', '')])
1316
1346
def test__get_matching_sections_explicit_over_glob(self):
1317
1347
# XXX: 2006-09-08 jamesh
1817
1846
self.assertIs(None, bzrdir_config.get_default_stack_on())
1849
class TestSection(tests.TestCase):
1851
# FIXME: Parametrize so that all sections produced by Stores run these
1852
# tests -- vila 2011-04-01
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'))
1859
def test_get_unknown_option(self):
1861
section = config.Section(None, a_dict)
1862
self.assertEquals('out of thin air',
1863
section.get('foo', 'out of thin air'))
1865
def test_options_is_shared(self):
1867
section = config.Section(None, a_dict)
1868
self.assertIs(a_dict, section.options)
1871
class TestMutableSection(tests.TestCase):
1873
# FIXME: Parametrize so that all sections (including os.environ and the
1874
# ones produced by Stores) run these tests -- vila 2011-04-01
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'))
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'))
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'))
1909
def test_remove_new_option(self):
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'])
1921
class TestStore(tests.TestCaseWithTransport):
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)
1929
dict([(k, section.get(k)) for k in expected_options.keys()]))
1932
class TestReadonlyStore(TestStore):
1934
scenarios = [(key, {'get_store': builder})
1935
for key, builder in test_store_builder_registry.iteritems()]
1938
super(TestReadonlyStore, self).setUp()
1939
self.branch = self.make_branch('branch')
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())
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()))
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])
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])
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')
1972
class TestMutableStore(TestStore):
1974
scenarios = [(key, {'store_id': key, 'get_store': builder})
1975
for key, builder in test_store_builder_registry.iteritems()]
1978
super(TestMutableStore, self).setUp()
1979
self.transport = self.get_transport()
1980
self.branch = self.make_branch('branch')
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)
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)
1993
self.assertEquals(False, self.has_store(store))
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')
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)
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))
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])
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')
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])
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')
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])
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')
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])
2053
class TestIniFileStore(TestStore):
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)
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())
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('''
2079
foo_in_DEFAULT=foo_DEFAULT
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']}),
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'}}),
2103
class TestLockableIniFileStore(TestStore):
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')
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
2122
class TestSectionMatcher(TestStore):
2124
scenarios = [('location', {'matcher': config.LocationMatcher})]
2126
def get_store(self, file_name):
2127
return config.IniFileStore(self.get_readonly_transport(), file_name)
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()))
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())
2141
class TestLocationSection(tests.TestCase):
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)
2148
def test_simple_option(self):
2149
section = self.get_section({'foo': 'bar'}, '')
2150
self.assertEquals('bar', section.get('foo'))
2152
def test_option_with_extra_path(self):
2153
section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
2155
self.assertEquals('bar/baz', section.get('foo'))
2157
def test_invalid_policy(self):
2158
section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
2160
# invalid policies are ignored
2161
self.assertEquals('bar', section.get('foo'))
2164
class TestLocationMatcher(TestStore):
2166
def get_store(self, file_name):
2167
return config.IniFileStore(self.get_readonly_transport(), file_name)
2169
def test_more_specific_sections_first(self):
2170
store = self.get_store('foo.conf')
2171
store._load_from_string('''
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])
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('''
2194
foo:policy = appendpath
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'))
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'
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)
2213
class TestStackGet(tests.TestCase):
2215
# FIXME: This should be parametrized for all known Stack or dedicated
2216
# paramerized tests created to avoid bloating -- vila 2011-03-31
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'))
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'))
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'))
2235
def test_get_for_empty_stack(self):
2236
conf_stack = config.Stack([])
2237
self.assertEquals(None, conf_stack.get('foo'))
2239
def test_get_for_empty_section_callable(self):
2240
conf_stack = config.Stack([lambda : []])
2241
self.assertEquals(None, conf_stack.get('foo'))
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')
2249
class TestStackWithTransport(tests.TestCaseWithTransport):
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')
2258
class TestStackSet(TestStackWithTransport):
2260
scenarios = [(key, {'get_stack': builder})
2261
for key, builder in test_stack_builder_registry.iteritems()]
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'))
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')
2277
class TestStackRemove(TestStackWithTransport):
2279
scenarios = [(key, {'get_stack': builder})
2280
for key, builder in test_stack_builder_registry.iteritems()]
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'))
2287
# Did we get it back ?
2288
self.assertEquals(None, conf.get('foo'))
2290
def test_remove_unknown(self):
2291
conf = self.get_stack(self)
2292
self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
2295
class TestConcreteStacks(TestStackWithTransport):
2297
scenarios = [(key, {'get_stack': builder})
2298
for key, builder in test_stack_builder_registry.iteritems()]
2300
def test_build_stack(self):
2301
stack = self.get_stack(self)
1820
2304
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1822
2306
def setUp(self):
1823
2307
super(TestConfigGetOptions, self).setUp()
1824
2308
create_configs(self)
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)