136
def create_configs(test):
137
"""Create configuration files for a given test.
139
This requires creating a tree (and populate the ``test.tree`` attribute)
140
and its associated branch and will populate the following attributes:
142
- branch_config: A BranchConfig for the associated branch.
144
- locations_config : A LocationConfig for the associated branch
146
- bazaar_config: A GlobalConfig.
148
The tree and branch are created in a 'tree' subdirectory so the tests can
149
still use the test directory to stay outside of the branch.
151
tree = test.make_branch_and_tree('tree')
153
test.branch_config = config.BranchConfig(tree.branch)
154
test.locations_config = config.LocationConfig(tree.basedir)
155
test.bazaar_config = config.GlobalConfig()
158
def create_configs_with_file_option(test):
159
"""Create configuration files with a ``file`` option set in each.
161
This builds on ``create_configs`` and add one ``file`` option in each
162
configuration with a value which allows identifying the configuration file.
165
test.bazaar_config.set_user_option('file', 'bazaar')
166
test.locations_config.set_user_option('file', 'locations')
167
test.branch_config.set_user_option('file', 'branch')
170
class TestOptionsMixin:
172
def assertOptions(self, expected, conf):
173
# We don't care about the parser (as it will make tests hard to write
174
# and error-prone anyway)
175
self.assertThat([opt[:4] for opt in conf._get_options()],
176
matchers.Equals(expected))
179
134
class InstrumentedConfigObj(object):
180
135
"""A config obj look-enough-alike to record calls made to it."""
315
270
co = config.ConfigObj()
316
271
co['test'] = 'foo#bar'
318
co.write(outfile=outfile)
319
lines = outfile.getvalue().splitlines()
320
273
self.assertEqual(lines, ['test = "foo#bar"'])
321
274
co2 = config.ConfigObj(lines)
322
275
self.assertEqual(co2['test'], 'foo#bar')
324
def test_triple_quotes(self):
325
# Bug #710410: if the value string has triple quotes
326
# then ConfigObj versions up to 4.7.2 will quote them wrong
327
# and won't able to read them back
328
triple_quotes_value = '''spam
329
""" that's my spam """
331
co = config.ConfigObj()
332
co['test'] = triple_quotes_value
333
# While writing this test another bug in ConfigObj has been found:
334
# method co.write() without arguments produces list of lines
335
# one option per line, and multiline values are not split
336
# across multiple lines,
337
# and that breaks the parsing these lines back by ConfigObj.
338
# This issue only affects test, but it's better to avoid
339
# `co.write()` construct at all.
340
# [bialix 20110222] bug report sent to ConfigObj's author
342
co.write(outfile=outfile)
343
output = outfile.getvalue()
344
# now we're trying to read it back
345
co2 = config.ConfigObj(StringIO(output))
346
self.assertEquals(triple_quotes_value, co2['test'])
349
278
erroneous_config = """[section] # line 1
350
279
good=good # line 2
463
392
'/home/bogus/.cache')
466
class TestXDGConfigDir(tests.TestCaseInTempDir):
467
# must be in temp dir because config tests for the existence of the bazaar
468
# subdirectory of $XDG_CONFIG_HOME
471
if sys.platform in ('darwin', 'win32'):
472
raise tests.TestNotApplicable(
473
'XDG config dir not used on this platform')
474
super(TestXDGConfigDir, self).setUp()
475
self.overrideEnv('HOME', self.test_home_dir)
476
# BZR_HOME overrides everything we want to test so unset it.
477
self.overrideEnv('BZR_HOME', None)
479
def test_xdg_config_dir_exists(self):
480
"""When ~/.config/bazaar exists, use it as the config dir."""
481
newdir = osutils.pathjoin(self.test_home_dir, '.config', 'bazaar')
483
self.assertEqual(config.config_dir(), newdir)
485
def test_xdg_config_home(self):
486
"""When XDG_CONFIG_HOME is set, use it."""
487
xdgconfigdir = osutils.pathjoin(self.test_home_dir, 'xdgconfig')
488
self.overrideEnv('XDG_CONFIG_HOME', xdgconfigdir)
489
newdir = osutils.pathjoin(xdgconfigdir, 'bazaar')
491
self.assertEqual(config.config_dir(), newdir)
494
395
class TestIniConfig(tests.TestCaseInTempDir):
496
397
def make_config_parser(self, s):
555
455
self.assertFileEqual(content, 'test.conf')
558
class TestIniConfigOptionExpansionDefaultValue(tests.TestCaseInTempDir):
559
"""What is the default value of expand for config options.
561
This is an opt-in beta feature used to evaluate whether or not option
562
references can appear in dangerous place raising exceptions, disapearing
563
(and as such corrupting data) or if it's safe to activate the option by
566
Note that these tests relies on config._expand_default_value being already
567
overwritten in the parent class setUp.
571
super(TestIniConfigOptionExpansionDefaultValue, self).setUp()
575
self.warnings.append(args[0] % args[1:])
576
self.overrideAttr(trace, 'warning', warning)
578
def get_config(self, expand):
579
c = config.GlobalConfig.from_string('bzr.config.expand=%s' % (expand,),
583
def assertExpandIs(self, expected):
584
actual = config._get_expand_default_value()
585
#self.config.get_user_option_as_bool('bzr.config.expand')
586
self.assertEquals(expected, actual)
588
def test_default_is_None(self):
589
self.assertEquals(None, config._expand_default_value)
591
def test_default_is_False_even_if_None(self):
592
self.config = self.get_config(None)
593
self.assertExpandIs(False)
595
def test_default_is_False_even_if_invalid(self):
596
self.config = self.get_config('<your choice>')
597
self.assertExpandIs(False)
599
# Huh ? My choice is False ? Thanks, always happy to hear that :D
600
# Wait, you've been warned !
601
self.assertLength(1, self.warnings)
603
'Value "<your choice>" is not a boolean for "bzr.config.expand"',
606
def test_default_is_True(self):
607
self.config = self.get_config(True)
608
self.assertExpandIs(True)
610
def test_default_is_False(self):
611
self.config = self.get_config(False)
612
self.assertExpandIs(False)
615
class TestIniConfigOptionExpansion(tests.TestCase):
616
"""Test option expansion from the IniConfig level.
618
What we really want here is to test the Config level, but the class being
619
abstract as far as storing values is concerned, this can't be done
622
# FIXME: This should be rewritten when all configs share a storage
623
# implementation -- vila 2011-02-18
625
def get_config(self, string=None):
628
c = config.IniBasedConfig.from_string(string)
631
def assertExpansion(self, expected, conf, string, env=None):
632
self.assertEquals(expected, conf.expand_options(string, env))
634
def test_no_expansion(self):
635
c = self.get_config('')
636
self.assertExpansion('foo', c, 'foo')
638
def test_env_adding_options(self):
639
c = self.get_config('')
640
self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
642
def test_env_overriding_options(self):
643
c = self.get_config('foo=baz')
644
self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
646
def test_simple_ref(self):
647
c = self.get_config('foo=xxx')
648
self.assertExpansion('xxx', c, '{foo}')
650
def test_unknown_ref(self):
651
c = self.get_config('')
652
self.assertRaises(errors.ExpandingUnknownOption,
653
c.expand_options, '{foo}')
655
def test_indirect_ref(self):
656
c = self.get_config('''
660
self.assertExpansion('xxx', c, '{bar}')
662
def test_embedded_ref(self):
663
c = self.get_config('''
667
self.assertExpansion('xxx', c, '{{bar}}')
669
def test_simple_loop(self):
670
c = self.get_config('foo={foo}')
671
self.assertRaises(errors.OptionExpansionLoop, c.expand_options, '{foo}')
673
def test_indirect_loop(self):
674
c = self.get_config('''
678
e = self.assertRaises(errors.OptionExpansionLoop,
679
c.expand_options, '{foo}')
680
self.assertEquals('foo->bar->baz', e.refs)
681
self.assertEquals('{foo}', e.string)
684
conf = self.get_config('''
688
list={foo},{bar},{baz}
690
self.assertEquals(['start', 'middle', 'end'],
691
conf.get_user_option('list', expand=True))
693
def test_cascading_list(self):
694
conf = self.get_config('''
700
self.assertEquals(['start', 'middle', 'end'],
701
conf.get_user_option('list', expand=True))
703
def test_pathological_hidden_list(self):
704
conf = self.get_config('''
710
hidden={start}{middle}{end}
712
# Nope, it's either a string or a list, and the list wins as soon as a
713
# ',' appears, so the string concatenation never occur.
714
self.assertEquals(['{foo', '}', '{', 'bar}'],
715
conf.get_user_option('hidden', expand=True))
717
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
719
def get_config(self, location, string=None):
722
# Since we don't save the config we won't strictly require to inherit
723
# from TestCaseInTempDir, but an error occurs so quickly...
724
c = config.LocationConfig.from_string(string, location)
727
def test_dont_cross_unrelated_section(self):
728
c = self.get_config('/another/branch/path','''
733
[/another/branch/path]
736
self.assertRaises(errors.ExpandingUnknownOption,
737
c.get_user_option, 'bar', expand=True)
739
def test_cross_related_sections(self):
740
c = self.get_config('/project/branch/path','''
744
[/project/branch/path]
747
self.assertEquals('quux', c.get_user_option('bar', expand=True))
750
458
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
752
460
def test_cannot_reload_without_name(self):
1177
883
change_editor = my_config.get_change_editor('old', 'new')
1178
884
self.assertIs(None, change_editor)
1180
def test_get_merge_tools(self):
1181
conf = self._get_sample_config()
1182
tools = conf.get_merge_tools()
1183
self.log(repr(tools))
1185
{u'funkytool' : u'funkytool "arg with spaces" {this_temp}',
1186
u'sometool' : u'sometool {base} {this} {other} -o {result}'},
1189
def test_get_merge_tools_empty(self):
1190
conf = self._get_empty_config()
1191
tools = conf.get_merge_tools()
1192
self.assertEqual({}, tools)
1194
def test_find_merge_tool(self):
1195
conf = self._get_sample_config()
1196
cmdline = conf.find_merge_tool('sometool')
1197
self.assertEqual('sometool {base} {this} {other} -o {result}', cmdline)
1199
def test_find_merge_tool_not_found(self):
1200
conf = self._get_sample_config()
1201
cmdline = conf.find_merge_tool('DOES NOT EXIST')
1202
self.assertIs(cmdline, None)
1204
def test_find_merge_tool_known(self):
1205
conf = self._get_empty_config()
1206
cmdline = conf.find_merge_tool('kdiff3')
1207
self.assertEquals('kdiff3 {base} {this} {other} -o {result}', cmdline)
1209
def test_find_merge_tool_override_known(self):
1210
conf = self._get_empty_config()
1211
conf.set_user_option('bzr.mergetool.kdiff3', 'kdiff3 blah')
1212
cmdline = conf.find_merge_tool('kdiff3')
1213
self.assertEqual('kdiff3 blah', cmdline)
1216
887
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
1261
932
def test_get_global_config(self):
1262
933
my_config = config.BranchConfig(FakeBranch('http://example.com'))
1263
934
global_config = my_config._get_global_config()
1264
self.assertIsInstance(global_config, config.GlobalConfig)
1265
self.assertIs(global_config, my_config._get_global_config())
1267
def assertLocationMatching(self, expected):
1268
self.assertEqual(expected,
1269
list(self.my_location_config._get_matching_sections()))
935
self.failUnless(isinstance(global_config, config.GlobalConfig))
936
self.failUnless(global_config is my_config._get_global_config())
1271
938
def test__get_matching_sections_no_match(self):
1272
939
self.get_branch_config('/')
1273
self.assertLocationMatching([])
940
self.assertEqual([], self.my_location_config._get_matching_sections())
1275
942
def test__get_matching_sections_exact(self):
1276
943
self.get_branch_config('http://www.example.com')
1277
self.assertLocationMatching([('http://www.example.com', '')])
944
self.assertEqual([('http://www.example.com', '')],
945
self.my_location_config._get_matching_sections())
1279
947
def test__get_matching_sections_suffix_does_not(self):
1280
948
self.get_branch_config('http://www.example.com-com')
1281
self.assertLocationMatching([])
949
self.assertEqual([], self.my_location_config._get_matching_sections())
1283
951
def test__get_matching_sections_subdir_recursive(self):
1284
952
self.get_branch_config('http://www.example.com/com')
1285
self.assertLocationMatching([('http://www.example.com', 'com')])
953
self.assertEqual([('http://www.example.com', 'com')],
954
self.my_location_config._get_matching_sections())
1287
956
def test__get_matching_sections_ignoreparent(self):
1288
957
self.get_branch_config('http://www.example.com/ignoreparent')
1289
self.assertLocationMatching([('http://www.example.com/ignoreparent',
958
self.assertEqual([('http://www.example.com/ignoreparent', '')],
959
self.my_location_config._get_matching_sections())
1292
961
def test__get_matching_sections_ignoreparent_subdir(self):
1293
962
self.get_branch_config(
1294
963
'http://www.example.com/ignoreparent/childbranch')
1295
self.assertLocationMatching([('http://www.example.com/ignoreparent',
964
self.assertEqual([('http://www.example.com/ignoreparent',
966
self.my_location_config._get_matching_sections())
1298
968
def test__get_matching_sections_subdir_trailing_slash(self):
1299
969
self.get_branch_config('/b')
1300
self.assertLocationMatching([('/b/', '')])
970
self.assertEqual([('/b/', '')],
971
self.my_location_config._get_matching_sections())
1302
973
def test__get_matching_sections_subdir_child(self):
1303
974
self.get_branch_config('/a/foo')
1304
self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
975
self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
976
self.my_location_config._get_matching_sections())
1306
978
def test__get_matching_sections_subdir_child_child(self):
1307
979
self.get_branch_config('/a/foo/bar')
1308
self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
980
self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
981
self.my_location_config._get_matching_sections())
1310
983
def test__get_matching_sections_trailing_slash_with_children(self):
1311
984
self.get_branch_config('/a/')
1312
self.assertLocationMatching([('/a/', '')])
985
self.assertEqual([('/a/', '')],
986
self.my_location_config._get_matching_sections())
1314
988
def test__get_matching_sections_explicit_over_glob(self):
1315
989
# XXX: 2006-09-08 jamesh
1814
1471
self.assertIs(None, bzrdir_config.get_default_stack_on())
1817
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1820
super(TestConfigGetOptions, self).setUp()
1821
create_configs(self)
1823
# One variable in none of the above
1824
def test_no_variable(self):
1825
# Using branch should query branch, locations and bazaar
1826
self.assertOptions([], self.branch_config)
1828
def test_option_in_bazaar(self):
1829
self.bazaar_config.set_user_option('file', 'bazaar')
1830
self.assertOptions([('file', 'bazaar', 'DEFAULT', 'bazaar')],
1833
def test_option_in_locations(self):
1834
self.locations_config.set_user_option('file', 'locations')
1836
[('file', 'locations', self.tree.basedir, 'locations')],
1837
self.locations_config)
1839
def test_option_in_branch(self):
1840
self.branch_config.set_user_option('file', 'branch')
1841
self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
1844
def test_option_in_bazaar_and_branch(self):
1845
self.bazaar_config.set_user_option('file', 'bazaar')
1846
self.branch_config.set_user_option('file', 'branch')
1847
self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
1848
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
1851
def test_option_in_branch_and_locations(self):
1852
# Hmm, locations override branch :-/
1853
self.locations_config.set_user_option('file', 'locations')
1854
self.branch_config.set_user_option('file', 'branch')
1856
[('file', 'locations', self.tree.basedir, 'locations'),
1857
('file', 'branch', 'DEFAULT', 'branch'),],
1860
def test_option_in_bazaar_locations_and_branch(self):
1861
self.bazaar_config.set_user_option('file', 'bazaar')
1862
self.locations_config.set_user_option('file', 'locations')
1863
self.branch_config.set_user_option('file', 'branch')
1865
[('file', 'locations', self.tree.basedir, 'locations'),
1866
('file', 'branch', 'DEFAULT', 'branch'),
1867
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
1871
class TestConfigRemoveOption(tests.TestCaseWithTransport, TestOptionsMixin):
1874
super(TestConfigRemoveOption, self).setUp()
1875
create_configs_with_file_option(self)
1877
def test_remove_in_locations(self):
1878
self.locations_config.remove_user_option('file', self.tree.basedir)
1880
[('file', 'branch', 'DEFAULT', 'branch'),
1881
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
1884
def test_remove_in_branch(self):
1885
self.branch_config.remove_user_option('file')
1887
[('file', 'locations', self.tree.basedir, 'locations'),
1888
('file', 'bazaar', 'DEFAULT', 'bazaar'),],
1891
def test_remove_in_bazaar(self):
1892
self.bazaar_config.remove_user_option('file')
1894
[('file', 'locations', self.tree.basedir, 'locations'),
1895
('file', 'branch', 'DEFAULT', 'branch'),],
1899
class TestConfigGetSections(tests.TestCaseWithTransport):
1902
super(TestConfigGetSections, self).setUp()
1903
create_configs(self)
1905
def assertSectionNames(self, expected, conf, name=None):
1906
"""Check which sections are returned for a given config.
1908
If fallback configurations exist their sections can be included.
1910
:param expected: A list of section names.
1912
:param conf: The configuration that will be queried.
1914
:param name: An optional section name that will be passed to
1917
sections = list(conf._get_sections(name))
1918
self.assertLength(len(expected), sections)
1919
self.assertEqual(expected, [name for name, _, _ in sections])
1921
def test_bazaar_default_section(self):
1922
self.assertSectionNames(['DEFAULT'], self.bazaar_config)
1924
def test_locations_default_section(self):
1925
# No sections are defined in an empty file
1926
self.assertSectionNames([], self.locations_config)
1928
def test_locations_named_section(self):
1929
self.locations_config.set_user_option('file', 'locations')
1930
self.assertSectionNames([self.tree.basedir], self.locations_config)
1932
def test_locations_matching_sections(self):
1933
loc_config = self.locations_config
1934
loc_config.set_user_option('file', 'locations')
1935
# We need to cheat a bit here to create an option in sections above and
1936
# below the 'location' one.
1937
parser = loc_config._get_parser()
1938
# locations.cong deals with '/' ignoring native os.sep
1939
location_names = self.tree.basedir.split('/')
1940
parent = '/'.join(location_names[:-1])
1941
child = '/'.join(location_names + ['child'])
1943
parser[parent]['file'] = 'parent'
1945
parser[child]['file'] = 'child'
1946
self.assertSectionNames([self.tree.basedir, parent], loc_config)
1948
def test_branch_data_default_section(self):
1949
self.assertSectionNames([None],
1950
self.branch_config._get_branch_data_config())
1952
def test_branch_default_sections(self):
1953
# No sections are defined in an empty locations file
1954
self.assertSectionNames([None, 'DEFAULT'],
1956
# Unless we define an option
1957
self.branch_config._get_location_config().set_user_option(
1958
'file', 'locations')
1959
self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
1962
def test_bazaar_named_section(self):
1963
# We need to cheat as the API doesn't give direct access to sections
1964
# other than DEFAULT.
1965
self.bazaar_config.set_alias('bazaar', 'bzr')
1966
self.assertSectionNames(['ALIASES'], self.bazaar_config, 'ALIASES')
1969
1474
class TestAuthenticationConfigFile(tests.TestCase):
1970
1475
"""Test the authentication.conf file matching"""