~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: 2006-06-23 18:09:10 UTC
  • mfrom: (1793.2.10 bundles)
  • Revision ID: pqm@pqm.ubuntu.com-20060623180910-c45d7b3db60625f7
Ensure that crlf bundles don't cause path to be treated as branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005, 2006 by 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
22
24
 
23
25
#import bzrlib specific imports here
24
 
from bzrlib import (
25
 
    branch,
26
 
    bzrdir,
27
 
    config,
28
 
    diff,
29
 
    errors,
30
 
    osutils,
31
 
    mail_client,
32
 
    ui,
33
 
    urlutils,
34
 
    tests,
35
 
    trace,
36
 
    transport,
37
 
    )
38
 
from bzrlib.util.configobj import configobj
 
26
import bzrlib.config as config
 
27
from bzrlib.branch import Branch
 
28
from bzrlib.bzrdir import BzrDir
 
29
import bzrlib.errors as errors
 
30
from bzrlib.tests import TestCase, TestCaseInTempDir
39
31
 
40
32
 
41
33
sample_long_alias="log -r-15..-1 --line"
42
 
sample_config_text = u"""
43
 
[DEFAULT]
44
 
email=Erik B\u00e5gfors <erik@bagfors.nu>
45
 
editor=vim
46
 
change_editor=vimdiff -of @new_path @old_path
47
 
gpg_signing_command=gnome-gpg
48
 
log_format=short
49
 
user_global_option=something
50
 
[ALIASES]
51
 
h=help
52
 
ll=""" + sample_long_alias + "\n"
53
 
 
54
 
 
55
 
sample_always_signatures = """
56
 
[DEFAULT]
57
 
check_signatures=ignore
58
 
create_signatures=always
59
 
"""
60
 
 
61
 
sample_ignore_signatures = """
62
 
[DEFAULT]
63
 
check_signatures=require
64
 
create_signatures=never
65
 
"""
66
 
 
67
 
sample_maybe_signatures = """
68
 
[DEFAULT]
69
 
check_signatures=ignore
70
 
create_signatures=when-required
71
 
"""
72
 
 
73
 
sample_branches_text = """
74
 
[http://www.example.com]
75
 
# Top level policy
76
 
email=Robert Collins <robertc@example.org>
77
 
normal_option = normal
78
 
appendpath_option = append
79
 
appendpath_option:policy = appendpath
80
 
norecurse_option = norecurse
81
 
norecurse_option:policy = norecurse
82
 
[http://www.example.com/ignoreparent]
83
 
# different project: ignore parent dir config
84
 
ignore_parents=true
85
 
[http://www.example.com/norecurse]
86
 
# configuration items that only apply to this dir
87
 
recurse=false
88
 
normal_option = norecurse
89
 
[http://www.example.com/dir]
90
 
appendpath_option = normal
91
 
[/b/]
92
 
check_signatures=require
93
 
# test trailing / matching with no children
94
 
[/a/]
95
 
check_signatures=check-available
96
 
gpg_signing_command=false
97
 
user_local_option=local
98
 
# test trailing / matching
99
 
[/a/*]
100
 
#subdirs will match but not the parent
101
 
[/a/c]
102
 
check_signatures=ignore
103
 
post_commit=bzrlib.tests.test_config.post_commit
104
 
#testing explicit beats globs
105
 
"""
 
34
sample_config_text = ("[DEFAULT]\n"
 
35
                      u"email=Erik B\u00e5gfors <erik@bagfors.nu>\n"
 
36
                      "editor=vim\n"
 
37
                      "gpg_signing_command=gnome-gpg\n"
 
38
                      "log_format=short\n"
 
39
                      "user_global_option=something\n"
 
40
                      "[ALIASES]\n"
 
41
                      "h=help\n"
 
42
                      "ll=" + sample_long_alias + "\n")
 
43
 
 
44
 
 
45
sample_always_signatures = ("[DEFAULT]\n"
 
46
                            "check_signatures=ignore\n"
 
47
                            "create_signatures=always")
 
48
 
 
49
 
 
50
sample_ignore_signatures = ("[DEFAULT]\n"
 
51
                            "check_signatures=require\n"
 
52
                            "create_signatures=never")
 
53
 
 
54
 
 
55
sample_maybe_signatures = ("[DEFAULT]\n"
 
56
                            "check_signatures=ignore\n"
 
57
                            "create_signatures=when-required")
 
58
 
 
59
 
 
60
sample_branches_text = ("[http://www.example.com]\n"
 
61
                        "# Top level policy\n"
 
62
                        "email=Robert Collins <robertc@example.org>\n"
 
63
                        "[http://www.example.com/useglobal]\n"
 
64
                        "# different project, forces global lookup\n"
 
65
                        "recurse=false\n"
 
66
                        "[/b/]\n"
 
67
                        "check_signatures=require\n"
 
68
                        "# test trailing / matching with no children\n"
 
69
                        "[/a/]\n"
 
70
                        "check_signatures=check-available\n"
 
71
                        "gpg_signing_command=false\n"
 
72
                        "user_local_option=local\n"
 
73
                        "# test trailing / matching\n"
 
74
                        "[/a/*]\n"
 
75
                        "#subdirs will match but not the parent\n"
 
76
                        "recurse=False\n"
 
77
                        "[/a/c]\n"
 
78
                        "check_signatures=ignore\n"
 
79
                        "post_commit=bzrlib.tests.test_config.post_commit\n"
 
80
                        "#testing explicit beats globs\n")
 
81
 
106
82
 
107
83
 
108
84
class InstrumentedConfigObj(object):
122
98
    def __setitem__(self, key, value):
123
99
        self._calls.append(('__setitem__', key, value))
124
100
 
125
 
    def __delitem__(self, key):
126
 
        self._calls.append(('__delitem__', key))
127
 
 
128
 
    def keys(self):
129
 
        self._calls.append(('keys',))
130
 
        return []
131
 
 
132
101
    def write(self, arg):
133
102
        self._calls.append(('write',))
134
103
 
135
 
    def as_bool(self, value):
136
 
        self._calls.append(('as_bool', value))
137
 
        return False
138
 
 
139
 
    def get_value(self, section, name):
140
 
        self._calls.append(('get_value', section, name))
141
 
        return None
142
 
 
143
104
 
144
105
class FakeBranch(object):
145
106
 
148
109
            self.base = "http://example.com/branches/demo"
149
110
        else:
150
111
            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')
 
112
        self.control_files = FakeControlFiles(user_id=user_id)
156
113
 
157
114
    def lock_write(self):
158
115
        pass
161
118
        pass
162
119
 
163
120
 
164
 
class FakeControlFilesAndTransport(object):
 
121
class FakeControlFiles(object):
165
122
 
166
123
    def __init__(self, user_id=None):
 
124
        self.email = user_id
167
125
        self.files = {}
168
 
        if user_id:
169
 
            self.files['email'] = user_id
170
 
        self._transport = self
171
126
 
172
127
    def get_utf8(self, filename):
173
 
        # from LockableFiles
174
 
        raise AssertionError("get_utf8 should no longer be used")
 
128
        if filename != 'email':
 
129
            raise NotImplementedError
 
130
        if self.email is not None:
 
131
            return StringIO(self.email)
 
132
        raise errors.NoSuchFile(filename)
175
133
 
176
134
    def get(self, filename):
177
 
        # from Transport
178
135
        try:
179
136
            return StringIO(self.files[filename])
180
137
        except KeyError:
181
138
            raise errors.NoSuchFile(filename)
182
139
 
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
140
    def put(self, filename, fileobj):
191
141
        self.files[filename] = fileobj.read()
192
142
 
193
 
    def put_file(self, filename, fileobj):
194
 
        return self.put(filename, fileobj)
195
 
 
196
143
 
197
144
class InstrumentedConfig(config.Config):
198
145
    """An instrumented config that supplies stubs for template methods."""
199
 
 
 
146
    
200
147
    def __init__(self):
201
148
        super(InstrumentedConfig, self).__init__()
202
149
        self._calls = []
210
157
        self._calls.append('_get_signature_checking')
211
158
        return self._signatures
212
159
 
213
 
    def _get_change_editor(self):
214
 
        self._calls.append('_get_change_editor')
215
 
        return 'vimdiff -fo @new_path @old_path'
216
 
 
217
160
 
218
161
bool_config = """[DEFAULT]
219
162
active = true
222
165
active = True
223
166
nonactive = False
224
167
"""
225
 
 
226
 
 
227
 
class TestConfigObj(tests.TestCase):
228
 
 
 
168
class TestConfigObj(TestCase):
229
169
    def test_get_bool(self):
230
 
        co = config.ConfigObj(StringIO(bool_config))
 
170
        from bzrlib.config import ConfigObj
 
171
        co = ConfigObj(StringIO(bool_config))
231
172
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
232
173
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
233
174
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
234
175
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
235
176
 
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
 
 
249
 
erroneous_config = """[section] # line 1
250
 
good=good # line 2
251
 
[section] # line 3
252
 
whocares=notme # line 4
253
 
"""
254
 
 
255
 
 
256
 
class TestConfigObjErrors(tests.TestCase):
257
 
 
258
 
    def test_duplicate_section_name_error_line(self):
259
 
        try:
260
 
            co = configobj.ConfigObj(StringIO(erroneous_config),
261
 
                                     raise_errors=True)
262
 
        except config.configobj.DuplicateError, e:
263
 
            self.assertEqual(3, e.line_number)
264
 
        else:
265
 
            self.fail('Error in config file not detected')
266
 
 
267
 
 
268
 
class TestConfig(tests.TestCase):
 
177
 
 
178
class TestConfig(TestCase):
269
179
 
270
180
    def test_constructs(self):
271
181
        config.Config()
272
 
 
 
182
 
273
183
    def test_no_default_editor(self):
274
184
        self.assertRaises(NotImplementedError, config.Config().get_editor)
275
185
 
320
230
        my_config = config.Config()
321
231
        self.assertEqual('long', my_config.log_format())
322
232
 
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
 
 
332
 
class TestConfigPath(tests.TestCase):
 
233
 
 
234
class TestConfigPath(TestCase):
333
235
 
334
236
    def setUp(self):
335
237
        super(TestConfigPath, self).setUp()
 
238
        self.old_home = os.environ.get('HOME', None)
 
239
        self.old_appdata = os.environ.get('APPDATA', None)
336
240
        os.environ['HOME'] = '/home/bogus'
337
 
        os.environ['XDG_CACHE_DIR'] = ''
338
 
        if sys.platform == 'win32':
339
 
            os.environ['BZR_HOME'] = \
340
 
                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'
 
241
        os.environ['APPDATA'] = \
 
242
            r'C:\Documents and Settings\bogus\Application Data'
345
243
 
 
244
    def tearDown(self):
 
245
        if self.old_home is None:
 
246
            del os.environ['HOME']
 
247
        else:
 
248
            os.environ['HOME'] = self.old_home
 
249
        if self.old_appdata is None:
 
250
            del os.environ['APPDATA']
 
251
        else:
 
252
            os.environ['APPDATA'] = self.old_appdata
 
253
        super(TestConfigPath, self).tearDown()
 
254
    
346
255
    def test_config_dir(self):
347
 
        self.assertEqual(config.config_dir(), self.bzr_home)
 
256
        if sys.platform == 'win32':
 
257
            self.assertEqual(config.config_dir(), 
 
258
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0')
 
259
        else:
 
260
            self.assertEqual(config.config_dir(), '/home/bogus/.bazaar')
348
261
 
349
262
    def test_config_filename(self):
350
 
        self.assertEqual(config.config_filename(),
351
 
                         self.bzr_home + '/bazaar.conf')
 
263
        if sys.platform == 'win32':
 
264
            self.assertEqual(config.config_filename(), 
 
265
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/bazaar.conf')
 
266
        else:
 
267
            self.assertEqual(config.config_filename(),
 
268
                             '/home/bogus/.bazaar/bazaar.conf')
352
269
 
353
270
    def test_branches_config_filename(self):
354
 
        self.assertEqual(config.branches_config_filename(),
355
 
                         self.bzr_home + '/branches.conf')
 
271
        if sys.platform == 'win32':
 
272
            self.assertEqual(config.branches_config_filename(), 
 
273
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/branches.conf')
 
274
        else:
 
275
            self.assertEqual(config.branches_config_filename(),
 
276
                             '/home/bogus/.bazaar/branches.conf')
356
277
 
357
278
    def test_locations_config_filename(self):
358
 
        self.assertEqual(config.locations_config_filename(),
359
 
                         self.bzr_home + '/locations.conf')
360
 
 
361
 
    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
 
 
369
 
 
370
 
class TestIniConfig(tests.TestCase):
371
 
 
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):
 
279
        if sys.platform == 'win32':
 
280
            self.assertEqual(config.locations_config_filename(), 
 
281
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0/locations.conf')
 
282
        else:
 
283
            self.assertEqual(config.locations_config_filename(),
 
284
                             '/home/bogus/.bazaar/locations.conf')
 
285
 
 
286
class TestIniConfig(TestCase):
379
287
 
380
288
    def test_contructs(self):
381
289
        my_config = config.IniBasedConfig("nothing")
385
293
        my_config = config.IniBasedConfig(None)
386
294
        self.failUnless(
387
295
            isinstance(my_config._get_parser(file=config_file),
388
 
                        configobj.ConfigObj))
 
296
                        ConfigObj))
389
297
 
390
298
    def test_cached(self):
391
299
        config_file = StringIO(sample_config_text.encode('utf-8'))
394
302
        self.failUnless(my_config._get_parser() is parser)
395
303
 
396
304
 
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
 
class TestGetConfig(tests.TestCase):
 
305
class TestGetConfig(TestCase):
452
306
 
453
307
    def test_constructs(self):
454
308
        my_config = config.GlobalConfig()
455
309
 
456
310
    def test_calls_read_filenames(self):
457
 
        # replace the class that is constructed, to check its parameters
 
311
        # replace the class that is constructured, to check its parameters
458
312
        oldparserclass = config.ConfigObj
459
313
        config.ConfigObj = InstrumentedConfigObj
460
314
        my_config = config.GlobalConfig()
467
321
                                          'utf-8')])
468
322
 
469
323
 
470
 
class TestBranchConfig(tests.TestCaseWithTransport):
 
324
class TestBranchConfig(TestCaseInTempDir):
471
325
 
472
326
    def test_constructs(self):
473
327
        branch = FakeBranch()
483
337
 
484
338
    def test_get_config(self):
485
339
        """The Branch.get_config method works properly"""
486
 
        b = bzrdir.BzrDir.create_standalone_workingtree('.').branch
 
340
        b = BzrDir.create_standalone_workingtree('.').branch
487
341
        my_config = b.get_config()
488
342
        self.assertIs(my_config.get_user_option('wacky'), None)
489
343
        my_config.set_user_option('wacky', 'unlikely')
490
344
        self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
491
345
 
492
346
        # Ensure we get the same thing if we start again
493
 
        b2 = branch.Branch.open('.')
 
347
        b2 = Branch.open('.')
494
348
        my_config2 = b2.get_config()
495
349
        self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
496
350
 
497
 
    def test_has_explicit_nickname(self):
498
 
        b = self.make_branch('.')
499
 
        self.assertFalse(b.get_config().has_explicit_nickname())
500
 
        b.nick = 'foo'
501
 
        self.assertTrue(b.get_config().has_explicit_nickname())
502
 
 
503
 
    def test_config_url(self):
504
 
        """The Branch.get_config will use section that uses a local url"""
505
 
        branch = self.make_branch('branch')
506
 
        self.assertEqual('branch', branch.nick)
507
 
 
508
 
        locations = config.locations_config_filename()
509
 
        config.ensure_config_dir_exists()
510
 
        local_url = urlutils.local_path_to_url('branch')
511
 
        open(locations, 'wb').write('[%s]\nnickname = foobar'
512
 
                                    % (local_url,))
513
 
        self.assertEqual('foobar', branch.nick)
514
 
 
515
 
    def test_config_local_path(self):
516
 
        """The Branch.get_config will use a local system path"""
517
 
        branch = self.make_branch('branch')
518
 
        self.assertEqual('branch', branch.nick)
519
 
 
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'),))
524
 
        self.assertEqual('barry', branch.nick)
525
 
 
526
 
    def test_config_creates_local(self):
527
 
        """Creating a new entry in config uses a local path."""
528
 
        branch = self.make_branch('branch', format='knit')
529
 
        branch.set_push_location('http://foobar')
530
 
        locations = config.locations_config_filename()
531
 
        local_path = osutils.getcwd().encode('utf8')
532
 
        # Surprisingly ConfigObj doesn't create a trailing newline
533
 
        self.check_file_contents(locations,
534
 
                                 '[%s/branch]\n'
535
 
                                 'push_location = http://foobar\n'
536
 
                                 'push_location:policy = norecurse\n'
537
 
                                 % (local_path,))
538
 
 
539
 
    def test_autonick_urlencoded(self):
540
 
        b = self.make_branch('!repo')
541
 
        self.assertEqual('!repo', b.get_config().get_nickname())
542
 
 
543
 
    def test_warn_if_masked(self):
544
 
        _warning = trace.warning
545
 
        warnings = []
546
 
        def warning(*args):
547
 
            warnings.append(args[0] % args[1:])
548
 
 
549
 
        def set_option(store, warn_masked=True):
550
 
            warnings[:] = []
551
 
            conf.set_user_option('example_option', repr(store), store=store,
552
 
                                 warn_masked=warn_masked)
553
 
        def assertWarning(warning):
554
 
            if warning is None:
555
 
                self.assertEqual(0, len(warnings))
556
 
            else:
557
 
                self.assertEqual(1, len(warnings))
558
 
                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):
 
351
 
 
352
class TestGlobalConfigItems(TestCase):
582
353
 
583
354
    def test_user_id(self):
584
355
        config_file = StringIO(sample_config_text.encode('utf-8'))
658
429
        my_config = self._get_sample_config()
659
430
        self.assertEqual("something",
660
431
                         my_config.get_user_option('user_global_option'))
661
 
 
 
432
        
662
433
    def test_post_commit_default(self):
663
434
        my_config = self._get_sample_config()
664
435
        self.assertEqual(None, my_config.post_commit())
671
442
        my_config = self._get_sample_config()
672
443
        self.assertEqual('help', my_config.get_alias('h'))
673
444
 
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
445
    def test_get_no_alias(self):
683
446
        my_config = self._get_sample_config()
684
447
        self.assertEqual(None, my_config.get_alias('foo'))
687
450
        my_config = self._get_sample_config()
688
451
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
689
452
 
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
 
 
725
 
class TestLocationConfig(tests.TestCaseInTempDir):
 
453
 
 
454
class TestLocationConfig(TestCaseInTempDir):
726
455
 
727
456
    def test_constructs(self):
728
457
        my_config = config.LocationConfig('http://example.com')
732
461
        # This is testing the correct file names are provided.
733
462
        # TODO: consolidate with the test for GlobalConfigs filename checks.
734
463
        #
735
 
        # replace the class that is constructed, to check its parameters
 
464
        # replace the class that is constructured, to check its parameters
736
465
        oldparserclass = config.ConfigObj
737
466
        config.ConfigObj = InstrumentedConfigObj
738
467
        try:
744
473
        self.assertEqual(parser._calls,
745
474
                         [('__init__', config.locations_config_filename(),
746
475
                           'utf-8')])
747
 
        config.ensure_config_dir_exists()
748
 
        #os.mkdir(config.config_dir())
 
476
        os.mkdir(config.config_dir())
749
477
        f = file(config.branches_config_filename(), 'wb')
750
478
        f.write('')
751
479
        f.close()
763
491
        self.failUnless(isinstance(global_config, config.GlobalConfig))
764
492
        self.failUnless(global_config is my_config._get_global_config())
765
493
 
766
 
    def test__get_matching_sections_no_match(self):
 
494
    def test__get_section_no_match(self):
767
495
        self.get_branch_config('/')
768
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
769
 
 
770
 
    def test__get_matching_sections_exact(self):
 
496
        self.assertEqual(None, self.my_location_config._get_section())
 
497
        
 
498
    def test__get_section_exact(self):
771
499
        self.get_branch_config('http://www.example.com')
772
 
        self.assertEqual([('http://www.example.com', '')],
773
 
                         self.my_location_config._get_matching_sections())
774
 
 
775
 
    def test__get_matching_sections_suffix_does_not(self):
 
500
        self.assertEqual('http://www.example.com',
 
501
                         self.my_location_config._get_section())
 
502
   
 
503
    def test__get_section_suffix_does_not(self):
776
504
        self.get_branch_config('http://www.example.com-com')
777
 
        self.assertEqual([], self.my_location_config._get_matching_sections())
 
505
        self.assertEqual(None, self.my_location_config._get_section())
778
506
 
779
 
    def test__get_matching_sections_subdir_recursive(self):
 
507
    def test__get_section_subdir_recursive(self):
780
508
        self.get_branch_config('http://www.example.com/com')
781
 
        self.assertEqual([('http://www.example.com', 'com')],
782
 
                         self.my_location_config._get_matching_sections())
783
 
 
784
 
    def test__get_matching_sections_ignoreparent(self):
785
 
        self.get_branch_config('http://www.example.com/ignoreparent')
786
 
        self.assertEqual([('http://www.example.com/ignoreparent', '')],
787
 
                         self.my_location_config._get_matching_sections())
788
 
 
789
 
    def test__get_matching_sections_ignoreparent_subdir(self):
 
509
        self.assertEqual('http://www.example.com',
 
510
                         self.my_location_config._get_section())
 
511
 
 
512
    def test__get_section_subdir_matches(self):
 
513
        self.get_branch_config('http://www.example.com/useglobal')
 
514
        self.assertEqual('http://www.example.com/useglobal',
 
515
                         self.my_location_config._get_section())
 
516
 
 
517
    def test__get_section_subdir_nonrecursive(self):
790
518
        self.get_branch_config(
791
 
            'http://www.example.com/ignoreparent/childbranch')
792
 
        self.assertEqual([('http://www.example.com/ignoreparent',
793
 
                           'childbranch')],
794
 
                         self.my_location_config._get_matching_sections())
 
519
            'http://www.example.com/useglobal/childbranch')
 
520
        self.assertEqual('http://www.example.com',
 
521
                         self.my_location_config._get_section())
795
522
 
796
 
    def test__get_matching_sections_subdir_trailing_slash(self):
 
523
    def test__get_section_subdir_trailing_slash(self):
797
524
        self.get_branch_config('/b')
798
 
        self.assertEqual([('/b/', '')],
799
 
                         self.my_location_config._get_matching_sections())
 
525
        self.assertEqual('/b/', self.my_location_config._get_section())
800
526
 
801
 
    def test__get_matching_sections_subdir_child(self):
 
527
    def test__get_section_subdir_child(self):
802
528
        self.get_branch_config('/a/foo')
803
 
        self.assertEqual([('/a/*', ''), ('/a/', 'foo')],
804
 
                         self.my_location_config._get_matching_sections())
 
529
        self.assertEqual('/a/*', self.my_location_config._get_section())
805
530
 
806
 
    def test__get_matching_sections_subdir_child_child(self):
 
531
    def test__get_section_subdir_child_child(self):
807
532
        self.get_branch_config('/a/foo/bar')
808
 
        self.assertEqual([('/a/*', 'bar'), ('/a/', 'foo/bar')],
809
 
                         self.my_location_config._get_matching_sections())
 
533
        self.assertEqual('/a/', self.my_location_config._get_section())
810
534
 
811
 
    def test__get_matching_sections_trailing_slash_with_children(self):
 
535
    def test__get_section_trailing_slash_with_children(self):
812
536
        self.get_branch_config('/a/')
813
 
        self.assertEqual([('/a/', '')],
814
 
                         self.my_location_config._get_matching_sections())
 
537
        self.assertEqual('/a/', self.my_location_config._get_section())
815
538
 
816
 
    def test__get_matching_sections_explicit_over_glob(self):
817
 
        # XXX: 2006-09-08 jamesh
818
 
        # This test only passes because ord('c') > ord('*').  If there
819
 
        # was a config section for '/a/?', it would get precedence
820
 
        # over '/a/c'.
 
539
    def test__get_section_explicit_over_glob(self):
821
540
        self.get_branch_config('/a/c')
822
 
        self.assertEqual([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')],
823
 
                         self.my_location_config._get_matching_sections())
824
 
 
825
 
    def test__get_option_policy_normal(self):
826
 
        self.get_branch_config('http://www.example.com')
827
 
        self.assertEqual(
828
 
            self.my_location_config._get_config_policy(
829
 
            'http://www.example.com', 'normal_option'),
830
 
            config.POLICY_NONE)
831
 
 
832
 
    def test__get_option_policy_norecurse(self):
833
 
        self.get_branch_config('http://www.example.com')
834
 
        self.assertEqual(
835
 
            self.my_location_config._get_option_policy(
836
 
            'http://www.example.com', 'norecurse_option'),
837
 
            config.POLICY_NORECURSE)
838
 
        # Test old recurse=False setting:
839
 
        self.assertEqual(
840
 
            self.my_location_config._get_option_policy(
841
 
            'http://www.example.com/norecurse', 'normal_option'),
842
 
            config.POLICY_NORECURSE)
843
 
 
844
 
    def test__get_option_policy_normal(self):
845
 
        self.get_branch_config('http://www.example.com')
846
 
        self.assertEqual(
847
 
            self.my_location_config._get_option_policy(
848
 
            'http://www.example.com', 'appendpath_option'),
849
 
            config.POLICY_APPENDPATH)
 
541
        self.assertEqual('/a/c', self.my_location_config._get_section())
 
542
 
850
543
 
851
544
    def test_location_without_username(self):
852
 
        self.get_branch_config('http://www.example.com/ignoreparent')
 
545
        self.get_branch_config('http://www.example.com/useglobal')
853
546
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
854
547
                         self.my_config.username())
855
548
 
876
569
        self.get_branch_config('/a/c')
877
570
        self.assertEqual(config.CHECK_NEVER,
878
571
                         self.my_config.signature_checking())
879
 
 
 
572
        
880
573
    def test_signatures_when_available(self):
881
574
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
882
575
        self.assertEqual(config.CHECK_IF_POSSIBLE,
883
576
                         self.my_config.signature_checking())
884
 
 
 
577
        
885
578
    def test_signatures_always(self):
886
579
        self.get_branch_config('/b')
887
580
        self.assertEqual(config.CHECK_ALWAYS,
888
581
                         self.my_config.signature_checking())
889
 
 
 
582
        
890
583
    def test_gpg_signing_command(self):
891
584
        self.get_branch_config('/b')
892
585
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
904
597
        self.get_branch_config('/a')
905
598
        self.assertEqual('local',
906
599
                         self.my_config.get_user_option('user_local_option'))
907
 
 
908
 
    def test_get_user_option_appendpath(self):
909
 
        # returned as is for the base path:
910
 
        self.get_branch_config('http://www.example.com')
911
 
        self.assertEqual('append',
912
 
                         self.my_config.get_user_option('appendpath_option'))
913
 
        # Extra path components get appended:
914
 
        self.get_branch_config('http://www.example.com/a/b/c')
915
 
        self.assertEqual('append/a/b/c',
916
 
                         self.my_config.get_user_option('appendpath_option'))
917
 
        # Overriden for http://www.example.com/dir, where it is a
918
 
        # normal option:
919
 
        self.get_branch_config('http://www.example.com/dir/a/b/c')
920
 
        self.assertEqual('normal',
921
 
                         self.my_config.get_user_option('appendpath_option'))
922
 
 
923
 
    def test_get_user_option_norecurse(self):
924
 
        self.get_branch_config('http://www.example.com')
925
 
        self.assertEqual('norecurse',
926
 
                         self.my_config.get_user_option('norecurse_option'))
927
 
        self.get_branch_config('http://www.example.com/dir')
928
 
        self.assertEqual(None,
929
 
                         self.my_config.get_user_option('norecurse_option'))
930
 
        # http://www.example.com/norecurse is a recurse=False section
931
 
        # that redefines normal_option.  Subdirectories do not pick up
932
 
        # this redefinition.
933
 
        self.get_branch_config('http://www.example.com/norecurse')
934
 
        self.assertEqual('norecurse',
935
 
                         self.my_config.get_user_option('normal_option'))
936
 
        self.get_branch_config('http://www.example.com/norecurse/subdir')
937
 
        self.assertEqual('normal',
938
 
                         self.my_config.get_user_option('normal_option'))
939
 
 
940
 
    def test_set_user_option_norecurse(self):
941
 
        self.get_branch_config('http://www.example.com')
942
 
        self.my_config.set_user_option('foo', 'bar',
943
 
                                       store=config.STORE_LOCATION_NORECURSE)
944
 
        self.assertEqual(
945
 
            self.my_location_config._get_option_policy(
946
 
            'http://www.example.com', 'foo'),
947
 
            config.POLICY_NORECURSE)
948
 
 
949
 
    def test_set_user_option_appendpath(self):
950
 
        self.get_branch_config('http://www.example.com')
951
 
        self.my_config.set_user_option('foo', 'bar',
952
 
                                       store=config.STORE_LOCATION_APPENDPATH)
953
 
        self.assertEqual(
954
 
            self.my_location_config._get_option_policy(
955
 
            'http://www.example.com', 'foo'),
956
 
            config.POLICY_APPENDPATH)
957
 
 
958
 
    def test_set_user_option_change_policy(self):
959
 
        self.get_branch_config('http://www.example.com')
960
 
        self.my_config.set_user_option('norecurse_option', 'normal',
961
 
                                       store=config.STORE_LOCATION)
962
 
        self.assertEqual(
963
 
            self.my_location_config._get_option_policy(
964
 
            'http://www.example.com', 'norecurse_option'),
965
 
            config.POLICY_NONE)
966
 
 
967
 
    def test_set_user_option_recurse_false_section(self):
968
 
        # The following section has recurse=False set.  The test is to
969
 
        # make sure that a normal option can be added to the section,
970
 
        # converting recurse=False to the norecurse policy.
971
 
        self.get_branch_config('http://www.example.com/norecurse')
972
 
        self.callDeprecated(['The recurse option is deprecated as of 0.14.  '
973
 
                             'The section "http://www.example.com/norecurse" '
974
 
                             'has been converted to use policies.'],
975
 
                            self.my_config.set_user_option,
976
 
                            'foo', 'bar', store=config.STORE_LOCATION)
977
 
        self.assertEqual(
978
 
            self.my_location_config._get_option_policy(
979
 
            'http://www.example.com/norecurse', 'foo'),
980
 
            config.POLICY_NONE)
981
 
        # The previously existing option is still norecurse:
982
 
        self.assertEqual(
983
 
            self.my_location_config._get_option_policy(
984
 
            'http://www.example.com/norecurse', 'normal_option'),
985
 
            config.POLICY_NORECURSE)
986
 
 
 
600
        
987
601
    def test_post_commit_default(self):
988
602
        self.get_branch_config('/a/c')
989
603
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1016
630
 
1017
631
        os.mkdir = checked_mkdir
1018
632
        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)
 
633
            self.my_config.set_user_option('foo', 'bar', local=True)
1024
634
        finally:
1025
635
            os.mkdir = real_mkdir
1026
636
 
1030
640
                          ('__setitem__', '/a/c', {}),
1031
641
                          ('__getitem__', '/a/c'),
1032
642
                          ('__setitem__', 'foo', 'bar'),
1033
 
                          ('__getitem__', '/a/c'),
1034
 
                          ('as_bool', 'recurse'),
1035
 
                          ('__getitem__', '/a/c'),
1036
 
                          ('__delitem__', 'recurse'),
1037
 
                          ('__getitem__', '/a/c'),
1038
 
                          ('keys',),
1039
 
                          ('__getitem__', '/a/c'),
1040
 
                          ('__contains__', 'foo:policy'),
1041
643
                          ('write',)],
1042
644
                         record._calls[1:])
1043
645
 
1046
648
        self.assertIs(self.my_config.get_user_option('foo'), None)
1047
649
        self.my_config.set_user_option('foo', 'bar')
1048
650
        self.assertEqual(
1049
 
            self.my_config.branch.control_files.files['branch.conf'].strip(),
 
651
            self.my_config.branch.control_files.files['branch.conf'], 
1050
652
            'foo = bar')
1051
653
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
1052
 
        self.my_config.set_user_option('foo', 'baz',
1053
 
                                       store=config.STORE_LOCATION)
 
654
        self.my_config.set_user_option('foo', 'baz', local=True)
1054
655
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1055
656
        self.my_config.set_user_option('foo', 'qux')
1056
657
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1057
 
 
1058
 
    def test_get_bzr_remote_path(self):
1059
 
        my_config = config.LocationConfig('/a/c')
1060
 
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1061
 
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
1062
 
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
1063
 
        os.environ['BZR_REMOTE_PATH'] = '/environ-bzr'
1064
 
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
1065
 
 
 
658
        
1066
659
 
1067
660
precedence_global = 'option = global'
1068
661
precedence_branch = 'option = branch'
1075
668
"""
1076
669
 
1077
670
 
1078
 
class TestBranchConfigItems(tests.TestCaseInTempDir):
 
671
class TestBranchConfigItems(TestCaseInTempDir):
1079
672
 
1080
 
    def get_branch_config(self, global_config=None, location=None,
 
673
    def get_branch_config(self, global_config=None, location=None, 
1081
674
                          location_config=None, branch_data_config=None):
1082
675
        my_config = config.BranchConfig(FakeBranch(location))
1083
676
        if global_config is not None:
1097
690
        my_config = config.BranchConfig(branch)
1098
691
        self.assertEqual("Robert Collins <robertc@example.net>",
1099
692
                         my_config.username())
1100
 
        my_config.branch.control_files.files['email'] = "John"
1101
 
        my_config.set_user_option('email',
 
693
        branch.control_files.email = "John"
 
694
        my_config.set_user_option('email', 
1102
695
                                  "Robert Collins <robertc@example.org>")
1103
696
        self.assertEqual("John", my_config.username())
1104
 
        del my_config.branch.control_files.files['email']
 
697
        branch.control_files.email = None
1105
698
        self.assertEqual("Robert Collins <robertc@example.org>",
1106
699
                         my_config.username())
1107
700
 
1108
701
    def test_not_set_in_branch(self):
1109
702
        my_config = self.get_branch_config(sample_config_text)
 
703
        my_config.branch.control_files.email = None
1110
704
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1111
705
                         my_config._get_user_id())
1112
 
        my_config.branch.control_files.files['email'] = "John"
 
706
        my_config.branch.control_files.email = "John"
1113
707
        self.assertEqual("John", my_config._get_user_id())
1114
708
 
1115
 
    def test_BZR_EMAIL_OVERRIDES(self):
1116
 
        os.environ['BZR_EMAIL'] = "Robert Collins <robertc@example.org>"
 
709
    def test_BZREMAIL_OVERRIDES(self):
 
710
        os.environ['BZREMAIL'] = "Robert Collins <robertc@example.org>"
1117
711
        branch = FakeBranch()
1118
712
        my_config = config.BranchConfig(branch)
1119
713
        self.assertEqual("Robert Collins <robertc@example.org>",
1120
714
                         my_config.username())
1121
 
 
 
715
    
1122
716
    def test_signatures_forced(self):
1123
717
        my_config = self.get_branch_config(
1124
718
            global_config=sample_always_signatures)
1161
755
        # post-commit is ignored when bresent in branch data
1162
756
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1163
757
                         my_config.post_commit())
1164
 
        my_config.set_user_option('post_commit', 'rmtree_root',
1165
 
                                  store=config.STORE_LOCATION)
 
758
        my_config.set_user_option('post_commit', 'rmtree_root', local=True)
1166
759
        self.assertEqual('rmtree_root', my_config.post_commit())
1167
760
 
1168
761
    def test_config_precedence(self):
1169
762
        my_config = self.get_branch_config(global_config=precedence_global)
1170
763
        self.assertEqual(my_config.get_user_option('option'), 'global')
1171
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
764
        my_config = self.get_branch_config(global_config=precedence_global, 
1172
765
                                      branch_data_config=precedence_branch)
1173
766
        self.assertEqual(my_config.get_user_option('option'), 'branch')
1174
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
767
        my_config = self.get_branch_config(global_config=precedence_global, 
1175
768
                                      branch_data_config=precedence_branch,
1176
769
                                      location_config=precedence_location)
1177
770
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
1178
 
        my_config = self.get_branch_config(global_config=precedence_global,
 
771
        my_config = self.get_branch_config(global_config=precedence_global, 
1179
772
                                      branch_data_config=precedence_branch,
1180
773
                                      location_config=precedence_location,
1181
774
                                      location='http://example.com/specific')
1182
775
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1183
776
 
1184
 
    def test_get_mail_client(self):
1185
 
        config = self.get_branch_config()
1186
 
        client = config.get_mail_client()
1187
 
        self.assertIsInstance(client, mail_client.DefaultMail)
1188
 
 
1189
 
        # Specific clients
1190
 
        config.set_user_option('mail_client', 'evolution')
1191
 
        client = config.get_mail_client()
1192
 
        self.assertIsInstance(client, mail_client.Evolution)
1193
 
 
1194
 
        config.set_user_option('mail_client', 'kmail')
1195
 
        client = config.get_mail_client()
1196
 
        self.assertIsInstance(client, mail_client.KMail)
1197
 
 
1198
 
        config.set_user_option('mail_client', 'mutt')
1199
 
        client = config.get_mail_client()
1200
 
        self.assertIsInstance(client, mail_client.Mutt)
1201
 
 
1202
 
        config.set_user_option('mail_client', 'thunderbird')
1203
 
        client = config.get_mail_client()
1204
 
        self.assertIsInstance(client, mail_client.Thunderbird)
1205
 
 
1206
 
        # Generic options
1207
 
        config.set_user_option('mail_client', 'default')
1208
 
        client = config.get_mail_client()
1209
 
        self.assertIsInstance(client, mail_client.DefaultMail)
1210
 
 
1211
 
        config.set_user_option('mail_client', 'editor')
1212
 
        client = config.get_mail_client()
1213
 
        self.assertIsInstance(client, mail_client.Editor)
1214
 
 
1215
 
        config.set_user_option('mail_client', 'mapi')
1216
 
        client = config.get_mail_client()
1217
 
        self.assertIsInstance(client, mail_client.MAPIClient)
1218
 
 
1219
 
        config.set_user_option('mail_client', 'xdg-email')
1220
 
        client = config.get_mail_client()
1221
 
        self.assertIsInstance(client, mail_client.XDGEmail)
1222
 
 
1223
 
        config.set_user_option('mail_client', 'firebird')
1224
 
        self.assertRaises(errors.UnknownMailClient, config.get_mail_client)
1225
 
 
1226
 
 
1227
 
class TestMailAddressExtraction(tests.TestCase):
 
777
 
 
778
class TestMailAddressExtraction(TestCase):
1228
779
 
1229
780
    def test_extract_email_address(self):
1230
781
        self.assertEqual('jane@test.com',
1231
782
                         config.extract_email_address('Jane <jane@test.com>'))
1232
 
        self.assertRaises(errors.NoEmailInUsername,
 
783
        self.assertRaises(errors.BzrError,
1233
784
                          config.extract_email_address, 'Jane Tester')
1234
 
 
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
 
 
1247
 
class TestTreeConfig(tests.TestCaseWithTransport):
1248
 
 
1249
 
    def test_get_value(self):
1250
 
        """Test that retreiving a value from a section is possible"""
1251
 
        branch = self.make_branch('.')
1252
 
        tree_config = config.TreeConfig(branch)
1253
 
        tree_config.set_option('value', 'key', 'SECTION')
1254
 
        tree_config.set_option('value2', 'key2')
1255
 
        tree_config.set_option('value3-top', 'key3')
1256
 
        tree_config.set_option('value3-section', 'key3', 'SECTION')
1257
 
        value = tree_config.get_option('key', 'SECTION')
1258
 
        self.assertEqual(value, 'value')
1259
 
        value = tree_config.get_option('key2')
1260
 
        self.assertEqual(value, 'value2')
1261
 
        self.assertEqual(tree_config.get_option('non-existant'), None)
1262
 
        value = tree_config.get_option('non-existant', 'SECTION')
1263
 
        self.assertEqual(value, None)
1264
 
        value = tree_config.get_option('non-existant', default='default')
1265
 
        self.assertEqual(value, 'default')
1266
 
        self.assertEqual(tree_config.get_option('key2', 'NOSECTION'), None)
1267
 
        value = tree_config.get_option('key2', 'NOSECTION', default='default')
1268
 
        self.assertEqual(value, 'default')
1269
 
        value = tree_config.get_option('key3')
1270
 
        self.assertEqual(value, 'value3-top')
1271
 
        value = tree_config.get_option('key3', 'SECTION')
1272
 
        self.assertEqual(value, 'value3-section')
1273
 
 
1274
 
 
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
 
class TestAuthenticationConfigFile(tests.TestCase):
1316
 
    """Test the authentication.conf file matching"""
1317
 
 
1318
 
    def _got_user_passwd(self, expected_user, expected_password,
1319
 
                         config, *args, **kwargs):
1320
 
        credentials = config.get_credentials(*args, **kwargs)
1321
 
        if credentials is None:
1322
 
            user = None
1323
 
            password = None
1324
 
        else:
1325
 
            user = credentials['user']
1326
 
            password = credentials['password']
1327
 
        self.assertEquals(expected_user, user)
1328
 
        self.assertEquals(expected_password, password)
1329
 
 
1330
 
    def test_empty_config(self):
1331
 
        conf = config.AuthenticationConfig(_file=StringIO())
1332
 
        self.assertEquals({}, conf._get_config())
1333
 
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
1334
 
 
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):
1340
 
        conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
1341
 
        self.assertRaises(errors.ParseConfigError, conf._get_config)
1342
 
 
1343
 
    def test_auth_value_not_boolean(self):
1344
 
        conf = config.AuthenticationConfig(_file=StringIO(
1345
 
                """[broken]
1346
 
scheme=ftp
1347
 
user=joe
1348
 
verify_certificates=askme # Error: Not a boolean
1349
 
"""))
1350
 
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1351
 
 
1352
 
    def test_auth_value_not_int(self):
1353
 
        conf = config.AuthenticationConfig(_file=StringIO(
1354
 
                """[broken]
1355
 
scheme=ftp
1356
 
user=joe
1357
 
port=port # Error: Not an int
1358
 
"""))
1359
 
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
1360
 
 
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
 
    def test_credentials_for_scheme_host(self):
1372
 
        conf = config.AuthenticationConfig(_file=StringIO(
1373
 
                """# Identity on foo.net
1374
 
[ftp definition]
1375
 
scheme=ftp
1376
 
host=foo.net
1377
 
user=joe
1378
 
password=secret-pass
1379
 
"""))
1380
 
        # Basic matching
1381
 
        self._got_user_passwd('joe', 'secret-pass', conf, 'ftp', 'foo.net')
1382
 
        # different scheme
1383
 
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
1384
 
        # different host
1385
 
        self._got_user_passwd(None, None, conf, 'ftp', 'bar.net')
1386
 
 
1387
 
    def test_credentials_for_host_port(self):
1388
 
        conf = config.AuthenticationConfig(_file=StringIO(
1389
 
                """# Identity on foo.net
1390
 
[ftp definition]
1391
 
scheme=ftp
1392
 
port=10021
1393
 
host=foo.net
1394
 
user=joe
1395
 
password=secret-pass
1396
 
"""))
1397
 
        # No port
1398
 
        self._got_user_passwd('joe', 'secret-pass',
1399
 
                              conf, 'ftp', 'foo.net', port=10021)
1400
 
        # different port
1401
 
        self._got_user_passwd(None, None, conf, 'ftp', 'foo.net')
1402
 
 
1403
 
    def test_for_matching_host(self):
1404
 
        conf = config.AuthenticationConfig(_file=StringIO(
1405
 
                """# Identity on foo.net
1406
 
[sourceforge]
1407
 
scheme=bzr
1408
 
host=bzr.sf.net
1409
 
user=joe
1410
 
password=joepass
1411
 
[sourceforge domain]
1412
 
scheme=bzr
1413
 
host=.bzr.sf.net
1414
 
user=georges
1415
 
password=bendover
1416
 
"""))
1417
 
        # matching domain
1418
 
        self._got_user_passwd('georges', 'bendover',
1419
 
                              conf, 'bzr', 'foo.bzr.sf.net')
1420
 
        # phishing attempt
1421
 
        self._got_user_passwd(None, None,
1422
 
                              conf, 'bzr', 'bbzr.sf.net')
1423
 
 
1424
 
    def test_for_matching_host_None(self):
1425
 
        conf = config.AuthenticationConfig(_file=StringIO(
1426
 
                """# Identity on foo.net
1427
 
[catchup bzr]
1428
 
scheme=bzr
1429
 
user=joe
1430
 
password=joepass
1431
 
[DEFAULT]
1432
 
user=georges
1433
 
password=bendover
1434
 
"""))
1435
 
        # match no host
1436
 
        self._got_user_passwd('joe', 'joepass',
1437
 
                              conf, 'bzr', 'quux.net')
1438
 
        # no host but different scheme
1439
 
        self._got_user_passwd('georges', 'bendover',
1440
 
                              conf, 'ftp', 'quux.net')
1441
 
 
1442
 
    def test_credentials_for_path(self):
1443
 
        conf = config.AuthenticationConfig(_file=StringIO(
1444
 
                """
1445
 
[http dir1]
1446
 
scheme=http
1447
 
host=bar.org
1448
 
path=/dir1
1449
 
user=jim
1450
 
password=jimpass
1451
 
[http dir2]
1452
 
scheme=http
1453
 
host=bar.org
1454
 
path=/dir2
1455
 
user=georges
1456
 
password=bendover
1457
 
"""))
1458
 
        # no path no dice
1459
 
        self._got_user_passwd(None, None,
1460
 
                              conf, 'http', host='bar.org', path='/dir3')
1461
 
        # matching path
1462
 
        self._got_user_passwd('georges', 'bendover',
1463
 
                              conf, 'http', host='bar.org', path='/dir2')
1464
 
        # matching subdir
1465
 
        self._got_user_passwd('jim', 'jimpass',
1466
 
                              conf, 'http', host='bar.org',path='/dir1/subdir')
1467
 
 
1468
 
    def test_credentials_for_user(self):
1469
 
        conf = config.AuthenticationConfig(_file=StringIO(
1470
 
                """
1471
 
[with user]
1472
 
scheme=http
1473
 
host=bar.org
1474
 
user=jim
1475
 
password=jimpass
1476
 
"""))
1477
 
        # Get user
1478
 
        self._got_user_passwd('jim', 'jimpass',
1479
 
                              conf, 'http', 'bar.org')
1480
 
        # Get same user
1481
 
        self._got_user_passwd('jim', 'jimpass',
1482
 
                              conf, 'http', 'bar.org', user='jim')
1483
 
        # Don't get a different user if one is specified
1484
 
        self._got_user_passwd(None, None,
1485
 
                              conf, 'http', 'bar.org', user='georges')
1486
 
 
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
 
    def test_verify_certificates(self):
1500
 
        conf = config.AuthenticationConfig(_file=StringIO(
1501
 
                """
1502
 
[self-signed]
1503
 
scheme=https
1504
 
host=bar.org
1505
 
user=jim
1506
 
password=jimpass
1507
 
verify_certificates=False
1508
 
[normal]
1509
 
scheme=https
1510
 
host=foo.net
1511
 
user=georges
1512
 
password=bendover
1513
 
"""))
1514
 
        credentials = conf.get_credentials('https', 'bar.org')
1515
 
        self.assertEquals(False, credentials.get('verify_certificates'))
1516
 
        credentials = conf.get_credentials('https', 'foo.net')
1517
 
        self.assertEquals(True, credentials.get('verify_certificates'))
1518
 
 
1519
 
 
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
 
class TestAuthenticationConfig(tests.TestCase):
1552
 
    """Test AuthenticationConfig behaviour"""
1553
 
 
1554
 
    def _check_default_password_prompt(self, expected_prompt_format, scheme,
1555
 
                                       host=None, port=None, realm=None,
1556
 
                                       path=None):
1557
 
        if host is None:
1558
 
            host = 'bar.org'
1559
 
        user, password = 'jim', 'precious'
1560
 
        expected_prompt = expected_prompt_format % {
1561
 
            'scheme': scheme, 'host': host, 'port': port,
1562
 
            'user': user, 'realm': realm}
1563
 
 
1564
 
        stdout = tests.StringIOWrapper()
1565
 
        stderr = tests.StringIOWrapper()
1566
 
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
1567
 
                                            stdout=stdout, stderr=stderr)
1568
 
        # We use an empty conf so that the user is always prompted
1569
 
        conf = config.AuthenticationConfig()
1570
 
        self.assertEquals(password,
1571
 
                          conf.get_password(scheme, host, user, port=port,
1572
 
                                            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)
1619
 
        # SMTP port handling is a bit special (it's handled if embedded in the
1620
 
        # host too)
1621
 
        # FIXME: should we: forbid that, extend it to other schemes, leave
1622
 
        # 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(
1628
 
            'SMTP %(user)s@%(host)s:%(port)d password: ',
1629
 
            'smtp', port=10025)
1630
 
 
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
 
 
1805
 
# FIXME: Once we have a way to declare authentication to all test servers, we
1806
 
# can implement generic tests.
1807
 
# test_user_password_in_url
1808
 
# test_user_in_url_password_from_config
1809
 
# test_user_in_url_password_prompted
1810
 
# test_user_in_config
1811
 
# test_user_getpass.getuser
1812
 
# test_user_prompted ?
1813
 
class TestAuthenticationRing(tests.TestCaseWithTransport):
1814
 
    pass