315
310
co = config.ConfigObj()
316
311
co['test'] = 'foo#bar'
318
co.write(outfile=outfile)
319
lines = outfile.getvalue().splitlines()
320
313
self.assertEqual(lines, ['test = "foo#bar"'])
321
314
co2 = config.ConfigObj(lines)
322
315
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
318
erroneous_config = """[section] # line 1
350
319
good=good # line 2
463
432
'/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
435
class TestIniConfig(tests.TestCaseInTempDir):
496
437
def make_config_parser(self, s):
555
495
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
498
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
752
500
def test_cannot_reload_without_name(self):
1177
925
change_editor = my_config.get_change_editor('old', 'new')
1178
926
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
929
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
1261
974
def test_get_global_config(self):
1262
975
my_config = config.BranchConfig(FakeBranch('http://example.com'))
1263
976
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()))
977
self.failUnless(isinstance(global_config, config.GlobalConfig))
978
self.failUnless(global_config is my_config._get_global_config())
1271
980
def test__get_matching_sections_no_match(self):
1272
981
self.get_branch_config('/')
1273
self.assertLocationMatching([])
982
self.assertEqual([], self.my_location_config._get_matching_sections())
1275
984
def test__get_matching_sections_exact(self):
1276
985
self.get_branch_config('http://www.example.com')
1277
self.assertLocationMatching([('http://www.example.com', '')])
986
self.assertEqual([('http://www.example.com', '')],
987
self.my_location_config._get_matching_sections())
1279
989
def test__get_matching_sections_suffix_does_not(self):
1280
990
self.get_branch_config('http://www.example.com-com')
1281
self.assertLocationMatching([])
991
self.assertEqual([], self.my_location_config._get_matching_sections())
1283
993
def test__get_matching_sections_subdir_recursive(self):
1284
994
self.get_branch_config('http://www.example.com/com')
1285
self.assertLocationMatching([('http://www.example.com', 'com')])
995
self.assertEqual([('http://www.example.com', 'com')],
996
self.my_location_config._get_matching_sections())
1287
998
def test__get_matching_sections_ignoreparent(self):
1288
999
self.get_branch_config('http://www.example.com/ignoreparent')
1289
self.assertLocationMatching([('http://www.example.com/ignoreparent',
1000
self.assertEqual([('http://www.example.com/ignoreparent', '')],
1001
self.my_location_config._get_matching_sections())
1292
1003
def test__get_matching_sections_ignoreparent_subdir(self):
1293
1004
self.get_branch_config(
1294
1005
'http://www.example.com/ignoreparent/childbranch')
1295
self.assertLocationMatching([('http://www.example.com/ignoreparent',
1006
self.assertEqual([('http://www.example.com/ignoreparent',
1008
self.my_location_config._get_matching_sections())
1298
1010
def test__get_matching_sections_subdir_trailing_slash(self):
1299
1011
self.get_branch_config('/b')
1300
self.assertLocationMatching([('/b/', '')])
1012
self.assertEqual([('/b/', '')],
1013
self.my_location_config._get_matching_sections())
1302
1015
def test__get_matching_sections_subdir_child(self):
1303
1016
self.get_branch_config('/a/foo')
1304
self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1017
self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
1018
self.my_location_config._get_matching_sections())
1306
1020
def test__get_matching_sections_subdir_child_child(self):
1307
1021
self.get_branch_config('/a/foo/bar')
1308
self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1022
self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
1023
self.my_location_config._get_matching_sections())
1310
1025
def test__get_matching_sections_trailing_slash_with_children(self):
1311
1026
self.get_branch_config('/a/')
1312
self.assertLocationMatching([('/a/', '')])
1027
self.assertEqual([('/a/', '')],
1028
self.my_location_config._get_matching_sections())
1314
1030
def test__get_matching_sections_explicit_over_glob(self):
1315
1031
# XXX: 2006-09-08 jamesh