315
314
co = config.ConfigObj()
316
315
co['test'] = 'foo#bar'
318
co.write(outfile=outfile)
319
lines = outfile.getvalue().splitlines()
320
317
self.assertEqual(lines, ['test = "foo#bar"'])
321
318
co2 = config.ConfigObj(lines)
322
319
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
322
erroneous_config = """[section] # line 1
350
323
good=good # line 2
555
527
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
530
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
752
532
def test_cannot_reload_without_name(self):
1261
1041
def test_get_global_config(self):
1262
1042
my_config = config.BranchConfig(FakeBranch('http://example.com'))
1263
1043
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()))
1044
self.failUnless(isinstance(global_config, config.GlobalConfig))
1045
self.failUnless(global_config is my_config._get_global_config())
1271
1047
def test__get_matching_sections_no_match(self):
1272
1048
self.get_branch_config('/')
1273
self.assertLocationMatching([])
1049
self.assertEqual([], self.my_location_config._get_matching_sections())
1275
1051
def test__get_matching_sections_exact(self):
1276
1052
self.get_branch_config('http://www.example.com')
1277
self.assertLocationMatching([('http://www.example.com', '')])
1053
self.assertEqual([('http://www.example.com', '')],
1054
self.my_location_config._get_matching_sections())
1279
1056
def test__get_matching_sections_suffix_does_not(self):
1280
1057
self.get_branch_config('http://www.example.com-com')
1281
self.assertLocationMatching([])
1058
self.assertEqual([], self.my_location_config._get_matching_sections())
1283
1060
def test__get_matching_sections_subdir_recursive(self):
1284
1061
self.get_branch_config('http://www.example.com/com')
1285
self.assertLocationMatching([('http://www.example.com', 'com')])
1062
self.assertEqual([('http://www.example.com', 'com')],
1063
self.my_location_config._get_matching_sections())
1287
1065
def test__get_matching_sections_ignoreparent(self):
1288
1066
self.get_branch_config('http://www.example.com/ignoreparent')
1289
self.assertLocationMatching([('http://www.example.com/ignoreparent',
1067
self.assertEqual([('http://www.example.com/ignoreparent', '')],
1068
self.my_location_config._get_matching_sections())
1292
1070
def test__get_matching_sections_ignoreparent_subdir(self):
1293
1071
self.get_branch_config(
1294
1072
'http://www.example.com/ignoreparent/childbranch')
1295
self.assertLocationMatching([('http://www.example.com/ignoreparent',
1073
self.assertEqual([('http://www.example.com/ignoreparent',
1075
self.my_location_config._get_matching_sections())
1298
1077
def test__get_matching_sections_subdir_trailing_slash(self):
1299
1078
self.get_branch_config('/b')
1300
self.assertLocationMatching([('/b/', '')])
1079
self.assertEqual([('/b/', '')],
1080
self.my_location_config._get_matching_sections())
1302
1082
def test__get_matching_sections_subdir_child(self):
1303
1083
self.get_branch_config('/a/foo')
1304
self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1084
self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
1085
self.my_location_config._get_matching_sections())
1306
1087
def test__get_matching_sections_subdir_child_child(self):
1307
1088
self.get_branch_config('/a/foo/bar')
1308
self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1089
self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
1090
self.my_location_config._get_matching_sections())
1310
1092
def test__get_matching_sections_trailing_slash_with_children(self):
1311
1093
self.get_branch_config('/a/')
1312
self.assertLocationMatching([('/a/', '')])
1094
self.assertEqual([('/a/', '')],
1095
self.my_location_config._get_matching_sections())
1314
1097
def test__get_matching_sections_explicit_over_glob(self):
1315
1098
# XXX: 2006-09-08 jamesh