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))
134
179
class InstrumentedConfigObj(object):
135
180
"""A config obj look-enough-alike to record calls made to it."""
270
315
co = config.ConfigObj()
271
316
co['test'] = 'foo#bar'
318
co.write(outfile=outfile)
319
lines = outfile.getvalue().splitlines()
273
320
self.assertEqual(lines, ['test = "foo#bar"'])
274
321
co2 = config.ConfigObj(lines)
275
322
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'])
278
349
erroneous_config = """[section] # line 1
279
350
good=good # line 2
392
463
'/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)
395
494
class TestIniConfig(tests.TestCaseInTempDir):
397
496
def make_config_parser(self, s):
455
555
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))
458
750
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
460
752
def test_cannot_reload_without_name(self):
883
1177
change_editor = my_config.get_change_editor('old', 'new')
884
1178
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)
887
1216
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
935
1264
self.failUnless(isinstance(global_config, config.GlobalConfig))
936
1265
self.failUnless(global_config is my_config._get_global_config())
1267
def assertLocationMatching(self, expected):
1268
self.assertEqual(expected,
1269
list(self.my_location_config._get_matching_sections()))
938
1271
def test__get_matching_sections_no_match(self):
939
1272
self.get_branch_config('/')
940
self.assertEqual([], self.my_location_config._get_matching_sections())
1273
self.assertLocationMatching([])
942
1275
def test__get_matching_sections_exact(self):
943
1276
self.get_branch_config('http://www.example.com')
944
self.assertEqual([('http://www.example.com', '')],
945
self.my_location_config._get_matching_sections())
1277
self.assertLocationMatching([('http://www.example.com', '')])
947
1279
def test__get_matching_sections_suffix_does_not(self):
948
1280
self.get_branch_config('http://www.example.com-com')
949
self.assertEqual([], self.my_location_config._get_matching_sections())
1281
self.assertLocationMatching([])
951
1283
def test__get_matching_sections_subdir_recursive(self):
952
1284
self.get_branch_config('http://www.example.com/com')
953
self.assertEqual([('http://www.example.com', 'com')],
954
self.my_location_config._get_matching_sections())
1285
self.assertLocationMatching([('http://www.example.com', 'com')])
956
1287
def test__get_matching_sections_ignoreparent(self):
957
1288
self.get_branch_config('http://www.example.com/ignoreparent')
958
self.assertEqual([('http://www.example.com/ignoreparent', '')],
959
self.my_location_config._get_matching_sections())
1289
self.assertLocationMatching([('http://www.example.com/ignoreparent',
961
1292
def test__get_matching_sections_ignoreparent_subdir(self):
962
1293
self.get_branch_config(
963
1294
'http://www.example.com/ignoreparent/childbranch')
964
self.assertEqual([('http://www.example.com/ignoreparent',
966
self.my_location_config._get_matching_sections())
1295
self.assertLocationMatching([('http://www.example.com/ignoreparent',
968
1298
def test__get_matching_sections_subdir_trailing_slash(self):
969
1299
self.get_branch_config('/b')
970
self.assertEqual([('/b/', '')],
971
self.my_location_config._get_matching_sections())
1300
self.assertLocationMatching([('/b/', '')])
973
1302
def test__get_matching_sections_subdir_child(self):
974
1303
self.get_branch_config('/a/foo')
975
self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
976
self.my_location_config._get_matching_sections())
1304
self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
978
1306
def test__get_matching_sections_subdir_child_child(self):
979
1307
self.get_branch_config('/a/foo/bar')
980
self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
981
self.my_location_config._get_matching_sections())
1308
self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
983
1310
def test__get_matching_sections_trailing_slash_with_children(self):
984
1311
self.get_branch_config('/a/')
985
self.assertEqual([('/a/', '')],
986
self.my_location_config._get_matching_sections())
1312
self.assertLocationMatching([('/a/', '')])
988
1314
def test__get_matching_sections_explicit_over_glob(self):
989
1315
# XXX: 2006-09-08 jamesh
1471
1814
self.assertIs(None, bzrdir_config.get_default_stack_on())
1474
def create_configs(test):
1475
"""Create configuration files for a given test.
1477
This requires creating a tree (and populate the ``test.tree`` attribute and
1478
its associated branch and will populate the following attributes:
1480
- branch_config: A BranchConfig for the associated branch.
1482
- locations_config : A LocationConfig for the associated branch
1484
- bazaar_config: A GlobalConfig.
1486
The tree and branch are created in a 'tree' subdirectory so the tests can
1487
still use the test directory to stay outside of the branch.
1489
tree = test.make_branch_and_tree('tree')
1491
test.branch_config = config.BranchConfig(tree.branch)
1492
test.locations_config = config.LocationConfig(tree.basedir)
1493
test.bazaar_config = config.GlobalConfig()
1496
def create_configs_with_file_option(test):
1497
"""Create configuration files with a ``file`` option set in each.
1499
This builds on ``create_configs`` and add one ``file`` option in each
1500
configuration with a value which allows identifying the configuration file.
1502
create_configs(test)
1503
test.bazaar_config.set_user_option('file', 'bazaar')
1504
test.locations_config.set_user_option('file', 'locations')
1505
test.branch_config.set_user_option('file', 'branch')
1508
class TestConfigGetOptions(tests.TestCaseWithTransport):
1817
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1510
1819
def setUp(self):
1511
1820
super(TestConfigGetOptions, self).setUp()
1512
1821
create_configs(self)
1514
def assertOptions(self, expected, conf):
1515
actual = list(conf._get_options())
1516
self.assertEqual(expected, actual)
1518
1823
# One variable in none of the above
1519
1824
def test_no_variable(self):
1520
1825
# Using branch should query branch, locations and bazaar