~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_config.py

  • Committer: Vincent Ladeuil
  • Date: 2007-11-24 14:20:59 UTC
  • mto: (3928.1.1 bzr.integration)
  • mto: This revision was merged to the branch mainline in revision 3929.
  • Revision ID: v.ladeuil+lp@free.fr-20071124142059-2114qtsgfdv8g9p1
Ssl files needed for the test https server.

* bzrlib/tests/ssl_certs/create_ssls.py: 
Script to create the ssl keys and certificates.

* bzrlib/tests/ssl_certs/server.crt: 
Server certificate signed by the certificate authority.

* bzrlib/tests/ssl_certs/server.csr: 
Server certificate signing request.

* bzrlib/tests/ssl_certs/server_without_pass.key: 
Server key usable without password.

* bzrlib/tests/ssl_certs/server_with_pass.key: 
Server key.

* bzrlib/tests/ssl_certs/ca.key: 
Certificate authority private key.

* bzrlib/tests/ssl_certs/ca.crt: 
Certificate authority certificate.

* bzrlib/tests/ssl_certs/__init__.py: 
Provide access to ssl files (keys and certificates). 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
2
#   Authors: Robert Collins <robert.collins@canonical.com>
2
3
#
3
4
# This program is free software; you can redistribute it and/or modify
4
5
# it under the terms of the GNU General Public License as published by
12
13
#
13
14
# You should have received a copy of the GNU General Public License
14
15
# along with this program; if not, write to the Free Software
15
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
 
17
18
"""Tests for finding and reading the bzr config file[s]."""
18
19
# import system imports here
 
20
from bzrlib.util.configobj.configobj import ConfigObj, ConfigObjError
19
21
from cStringIO import StringIO
20
22
import os
21
23
import sys
25
27
    branch,
26
28
    bzrdir,
27
29
    config,
28
 
    diff,
29
30
    errors,
30
31
    osutils,
31
32
    mail_client,
33
34
    urlutils,
34
35
    tests,
35
36
    trace,
36
 
    transport,
37
37
    )
38
 
from bzrlib.util.configobj import configobj
39
38
 
40
39
 
41
40
sample_long_alias="log -r-15..-1 --line"
43
42
[DEFAULT]
44
43
email=Erik B\u00e5gfors <erik@bagfors.nu>
45
44
editor=vim
46
 
change_editor=vimdiff -of @new_path @old_path
47
45
gpg_signing_command=gnome-gpg
48
46
log_format=short
49
47
user_global_option=something
148
146
            self.base = "http://example.com/branches/demo"
149
147
        else:
150
148
            self.base = base
151
 
        self._transport = self.control_files = \
152
 
            FakeControlFilesAndTransport(user_id=user_id)
153
 
 
154
 
    def _get_config(self):
155
 
        return config.TransportConfig(self._transport, 'branch.conf')
 
149
        self.control_files = FakeControlFiles(user_id=user_id)
156
150
 
157
151
    def lock_write(self):
158
152
        pass
161
155
        pass
162
156
 
163
157
 
164
 
class FakeControlFilesAndTransport(object):
 
158
class FakeControlFiles(object):
165
159
 
166
160
    def __init__(self, user_id=None):
 
161
        self.email = user_id
167
162
        self.files = {}
168
 
        if user_id:
169
 
            self.files['email'] = user_id
170
 
        self._transport = self
171
163
 
172
164
    def get_utf8(self, filename):
173
 
        # from LockableFiles
174
 
        raise AssertionError("get_utf8 should no longer be used")
 
165
        if filename != 'email':
 
166
            raise NotImplementedError
 
167
        if self.email is not None:
 
168
            return StringIO(self.email)
 
169
        raise errors.NoSuchFile(filename)
175
170
 
176
171
    def get(self, filename):
177
 
        # from Transport
178
172
        try:
179
173
            return StringIO(self.files[filename])
180
174
        except KeyError:
181
175
            raise errors.NoSuchFile(filename)
182
176
 
183
 
    def get_bytes(self, filename):
184
 
        # from Transport
185
 
        try:
186
 
            return self.files[filename]
187
 
        except KeyError:
188
 
            raise errors.NoSuchFile(filename)
189
 
 
190
177
    def put(self, filename, fileobj):
191
178
        self.files[filename] = fileobj.read()
192
179
 
193
 
    def put_file(self, filename, fileobj):
194
 
        return self.put(filename, fileobj)
195
 
 
196
180
 
197
181
class InstrumentedConfig(config.Config):
198
182
    """An instrumented config that supplies stubs for template methods."""
199
 
 
 
183
    
200
184
    def __init__(self):
201
185
        super(InstrumentedConfig, self).__init__()
202
186
        self._calls = []
210
194
        self._calls.append('_get_signature_checking')
211
195
        return self._signatures
212
196
 
213
 
    def _get_change_editor(self):
214
 
        self._calls.append('_get_change_editor')
215
 
        return 'vimdiff -fo @new_path @old_path'
216
 
 
217
197
 
218
198
bool_config = """[DEFAULT]
219
199
active = true
222
202
active = True
223
203
nonactive = False
224
204
"""
225
 
 
226
 
 
227
205
class TestConfigObj(tests.TestCase):
228
 
 
229
206
    def test_get_bool(self):
230
 
        co = config.ConfigObj(StringIO(bool_config))
 
207
        from bzrlib.config import ConfigObj
 
208
        co = ConfigObj(StringIO(bool_config))
231
209
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
232
210
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
233
211
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
234
212
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
235
213
 
236
 
    def test_hash_sign_in_value(self):
237
 
        """
238
 
        Before 4.5.0, ConfigObj did not quote # signs in values, so they'd be
239
 
        treated as comments when read in again. (#86838)
240
 
        """
241
 
        co = config.ConfigObj()
242
 
        co['test'] = 'foo#bar'
243
 
        lines = co.write()
244
 
        self.assertEqual(lines, ['test = "foo#bar"'])
245
 
        co2 = config.ConfigObj(lines)
246
 
        self.assertEqual(co2['test'], 'foo#bar')
247
 
 
248
214
 
249
215
erroneous_config = """[section] # line 1
250
216
good=good # line 2
251
217
[section] # line 3
252
218
whocares=notme # line 4
253
219
"""
254
 
 
255
 
 
256
220
class TestConfigObjErrors(tests.TestCase):
257
221
 
258
222
    def test_duplicate_section_name_error_line(self):
259
223
        try:
260
 
            co = configobj.ConfigObj(StringIO(erroneous_config),
261
 
                                     raise_errors=True)
 
224
            co = ConfigObj(StringIO(erroneous_config), raise_errors=True)
262
225
        except config.configobj.DuplicateError, e:
263
226
            self.assertEqual(3, e.line_number)
264
227
        else:
265
228
            self.fail('Error in config file not detected')
266
229
 
267
 
 
268
230
class TestConfig(tests.TestCase):
269
231
 
270
232
    def test_constructs(self):
271
233
        config.Config()
272
 
 
 
234
 
273
235
    def test_no_default_editor(self):
274
236
        self.assertRaises(NotImplementedError, config.Config().get_editor)
275
237
 
320
282
        my_config = config.Config()
321
283
        self.assertEqual('long', my_config.log_format())
322
284
 
323
 
    def test_get_change_editor(self):
324
 
        my_config = InstrumentedConfig()
325
 
        change_editor = my_config.get_change_editor('old_tree', 'new_tree')
326
 
        self.assertEqual(['_get_change_editor'], my_config._calls)
327
 
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
328
 
        self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
329
 
                         change_editor.command_template)
330
 
 
331
285
 
332
286
class TestConfigPath(tests.TestCase):
333
287
 
334
288
    def setUp(self):
335
289
        super(TestConfigPath, self).setUp()
336
290
        os.environ['HOME'] = '/home/bogus'
337
 
        os.environ['XDG_CACHE_DIR'] = ''
338
291
        if sys.platform == 'win32':
339
292
            os.environ['BZR_HOME'] = \
340
293
                r'C:\Documents and Settings\bogus\Application Data'
341
 
            self.bzr_home = \
342
 
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
343
 
        else:
344
 
            self.bzr_home = '/home/bogus/.bazaar'
345
294
 
346
295
    def test_config_dir(self):
347
 
        self.assertEqual(config.config_dir(), self.bzr_home)
 
296
        if sys.platform == 'win32':
 
297
            self.assertEqual(config.config_dir(), 
 
298
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
 
299
        else:
 
300
            self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
348
301
 
349
302
    def test_config_filename(self):
350
 
        self.assertEqual(config.config_filename(),
351
 
                         self.bzr_home + '/bazaar.conf')
 
303
        if sys.platform == 'win32':
 
304
            self.assertEqual(config.config_filename(), 
 
305
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
 
306
        else:
 
307
            self.assertEqual(config.config_filename(),
 
308
                             '/home/bogus/.bazaar/bazaar.conf')
352
309
 
353
310
    def test_branches_config_filename(self):
354
 
        self.assertEqual(config.branches_config_filename(),
355
 
                         self.bzr_home + '/branches.conf')
 
311
        if sys.platform == 'win32':
 
312
            self.assertEqual(config.branches_config_filename(), 
 
313
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
 
314
        else:
 
315
            self.assertEqual(config.branches_config_filename(),
 
316
                             '/home/bogus/.bazaar/branches.conf')
356
317
 
357
318
    def test_locations_config_filename(self):
358
 
        self.assertEqual(config.locations_config_filename(),
359
 
                         self.bzr_home + '/locations.conf')
 
319
        if sys.platform == 'win32':
 
320
            self.assertEqual(config.locations_config_filename(), 
 
321
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/locations.conf')
 
322
        else:
 
323
            self.assertEqual(config.locations_config_filename(),
 
324
                             '/home/bogus/.bazaar/locations.conf')
360
325
 
361
326
    def test_authentication_config_filename(self):
362
 
        self.assertEqual(config.authentication_config_filename(),
363
 
                         self.bzr_home + '/authentication.conf')
364
 
 
365
 
    def test_xdg_cache_dir(self):
366
 
        self.assertEqual(config.xdg_cache_dir(),
367
 
            '/home/bogus/.cache')
368
 
 
 
327
        if sys.platform == 'win32':
 
328
            self.assertEqual(config.authentication_config_filename(), 
 
329
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/authentication.conf')
 
330
        else:
 
331
            self.assertEqual(config.authentication_config_filename(),
 
332
                             '/home/bogus/.bazaar/authentication.conf')
369
333
 
370
334
class TestIniConfig(tests.TestCase):
371
335
 
372
 
    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
376
 
 
377
 
 
378
 
class TestIniConfigBuilding(TestIniConfig):
379
 
 
380
336
    def test_contructs(self):
381
337
        my_config = config.IniBasedConfig("nothing")
382
338
 
385
341
        my_config = config.IniBasedConfig(None)
386
342
        self.failUnless(
387
343
            isinstance(my_config._get_parser(file=config_file),
388
 
                        configobj.ConfigObj))
 
344
                        ConfigObj))
389
345
 
390
346
    def test_cached(self):
391
347
        config_file = StringIO(sample_config_text.encode('utf-8'))
394
350
        self.failUnless(my_config._get_parser() is parser)
395
351
 
396
352
 
397
 
class TestGetUserOptionAs(TestIniConfig):
398
 
 
399
 
    def test_get_user_option_as_bool(self):
400
 
        conf, parser = self.make_config_parser("""
401
 
a_true_bool = true
402
 
a_false_bool = 0
403
 
an_invalid_bool = maybe
404
 
a_list = hmm, who knows ? # This is interpreted as a list !
405
 
""")
406
 
        get_bool = conf.get_user_option_as_bool
407
 
        self.assertEqual(True, get_bool('a_true_bool'))
408
 
        self.assertEqual(False, get_bool('a_false_bool'))
409
 
        warnings = []
410
 
        def warning(*args):
411
 
            warnings.append(args[0] % args[1:])
412
 
        self.overrideAttr(trace, 'warning', warning)
413
 
        msg = 'Value "%s" is not a boolean for "%s"'
414
 
        self.assertIs(None, get_bool('an_invalid_bool'))
415
 
        self.assertEquals(msg % ('maybe', 'an_invalid_bool'), warnings[0])
416
 
        warnings = []
417
 
        self.assertIs(None, get_bool('not_defined_in_this_config'))
418
 
        self.assertEquals([], warnings)
419
 
 
420
 
    def test_get_user_option_as_list(self):
421
 
        conf, parser = self.make_config_parser("""
422
 
a_list = a,b,c
423
 
length_1 = 1,
424
 
one_item = x
425
 
""")
426
 
        get_list = conf.get_user_option_as_list
427
 
        self.assertEqual(['a', 'b', 'c'], get_list('a_list'))
428
 
        self.assertEqual(['1'], get_list('length_1'))
429
 
        self.assertEqual('x', conf.get_user_option('one_item'))
430
 
        # automatically cast to list
431
 
        self.assertEqual(['x'], get_list('one_item'))
432
 
 
433
 
 
434
 
class TestSupressWarning(TestIniConfig):
435
 
 
436
 
    def make_warnings_config(self, s):
437
 
        conf, parser = self.make_config_parser(s)
438
 
        return conf.suppress_warning
439
 
 
440
 
    def test_suppress_warning_unknown(self):
441
 
        suppress_warning = self.make_warnings_config('')
442
 
        self.assertEqual(False, suppress_warning('unknown_warning'))
443
 
 
444
 
    def test_suppress_warning_known(self):
445
 
        suppress_warning = self.make_warnings_config('suppress_warnings=a,b')
446
 
        self.assertEqual(False, suppress_warning('c'))
447
 
        self.assertEqual(True, suppress_warning('a'))
448
 
        self.assertEqual(True, suppress_warning('b'))
449
 
 
450
 
 
451
353
class TestGetConfig(tests.TestCase):
452
354
 
453
355
    def test_constructs(self):
454
356
        my_config = config.GlobalConfig()
455
357
 
456
358
    def test_calls_read_filenames(self):
457
 
        # replace the class that is constructed, to check its parameters
 
359
        # replace the class that is constructured, to check its parameters
458
360
        oldparserclass = config.ConfigObj
459
361
        config.ConfigObj = InstrumentedConfigObj
460
362
        my_config = config.GlobalConfig()
508
410
        locations = config.locations_config_filename()
509
411
        config.ensure_config_dir_exists()
510
412
        local_url = urlutils.local_path_to_url('branch')
511
 
        open(locations, 'wb').write('[%s]\nnickname = foobar'
 
413
        open(locations, 'wb').write('[%s]\nnickname = foobar' 
512
414
                                    % (local_url,))
513
415
        self.assertEqual('foobar', branch.nick)
514
416
 
519
421
 
520
422
        locations = config.locations_config_filename()
521
423
        config.ensure_config_dir_exists()
522
 
        open(locations, 'wb').write('[%s/branch]\nnickname = barry'
 
424
        open(locations, 'wb').write('[%s/branch]\nnickname = barry' 
523
425
                                    % (osutils.getcwd().encode('utf8'),))
524
426
        self.assertEqual('barry', branch.nick)
525
427
 
531
433
        local_path = osutils.getcwd().encode('utf8')
532
434
        # Surprisingly ConfigObj doesn't create a trailing newline
533
435
        self.check_file_contents(locations,
534
 
                                 '[%s/branch]\n'
535
 
                                 'push_location = http://foobar\n'
536
 
                                 'push_location:policy = norecurse\n'
537
 
                                 % (local_path,))
 
436
            '[%s/branch]\npush_location = http://foobar\npush_location:policy = norecurse' % (local_path,))
538
437
 
539
438
    def test_autonick_urlencoded(self):
540
439
        b = self.make_branch('!repo')
658
557
        my_config = self._get_sample_config()
659
558
        self.assertEqual("something",
660
559
                         my_config.get_user_option('user_global_option'))
661
 
 
 
560
        
662
561
    def test_post_commit_default(self):
663
562
        my_config = self._get_sample_config()
664
563
        self.assertEqual(None, my_config.post_commit())
671
570
        my_config = self._get_sample_config()
672
571
        self.assertEqual('help', my_config.get_alias('h'))
673
572
 
674
 
    def test_get_aliases(self):
675
 
        my_config = self._get_sample_config()
676
 
        aliases = my_config.get_aliases()
677
 
        self.assertEqual(2, len(aliases))
678
 
        sorted_keys = sorted(aliases)
679
 
        self.assertEqual('help', aliases[sorted_keys[0]])
680
 
        self.assertEqual(sample_long_alias, aliases[sorted_keys[1]])
681
 
 
682
573
    def test_get_no_alias(self):
683
574
        my_config = self._get_sample_config()
684
575
        self.assertEqual(None, my_config.get_alias('foo'))
687
578
        my_config = self._get_sample_config()
688
579
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
689
580
 
690
 
    def test_get_change_editor(self):
691
 
        my_config = self._get_sample_config()
692
 
        change_editor = my_config.get_change_editor('old', 'new')
693
 
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
694
 
        self.assertEqual('vimdiff -of @new_path @old_path',
695
 
                         ' '.join(change_editor.command_template))
696
 
 
697
 
    def test_get_no_change_editor(self):
698
 
        my_config = self._get_empty_config()
699
 
        change_editor = my_config.get_change_editor('old', 'new')
700
 
        self.assertIs(None, change_editor)
701
 
 
702
 
 
703
 
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
704
 
 
705
 
    def test_empty(self):
706
 
        my_config = config.GlobalConfig()
707
 
        self.assertEqual(0, len(my_config.get_aliases()))
708
 
 
709
 
    def test_set_alias(self):
710
 
        my_config = config.GlobalConfig()
711
 
        alias_value = 'commit --strict'
712
 
        my_config.set_alias('commit', alias_value)
713
 
        new_config = config.GlobalConfig()
714
 
        self.assertEqual(alias_value, new_config.get_alias('commit'))
715
 
 
716
 
    def test_remove_alias(self):
717
 
        my_config = config.GlobalConfig()
718
 
        my_config.set_alias('commit', 'commit --strict')
719
 
        # Now remove the alias again.
720
 
        my_config.unset_alias('commit')
721
 
        new_config = config.GlobalConfig()
722
 
        self.assertIs(None, new_config.get_alias('commit'))
723
 
 
724
581
 
725
582
class TestLocationConfig(tests.TestCaseInTempDir):
726
583
 
732
589
        # This is testing the correct file names are provided.
733
590
        # TODO: consolidate with the test for GlobalConfigs filename checks.
734
591
        #
735
 
        # replace the class that is constructed, to check its parameters
 
592
        # replace the class that is constructured, to check its parameters
736
593
        oldparserclass = config.ConfigObj
737
594
        config.ConfigObj = InstrumentedConfigObj
738
595
        try:
766
623
    def test__get_matching_sections_no_match(self):
767
624
        self.get_branch_config('/')
768
625
        self.assertEqual([], self.my_location_config._get_matching_sections())
769
 
 
 
626
        
770
627
    def test__get_matching_sections_exact(self):
771
628
        self.get_branch_config('http://www.example.com')
772
629
        self.assertEqual([('http://www.example.com', '')],
773
630
                         self.my_location_config._get_matching_sections())
774
 
 
 
631
   
775
632
    def test__get_matching_sections_suffix_does_not(self):
776
633
        self.get_branch_config('http://www.example.com-com')
777
634
        self.assertEqual([], self.my_location_config._get_matching_sections())
789
646
    def test__get_matching_sections_ignoreparent_subdir(self):
790
647
        self.get_branch_config(
791
648
            'http://www.example.com/ignoreparent/childbranch')
792
 
        self.assertEqual([('http://www.example.com/ignoreparent',
793
 
                           'childbranch')],
 
649
        self.assertEqual([('http://www.example.com/ignoreparent', 'childbranch')],
794
650
                         self.my_location_config._get_matching_sections())
795
651
 
796
652
    def test__get_matching_sections_subdir_trailing_slash(self):
876
732
        self.get_branch_config('/a/c')
877
733
        self.assertEqual(config.CHECK_NEVER,
878
734
                         self.my_config.signature_checking())
879
 
 
 
735
        
880
736
    def test_signatures_when_available(self):
881
737
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
882
738
        self.assertEqual(config.CHECK_IF_POSSIBLE,
883
739
                         self.my_config.signature_checking())
884
 
 
 
740
        
885
741
    def test_signatures_always(self):
886
742
        self.get_branch_config('/b')
887
743
        self.assertEqual(config.CHECK_ALWAYS,
888
744
                         self.my_config.signature_checking())
889
 
 
 
745
        
890
746
    def test_gpg_signing_command(self):
891
747
        self.get_branch_config('/b')
892
748
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
1046
902
        self.assertIs(self.my_config.get_user_option('foo'), None)
1047
903
        self.my_config.set_user_option('foo', 'bar')
1048
904
        self.assertEqual(
1049
 
            self.my_config.branch.control_files.files['branch.conf'].strip(),
 
905
            self.my_config.branch.control_files.files['branch.conf'], 
1050
906
            'foo = bar')
1051
907
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
1052
908
        self.my_config.set_user_option('foo', 'baz',
1054
910
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1055
911
        self.my_config.set_user_option('foo', 'qux')
1056
912
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1057
 
 
 
913
        
1058
914
    def test_get_bzr_remote_path(self):
1059
915
        my_config = config.LocationConfig('/a/c')
1060
916
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1077
933
 
1078
934
class TestBranchConfigItems(tests.TestCaseInTempDir):
1079
935
 
1080
 
    def get_branch_config(self, global_config=None, location=None,
 
936
    def get_branch_config(self, global_config=None, location=None, 
1081
937
                          location_config=None, branch_data_config=None):
1082
938
        my_config = config.BranchConfig(FakeBranch(location))
1083
939
        if global_config is not None:
1097
953
        my_config = config.BranchConfig(branch)
1098
954
        self.assertEqual("Robert Collins <robertc@example.net>",
1099
955
                         my_config.username())
1100
 
        my_config.branch.control_files.files['email'] = "John"
1101
 
        my_config.set_user_option('email',
 
956
        branch.control_files.email = "John"
 
957
        my_config.set_user_option('email', 
1102
958
                                  "Robert Collins <robertc@example.org>")
1103
959
        self.assertEqual("John", my_config.username())
1104
 
        del my_config.branch.control_files.files['email']
 
960
        branch.control_files.email = None
1105
961
        self.assertEqual("Robert Collins <robertc@example.org>",
1106
962
                         my_config.username())
1107
963
 
1108
964
    def test_not_set_in_branch(self):
1109
965
        my_config = self.get_branch_config(sample_config_text)
 
966
        my_config.branch.control_files.email = None
1110
967
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1111
968
                         my_config._get_user_id())
1112
 
        my_config.branch.control_files.files['email'] = "John"
 
969
        my_config.branch.control_files.email = "John"
1113
970
        self.assertEqual("John", my_config._get_user_id())
1114
971
 
1115
972
    def test_BZR_EMAIL_OVERRIDES(self):
1118
975
        my_config = config.BranchConfig(branch)
1119
976
        self.assertEqual("Robert Collins <robertc@example.org>",
1120
977
                         my_config.username())
1121
 
 
 
978
    
1122
979
    def test_signatures_forced(self):
1123
980
        my_config = self.get_branch_config(
1124
981
            global_config=sample_always_signatures)
1168
1025
    def test_config_precedence(self):
1169
1026
        my_config = self.get_branch_config(global_config=precedence_global)
1170
1027
        self.assertEqual(my_config.get_user_option('option'), 'global')
1171
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
1028
        my_config = self.get_branch_config(global_config=precedence_global, 
1172
1029
                                      branch_data_config=precedence_branch)
1173
1030
        self.assertEqual(my_config.get_user_option('option'), 'branch')
1174
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
1031
        my_config = self.get_branch_config(global_config=precedence_global, 
1175
1032
                                      branch_data_config=precedence_branch,
1176
1033
                                      location_config=precedence_location)
1177
1034
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
1178
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
1035
        my_config = self.get_branch_config(global_config=precedence_global, 
1179
1036
                                      branch_data_config=precedence_branch,
1180
1037
                                      location_config=precedence_location,
1181
1038
                                      location='http://example.com/specific')
1232
1089
        self.assertRaises(errors.NoEmailInUsername,
1233
1090
                          config.extract_email_address, 'Jane Tester')
1234
1091
 
1235
 
    def test_parse_username(self):
1236
 
        self.assertEqual(('', 'jdoe@example.com'),
1237
 
                         config.parse_username('jdoe@example.com'))
1238
 
        self.assertEqual(('', 'jdoe@example.com'),
1239
 
                         config.parse_username('<jdoe@example.com>'))
1240
 
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1241
 
                         config.parse_username('John Doe <jdoe@example.com>'))
1242
 
        self.assertEqual(('John Doe', ''),
1243
 
                         config.parse_username('John Doe'))
1244
 
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1245
 
                         config.parse_username('John Doe jdoe@example.com'))
1246
1092
 
1247
1093
class TestTreeConfig(tests.TestCaseWithTransport):
1248
1094
 
1272
1118
        self.assertEqual(value, 'value3-section')
1273
1119
 
1274
1120
 
1275
 
class TestTransportConfig(tests.TestCaseWithTransport):
1276
 
 
1277
 
    def test_get_value(self):
1278
 
        """Test that retreiving a value from a section is possible"""
1279
 
        bzrdir_config = config.TransportConfig(transport.get_transport('.'),
1280
 
                                               'control.conf')
1281
 
        bzrdir_config.set_option('value', 'key', 'SECTION')
1282
 
        bzrdir_config.set_option('value2', 'key2')
1283
 
        bzrdir_config.set_option('value3-top', 'key3')
1284
 
        bzrdir_config.set_option('value3-section', 'key3', 'SECTION')
1285
 
        value = bzrdir_config.get_option('key', 'SECTION')
1286
 
        self.assertEqual(value, 'value')
1287
 
        value = bzrdir_config.get_option('key2')
1288
 
        self.assertEqual(value, 'value2')
1289
 
        self.assertEqual(bzrdir_config.get_option('non-existant'), None)
1290
 
        value = bzrdir_config.get_option('non-existant', 'SECTION')
1291
 
        self.assertEqual(value, None)
1292
 
        value = bzrdir_config.get_option('non-existant', default='default')
1293
 
        self.assertEqual(value, 'default')
1294
 
        self.assertEqual(bzrdir_config.get_option('key2', 'NOSECTION'), None)
1295
 
        value = bzrdir_config.get_option('key2', 'NOSECTION',
1296
 
                                         default='default')
1297
 
        self.assertEqual(value, 'default')
1298
 
        value = bzrdir_config.get_option('key3')
1299
 
        self.assertEqual(value, 'value3-top')
1300
 
        value = bzrdir_config.get_option('key3', 'SECTION')
1301
 
        self.assertEqual(value, 'value3-section')
1302
 
 
1303
 
    def test_set_unset_default_stack_on(self):
1304
 
        my_dir = self.make_bzrdir('.')
1305
 
        bzrdir_config = config.BzrDirConfig(my_dir)
1306
 
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1307
 
        bzrdir_config.set_default_stack_on('Foo')
1308
 
        self.assertEqual('Foo', bzrdir_config._config.get_option(
1309
 
                         'default_stack_on'))
1310
 
        self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
1311
 
        bzrdir_config.set_default_stack_on(None)
1312
 
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1313
 
 
1314
 
 
1315
1121
class TestAuthenticationConfigFile(tests.TestCase):
1316
1122
    """Test the authentication.conf file matching"""
1317
1123
 
1332
1138
        self.assertEquals({}, conf._get_config())
1333
1139
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
1334
1140
 
1335
 
    def test_missing_auth_section_header(self):
1336
 
        conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
1337
 
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1338
 
 
1339
 
    def test_auth_section_header_not_closed(self):
 
1141
    def test_broken_config(self):
1340
1142
        conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
1341
1143
        self.assertRaises(errors.ParseConfigError, conf._get_config)
1342
1144
 
1343
 
    def test_auth_value_not_boolean(self):
1344
1145
        conf = config.AuthenticationConfig(_file=StringIO(
1345
1146
                """[broken]
1346
1147
scheme=ftp
1348
1149
verify_certificates=askme # Error: Not a boolean
1349
1150
"""))
1350
1151
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1351
 
 
1352
 
    def test_auth_value_not_int(self):
1353
1152
        conf = config.AuthenticationConfig(_file=StringIO(
1354
1153
                """[broken]
1355
1154
scheme=ftp
1358
1157
"""))
1359
1158
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1360
1159
 
1361
 
    def test_unknown_password_encoding(self):
1362
 
        conf = config.AuthenticationConfig(_file=StringIO(
1363
 
                """[broken]
1364
 
scheme=ftp
1365
 
user=joe
1366
 
password_encoding=unknown
1367
 
"""))
1368
 
        self.assertRaises(ValueError, conf.get_password,
1369
 
                          'ftp', 'foo.net', 'joe')
1370
 
 
1371
1160
    def test_credentials_for_scheme_host(self):
1372
1161
        conf = config.AuthenticationConfig(_file=StringIO(
1373
1162
                """# Identity on foo.net
1484
1273
        self._got_user_passwd(None, None,
1485
1274
                              conf, 'http', 'bar.org', user='georges')
1486
1275
 
1487
 
    def test_credentials_for_user_without_password(self):
1488
 
        conf = config.AuthenticationConfig(_file=StringIO(
1489
 
                """
1490
 
[without password]
1491
 
scheme=http
1492
 
host=bar.org
1493
 
user=jim
1494
 
"""))
1495
 
        # Get user but no password
1496
 
        self._got_user_passwd('jim', None,
1497
 
                              conf, 'http', 'bar.org')
1498
 
 
1499
1276
    def test_verify_certificates(self):
1500
1277
        conf = config.AuthenticationConfig(_file=StringIO(
1501
1278
                """
1517
1294
        self.assertEquals(True, credentials.get('verify_certificates'))
1518
1295
 
1519
1296
 
1520
 
class TestAuthenticationStorage(tests.TestCaseInTempDir):
1521
 
 
1522
 
    def test_set_credentials(self):
1523
 
        conf = config.AuthenticationConfig()
1524
 
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password',
1525
 
        99, path='/foo', verify_certificates=False, realm='realm')
1526
 
        credentials = conf.get_credentials(host='host', scheme='scheme',
1527
 
                                           port=99, path='/foo',
1528
 
                                           realm='realm')
1529
 
        CREDENTIALS = {'name': 'name', 'user': 'user', 'password': 'password',
1530
 
                       'verify_certificates': False, 'scheme': 'scheme', 
1531
 
                       'host': 'host', 'port': 99, 'path': '/foo', 
1532
 
                       'realm': 'realm'}
1533
 
        self.assertEqual(CREDENTIALS, credentials)
1534
 
        credentials_from_disk = config.AuthenticationConfig().get_credentials(
1535
 
            host='host', scheme='scheme', port=99, path='/foo', realm='realm')
1536
 
        self.assertEqual(CREDENTIALS, credentials_from_disk)
1537
 
 
1538
 
    def test_reset_credentials_different_name(self):
1539
 
        conf = config.AuthenticationConfig()
1540
 
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password'),
1541
 
        conf.set_credentials('name2', 'host', 'user2', 'scheme', 'password'),
1542
 
        self.assertIs(None, conf._get_config().get('name'))
1543
 
        credentials = conf.get_credentials(host='host', scheme='scheme')
1544
 
        CREDENTIALS = {'name': 'name2', 'user': 'user2', 'password':
1545
 
                       'password', 'verify_certificates': True, 
1546
 
                       'scheme': 'scheme', 'host': 'host', 'port': None, 
1547
 
                       'path': None, 'realm': None}
1548
 
        self.assertEqual(CREDENTIALS, credentials)
1549
 
 
1550
 
 
1551
1297
class TestAuthenticationConfig(tests.TestCase):
1552
1298
    """Test AuthenticationConfig behaviour"""
1553
1299
 
1554
 
    def _check_default_password_prompt(self, expected_prompt_format, scheme,
1555
 
                                       host=None, port=None, realm=None,
1556
 
                                       path=None):
 
1300
    def _check_default_prompt(self, expected_prompt_format, scheme,
 
1301
                              host=None, port=None, realm=None, path=None):
1557
1302
        if host is None:
1558
1303
            host = 'bar.org'
1559
1304
        user, password = 'jim', 'precious'
1562
1307
            'user': user, 'realm': realm}
1563
1308
 
1564
1309
        stdout = tests.StringIOWrapper()
1565
 
        stderr = tests.StringIOWrapper()
1566
1310
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
1567
 
                                            stdout=stdout, stderr=stderr)
 
1311
                                            stdout=stdout)
1568
1312
        # We use an empty conf so that the user is always prompted
1569
1313
        conf = config.AuthenticationConfig()
1570
1314
        self.assertEquals(password,
1571
1315
                          conf.get_password(scheme, host, user, port=port,
1572
1316
                                            realm=realm, path=path))
1573
 
        self.assertEquals(expected_prompt, stderr.getvalue())
1574
 
        self.assertEquals('', stdout.getvalue())
1575
 
 
1576
 
    def _check_default_username_prompt(self, expected_prompt_format, scheme,
1577
 
                                       host=None, port=None, realm=None,
1578
 
                                       path=None):
1579
 
        if host is None:
1580
 
            host = 'bar.org'
1581
 
        username = 'jim'
1582
 
        expected_prompt = expected_prompt_format % {
1583
 
            'scheme': scheme, 'host': host, 'port': port,
1584
 
            'realm': realm}
1585
 
        stdout = tests.StringIOWrapper()
1586
 
        stderr = tests.StringIOWrapper()
1587
 
        ui.ui_factory = tests.TestUIFactory(stdin=username+ '\n',
1588
 
                                            stdout=stdout, stderr=stderr)
1589
 
        # We use an empty conf so that the user is always prompted
1590
 
        conf = config.AuthenticationConfig()
1591
 
        self.assertEquals(username, conf.get_user(scheme, host, port=port,
1592
 
                          realm=realm, path=path, ask=True))
1593
 
        self.assertEquals(expected_prompt, stderr.getvalue())
1594
 
        self.assertEquals('', stdout.getvalue())
1595
 
 
1596
 
    def test_username_defaults_prompts(self):
1597
 
        # HTTP prompts can't be tested here, see test_http.py
1598
 
        self._check_default_username_prompt('FTP %(host)s username: ', 'ftp')
1599
 
        self._check_default_username_prompt(
1600
 
            'FTP %(host)s:%(port)d username: ', 'ftp', port=10020)
1601
 
        self._check_default_username_prompt(
1602
 
            'SSH %(host)s:%(port)d username: ', 'ssh', port=12345)
1603
 
 
1604
 
    def test_username_default_no_prompt(self):
1605
 
        conf = config.AuthenticationConfig()
1606
 
        self.assertEquals(None,
1607
 
            conf.get_user('ftp', 'example.com'))
1608
 
        self.assertEquals("explicitdefault",
1609
 
            conf.get_user('ftp', 'example.com', default="explicitdefault"))
1610
 
 
1611
 
    def test_password_default_prompts(self):
1612
 
        # HTTP prompts can't be tested here, see test_http.py
1613
 
        self._check_default_password_prompt(
1614
 
            'FTP %(user)s@%(host)s password: ', 'ftp')
1615
 
        self._check_default_password_prompt(
1616
 
            'FTP %(user)s@%(host)s:%(port)d password: ', 'ftp', port=10020)
1617
 
        self._check_default_password_prompt(
1618
 
            'SSH %(user)s@%(host)s:%(port)d password: ', 'ssh', port=12345)
 
1317
        self.assertEquals(stdout.getvalue(), expected_prompt)
 
1318
 
 
1319
    def test_default_prompts(self):
 
1320
        # HTTP prompts can't be tested here, see test_http.py
 
1321
        self._check_default_prompt('FTP %(user)s@%(host)s password: ', 'ftp')
 
1322
        self._check_default_prompt('FTP %(user)s@%(host)s:%(port)d password: ',
 
1323
                                   'ftp', port=10020)
 
1324
 
 
1325
        self._check_default_prompt('SSH %(user)s@%(host)s:%(port)d password: ',
 
1326
                                   'ssh', port=12345)
1619
1327
        # SMTP port handling is a bit special (it's handled if embedded in the
1620
1328
        # host too)
1621
1329
        # FIXME: should we: forbid that, extend it to other schemes, leave
1622
1330
        # things as they are that's fine thank you ?
1623
 
        self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
1624
 
                                            'smtp')
1625
 
        self._check_default_password_prompt('SMTP %(user)s@%(host)s password: ',
1626
 
                                            'smtp', host='bar.org:10025')
1627
 
        self._check_default_password_prompt(
 
1331
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
 
1332
                                   'smtp')
 
1333
        self._check_default_prompt('SMTP %(user)s@%(host)s password: ',
 
1334
                                   'smtp', host='bar.org:10025')
 
1335
        self._check_default_prompt(
1628
1336
            'SMTP %(user)s@%(host)s:%(port)d password: ',
1629
1337
            'smtp', port=10025)
1630
1338
 
1631
 
    def test_ssh_password_emits_warning(self):
1632
 
        conf = config.AuthenticationConfig(_file=StringIO(
1633
 
                """
1634
 
[ssh with password]
1635
 
scheme=ssh
1636
 
host=bar.org
1637
 
user=jim
1638
 
password=jimpass
1639
 
"""))
1640
 
        entered_password = 'typed-by-hand'
1641
 
        stdout = tests.StringIOWrapper()
1642
 
        stderr = tests.StringIOWrapper()
1643
 
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1644
 
                                            stdout=stdout, stderr=stderr)
1645
 
 
1646
 
        # Since the password defined in the authentication config is ignored,
1647
 
        # the user is prompted
1648
 
        self.assertEquals(entered_password,
1649
 
                          conf.get_password('ssh', 'bar.org', user='jim'))
1650
 
        self.assertContainsRe(
1651
 
            self.get_log(),
1652
 
            'password ignored in section \[ssh with password\]')
1653
 
 
1654
 
    def test_ssh_without_password_doesnt_emit_warning(self):
1655
 
        conf = config.AuthenticationConfig(_file=StringIO(
1656
 
                """
1657
 
[ssh with password]
1658
 
scheme=ssh
1659
 
host=bar.org
1660
 
user=jim
1661
 
"""))
1662
 
        entered_password = 'typed-by-hand'
1663
 
        stdout = tests.StringIOWrapper()
1664
 
        stderr = tests.StringIOWrapper()
1665
 
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
1666
 
                                            stdout=stdout,
1667
 
                                            stderr=stderr)
1668
 
 
1669
 
        # Since the password defined in the authentication config is ignored,
1670
 
        # the user is prompted
1671
 
        self.assertEquals(entered_password,
1672
 
                          conf.get_password('ssh', 'bar.org', user='jim'))
1673
 
        # No warning shoud be emitted since there is no password. We are only
1674
 
        # providing "user".
1675
 
        self.assertNotContainsRe(
1676
 
            self.get_log(),
1677
 
            'password ignored in section \[ssh with password\]')
1678
 
 
1679
 
    def test_uses_fallback_stores(self):
1680
 
        self.overrideAttr(config, 'credential_store_registry',
1681
 
                          config.CredentialStoreRegistry())
1682
 
        store = StubCredentialStore()
1683
 
        store.add_credentials("http", "example.com", "joe", "secret")
1684
 
        config.credential_store_registry.register("stub", store, fallback=True)
1685
 
        conf = config.AuthenticationConfig(_file=StringIO())
1686
 
        creds = conf.get_credentials("http", "example.com")
1687
 
        self.assertEquals("joe", creds["user"])
1688
 
        self.assertEquals("secret", creds["password"])
1689
 
 
1690
 
 
1691
 
class StubCredentialStore(config.CredentialStore):
1692
 
 
1693
 
    def __init__(self):
1694
 
        self._username = {}
1695
 
        self._password = {}
1696
 
 
1697
 
    def add_credentials(self, scheme, host, user, password=None):
1698
 
        self._username[(scheme, host)] = user
1699
 
        self._password[(scheme, host)] = password
1700
 
 
1701
 
    def get_credentials(self, scheme, host, port=None, user=None,
1702
 
        path=None, realm=None):
1703
 
        key = (scheme, host)
1704
 
        if not key in self._username:
1705
 
            return None
1706
 
        return { "scheme": scheme, "host": host, "port": port,
1707
 
                "user": self._username[key], "password": self._password[key]}
1708
 
 
1709
 
 
1710
 
class CountingCredentialStore(config.CredentialStore):
1711
 
 
1712
 
    def __init__(self):
1713
 
        self._calls = 0
1714
 
 
1715
 
    def get_credentials(self, scheme, host, port=None, user=None,
1716
 
        path=None, realm=None):
1717
 
        self._calls += 1
1718
 
        return None
1719
 
 
1720
 
 
1721
 
class TestCredentialStoreRegistry(tests.TestCase):
1722
 
 
1723
 
    def _get_cs_registry(self):
1724
 
        return config.credential_store_registry
1725
 
 
1726
 
    def test_default_credential_store(self):
1727
 
        r = self._get_cs_registry()
1728
 
        default = r.get_credential_store(None)
1729
 
        self.assertIsInstance(default, config.PlainTextCredentialStore)
1730
 
 
1731
 
    def test_unknown_credential_store(self):
1732
 
        r = self._get_cs_registry()
1733
 
        # It's hard to imagine someone creating a credential store named
1734
 
        # 'unknown' so we use that as an never registered key.
1735
 
        self.assertRaises(KeyError, r.get_credential_store, 'unknown')
1736
 
 
1737
 
    def test_fallback_none_registered(self):
1738
 
        r = config.CredentialStoreRegistry()
1739
 
        self.assertEquals(None,
1740
 
                          r.get_fallback_credentials("http", "example.com"))
1741
 
 
1742
 
    def test_register(self):
1743
 
        r = config.CredentialStoreRegistry()
1744
 
        r.register("stub", StubCredentialStore(), fallback=False)
1745
 
        r.register("another", StubCredentialStore(), fallback=True)
1746
 
        self.assertEquals(["another", "stub"], r.keys())
1747
 
 
1748
 
    def test_register_lazy(self):
1749
 
        r = config.CredentialStoreRegistry()
1750
 
        r.register_lazy("stub", "bzrlib.tests.test_config",
1751
 
                        "StubCredentialStore", fallback=False)
1752
 
        self.assertEquals(["stub"], r.keys())
1753
 
        self.assertIsInstance(r.get_credential_store("stub"),
1754
 
                              StubCredentialStore)
1755
 
 
1756
 
    def test_is_fallback(self):
1757
 
        r = config.CredentialStoreRegistry()
1758
 
        r.register("stub1", None, fallback=False)
1759
 
        r.register("stub2", None, fallback=True)
1760
 
        self.assertEquals(False, r.is_fallback("stub1"))
1761
 
        self.assertEquals(True, r.is_fallback("stub2"))
1762
 
 
1763
 
    def test_no_fallback(self):
1764
 
        r = config.CredentialStoreRegistry()
1765
 
        store = CountingCredentialStore()
1766
 
        r.register("count", store, fallback=False)
1767
 
        self.assertEquals(None,
1768
 
                          r.get_fallback_credentials("http", "example.com"))
1769
 
        self.assertEquals(0, store._calls)
1770
 
 
1771
 
    def test_fallback_credentials(self):
1772
 
        r = config.CredentialStoreRegistry()
1773
 
        store = StubCredentialStore()
1774
 
        store.add_credentials("http", "example.com",
1775
 
                              "somebody", "geheim")
1776
 
        r.register("stub", store, fallback=True)
1777
 
        creds = r.get_fallback_credentials("http", "example.com")
1778
 
        self.assertEquals("somebody", creds["user"])
1779
 
        self.assertEquals("geheim", creds["password"])
1780
 
 
1781
 
    def test_fallback_first_wins(self):
1782
 
        r = config.CredentialStoreRegistry()
1783
 
        stub1 = StubCredentialStore()
1784
 
        stub1.add_credentials("http", "example.com",
1785
 
                              "somebody", "stub1")
1786
 
        r.register("stub1", stub1, fallback=True)
1787
 
        stub2 = StubCredentialStore()
1788
 
        stub2.add_credentials("http", "example.com",
1789
 
                              "somebody", "stub2")
1790
 
        r.register("stub2", stub1, fallback=True)
1791
 
        creds = r.get_fallback_credentials("http", "example.com")
1792
 
        self.assertEquals("somebody", creds["user"])
1793
 
        self.assertEquals("stub1", creds["password"])
1794
 
 
1795
 
 
1796
 
class TestPlainTextCredentialStore(tests.TestCase):
1797
 
 
1798
 
    def test_decode_password(self):
1799
 
        r = config.credential_store_registry
1800
 
        plain_text = r.get_credential_store()
1801
 
        decoded = plain_text.decode_password(dict(password='secret'))
1802
 
        self.assertEquals('secret', decoded)
1803
 
 
1804
1339
 
1805
1340
# FIXME: Once we have a way to declare authentication to all test servers, we
1806
1341
# can implement generic tests.