~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2011-04-18 04:55:00 UTC
  • mfrom: (5784.2.1 754188-apport-test)
  • Revision ID: pqm@pqm.ubuntu.com-20110418045500-ce6lkgyiq7f47q43
(mbp) Rewrite test_report_bug_legacy away from using doctest (see bug
 764188) (Martin Pool)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 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
21
21
import sys
22
22
import threading
23
23
 
 
24
 
 
25
from testtools import matchers
 
26
 
24
27
#import bzrlib specific imports here
25
28
from bzrlib import (
26
29
    branch,
30
33
    errors,
31
34
    osutils,
32
35
    mail_client,
 
36
    mergetools,
33
37
    ui,
34
38
    urlutils,
35
39
    tests,
36
40
    trace,
37
41
    transport,
38
42
    )
39
 
from bzrlib.tests import features
 
43
from bzrlib.tests import (
 
44
    features,
 
45
    TestSkipped,
 
46
    scenarios,
 
47
    )
40
48
from bzrlib.util.configobj import configobj
41
49
 
42
50
 
52
60
          'config_section': '.'}),]
53
61
 
54
62
 
55
 
def load_tests(standard_tests, module, loader):
56
 
    suite = loader.suiteClass()
57
 
 
58
 
    lc_tests, remaining_tests = tests.split_suite_by_condition(
59
 
        standard_tests, tests.condition_isinstance((
60
 
                TestLockableConfig,
61
 
                )))
62
 
    tests.multiply_tests(lc_tests, lockable_config_scenarios(), suite)
63
 
    suite.addTest(remaining_tests)
64
 
    return suite
 
63
load_tests = scenarios.load_tests_apply_scenarios
65
64
 
66
65
 
67
66
sample_long_alias="log -r-15..-1 --line"
73
72
gpg_signing_command=gnome-gpg
74
73
log_format=short
75
74
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
76
78
[ALIASES]
77
79
h=help
78
80
ll=""" + sample_long_alias + "\n"
131
133
"""
132
134
 
133
135
 
 
136
def create_configs(test):
 
137
    """Create configuration files for a given test.
 
138
 
 
139
    This requires creating a tree (and populate the ``test.tree`` attribute)
 
140
    and its associated branch and will populate the following attributes:
 
141
 
 
142
    - branch_config: A BranchConfig for the associated branch.
 
143
 
 
144
    - locations_config : A LocationConfig for the associated branch
 
145
 
 
146
    - bazaar_config: A GlobalConfig.
 
147
 
 
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.
 
150
    """
 
151
    tree = test.make_branch_and_tree('tree')
 
152
    test.tree = tree
 
153
    test.branch_config = config.BranchConfig(tree.branch)
 
154
    test.locations_config = config.LocationConfig(tree.basedir)
 
155
    test.bazaar_config = config.GlobalConfig()
 
156
 
 
157
 
 
158
def create_configs_with_file_option(test):
 
159
    """Create configuration files with a ``file`` option set in each.
 
160
 
 
161
    This builds on ``create_configs`` and add one ``file`` option in each
 
162
    configuration with a value which allows identifying the configuration file.
 
163
    """
 
164
    create_configs(test)
 
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')
 
168
 
 
169
 
 
170
class TestOptionsMixin:
 
171
 
 
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))
 
177
 
 
178
 
134
179
class InstrumentedConfigObj(object):
135
180
    """A config obj look-enough-alike to record calls made to it."""
136
181
 
269
314
        """
270
315
        co = config.ConfigObj()
271
316
        co['test'] = 'foo#bar'
272
 
        lines = co.write()
 
317
        outfile = StringIO()
 
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')
276
323
 
 
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
 
277
348
 
278
349
erroneous_config = """[section] # line 1
279
350
good=good # line 2
362
433
 
363
434
    def setUp(self):
364
435
        super(TestConfigPath, self).setUp()
365
 
        os.environ['HOME'] = '/home/bogus'
366
 
        os.environ['XDG_CACHE_DIR'] = ''
 
436
        self.overrideEnv('HOME', '/home/bogus')
 
437
        self.overrideEnv('XDG_CACHE_DIR', '')
367
438
        if sys.platform == 'win32':
368
 
            os.environ['BZR_HOME'] = \
369
 
                r'C:\Documents and Settings\bogus\Application Data'
 
439
            self.overrideEnv(
 
440
                'BZR_HOME', r'C:\Documents and Settings\bogus\Application Data')
370
441
            self.bzr_home = \
371
442
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
372
443
        else:
392
463
            '/home/bogus/.cache')
393
464
 
394
465
 
 
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
 
395
494
class TestIniConfig(tests.TestCaseInTempDir):
396
495
 
397
496
    def make_config_parser(self, s):
411
510
    def test_cached(self):
412
511
        my_config = config.IniBasedConfig.from_string(sample_config_text)
413
512
        parser = my_config._get_parser()
414
 
        self.failUnless(my_config._get_parser() is parser)
 
513
        self.assertTrue(my_config._get_parser() is parser)
415
514
 
416
515
    def _dummy_chown(self, path, uid, gid):
417
516
        self.path, self.uid, self.gid = path, uid, gid
442
541
            ' Use IniBasedConfig(_content=xxx) instead.'],
443
542
            conf._get_parser, file=config_file)
444
543
 
 
544
 
445
545
class TestIniConfigSaving(tests.TestCaseInTempDir):
446
546
 
447
547
    def test_cant_save_without_a_file_name(self):
455
555
        self.assertFileEqual(content, 'test.conf')
456
556
 
457
557
 
 
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
 
458
750
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
459
751
 
460
752
    def test_cannot_reload_without_name(self):
477
769
 
478
770
class TestLockableConfig(tests.TestCaseInTempDir):
479
771
 
 
772
    scenarios = lockable_config_scenarios()
 
773
 
480
774
    # Set by load_tests
481
775
    config_class = None
482
776
    config_args = None
668
962
            parser = my_config._get_parser()
669
963
        finally:
670
964
            config.ConfigObj = oldparserclass
671
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
965
        self.assertIsInstance(parser, InstrumentedConfigObj)
672
966
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
673
967
                                          'utf-8')])
674
968
 
685
979
        my_config = config.BranchConfig(branch)
686
980
        location_config = my_config._get_location_config()
687
981
        self.assertEqual(branch.base, location_config.location)
688
 
        self.failUnless(location_config is my_config._get_location_config())
 
982
        self.assertIs(location_config, my_config._get_location_config())
689
983
 
690
984
    def test_get_config(self):
691
985
        """The Branch.get_config method works properly"""
883
1177
        change_editor = my_config.get_change_editor('old', 'new')
884
1178
        self.assertIs(None, change_editor)
885
1179
 
 
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
 
886
1215
 
887
1216
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
888
1217
 
906
1235
        self.assertIs(None, new_config.get_alias('commit'))
907
1236
 
908
1237
 
909
 
class TestLocationConfig(tests.TestCaseInTempDir):
 
1238
class TestLocationConfig(tests.TestCaseInTempDir, TestOptionsMixin):
910
1239
 
911
1240
    def test_constructs(self):
912
1241
        my_config = config.LocationConfig('http://example.com')
924
1253
            parser = my_config._get_parser()
925
1254
        finally:
926
1255
            config.ConfigObj = oldparserclass
927
 
        self.failUnless(isinstance(parser, InstrumentedConfigObj))
 
1256
        self.assertIsInstance(parser, InstrumentedConfigObj)
928
1257
        self.assertEqual(parser._calls,
929
1258
                         [('__init__', config.locations_config_filename(),
930
1259
                           'utf-8')])
932
1261
    def test_get_global_config(self):
933
1262
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
934
1263
        global_config = my_config._get_global_config()
935
 
        self.failUnless(isinstance(global_config, config.GlobalConfig))
936
 
        self.failUnless(global_config is 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()))
937
1270
 
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([])
941
1274
 
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', '')])
946
1278
 
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([])
950
1282
 
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')])
955
1286
 
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',
 
1290
                                      '')])
960
1291
 
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',
965
 
                           'childbranch')],
966
 
                         self.my_location_config._get_matching_sections())
 
1295
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
 
1296
                                      'childbranch')])
967
1297
 
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/', '')])
972
1301
 
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')])
977
1305
 
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')])
982
1309
 
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/', '')])
987
1313
 
988
1314
    def test__get_matching_sections_explicit_over_glob(self):
989
1315
        # XXX: 2006-09-08 jamesh
991
1317
        # was a config section for '/a/?', it would get precedence
992
1318
        # over '/a/c'.
993
1319
        self.get_branch_config('/a/c')
994
 
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
995
 
                         self.my_location_config._get_matching_sections())
 
1320
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
996
1321
 
997
1322
    def test__get_option_policy_normal(self):
998
1323
        self.get_branch_config('http://www.example.com')
1020
1345
            'http://www.example.com', 'appendpath_option'),
1021
1346
            config.POLICY_APPENDPATH)
1022
1347
 
 
1348
    def test__get_options_with_policy(self):
 
1349
        self.get_branch_config('/dir/subdir',
 
1350
                               location_config="""\
 
1351
[/dir]
 
1352
other_url = /other-dir
 
1353
other_url:policy = appendpath
 
1354
[/dir/subdir]
 
1355
other_url = /other-subdir
 
1356
""")
 
1357
        self.assertOptions(
 
1358
            [(u'other_url', u'/other-subdir', u'/dir/subdir', 'locations'),
 
1359
             (u'other_url', u'/other-dir', u'/dir', 'locations'),
 
1360
             (u'other_url:policy', u'appendpath', u'/dir', 'locations')],
 
1361
            self.my_location_config)
 
1362
 
1023
1363
    def test_location_without_username(self):
1024
1364
        self.get_branch_config('http://www.example.com/ignoreparent')
1025
1365
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
1161
1501
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1162
1502
                         self.my_config.post_commit())
1163
1503
 
1164
 
    def get_branch_config(self, location, global_config=None):
 
1504
    def get_branch_config(self, location, global_config=None,
 
1505
                          location_config=None):
1165
1506
        my_branch = FakeBranch(location)
1166
1507
        if global_config is None:
1167
1508
            global_config = sample_config_text
 
1509
        if location_config is None:
 
1510
            location_config = sample_branches_text
1168
1511
 
1169
1512
        my_global_config = config.GlobalConfig.from_string(global_config,
1170
1513
                                                           save=True)
1171
1514
        my_location_config = config.LocationConfig.from_string(
1172
 
            sample_branches_text, my_branch.base, save=True)
 
1515
            location_config, my_branch.base, save=True)
1173
1516
        my_config = config.BranchConfig(my_branch)
1174
1517
        self.my_config = my_config
1175
1518
        self.my_location_config = my_config._get_location_config()
1220
1563
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1221
1564
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
1222
1565
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
1223
 
        os.environ['BZR_REMOTE_PATH'] = '/environ-bzr'
 
1566
        self.overrideEnv('BZR_REMOTE_PATH', '/environ-bzr')
1224
1567
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
1225
1568
 
1226
1569
 
1272
1615
        self.assertEqual("John", my_config._get_user_id())
1273
1616
 
1274
1617
    def test_BZR_EMAIL_OVERRIDES(self):
1275
 
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
 
1618
        self.overrideEnv('BZR_EMAIL', "Robert Collins <robertc@example.org>")
1276
1619
        branch = FakeBranch()
1277
1620
        my_config = config.BranchConfig(branch)
1278
1621
        self.assertEqual("Robert Collins <robertc@example.org>",
1471
1814
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1472
1815
 
1473
1816
 
1474
 
def create_configs(test):
1475
 
    """Create configuration files for a given test.
1476
 
 
1477
 
    This requires creating a tree (and populate the ``test.tree`` attribute and
1478
 
    its associated branch and will populate the following attributes:
1479
 
 
1480
 
    - branch_config: A BranchConfig for the associated branch.
1481
 
 
1482
 
    - locations_config : A LocationConfig for the associated branch
1483
 
 
1484
 
    - bazaar_config: A GlobalConfig.
1485
 
 
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.
1488
 
    """
1489
 
    tree = test.make_branch_and_tree('tree')
1490
 
    test.tree = tree
1491
 
    test.branch_config = config.BranchConfig(tree.branch)
1492
 
    test.locations_config = config.LocationConfig(tree.basedir)
1493
 
    test.bazaar_config = config.GlobalConfig()
1494
 
 
1495
 
 
1496
 
def create_configs_with_file_option(test):
1497
 
    """Create configuration files with a ``file`` option set in each.
1498
 
 
1499
 
    This builds on ``create_configs`` and add one ``file`` option in each
1500
 
    configuration with a value which allows identifying the configuration file.
1501
 
    """
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')
1506
 
 
1507
 
 
1508
 
class TestConfigGetOptions(tests.TestCaseWithTransport):
 
1817
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
1509
1818
 
1510
1819
    def setUp(self):
1511
1820
        super(TestConfigGetOptions, self).setUp()
1512
1821
        create_configs(self)
1513
1822
 
1514
 
    def assertOptions(self, expected, conf):
1515
 
        actual = list(conf._get_options())
1516
 
        self.assertEqual(expected, actual)
1517
 
 
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
1563
1868
            self.branch_config)
1564
1869
 
1565
1870
 
1566
 
class TestConfigRemoveOption(tests.TestCaseWithTransport):
 
1871
class TestConfigRemoveOption(tests.TestCaseWithTransport, TestOptionsMixin):
1567
1872
 
1568
1873
    def setUp(self):
1569
1874
        super(TestConfigRemoveOption, self).setUp()
1570
1875
        create_configs_with_file_option(self)
1571
1876
 
1572
 
    def assertOptions(self, expected, conf):
1573
 
        actual = list(conf._get_options())
1574
 
        self.assertEqual(expected, actual)
1575
 
 
1576
1877
    def test_remove_in_locations(self):
1577
1878
        self.locations_config.remove_user_option('file', self.tree.basedir)
1578
1879
        self.assertOptions(
2165
2466
# test_user_prompted ?
2166
2467
class TestAuthenticationRing(tests.TestCaseWithTransport):
2167
2468
    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.assertTrue(realname)
 
2487
            self.assertTrue(address)
 
2488
        else:
 
2489
            self.assertEquals((None, None), (realname, address))
 
2490