~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Zearin
  • Date: 2010-11-12 22:08:18 UTC
  • mto: (5570.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 5572.
  • Revision ID: zearin@users.sourceforge.net-20101112220818-mb62len4zyxr8qvd
Fixed capitalization of XML and HTTP.  Fixed by hand and only where appropriate (e.g., left http://some/url lowercase, but capitalized "When making an HTTP request…").

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
from cStringIO import StringIO
20
20
import os
21
21
import sys
 
22
import threading
22
23
 
23
24
#import bzrlib specific imports here
24
25
from bzrlib import (
35
36
    trace,
36
37
    transport,
37
38
    )
 
39
from bzrlib.tests import (
 
40
    features,
 
41
    scenarios,
 
42
    )
38
43
from bzrlib.util.configobj import configobj
39
44
 
40
45
 
 
46
def lockable_config_scenarios():
 
47
    return [
 
48
        ('global',
 
49
         {'config_class': config.GlobalConfig,
 
50
          'config_args': [],
 
51
          'config_section': 'DEFAULT'}),
 
52
        ('locations',
 
53
         {'config_class': config.LocationConfig,
 
54
          'config_args': ['.'],
 
55
          'config_section': '.'}),]
 
56
 
 
57
 
 
58
load_tests = scenarios.load_tests_apply_scenarios
 
59
 
 
60
 
41
61
sample_long_alias="log -r-15..-1 --line"
42
62
sample_config_text = u"""
43
63
[DEFAULT]
129
149
        self._calls.append(('keys',))
130
150
        return []
131
151
 
 
152
    def reload(self):
 
153
        self._calls.append(('reload',))
 
154
 
132
155
    def write(self, arg):
133
156
        self._calls.append(('write',))
134
157
 
350
373
        self.assertEqual(config.config_filename(),
351
374
                         self.bzr_home + '/bazaar.conf')
352
375
 
353
 
    def test_branches_config_filename(self):
354
 
        self.assertEqual(config.branches_config_filename(),
355
 
                         self.bzr_home + '/branches.conf')
356
 
 
357
376
    def test_locations_config_filename(self):
358
377
        self.assertEqual(config.locations_config_filename(),
359
378
                         self.bzr_home + '/locations.conf')
367
386
            '/home/bogus/.cache')
368
387
 
369
388
 
370
 
class TestIniConfig(tests.TestCase):
 
389
class TestIniConfig(tests.TestCaseInTempDir):
371
390
 
372
391
    def make_config_parser(self, s):
373
 
        conf = config.IniBasedConfig(None)
374
 
        parser = conf._get_parser(file=StringIO(s.encode('utf-8')))
375
 
        return conf, parser
 
392
        conf = config.IniBasedConfig.from_string(s)
 
393
        return conf, conf._get_parser()
376
394
 
377
395
 
378
396
class TestIniConfigBuilding(TestIniConfig):
379
397
 
380
398
    def test_contructs(self):
381
 
        my_config = config.IniBasedConfig("nothing")
 
399
        my_config = config.IniBasedConfig()
382
400
 
383
401
    def test_from_fp(self):
384
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
385
 
        my_config = config.IniBasedConfig(None)
386
 
        self.failUnless(
387
 
            isinstance(my_config._get_parser(file=config_file),
388
 
                        configobj.ConfigObj))
 
402
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
403
        self.assertIsInstance(my_config._get_parser(), configobj.ConfigObj)
389
404
 
390
405
    def test_cached(self):
391
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
392
 
        my_config = config.IniBasedConfig(None)
393
 
        parser = my_config._get_parser(file=config_file)
 
406
        my_config = config.IniBasedConfig.from_string(sample_config_text)
 
407
        parser = my_config._get_parser()
394
408
        self.failUnless(my_config._get_parser() is parser)
395
409
 
 
410
    def _dummy_chown(self, path, uid, gid):
 
411
        self.path, self.uid, self.gid = path, uid, gid
 
412
 
 
413
    def test_ini_config_ownership(self):
 
414
        """Ensure that chown is happening during _write_config_file"""
 
415
        self.requireFeature(features.chown_feature)
 
416
        self.overrideAttr(os, 'chown', self._dummy_chown)
 
417
        self.path = self.uid = self.gid = None
 
418
        conf = config.IniBasedConfig(file_name='./foo.conf')
 
419
        conf._write_config_file()
 
420
        self.assertEquals(self.path, './foo.conf')
 
421
        self.assertTrue(isinstance(self.uid, int))
 
422
        self.assertTrue(isinstance(self.gid, int))
 
423
 
 
424
    def test_get_filename_parameter_is_deprecated_(self):
 
425
        conf = self.callDeprecated([
 
426
            'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
 
427
            ' Use file_name instead.'],
 
428
            config.IniBasedConfig, lambda: 'ini.conf')
 
429
        self.assertEqual('ini.conf', conf.file_name)
 
430
 
 
431
    def test_get_parser_file_parameter_is_deprecated_(self):
 
432
        config_file = StringIO(sample_config_text.encode('utf-8'))
 
433
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
434
        conf = self.callDeprecated([
 
435
            'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
 
436
            ' Use IniBasedConfig(_content=xxx) instead.'],
 
437
            conf._get_parser, file=config_file)
 
438
 
 
439
class TestIniConfigSaving(tests.TestCaseInTempDir):
 
440
 
 
441
    def test_cant_save_without_a_file_name(self):
 
442
        conf = config.IniBasedConfig()
 
443
        self.assertRaises(AssertionError, conf._write_config_file)
 
444
 
 
445
    def test_saved_with_content(self):
 
446
        content = 'foo = bar\n'
 
447
        conf = config.IniBasedConfig.from_string(
 
448
            content, file_name='./test.conf', save=True)
 
449
        self.assertFileEqual(content, 'test.conf')
 
450
 
 
451
 
 
452
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
 
453
 
 
454
    def test_cannot_reload_without_name(self):
 
455
        conf = config.IniBasedConfig.from_string(sample_config_text)
 
456
        self.assertRaises(AssertionError, conf.reload)
 
457
 
 
458
    def test_reload_see_new_value(self):
 
459
        c1 = config.IniBasedConfig.from_string('editor=vim\n',
 
460
                                               file_name='./test/conf')
 
461
        c1._write_config_file()
 
462
        c2 = config.IniBasedConfig.from_string('editor=emacs\n',
 
463
                                               file_name='./test/conf')
 
464
        c2._write_config_file()
 
465
        self.assertEqual('vim', c1.get_user_option('editor'))
 
466
        self.assertEqual('emacs', c2.get_user_option('editor'))
 
467
        # Make sure we get the Right value
 
468
        c1.reload()
 
469
        self.assertEqual('emacs', c1.get_user_option('editor'))
 
470
 
 
471
 
 
472
class TestLockableConfig(tests.TestCaseInTempDir):
 
473
 
 
474
    scenarios = lockable_config_scenarios()
 
475
 
 
476
    # Set by load_tests
 
477
    config_class = None
 
478
    config_args = None
 
479
    config_section = None
 
480
 
 
481
    def setUp(self):
 
482
        super(TestLockableConfig, self).setUp()
 
483
        self._content = '[%s]\none=1\ntwo=2\n' % (self.config_section,)
 
484
        self.config = self.create_config(self._content)
 
485
 
 
486
    def get_existing_config(self):
 
487
        return self.config_class(*self.config_args)
 
488
 
 
489
    def create_config(self, content):
 
490
        kwargs = dict(save=True)
 
491
        c = self.config_class.from_string(content, *self.config_args, **kwargs)
 
492
        return c
 
493
 
 
494
    def test_simple_read_access(self):
 
495
        self.assertEquals('1', self.config.get_user_option('one'))
 
496
 
 
497
    def test_simple_write_access(self):
 
498
        self.config.set_user_option('one', 'one')
 
499
        self.assertEquals('one', self.config.get_user_option('one'))
 
500
 
 
501
    def test_listen_to_the_last_speaker(self):
 
502
        c1 = self.config
 
503
        c2 = self.get_existing_config()
 
504
        c1.set_user_option('one', 'ONE')
 
505
        c2.set_user_option('two', 'TWO')
 
506
        self.assertEquals('ONE', c1.get_user_option('one'))
 
507
        self.assertEquals('TWO', c2.get_user_option('two'))
 
508
        # The second update respect the first one
 
509
        self.assertEquals('ONE', c2.get_user_option('one'))
 
510
 
 
511
    def test_last_speaker_wins(self):
 
512
        # If the same config is not shared, the same variable modified twice
 
513
        # can only see a single result.
 
514
        c1 = self.config
 
515
        c2 = self.get_existing_config()
 
516
        c1.set_user_option('one', 'c1')
 
517
        c2.set_user_option('one', 'c2')
 
518
        self.assertEquals('c2', c2._get_user_option('one'))
 
519
        # The first modification is still available until another refresh
 
520
        # occur
 
521
        self.assertEquals('c1', c1._get_user_option('one'))
 
522
        c1.set_user_option('two', 'done')
 
523
        self.assertEquals('c2', c1._get_user_option('one'))
 
524
 
 
525
    def test_writes_are_serialized(self):
 
526
        c1 = self.config
 
527
        c2 = self.get_existing_config()
 
528
 
 
529
        # We spawn a thread that will pause *during* the write
 
530
        before_writing = threading.Event()
 
531
        after_writing = threading.Event()
 
532
        writing_done = threading.Event()
 
533
        c1_orig = c1._write_config_file
 
534
        def c1_write_config_file():
 
535
            before_writing.set()
 
536
            c1_orig()
 
537
            # The lock is held we wait for the main thread to decide when to
 
538
            # continue
 
539
            after_writing.wait()
 
540
        c1._write_config_file = c1_write_config_file
 
541
        def c1_set_option():
 
542
            c1.set_user_option('one', 'c1')
 
543
            writing_done.set()
 
544
        t1 = threading.Thread(target=c1_set_option)
 
545
        # Collect the thread after the test
 
546
        self.addCleanup(t1.join)
 
547
        # Be ready to unblock the thread if the test goes wrong
 
548
        self.addCleanup(after_writing.set)
 
549
        t1.start()
 
550
        before_writing.wait()
 
551
        self.assertTrue(c1._lock.is_held)
 
552
        self.assertRaises(errors.LockContention,
 
553
                          c2.set_user_option, 'one', 'c2')
 
554
        self.assertEquals('c1', c1.get_user_option('one'))
 
555
        # Let the lock be released
 
556
        after_writing.set()
 
557
        writing_done.wait()
 
558
        c2.set_user_option('one', 'c2')
 
559
        self.assertEquals('c2', c2.get_user_option('one'))
 
560
 
 
561
    def test_read_while_writing(self):
 
562
       c1 = self.config
 
563
       # We spawn a thread that will pause *during* the write
 
564
       ready_to_write = threading.Event()
 
565
       do_writing = threading.Event()
 
566
       writing_done = threading.Event()
 
567
       c1_orig = c1._write_config_file
 
568
       def c1_write_config_file():
 
569
           ready_to_write.set()
 
570
           # The lock is held we wait for the main thread to decide when to
 
571
           # continue
 
572
           do_writing.wait()
 
573
           c1_orig()
 
574
           writing_done.set()
 
575
       c1._write_config_file = c1_write_config_file
 
576
       def c1_set_option():
 
577
           c1.set_user_option('one', 'c1')
 
578
       t1 = threading.Thread(target=c1_set_option)
 
579
       # Collect the thread after the test
 
580
       self.addCleanup(t1.join)
 
581
       # Be ready to unblock the thread if the test goes wrong
 
582
       self.addCleanup(do_writing.set)
 
583
       t1.start()
 
584
       # Ensure the thread is ready to write
 
585
       ready_to_write.wait()
 
586
       self.assertTrue(c1._lock.is_held)
 
587
       self.assertEquals('c1', c1.get_user_option('one'))
 
588
       # If we read during the write, we get the old value
 
589
       c2 = self.get_existing_config()
 
590
       self.assertEquals('1', c2.get_user_option('one'))
 
591
       # Let the writing occur and ensure it occurred
 
592
       do_writing.set()
 
593
       writing_done.wait()
 
594
       # Now we get the updated value
 
595
       c3 = self.get_existing_config()
 
596
       self.assertEquals('c1', c3.get_user_option('one'))
 
597
 
396
598
 
397
599
class TestGetUserOptionAs(TestIniConfig):
398
600
 
505
707
        branch = self.make_branch('branch')
506
708
        self.assertEqual('branch', branch.nick)
507
709
 
508
 
        locations = config.locations_config_filename()
509
 
        config.ensure_config_dir_exists()
510
710
        local_url = urlutils.local_path_to_url('branch')
511
 
        open(locations, 'wb').write('[%s]\nnickname = foobar'
512
 
                                    % (local_url,))
 
711
        conf = config.LocationConfig.from_string(
 
712
            '[%s]\nnickname = foobar' % (local_url,),
 
713
            local_url, save=True)
513
714
        self.assertEqual('foobar', branch.nick)
514
715
 
515
716
    def test_config_local_path(self):
517
718
        branch = self.make_branch('branch')
518
719
        self.assertEqual('branch', branch.nick)
519
720
 
520
 
        locations = config.locations_config_filename()
521
 
        config.ensure_config_dir_exists()
522
 
        open(locations, 'wb').write('[%s/branch]\nnickname = barry'
523
 
                                    % (osutils.getcwd().encode('utf8'),))
 
721
        local_path = osutils.getcwd().encode('utf8')
 
722
        conf = config.LocationConfig.from_string(
 
723
            '[%s/branch]\nnickname = barry' % (local_path,),
 
724
            'branch',  save=True)
524
725
        self.assertEqual('barry', branch.nick)
525
726
 
526
727
    def test_config_creates_local(self):
527
728
        """Creating a new entry in config uses a local path."""
528
729
        branch = self.make_branch('branch', format='knit')
529
730
        branch.set_push_location('http://foobar')
530
 
        locations = config.locations_config_filename()
531
731
        local_path = osutils.getcwd().encode('utf8')
532
732
        # Surprisingly ConfigObj doesn't create a trailing newline
533
 
        self.check_file_contents(locations,
 
733
        self.check_file_contents(config.locations_config_filename(),
534
734
                                 '[%s/branch]\n'
535
735
                                 'push_location = http://foobar\n'
536
736
                                 'push_location:policy = norecurse\n'
541
741
        self.assertEqual('!repo', b.get_config().get_nickname())
542
742
 
543
743
    def test_warn_if_masked(self):
544
 
        _warning = trace.warning
545
744
        warnings = []
546
745
        def warning(*args):
547
746
            warnings.append(args[0] % args[1:])
 
747
        self.overrideAttr(trace, 'warning', warning)
548
748
 
549
749
        def set_option(store, warn_masked=True):
550
750
            warnings[:] = []
556
756
            else:
557
757
                self.assertEqual(1, len(warnings))
558
758
                self.assertEqual(warning, warnings[0])
559
 
        trace.warning = warning
560
 
        try:
561
 
            branch = self.make_branch('.')
562
 
            conf = branch.get_config()
563
 
            set_option(config.STORE_GLOBAL)
564
 
            assertWarning(None)
565
 
            set_option(config.STORE_BRANCH)
566
 
            assertWarning(None)
567
 
            set_option(config.STORE_GLOBAL)
568
 
            assertWarning('Value "4" is masked by "3" from branch.conf')
569
 
            set_option(config.STORE_GLOBAL, warn_masked=False)
570
 
            assertWarning(None)
571
 
            set_option(config.STORE_LOCATION)
572
 
            assertWarning(None)
573
 
            set_option(config.STORE_BRANCH)
574
 
            assertWarning('Value "3" is masked by "0" from locations.conf')
575
 
            set_option(config.STORE_BRANCH, warn_masked=False)
576
 
            assertWarning(None)
577
 
        finally:
578
 
            trace.warning = _warning
579
 
 
580
 
 
581
 
class TestGlobalConfigItems(tests.TestCase):
 
759
        branch = self.make_branch('.')
 
760
        conf = branch.get_config()
 
761
        set_option(config.STORE_GLOBAL)
 
762
        assertWarning(None)
 
763
        set_option(config.STORE_BRANCH)
 
764
        assertWarning(None)
 
765
        set_option(config.STORE_GLOBAL)
 
766
        assertWarning('Value "4" is masked by "3" from branch.conf')
 
767
        set_option(config.STORE_GLOBAL, warn_masked=False)
 
768
        assertWarning(None)
 
769
        set_option(config.STORE_LOCATION)
 
770
        assertWarning(None)
 
771
        set_option(config.STORE_BRANCH)
 
772
        assertWarning('Value "3" is masked by "0" from locations.conf')
 
773
        set_option(config.STORE_BRANCH, warn_masked=False)
 
774
        assertWarning(None)
 
775
 
 
776
 
 
777
class TestGlobalConfigItems(tests.TestCaseInTempDir):
582
778
 
583
779
    def test_user_id(self):
584
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
585
 
        my_config = config.GlobalConfig()
586
 
        my_config._parser = my_config._get_parser(file=config_file)
 
780
        my_config = config.GlobalConfig.from_string(sample_config_text)
587
781
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
588
782
                         my_config._get_user_id())
589
783
 
590
784
    def test_absent_user_id(self):
591
 
        config_file = StringIO("")
592
785
        my_config = config.GlobalConfig()
593
 
        my_config._parser = my_config._get_parser(file=config_file)
594
786
        self.assertEqual(None, my_config._get_user_id())
595
787
 
596
788
    def test_configured_editor(self):
597
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
598
 
        my_config = config.GlobalConfig()
599
 
        my_config._parser = my_config._get_parser(file=config_file)
 
789
        my_config = config.GlobalConfig.from_string(sample_config_text)
600
790
        self.assertEqual("vim", my_config.get_editor())
601
791
 
602
792
    def test_signatures_always(self):
603
 
        config_file = StringIO(sample_always_signatures)
604
 
        my_config = config.GlobalConfig()
605
 
        my_config._parser = my_config._get_parser(file=config_file)
 
793
        my_config = config.GlobalConfig.from_string(sample_always_signatures)
606
794
        self.assertEqual(config.CHECK_NEVER,
607
795
                         my_config.signature_checking())
608
796
        self.assertEqual(config.SIGN_ALWAYS,
610
798
        self.assertEqual(True, my_config.signature_needed())
611
799
 
612
800
    def test_signatures_if_possible(self):
613
 
        config_file = StringIO(sample_maybe_signatures)
614
 
        my_config = config.GlobalConfig()
615
 
        my_config._parser = my_config._get_parser(file=config_file)
 
801
        my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
616
802
        self.assertEqual(config.CHECK_NEVER,
617
803
                         my_config.signature_checking())
618
804
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
620
806
        self.assertEqual(False, my_config.signature_needed())
621
807
 
622
808
    def test_signatures_ignore(self):
623
 
        config_file = StringIO(sample_ignore_signatures)
624
 
        my_config = config.GlobalConfig()
625
 
        my_config._parser = my_config._get_parser(file=config_file)
 
809
        my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
626
810
        self.assertEqual(config.CHECK_ALWAYS,
627
811
                         my_config.signature_checking())
628
812
        self.assertEqual(config.SIGN_NEVER,
630
814
        self.assertEqual(False, my_config.signature_needed())
631
815
 
632
816
    def _get_sample_config(self):
633
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
634
 
        my_config = config.GlobalConfig()
635
 
        my_config._parser = my_config._get_parser(file=config_file)
 
817
        my_config = config.GlobalConfig.from_string(sample_config_text)
636
818
        return my_config
637
819
 
638
820
    def test_gpg_signing_command(self):
641
823
        self.assertEqual(False, my_config.signature_needed())
642
824
 
643
825
    def _get_empty_config(self):
644
 
        config_file = StringIO("")
645
826
        my_config = config.GlobalConfig()
646
 
        my_config._parser = my_config._get_parser(file=config_file)
647
827
        return my_config
648
828
 
649
829
    def test_gpg_signing_command_unset(self):
744
924
        self.assertEqual(parser._calls,
745
925
                         [('__init__', config.locations_config_filename(),
746
926
                           'utf-8')])
747
 
        config.ensure_config_dir_exists()
748
 
        #os.mkdir(config.config_dir())
749
 
        f = file(config.branches_config_filename(), 'wb')
750
 
        f.write('')
751
 
        f.close()
752
 
        oldparserclass = config.ConfigObj
753
 
        config.ConfigObj = InstrumentedConfigObj
754
 
        try:
755
 
            my_config = config.LocationConfig('http://www.example.com')
756
 
            parser = my_config._get_parser()
757
 
        finally:
758
 
            config.ConfigObj = oldparserclass
759
927
 
760
928
    def test_get_global_config(self):
761
929
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
990
1158
                         self.my_config.post_commit())
991
1159
 
992
1160
    def get_branch_config(self, location, global_config=None):
 
1161
        my_branch = FakeBranch(location)
993
1162
        if global_config is None:
994
 
            global_file = StringIO(sample_config_text.encode('utf-8'))
995
 
        else:
996
 
            global_file = StringIO(global_config.encode('utf-8'))
997
 
        branches_file = StringIO(sample_branches_text.encode('utf-8'))
998
 
        self.my_config = config.BranchConfig(FakeBranch(location))
999
 
        # Force location config to use specified file
1000
 
        self.my_location_config = self.my_config._get_location_config()
1001
 
        self.my_location_config._get_parser(branches_file)
1002
 
        # Force global config to use specified file
1003
 
        self.my_config._get_global_config()._get_parser(global_file)
 
1163
            global_config = sample_config_text
 
1164
 
 
1165
        my_global_config = config.GlobalConfig.from_string(global_config,
 
1166
                                                           save=True)
 
1167
        my_location_config = config.LocationConfig.from_string(
 
1168
            sample_branches_text, my_branch.base, save=True)
 
1169
        my_config = config.BranchConfig(my_branch)
 
1170
        self.my_config = my_config
 
1171
        self.my_location_config = my_config._get_location_config()
1004
1172
 
1005
1173
    def test_set_user_setting_sets_and_saves(self):
1006
1174
        self.get_branch_config('/a/c')
1007
1175
        record = InstrumentedConfigObj("foo")
1008
1176
        self.my_location_config._parser = record
1009
1177
 
1010
 
        real_mkdir = os.mkdir
1011
 
        self.created = False
1012
 
        def checked_mkdir(path, mode=0777):
1013
 
            self.log('making directory: %s', path)
1014
 
            real_mkdir(path, mode)
1015
 
            self.created = True
1016
 
 
1017
 
        os.mkdir = checked_mkdir
1018
 
        try:
1019
 
            self.callDeprecated(['The recurse option is deprecated as of '
1020
 
                                 '0.14.  The section "/a/c" has been '
1021
 
                                 'converted to use policies.'],
1022
 
                                self.my_config.set_user_option,
1023
 
                                'foo', 'bar', store=config.STORE_LOCATION)
1024
 
        finally:
1025
 
            os.mkdir = real_mkdir
1026
 
 
1027
 
        self.failUnless(self.created, 'Failed to create ~/.bazaar')
1028
 
        self.assertEqual([('__contains__', '/a/c'),
 
1178
        self.callDeprecated(['The recurse option is deprecated as of '
 
1179
                             '0.14.  The section "/a/c" has been '
 
1180
                             'converted to use policies.'],
 
1181
                            self.my_config.set_user_option,
 
1182
                            'foo', 'bar', store=config.STORE_LOCATION)
 
1183
        self.assertEqual([('reload',),
 
1184
                          ('__contains__', '/a/c'),
1029
1185
                          ('__contains__', '/a/c/'),
1030
1186
                          ('__setitem__', '/a/c', {}),
1031
1187
                          ('__getitem__', '/a/c'),
1074
1230
option = exact
1075
1231
"""
1076
1232
 
1077
 
 
1078
1233
class TestBranchConfigItems(tests.TestCaseInTempDir):
1079
1234
 
1080
1235
    def get_branch_config(self, global_config=None, location=None,
1081
1236
                          location_config=None, branch_data_config=None):
1082
 
        my_config = config.BranchConfig(FakeBranch(location))
 
1237
        my_branch = FakeBranch(location)
1083
1238
        if global_config is not None:
1084
 
            global_file = StringIO(global_config.encode('utf-8'))
1085
 
            my_config._get_global_config()._get_parser(global_file)
1086
 
        self.my_location_config = my_config._get_location_config()
 
1239
            my_global_config = config.GlobalConfig.from_string(global_config,
 
1240
                                                               save=True)
1087
1241
        if location_config is not None:
1088
 
            location_file = StringIO(location_config.encode('utf-8'))
1089
 
            self.my_location_config._get_parser(location_file)
 
1242
            my_location_config = config.LocationConfig.from_string(
 
1243
                location_config, my_branch.base, save=True)
 
1244
        my_config = config.BranchConfig(my_branch)
1090
1245
        if branch_data_config is not None:
1091
1246
            my_config.branch.control_files.files['branch.conf'] = \
1092
1247
                branch_data_config
1106
1261
                         my_config.username())
1107
1262
 
1108
1263
    def test_not_set_in_branch(self):
1109
 
        my_config = self.get_branch_config(sample_config_text)
 
1264
        my_config = self.get_branch_config(global_config=sample_config_text)
1110
1265
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1111
1266
                         my_config._get_user_id())
1112
1267
        my_config.branch.control_files.files['email'] = "John"
1136
1291
 
1137
1292
    def test_gpg_signing_command(self):
1138
1293
        my_config = self.get_branch_config(
 
1294
            global_config=sample_config_text,
1139
1295
            # branch data cannot set gpg_signing_command
1140
1296
            branch_data_config="gpg_signing_command=pgp")
1141
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1142
 
        my_config._get_global_config()._get_parser(config_file)
1143
1297
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
1144
1298
 
1145
1299
    def test_get_user_option_global(self):
1146
 
        branch = FakeBranch()
1147
 
        my_config = config.BranchConfig(branch)
1148
 
        config_file = StringIO(sample_config_text.encode('utf-8'))
1149
 
        (my_config._get_global_config()._get_parser(config_file))
 
1300
        my_config = self.get_branch_config(global_config=sample_config_text)
1150
1301
        self.assertEqual('something',
1151
1302
                         my_config.get_user_option('user_global_option'))
1152
1303
 
1153
1304
    def test_post_commit_default(self):
1154
 
        branch = FakeBranch()
1155
 
        my_config = self.get_branch_config(sample_config_text, '/a/c',
1156
 
                                           sample_branches_text)
 
1305
        my_config = self.get_branch_config(global_config=sample_config_text,
 
1306
                                      location='/a/c',
 
1307
                                      location_config=sample_branches_text)
1157
1308
        self.assertEqual(my_config.branch.base, '/a/c')
1158
1309
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1159
1310
                         my_config.post_commit())
1160
1311
        my_config.set_user_option('post_commit', 'rmtree_root')
1161
 
        # post-commit is ignored when bresent in branch data
 
1312
        # post-commit is ignored when present in branch data
1162
1313
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1163
1314
                         my_config.post_commit())
1164
1315
        my_config.set_user_option('post_commit', 'rmtree_root',
1166
1317
        self.assertEqual('rmtree_root', my_config.post_commit())
1167
1318
 
1168
1319
    def test_config_precedence(self):
 
1320
        # FIXME: eager test, luckily no persitent config file makes it fail
 
1321
        # -- vila 20100716
1169
1322
        my_config = self.get_branch_config(global_config=precedence_global)
1170
1323
        self.assertEqual(my_config.get_user_option('option'), 'global')
1171
1324
        my_config = self.get_branch_config(global_config=precedence_global,
1172
 
                                      branch_data_config=precedence_branch)
 
1325
                                           branch_data_config=precedence_branch)
1173
1326
        self.assertEqual(my_config.get_user_option('option'), 'branch')
1174
 
        my_config = self.get_branch_config(global_config=precedence_global,
1175
 
                                      branch_data_config=precedence_branch,
1176
 
                                      location_config=precedence_location)
 
1327
        my_config = self.get_branch_config(
 
1328
            global_config=precedence_global,
 
1329
            branch_data_config=precedence_branch,
 
1330
            location_config=precedence_location)
1177
1331
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
1178
 
        my_config = self.get_branch_config(global_config=precedence_global,
1179
 
                                      branch_data_config=precedence_branch,
1180
 
                                      location_config=precedence_location,
1181
 
                                      location='http://example.com/specific')
 
1332
        my_config = self.get_branch_config(
 
1333
            global_config=precedence_global,
 
1334
            branch_data_config=precedence_branch,
 
1335
            location_config=precedence_location,
 
1336
            location='http://example.com/specific')
1182
1337
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1183
1338
 
1184
1339
    def test_get_mail_client(self):
1312
1467
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1313
1468
 
1314
1469
 
 
1470
def create_configs(test):
 
1471
    """Create configuration files for a given test.
 
1472
 
 
1473
    This requires creating a tree (and populate the ``test.tree`` attribute)
 
1474
    and its associated branch and will populate the following attributes:
 
1475
 
 
1476
    - branch_config: A BranchConfig for the associated branch.
 
1477
 
 
1478
    - locations_config : A LocationConfig for the associated branch
 
1479
 
 
1480
    - bazaar_config: A GlobalConfig.
 
1481
 
 
1482
    The tree and branch are created in a 'tree' subdirectory so the tests can
 
1483
    still use the test directory to stay outside of the branch.
 
1484
    """
 
1485
    tree = test.make_branch_and_tree('tree')
 
1486
    test.tree = tree
 
1487
    test.branch_config = config.BranchConfig(tree.branch)
 
1488
    test.locations_config = config.LocationConfig(tree.basedir)
 
1489
    test.bazaar_config = config.GlobalConfig()
 
1490
 
 
1491
 
 
1492
def create_configs_with_file_option(test):
 
1493
    """Create configuration files with a ``file`` option set in each.
 
1494
 
 
1495
    This builds on ``create_configs`` and add one ``file`` option in each
 
1496
    configuration with a value which allows identifying the configuration file.
 
1497
    """
 
1498
    create_configs(test)
 
1499
    test.bazaar_config.set_user_option('file', 'bazaar')
 
1500
    test.locations_config.set_user_option('file', 'locations')
 
1501
    test.branch_config.set_user_option('file', 'branch')
 
1502
 
 
1503
 
 
1504
class TestConfigGetOptions(tests.TestCaseWithTransport):
 
1505
 
 
1506
    def setUp(self):
 
1507
        super(TestConfigGetOptions, self).setUp()
 
1508
        create_configs(self)
 
1509
 
 
1510
    def assertOptions(self, expected, conf):
 
1511
        actual = list(conf._get_options())
 
1512
        self.assertEqual(expected, actual)
 
1513
 
 
1514
    # One variable in none of the above
 
1515
    def test_no_variable(self):
 
1516
        # Using branch should query branch, locations and bazaar
 
1517
        self.assertOptions([], self.branch_config)
 
1518
 
 
1519
    def test_option_in_bazaar(self):
 
1520
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1521
        self.assertOptions([('file', 'bazaar', 'DEFAULT', 'bazaar')],
 
1522
                           self.bazaar_config)
 
1523
 
 
1524
    def test_option_in_locations(self):
 
1525
        self.locations_config.set_user_option('file', 'locations')
 
1526
        self.assertOptions(
 
1527
            [('file', 'locations', self.tree.basedir, 'locations')],
 
1528
            self.locations_config)
 
1529
 
 
1530
    def test_option_in_branch(self):
 
1531
        self.branch_config.set_user_option('file', 'branch')
 
1532
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
 
1533
                           self.branch_config)
 
1534
 
 
1535
    def test_option_in_bazaar_and_branch(self):
 
1536
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1537
        self.branch_config.set_user_option('file', 'branch')
 
1538
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
 
1539
                            ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1540
                           self.branch_config)
 
1541
 
 
1542
    def test_option_in_branch_and_locations(self):
 
1543
        # Hmm, locations override branch :-/
 
1544
        self.locations_config.set_user_option('file', 'locations')
 
1545
        self.branch_config.set_user_option('file', 'branch')
 
1546
        self.assertOptions(
 
1547
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1548
             ('file', 'branch', 'DEFAULT', 'branch'),],
 
1549
            self.branch_config)
 
1550
 
 
1551
    def test_option_in_bazaar_locations_and_branch(self):
 
1552
        self.bazaar_config.set_user_option('file', 'bazaar')
 
1553
        self.locations_config.set_user_option('file', 'locations')
 
1554
        self.branch_config.set_user_option('file', 'branch')
 
1555
        self.assertOptions(
 
1556
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1557
             ('file', 'branch', 'DEFAULT', 'branch'),
 
1558
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1559
            self.branch_config)
 
1560
 
 
1561
 
 
1562
class TestConfigRemoveOption(tests.TestCaseWithTransport):
 
1563
 
 
1564
    def setUp(self):
 
1565
        super(TestConfigRemoveOption, self).setUp()
 
1566
        create_configs_with_file_option(self)
 
1567
 
 
1568
    def assertOptions(self, expected, conf):
 
1569
        actual = list(conf._get_options())
 
1570
        self.assertEqual(expected, actual)
 
1571
 
 
1572
    def test_remove_in_locations(self):
 
1573
        self.locations_config.remove_user_option('file', self.tree.basedir)
 
1574
        self.assertOptions(
 
1575
            [('file', 'branch', 'DEFAULT', 'branch'),
 
1576
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1577
            self.branch_config)
 
1578
 
 
1579
    def test_remove_in_branch(self):
 
1580
        self.branch_config.remove_user_option('file')
 
1581
        self.assertOptions(
 
1582
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1583
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
 
1584
            self.branch_config)
 
1585
 
 
1586
    def test_remove_in_bazaar(self):
 
1587
        self.bazaar_config.remove_user_option('file')
 
1588
        self.assertOptions(
 
1589
            [('file', 'locations', self.tree.basedir, 'locations'),
 
1590
             ('file', 'branch', 'DEFAULT', 'branch'),],
 
1591
            self.branch_config)
 
1592
 
 
1593
 
 
1594
class TestConfigGetSections(tests.TestCaseWithTransport):
 
1595
 
 
1596
    def setUp(self):
 
1597
        super(TestConfigGetSections, self).setUp()
 
1598
        create_configs(self)
 
1599
 
 
1600
    def assertSectionNames(self, expected, conf, name=None):
 
1601
        """Check which sections are returned for a given config.
 
1602
 
 
1603
        If fallback configurations exist their sections can be included.
 
1604
 
 
1605
        :param expected: A list of section names.
 
1606
 
 
1607
        :param conf: The configuration that will be queried.
 
1608
 
 
1609
        :param name: An optional section name that will be passed to
 
1610
            get_sections().
 
1611
        """
 
1612
        sections = list(conf._get_sections(name))
 
1613
        self.assertLength(len(expected), sections)
 
1614
        self.assertEqual(expected, [name for name, _, _ in sections])
 
1615
 
 
1616
    def test_bazaar_default_section(self):
 
1617
        self.assertSectionNames(['DEFAULT'], self.bazaar_config)
 
1618
 
 
1619
    def test_locations_default_section(self):
 
1620
        # No sections are defined in an empty file
 
1621
        self.assertSectionNames([], self.locations_config)
 
1622
 
 
1623
    def test_locations_named_section(self):
 
1624
        self.locations_config.set_user_option('file', 'locations')
 
1625
        self.assertSectionNames([self.tree.basedir], self.locations_config)
 
1626
 
 
1627
    def test_locations_matching_sections(self):
 
1628
        loc_config = self.locations_config
 
1629
        loc_config.set_user_option('file', 'locations')
 
1630
        # We need to cheat a bit here to create an option in sections above and
 
1631
        # below the 'location' one.
 
1632
        parser = loc_config._get_parser()
 
1633
        # locations.cong deals with '/' ignoring native os.sep
 
1634
        location_names = self.tree.basedir.split('/')
 
1635
        parent = '/'.join(location_names[:-1])
 
1636
        child = '/'.join(location_names + ['child'])
 
1637
        parser[parent] = {}
 
1638
        parser[parent]['file'] = 'parent'
 
1639
        parser[child] = {}
 
1640
        parser[child]['file'] = 'child'
 
1641
        self.assertSectionNames([self.tree.basedir, parent], loc_config)
 
1642
 
 
1643
    def test_branch_data_default_section(self):
 
1644
        self.assertSectionNames([None],
 
1645
                                self.branch_config._get_branch_data_config())
 
1646
 
 
1647
    def test_branch_default_sections(self):
 
1648
        # No sections are defined in an empty locations file
 
1649
        self.assertSectionNames([None, 'DEFAULT'],
 
1650
                                self.branch_config)
 
1651
        # Unless we define an option
 
1652
        self.branch_config._get_location_config().set_user_option(
 
1653
            'file', 'locations')
 
1654
        self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
 
1655
                                self.branch_config)
 
1656
 
 
1657
    def test_bazaar_named_section(self):
 
1658
        # We need to cheat as the API doesn't give direct access to sections
 
1659
        # other than DEFAULT.
 
1660
        self.bazaar_config.set_alias('bazaar', 'bzr')
 
1661
        self.assertSectionNames(['ALIASES'], self.bazaar_config, 'ALIASES')
 
1662
 
 
1663
 
1315
1664
class TestAuthenticationConfigFile(tests.TestCase):
1316
1665
    """Test the authentication.conf file matching"""
1317
1666