1814
1838
self.assertIs(None, bzrdir_config.get_default_stack_on())
1841
class TestSection(tests.TestCase):
1843
# FIXME: Parametrize so that all sections produced by Stores run these
1844
# tests -- vila 2011-04-01
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'))
1851
def test_get_unknown_option(self):
1853
section = config.Section(None, a_dict)
1854
self.assertEquals('out of thin air',
1855
section.get('foo', 'out of thin air'))
1857
def test_options_is_shared(self):
1859
section = config.Section(None, a_dict)
1860
self.assertIs(a_dict, section.options)
1863
class TestMutableSection(tests.TestCase):
1865
# FIXME: Parametrize so that all sections (including os.environ and the
1866
# ones produced by Stores) run these tests -- vila 2011-04-01
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'))
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'))
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'))
1901
def test_remove_new_option(self):
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'])
1913
class TestStore(tests.TestCaseWithTransport):
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)
1921
dict([(k, section.get(k)) for k in expected_options.keys()]))
1924
class TestReadonlyStore(TestStore):
1926
scenarios = [(key, {'get_store': builder})
1927
for key, builder in test_store_builder_registry.iteritems()]
1930
super(TestReadonlyStore, self).setUp()
1931
self.branch = self.make_branch('branch')
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())
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()))
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])
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])
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')
1964
class TestMutableStore(TestStore):
1966
scenarios = [(key, {'store_id': key, 'get_store': builder})
1967
for key, builder in test_store_builder_registry.iteritems()]
1970
super(TestMutableStore, self).setUp()
1971
self.transport = self.get_transport()
1972
self.branch = self.make_branch('branch')
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)
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)
1985
self.assertEquals(False, self.has_store(store))
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')
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)
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))
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])
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')
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])
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')
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])
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')
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])
2045
class TestIniFileStore(TestStore):
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)
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())
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('''
2071
foo_in_DEFAULT=foo_DEFAULT
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']}),
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'}}),
2095
class TestLockableIniFileStore(TestStore):
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')
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
2114
class TestSectionMatcher(TestStore):
2116
scenarios = [('location', {'matcher': config.LocationMatcher})]
2118
def get_store(self, file_name):
2119
return config.IniFileStore(self.get_readonly_transport(), file_name)
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()))
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())
2133
class TestLocationSection(tests.TestCase):
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)
2140
def test_simple_option(self):
2141
section = self.get_section({'foo': 'bar'}, '')
2142
self.assertEquals('bar', section.get('foo'))
2144
def test_option_with_extra_path(self):
2145
section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
2147
self.assertEquals('bar/baz', section.get('foo'))
2149
def test_invalid_policy(self):
2150
section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
2152
# invalid policies are ignored
2153
self.assertEquals('bar', section.get('foo'))
2156
class TestLocationMatcher(TestStore):
2158
def get_store(self, file_name):
2159
return config.IniFileStore(self.get_readonly_transport(), file_name)
2161
def test_more_specific_sections_first(self):
2162
store = self.get_store('foo.conf')
2163
store._load_from_string('''
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])
2182
class TestStackGet(tests.TestCase):
2184
# FIXME: This should be parametrized for all known Stack or dedicated
2185
# paramerized tests created to avoid bloating -- vila 2011-03-31
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'))
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'))
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'))
2204
def test_get_for_empty_stack(self):
2205
conf_stack = config.Stack([])
2206
self.assertEquals(None, conf_stack.get('foo'))
2208
def test_get_for_empty_section_callable(self):
2209
conf_stack = config.Stack([lambda : []])
2210
self.assertEquals(None, conf_stack.get('foo'))
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')
2218
class TestStackSet(tests.TestCaseWithTransport):
2220
# FIXME: This should be parametrized for all known Stack or dedicated
2221
# paramerized tests created to avoid bloating -- vila 2011-04-05
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'))
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')
2239
class TestStackRemove(tests.TestCaseWithTransport):
2241
# FIXME: This should be parametrized for all known Stack or dedicated
2242
# paramerized tests created to avoid bloating -- vila 2011-04-06
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'))
2250
# Did we get it back ?
2251
self.assertEquals(None, conf.get('foo'))
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')
1817
2259
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1819
2261
def setUp(self):
1820
2262
super(TestConfigGetOptions, self).setUp()
1821
2263
create_configs(self)
1823
# One variable in none of the above
1824
2265
def test_no_variable(self):
1825
2266
# Using branch should query branch, locations and bazaar
1826
2267
self.assertOptions([], self.branch_config)