~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

(gz) Change minimum required testtools version for selftest to 0.9.5 for
 unicode fixes (Martin [gz])

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
33
33
    errors,
34
34
    osutils,
35
35
    mail_client,
36
 
    mergetools,
37
36
    ui,
38
37
    urlutils,
39
38
    tests,
42
41
    )
43
42
from bzrlib.tests import (
44
43
    features,
45
 
    TestSkipped,
46
44
    scenarios,
47
45
    )
48
46
from bzrlib.util.configobj import configobj
72
70
gpg_signing_command=gnome-gpg
73
71
log_format=short
74
72
user_global_option=something
75
 
bzr.mergetool.sometool=sometool {base} {this} {other} -o {result}
76
 
bzr.mergetool.funkytool=funkytool "arg with spaces" {this_temp}
77
 
bzr.default_mergetool=sometool
78
73
[ALIASES]
79
74
h=help
80
75
ll=""" + sample_long_alias + "\n"
314
309
        """
315
310
        co = config.ConfigObj()
316
311
        co['test'] = 'foo#bar'
317
 
        outfile = StringIO()
318
 
        co.write(outfile=outfile)
319
 
        lines = outfile.getvalue().splitlines()
 
312
        lines = co.write()
320
313
        self.assertEqual(lines, ['test = "foo#bar"'])
321
314
        co2 = config.ConfigObj(lines)
322
315
        self.assertEqual(co2['test'], 'foo#bar')
323
316
 
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 """
330
 
eggs'''
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
341
 
        outfile = StringIO()
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'])
347
 
 
348
317
 
349
318
erroneous_config = """[section] # line 1
350
319
good=good # line 2
433
402
 
434
403
    def setUp(self):
435
404
        super(TestConfigPath, self).setUp()
436
 
        self.overrideEnv('HOME', '/home/bogus')
437
 
        self.overrideEnv('XDG_CACHE_DIR', '')
 
405
        os.environ['HOME'] = '/home/bogus'
 
406
        os.environ['XDG_CACHE_DIR'] = ''
438
407
        if sys.platform == 'win32':
439
 
            self.overrideEnv(
440
 
                'BZR_HOME', r'C:\Documents and Settings\bogus\Application Data')
 
408
            os.environ['BZR_HOME'] = \
 
409
                r'C:\Documents and Settings\bogus\Application Data'
441
410
            self.bzr_home = \
442
411
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
443
412
        else:
463
432
            '/home/bogus/.cache')
464
433
 
465
434
 
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
469
 
 
470
 
    def setUp(self):
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)
478
 
 
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')
482
 
        os.makedirs(newdir)
483
 
        self.assertEqual(config.config_dir(), newdir)
484
 
 
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')
490
 
        os.makedirs(newdir)
491
 
        self.assertEqual(config.config_dir(), newdir)
492
 
 
493
 
 
494
435
class TestIniConfig(tests.TestCaseInTempDir):
495
436
 
496
437
    def make_config_parser(self, s):
510
451
    def test_cached(self):
511
452
        my_config = config.IniBasedConfig.from_string(sample_config_text)
512
453
        parser = my_config._get_parser()
513
 
        self.assertTrue(my_config._get_parser() is parser)
 
454
        self.failUnless(my_config._get_parser() is parser)
514
455
 
515
456
    def _dummy_chown(self, path, uid, gid):
516
457
        self.path, self.uid, self.gid = path, uid, gid
541
482
            ' Use IniBasedConfig(_content=xxx) instead.'],
542
483
            conf._get_parser, file=config_file)
543
484
 
544
 
 
545
485
class TestIniConfigSaving(tests.TestCaseInTempDir):
546
486
 
547
487
    def test_cant_save_without_a_file_name(self):
555
495
        self.assertFileEqual(content, 'test.conf')
556
496
 
557
497
 
558
 
class TestIniConfigOptionExpansionDefaultValue(tests.TestCaseInTempDir):
559
 
    """What is the default value of expand for config options.
560
 
 
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
564
 
    default.
565
 
 
566
 
    Note that these tests relies on config._expand_default_value being already
567
 
    overwritten in the parent class setUp.
568
 
    """
569
 
 
570
 
    def setUp(self):
571
 
        super(TestIniConfigOptionExpansionDefaultValue, self).setUp()
572
 
        self.config = None
573
 
        self.warnings = []
574
 
        def warning(*args):
575
 
            self.warnings.append(args[0] % args[1:])
576
 
        self.overrideAttr(trace, 'warning', warning)
577
 
 
578
 
    def get_config(self, expand):
579
 
        c = config.GlobalConfig.from_string('bzr.config.expand=%s' % (expand,),
580
 
                                            save=True)
581
 
        return c
582
 
 
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)
587
 
 
588
 
    def test_default_is_None(self):
589
 
        self.assertEquals(None, config._expand_default_value)
590
 
 
591
 
    def test_default_is_False_even_if_None(self):
592
 
        self.config = self.get_config(None)
593
 
        self.assertExpandIs(False)
594
 
 
595
 
    def test_default_is_False_even_if_invalid(self):
596
 
        self.config = self.get_config('<your choice>')
597
 
        self.assertExpandIs(False)
598
 
        # ...
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)
602
 
        self.assertEquals(
603
 
            'Value "<your choice>" is not a boolean for "bzr.config.expand"',
604
 
            self.warnings[0])
605
 
 
606
 
    def test_default_is_True(self):
607
 
        self.config = self.get_config(True)
608
 
        self.assertExpandIs(True)
609
 
        
610
 
    def test_default_is_False(self):
611
 
        self.config = self.get_config(False)
612
 
        self.assertExpandIs(False)
613
 
        
614
 
 
615
 
class TestIniConfigOptionExpansion(tests.TestCase):
616
 
    """Test option expansion from the IniConfig level.
617
 
 
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
620
 
    properly (yet).
621
 
    """
622
 
    # FIXME: This should be rewritten when all configs share a storage
623
 
    # implementation -- vila 2011-02-18
624
 
 
625
 
    def get_config(self, string=None):
626
 
        if string is None:
627
 
            string = ''
628
 
        c = config.IniBasedConfig.from_string(string)
629
 
        return c
630
 
 
631
 
    def assertExpansion(self, expected, conf, string, env=None):
632
 
        self.assertEquals(expected, conf.expand_options(string, env))
633
 
 
634
 
    def test_no_expansion(self):
635
 
        c = self.get_config('')
636
 
        self.assertExpansion('foo', c, 'foo')
637
 
 
638
 
    def test_env_adding_options(self):
639
 
        c = self.get_config('')
640
 
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
641
 
 
642
 
    def test_env_overriding_options(self):
643
 
        c = self.get_config('foo=baz')
644
 
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
645
 
 
646
 
    def test_simple_ref(self):
647
 
        c = self.get_config('foo=xxx')
648
 
        self.assertExpansion('xxx', c, '{foo}')
649
 
 
650
 
    def test_unknown_ref(self):
651
 
        c = self.get_config('')
652
 
        self.assertRaises(errors.ExpandingUnknownOption,
653
 
                          c.expand_options, '{foo}')
654
 
 
655
 
    def test_indirect_ref(self):
656
 
        c = self.get_config('''
657
 
foo=xxx
658
 
bar={foo}
659
 
''')
660
 
        self.assertExpansion('xxx', c, '{bar}')
661
 
 
662
 
    def test_embedded_ref(self):
663
 
        c = self.get_config('''
664
 
foo=xxx
665
 
bar=foo
666
 
''')
667
 
        self.assertExpansion('xxx', c, '{{bar}}')
668
 
 
669
 
    def test_simple_loop(self):
670
 
        c = self.get_config('foo={foo}')
671
 
        self.assertRaises(errors.OptionExpansionLoop, c.expand_options, '{foo}')
672
 
 
673
 
    def test_indirect_loop(self):
674
 
        c = self.get_config('''
675
 
foo={bar}
676
 
bar={baz}
677
 
baz={foo}''')
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)
682
 
 
683
 
    def test_list(self):
684
 
        conf = self.get_config('''
685
 
foo=start
686
 
bar=middle
687
 
baz=end
688
 
list={foo},{bar},{baz}
689
 
''')
690
 
        self.assertEquals(['start', 'middle', 'end'],
691
 
                           conf.get_user_option('list', expand=True))
692
 
 
693
 
    def test_cascading_list(self):
694
 
        conf = self.get_config('''
695
 
foo=start,{bar}
696
 
bar=middle,{baz}
697
 
baz=end
698
 
list={foo}
699
 
''')
700
 
        self.assertEquals(['start', 'middle', 'end'],
701
 
                           conf.get_user_option('list', expand=True))
702
 
 
703
 
    def test_pathological_hidden_list(self):
704
 
        conf = self.get_config('''
705
 
foo=bin
706
 
bar=go
707
 
start={foo
708
 
middle=},{
709
 
end=bar}
710
 
hidden={start}{middle}{end}
711
 
''')
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))
716
 
 
717
 
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
718
 
 
719
 
    def get_config(self, location, string=None):
720
 
        if string is None:
721
 
            string = ''
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)
725
 
        return c
726
 
 
727
 
    def test_dont_cross_unrelated_section(self):
728
 
        c = self.get_config('/another/branch/path','''
729
 
[/one/branch/path]
730
 
foo = hello
731
 
bar = {foo}/2
732
 
 
733
 
[/another/branch/path]
734
 
bar = {foo}/2
735
 
''')
736
 
        self.assertRaises(errors.ExpandingUnknownOption,
737
 
                          c.get_user_option, 'bar', expand=True)
738
 
 
739
 
    def test_cross_related_sections(self):
740
 
        c = self.get_config('/project/branch/path','''
741
 
[/project]
742
 
foo = qu
743
 
 
744
 
[/project/branch/path]
745
 
bar = {foo}ux
746
 
''')
747
 
        self.assertEquals('quux', c.get_user_option('bar', expand=True))
748
 
 
749
 
 
750
498
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
751
499
 
752
500
    def test_cannot_reload_without_name(self):
962
710
            parser = my_config._get_parser()
963
711
        finally:
964
712
            config.ConfigObj = oldparserclass
965
 
        self.assertIsInstance(parser, InstrumentedConfigObj)
 
713
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
966
714
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
967
715
                                          'utf-8')])
968
716
 
979
727
        my_config = config.BranchConfig(branch)
980
728
        location_config = my_config._get_location_config()
981
729
        self.assertEqual(branch.base, location_config.location)
982
 
        self.assertIs(location_config, my_config._get_location_config())
 
730
        self.failUnless(location_config is my_config._get_location_config())
983
731
 
984
732
    def test_get_config(self):
985
733
        """The Branch.get_config method works properly"""
1177
925
        change_editor = my_config.get_change_editor('old', 'new')
1178
926
        self.assertIs(None, change_editor)
1179
927
 
1180
 
    def test_get_merge_tools(self):
1181
 
        conf = self._get_sample_config()
1182
 
        tools = conf.get_merge_tools()
1183
 
        self.log(repr(tools))
1184
 
        self.assertEqual(
1185
 
            {u'funkytool' : u'funkytool "arg with spaces" {this_temp}',
1186
 
            u'sometool' : u'sometool {base} {this} {other} -o {result}'},
1187
 
            tools)
1188
 
 
1189
 
    def test_get_merge_tools_empty(self):
1190
 
        conf = self._get_empty_config()
1191
 
        tools = conf.get_merge_tools()
1192
 
        self.assertEqual({}, tools)
1193
 
 
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)
1198
 
 
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)
1203
 
 
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)
1208
 
 
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)
1214
 
 
1215
928
 
1216
929
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
1217
930
 
1253
966
            parser = my_config._get_parser()
1254
967
        finally:
1255
968
            config.ConfigObj = oldparserclass
1256
 
        self.assertIsInstance(parser, InstrumentedConfigObj)
 
969
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
1257
970
        self.assertEqual(parser._calls,
1258
971
                         [('__init__', config.locations_config_filename(),
1259
972
                           'utf-8')])
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())
1266
 
 
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())
1270
979
 
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())
1274
983
 
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())
1278
988
 
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())
1282
992
 
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())
1286
997
 
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',
1290
 
                                      '')])
 
1000
        self.assertEqual([('http://www.example.com/ignoreparent', '')],
 
1001
                         self.my_location_config._get_matching_sections())
1291
1002
 
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',
1296
 
                                      'childbranch')])
 
1006
        self.assertEqual([('http://www.example.com/ignoreparent',
 
1007
                           'childbranch')],
 
1008
                         self.my_location_config._get_matching_sections())
1297
1009
 
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())
1301
1014
 
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())
1305
1019
 
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())
1309
1024
 
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())
1313
1029
 
1314
1030
    def test__get_matching_sections_explicit_over_glob(self):
1315
1031
        # XXX: 2006-09-08 jamesh
1317
1033
        # was a config section for '/a/?', it would get precedence
1318
1034
        # over '/a/c'.
1319
1035
        self.get_branch_config('/a/c')
1320
 
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
 
1036
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
 
1037
                         self.my_location_config._get_matching_sections())
1321
1038
 
1322
1039
    def test__get_option_policy_normal(self):
1323
1040
        self.get_branch_config('http://www.example.com')
1563
1280
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1564
1281
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
1565
1282
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
1566
 
        self.overrideEnv('BZR_REMOTE_PATH', '/environ-bzr')
 
1283
        os.environ['BZR_REMOTE_PATH'] = '/environ-bzr'
1567
1284
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
1568
1285
 
1569
1286
 
1615
1332
        self.assertEqual("John", my_config._get_user_id())
1616
1333
 
1617
1334
    def test_BZR_EMAIL_OVERRIDES(self):
1618
 
        self.overrideEnv('BZR_EMAIL', "Robert Collins <robertc@example.org>")
 
1335
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
1619
1336
        branch = FakeBranch()
1620
1337
        my_config = config.BranchConfig(branch)
1621
1338
        self.assertEqual("Robert Collins <robertc@example.org>",
2466
2183
# test_user_prompted ?
2467
2184
class TestAuthenticationRing(tests.TestCaseWithTransport):
2468
2185
    pass
2469
 
 
2470
 
 
2471
 
class TestAutoUserId(tests.TestCase):
2472
 
    """Test inferring an automatic user name."""
2473
 
 
2474
 
    def test_auto_user_id(self):
2475
 
        """Automatic inference of user name.
2476
 
        
2477
 
        This is a bit hard to test in an isolated way, because it depends on
2478
 
        system functions that go direct to /etc or perhaps somewhere else.
2479
 
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
2480
 
        to be able to choose a user name with no configuration.
2481
 
        """
2482
 
        if sys.platform == 'win32':
2483
 
            raise TestSkipped("User name inference not implemented on win32")
2484
 
        realname, address = config._auto_user_id()
2485
 
        if os.path.exists('/etc/mailname'):
2486
 
            self.assertIsNot(None, realname)
2487
 
            self.assertIsNot(None, address)
2488
 
        else:
2489
 
            self.assertEquals((None, None), (realname, address))
2490