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):
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):
1819
1510
def setUp(self):
1820
1511
super(TestConfigGetOptions, self).setUp()
1821
1512
create_configs(self)
1514
def assertOptions(self, expected, conf):
1515
actual = list(conf._get_options())
1516
self.assertEqual(expected, actual)
1823
1518
# One variable in none of the above
1824
1519
def test_no_variable(self):
1825
1520
# Using branch should query branch, locations and bazaar