/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5557.1.7 by John Arbash Meinel
Merge in the bzr.dev 5582
1
# Copyright (C) 2005-2011 Canonical Ltd
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
16
17
"""Tests for finding and reading the bzr config file[s]."""
18
# import system imports here
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
19
from cStringIO import StringIO
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
20
import os
21
import sys
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
22
import threading
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
23
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
24
25
from testtools import matchers
26
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
27
#import bzrlib specific imports here
1878.1.3 by John Arbash Meinel
some test cleanups
28
from bzrlib import (
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
29
    branch,
30
    bzrdir,
1878.1.3 by John Arbash Meinel
some test cleanups
31
    config,
4603.1.10 by Aaron Bentley
Provide change editor via config.
32
    diff,
1878.1.3 by John Arbash Meinel
some test cleanups
33
    errors,
34
    osutils,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
35
    mail_client,
5321.1.89 by Gordon Tyler
Moved mergetools config tests to bzrlib.tests.test_config.
36
    mergetools,
2900.2.14 by Vincent Ladeuil
More tests.
37
    ui,
1878.1.3 by John Arbash Meinel
some test cleanups
38
    urlutils,
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
39
    registry,
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
40
    remote,
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
41
    tests,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
42
    trace,
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
43
    transport,
1878.1.3 by John Arbash Meinel
some test cleanups
44
    )
5743.13.1 by Vincent Ladeuil
Deprecate _get_editor to identify its usages.
45
from bzrlib.symbol_versioning import (
46
    deprecated_in,
47
    deprecated_method,
48
    )
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
49
from bzrlib.transport import remote as transport_remote
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
50
from bzrlib.tests import (
51
    features,
5506.2.1 by Vincent Ladeuil
Implements ``bzr config --active option`` displaying only the value.
52
    scenarios,
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
53
    test_server,
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
54
    )
2991.2.4 by Vincent Ladeuil
Various fixes following local testing environment rebuild.
55
from bzrlib.util.configobj import configobj
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
56
57
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
58
def lockable_config_scenarios():
59
    return [
60
        ('global',
61
         {'config_class': config.GlobalConfig,
62
          'config_args': [],
63
          'config_section': 'DEFAULT'}),
64
        ('locations',
65
         {'config_class': config.LocationConfig,
66
          'config_args': ['.'],
67
          'config_section': '.'}),]
68
69
5506.2.1 by Vincent Ladeuil
Implements ``bzr config --active option`` displaying only the value.
70
load_tests = scenarios.load_tests_apply_scenarios
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
71
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
72
# Register helpers to build stores
73
config.test_store_builder_registry.register(
5743.5.13 by Vincent Ladeuil
Merge config-abstract-store into config-concrete-stores resolving conflicts
74
    'configobj', lambda test: config.IniFileStore(test.get_transport(),
75
                                                  'configobj.conf'))
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
76
config.test_store_builder_registry.register(
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
77
    'bazaar', lambda test: config.GlobalStore())
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
78
config.test_store_builder_registry.register(
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
79
    'location', lambda test: config.LocationStore())
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
80
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
81
82
def build_backing_branch(test, relpath,
83
                         transport_class=None, server_class=None):
84
    """Test helper to create a backing branch only once.
85
86
    Some tests needs multiple stores/stacks to check concurrent update
87
    behaviours. As such, they need to build different branch *objects* even if
88
    they share the branch on disk.
89
90
    :param relpath: The relative path to the branch. (Note that the helper
91
        should always specify the same relpath).
92
93
    :param transport_class: The Transport class the test needs to use.
94
95
    :param server_class: The server associated with the ``transport_class``
96
        above.
97
5743.10.9 by Vincent Ladeuil
Fix use of none where neither is required.
98
    Either both or neither of ``transport_class`` and ``server_class`` should
99
    be specified.
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
100
    """
101
    if transport_class is not None and server_class is not None:
102
        test.transport_class = transport_class
103
        test.transport_server = server_class
104
    elif not (transport_class is None and server_class is None):
105
        raise AssertionError('Specify both ``transport_class`` and '
5743.10.9 by Vincent Ladeuil
Fix use of none where neither is required.
106
                             '``server_class`` or neither of them')
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
107
    if getattr(test, 'backing_branch', None) is None:
108
        # First call, let's build the branch on disk
109
        test.backing_branch = test.make_branch(relpath)
110
111
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
112
def build_branch_store(test):
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
113
    build_backing_branch(test, 'branch')
114
    b = branch.Branch.open('branch')
115
    return config.BranchStore(b)
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
116
config.test_store_builder_registry.register('branch', build_branch_store)
117
118
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
119
def build_remote_branch_store(test):
120
    # There is only one permutation (but we won't be able to handle more with
121
    # this design anyway)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
122
    (transport_class,
123
     server_class) = transport_remote.get_test_permutations()[0]
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
124
    build_backing_branch(test, 'branch', transport_class, server_class)
125
    b = branch.Branch.open(test.get_url('branch'))
126
    return config.BranchStore(b)
127
config.test_store_builder_registry.register('remote_branch',
128
                                            build_remote_branch_store)
129
130
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
131
config.test_stack_builder_registry.register(
132
    'bazaar', lambda test: config.GlobalStack())
133
config.test_stack_builder_registry.register(
134
    'location', lambda test: config.LocationStack('.'))
135
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
136
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
137
def build_branch_stack(test):
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
138
    build_backing_branch(test, 'branch')
139
    b = branch.Branch.open('branch')
140
    return config.BranchStack(b)
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
141
config.test_stack_builder_registry.register('branch', build_branch_stack)
142
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
143
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
144
def build_remote_branch_stack(test):
145
    # There is only one permutation (but we won't be able to handle more with
146
    # this design anyway)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
147
    (transport_class,
148
     server_class) = transport_remote.get_test_permutations()[0]
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
149
    build_backing_branch(test, 'branch', transport_class, server_class)
150
    b = branch.Branch.open(test.get_url('branch'))
151
    return config.BranchStack(b)
152
config.test_stack_builder_registry.register('remote_branch',
153
                                            build_remote_branch_stack)
154
155
1553.6.12 by Erik Bågfors
remove AliasConfig, based on input from abentley
156
sample_long_alias="log -r-15..-1 --line"
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
157
sample_config_text = u"""
158
[DEFAULT]
159
email=Erik B\u00e5gfors <erik@bagfors.nu>
160
editor=vim
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
161
change_editor=vimdiff -of @new_path @old_path
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
162
gpg_signing_command=gnome-gpg
163
log_format=short
164
user_global_option=something
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
165
bzr.mergetool.sometool=sometool {base} {this} {other} -o {result}
5321.2.3 by Vincent Ladeuil
Prefix mergetools option names with 'bzr.'.
166
bzr.mergetool.funkytool=funkytool "arg with spaces" {this_temp}
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
167
bzr.default_mergetool=sometool
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
168
[ALIASES]
169
h=help
170
ll=""" + sample_long_alias + "\n"
171
172
173
sample_always_signatures = """
174
[DEFAULT]
175
check_signatures=ignore
176
create_signatures=always
177
"""
178
179
sample_ignore_signatures = """
180
[DEFAULT]
181
check_signatures=require
182
create_signatures=never
183
"""
184
185
sample_maybe_signatures = """
186
[DEFAULT]
187
check_signatures=ignore
188
create_signatures=when-required
189
"""
190
191
sample_branches_text = """
192
[http://www.example.com]
193
# Top level policy
194
email=Robert Collins <robertc@example.org>
2120.6.3 by James Henstridge
add some more tests for getting policy options, and behaviour of get_user_option in the presence of config policies
195
normal_option = normal
196
appendpath_option = append
2120.6.8 by James Henstridge
Change syntax for setting config option policies. Rather than
197
appendpath_option:policy = appendpath
2120.6.3 by James Henstridge
add some more tests for getting policy options, and behaviour of get_user_option in the presence of config policies
198
norecurse_option = norecurse
2120.6.8 by James Henstridge
Change syntax for setting config option policies. Rather than
199
norecurse_option:policy = norecurse
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
200
[http://www.example.com/ignoreparent]
201
# different project: ignore parent dir config
202
ignore_parents=true
203
[http://www.example.com/norecurse]
204
# configuration items that only apply to this dir
205
recurse=false
2120.6.3 by James Henstridge
add some more tests for getting policy options, and behaviour of get_user_option in the presence of config policies
206
normal_option = norecurse
207
[http://www.example.com/dir]
208
appendpath_option = normal
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
209
[/b/]
210
check_signatures=require
211
# test trailing / matching with no children
212
[/a/]
213
check_signatures=check-available
214
gpg_signing_command=false
215
user_local_option=local
216
# test trailing / matching
217
[/a/*]
218
#subdirs will match but not the parent
219
[/a/c]
220
check_signatures=ignore
221
post_commit=bzrlib.tests.test_config.post_commit
222
#testing explicit beats globs
223
"""
1553.6.3 by Erik Bågfors
tests for AliasesConfig
224
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
225
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
226
def create_configs(test):
227
    """Create configuration files for a given test.
228
229
    This requires creating a tree (and populate the ``test.tree`` attribute)
230
    and its associated branch and will populate the following attributes:
231
232
    - branch_config: A BranchConfig for the associated branch.
233
234
    - locations_config : A LocationConfig for the associated branch
235
236
    - bazaar_config: A GlobalConfig.
237
238
    The tree and branch are created in a 'tree' subdirectory so the tests can
239
    still use the test directory to stay outside of the branch.
240
    """
241
    tree = test.make_branch_and_tree('tree')
242
    test.tree = tree
243
    test.branch_config = config.BranchConfig(tree.branch)
244
    test.locations_config = config.LocationConfig(tree.basedir)
245
    test.bazaar_config = config.GlobalConfig()
246
5533.2.4 by Vincent Ladeuil
Fix whitespace issue.
247
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
248
def create_configs_with_file_option(test):
249
    """Create configuration files with a ``file`` option set in each.
250
251
    This builds on ``create_configs`` and add one ``file`` option in each
252
    configuration with a value which allows identifying the configuration file.
253
    """
254
    create_configs(test)
255
    test.bazaar_config.set_user_option('file', 'bazaar')
256
    test.locations_config.set_user_option('file', 'locations')
257
    test.branch_config.set_user_option('file', 'branch')
258
259
260
class TestOptionsMixin:
261
262
    def assertOptions(self, expected, conf):
263
        # We don't care about the parser (as it will make tests hard to write
264
        # and error-prone anyway)
265
        self.assertThat([opt[:4] for opt in conf._get_options()],
266
                        matchers.Equals(expected))
267
268
1474 by Robert Collins
Merge from Aaron Bentley.
269
class InstrumentedConfigObj(object):
270
    """A config obj look-enough-alike to record calls made to it."""
271
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
272
    def __contains__(self, thing):
273
        self._calls.append(('__contains__', thing))
274
        return False
275
276
    def __getitem__(self, key):
277
        self._calls.append(('__getitem__', key))
278
        return self
279
1551.2.20 by Aaron Bentley
Treated config files as utf-8
280
    def __init__(self, input, encoding=None):
281
        self._calls = [('__init__', input, encoding)]
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
282
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
283
    def __setitem__(self, key, value):
284
        self._calls.append(('__setitem__', key, value))
285
2120.6.4 by James Henstridge
add support for specifying policy when storing options
286
    def __delitem__(self, key):
287
        self._calls.append(('__delitem__', key))
288
289
    def keys(self):
290
        self._calls.append(('keys',))
291
        return []
292
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
293
    def reload(self):
294
        self._calls.append(('reload',))
295
1551.2.49 by abentley
Made ConfigObj output binary-identical files on win32 and *nix
296
    def write(self, arg):
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
297
        self._calls.append(('write',))
298
2120.6.4 by James Henstridge
add support for specifying policy when storing options
299
    def as_bool(self, value):
300
        self._calls.append(('as_bool', value))
301
        return False
302
303
    def get_value(self, section, name):
304
        self._calls.append(('get_value', section, name))
305
        return None
306
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
307
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
308
class FakeBranch(object):
309
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
310
    def __init__(self, base=None, user_id=None):
311
        if base is None:
312
            self.base = "http://example.com/branches/demo"
313
        else:
314
            self.base = base
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
315
        self._transport = self.control_files = \
316
            FakeControlFilesAndTransport(user_id=user_id)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
317
4226.1.7 by Robert Collins
Alter test_config.FakeBranch in accordance with the Branch change to have a _get_config.
318
    def _get_config(self):
319
        return config.TransportConfig(self._transport, 'branch.conf')
320
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
321
    def lock_write(self):
322
        pass
323
324
    def unlock(self):
325
        pass
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
326
327
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
328
class FakeControlFilesAndTransport(object):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
329
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
330
    def __init__(self, user_id=None):
331
        self.files = {}
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
332
        if user_id:
333
            self.files['email'] = user_id
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
334
        self._transport = self
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
335
1185.65.29 by Robert Collins
Implement final review suggestions.
336
    def get_utf8(self, filename):
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
337
        # from LockableFiles
338
        raise AssertionError("get_utf8 should no longer be used")
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
339
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
340
    def get(self, filename):
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
341
        # from Transport
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
342
        try:
343
            return StringIO(self.files[filename])
344
        except KeyError:
345
            raise errors.NoSuchFile(filename)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
346
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
347
    def get_bytes(self, filename):
348
        # from Transport
349
        try:
350
            return self.files[filename]
351
        except KeyError:
352
            raise errors.NoSuchFile(filename)
353
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
354
    def put(self, filename, fileobj):
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
355
        self.files[filename] = fileobj.read()
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
356
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
357
    def put_file(self, filename, fileobj):
358
        return self.put(filename, fileobj)
359
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
360
361
class InstrumentedConfig(config.Config):
362
    """An instrumented config that supplies stubs for template methods."""
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
363
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
364
    def __init__(self):
365
        super(InstrumentedConfig, self).__init__()
366
        self._calls = []
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
367
        self._signatures = config.CHECK_NEVER
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
368
369
    def _get_user_id(self):
370
        self._calls.append('_get_user_id')
371
        return "Robert Collins <robert.collins@example.org>"
372
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
373
    def _get_signature_checking(self):
374
        self._calls.append('_get_signature_checking')
375
        return self._signatures
376
4603.1.10 by Aaron Bentley
Provide change editor via config.
377
    def _get_change_editor(self):
378
        self._calls.append('_get_change_editor')
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
379
        return 'vimdiff -fo @new_path @old_path'
4603.1.10 by Aaron Bentley
Provide change editor via config.
380
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
381
1556.2.2 by Aaron Bentley
Fixed get_bool
382
bool_config = """[DEFAULT]
383
active = true
384
inactive = false
385
[UPPERCASE]
386
active = True
387
nonactive = False
388
"""
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
389
390
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
391
class TestConfigObj(tests.TestCase):
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
392
1556.2.2 by Aaron Bentley
Fixed get_bool
393
    def test_get_bool(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
394
        co = config.ConfigObj(StringIO(bool_config))
1556.2.2 by Aaron Bentley
Fixed get_bool
395
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
396
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
397
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
398
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
399
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
400
    def test_hash_sign_in_value(self):
401
        """
402
        Before 4.5.0, ConfigObj did not quote # signs in values, so they'd be
403
        treated as comments when read in again. (#86838)
404
        """
405
        co = config.ConfigObj()
406
        co['test'] = 'foo#bar'
5050.62.14 by Alexander Belchenko
don't use lines in the tests, and better comment about the corresponding bug in configobj; avoid using write() method without outfile parameter.
407
        outfile = StringIO()
408
        co.write(outfile=outfile)
409
        lines = outfile.getvalue().splitlines()
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
410
        self.assertEqual(lines, ['test = "foo#bar"'])
411
        co2 = config.ConfigObj(lines)
412
        self.assertEqual(co2['test'], 'foo#bar')
413
5050.62.10 by Alexander Belchenko
test to illustrate the problem
414
    def test_triple_quotes(self):
415
        # Bug #710410: if the value string has triple quotes
416
        # then ConfigObj versions up to 4.7.2 will quote them wrong
5050.62.12 by Alexander Belchenko
added NEWS entry
417
        # and won't able to read them back
5050.62.10 by Alexander Belchenko
test to illustrate the problem
418
        triple_quotes_value = '''spam
419
""" that's my spam """
420
eggs'''
421
        co = config.ConfigObj()
422
        co['test'] = triple_quotes_value
5050.62.14 by Alexander Belchenko
don't use lines in the tests, and better comment about the corresponding bug in configobj; avoid using write() method without outfile parameter.
423
        # While writing this test another bug in ConfigObj has been found:
5050.62.10 by Alexander Belchenko
test to illustrate the problem
424
        # method co.write() without arguments produces list of lines
425
        # one option per line, and multiline values are not split
426
        # across multiple lines,
5050.62.14 by Alexander Belchenko
don't use lines in the tests, and better comment about the corresponding bug in configobj; avoid using write() method without outfile parameter.
427
        # and that breaks the parsing these lines back by ConfigObj.
428
        # This issue only affects test, but it's better to avoid
429
        # `co.write()` construct at all.
430
        # [bialix 20110222] bug report sent to ConfigObj's author
5050.62.10 by Alexander Belchenko
test to illustrate the problem
431
        outfile = StringIO()
432
        co.write(outfile=outfile)
5050.62.14 by Alexander Belchenko
don't use lines in the tests, and better comment about the corresponding bug in configobj; avoid using write() method without outfile parameter.
433
        output = outfile.getvalue()
5050.62.10 by Alexander Belchenko
test to illustrate the problem
434
        # now we're trying to read it back
5050.62.14 by Alexander Belchenko
don't use lines in the tests, and better comment about the corresponding bug in configobj; avoid using write() method without outfile parameter.
435
        co2 = config.ConfigObj(StringIO(output))
5050.62.10 by Alexander Belchenko
test to illustrate the problem
436
        self.assertEquals(triple_quotes_value, co2['test'])
437
1556.2.2 by Aaron Bentley
Fixed get_bool
438
2900.1.1 by Vincent Ladeuil
439
erroneous_config = """[section] # line 1
440
good=good # line 2
441
[section] # line 3
442
whocares=notme # line 4
443
"""
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
444
445
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
446
class TestConfigObjErrors(tests.TestCase):
2900.1.1 by Vincent Ladeuil
447
448
    def test_duplicate_section_name_error_line(self):
449
        try:
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
450
            co = configobj.ConfigObj(StringIO(erroneous_config),
451
                                     raise_errors=True)
2900.1.1 by Vincent Ladeuil
452
        except config.configobj.DuplicateError, e:
453
            self.assertEqual(3, e.line_number)
454
        else:
455
            self.fail('Error in config file not detected')
456
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
457
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
458
class TestConfig(tests.TestCase):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
459
460
    def test_constructs(self):
461
        config.Config()
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
462
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
463
    def test_no_default_editor(self):
5743.13.1 by Vincent Ladeuil
Deprecate _get_editor to identify its usages.
464
        self.assertRaises(
465
            NotImplementedError,
466
            self.applyDeprecated, deprecated_in((2, 4, 0)),
467
            config.Config().get_editor)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
468
469
    def test_user_email(self):
470
        my_config = InstrumentedConfig()
471
        self.assertEqual('robert.collins@example.org', my_config.user_email())
472
        self.assertEqual(['_get_user_id'], my_config._calls)
473
474
    def test_username(self):
475
        my_config = InstrumentedConfig()
476
        self.assertEqual('Robert Collins <robert.collins@example.org>',
477
                         my_config.username())
478
        self.assertEqual(['_get_user_id'], my_config._calls)
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
479
480
    def test_signatures_default(self):
481
        my_config = config.Config()
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
482
        self.assertFalse(my_config.signature_needed())
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
483
        self.assertEqual(config.CHECK_IF_POSSIBLE,
484
                         my_config.signature_checking())
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
485
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
486
                         my_config.signing_policy())
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
487
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
488
    def test_signatures_template_method(self):
489
        my_config = InstrumentedConfig()
490
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
491
        self.assertEqual(['_get_signature_checking'], my_config._calls)
492
493
    def test_signatures_template_method_none(self):
494
        my_config = InstrumentedConfig()
495
        my_config._signatures = None
496
        self.assertEqual(config.CHECK_IF_POSSIBLE,
497
                         my_config.signature_checking())
498
        self.assertEqual(['_get_signature_checking'], my_config._calls)
499
1442.1.56 by Robert Collins
gpg_signing_command configuration item
500
    def test_gpg_signing_command_default(self):
501
        my_config = config.Config()
502
        self.assertEqual('gpg', my_config.gpg_signing_command())
503
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
504
    def test_get_user_option_default(self):
505
        my_config = config.Config()
506
        self.assertEqual(None, my_config.get_user_option('no_option'))
507
1472 by Robert Collins
post commit hook, first pass implementation
508
    def test_post_commit_default(self):
509
        my_config = config.Config()
510
        self.assertEqual(None, my_config.post_commit())
511
1553.2.9 by Erik Bågfors
log_formatter => log_format for "named" formatters
512
    def test_log_format_default(self):
1553.2.8 by Erik Bågfors
tests for config log_formatter
513
        my_config = config.Config()
1553.2.9 by Erik Bågfors
log_formatter => log_format for "named" formatters
514
        self.assertEqual('long', my_config.log_format())
1553.2.8 by Erik Bågfors
tests for config log_formatter
515
4603.1.10 by Aaron Bentley
Provide change editor via config.
516
    def test_get_change_editor(self):
517
        my_config = InstrumentedConfig()
518
        change_editor = my_config.get_change_editor('old_tree', 'new_tree')
519
        self.assertEqual(['_get_change_editor'], my_config._calls)
520
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
521
        self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
4603.1.10 by Aaron Bentley
Provide change editor via config.
522
                         change_editor.command_template)
523
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
524
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
525
class TestConfigPath(tests.TestCase):
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
526
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
527
    def setUp(self):
528
        super(TestConfigPath, self).setUp()
5570.3.9 by Vincent Ladeuil
More use cases for overrideEnv, _cleanEnvironment *may* contain too much variables now.
529
        self.overrideEnv('HOME', '/home/bogus')
530
        self.overrideEnv('XDG_CACHE_DIR', '')
2309.2.6 by Alexander Belchenko
bzr now use Win32 API to determine Application Data location, and don't rely solely on $APPDATA
531
        if sys.platform == 'win32':
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
532
            self.overrideEnv(
533
                'BZR_HOME', r'C:\Documents and Settings\bogus\Application Data')
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
534
            self.bzr_home = \
535
                'C:/Documents and Settings/bogus/Application Data/bazaar/2.0'
5519.4.3 by Neil Martinsen-Burrell
be permissive about using $XDG_CONFIG_HOME/bazaar, but dont complain
536
        else:
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
537
            self.bzr_home = '/home/bogus/.bazaar'
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
538
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
539
    def test_config_dir(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
540
        self.assertEqual(config.config_dir(), self.bzr_home)
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
541
542
    def test_config_filename(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
543
        self.assertEqual(config.config_filename(),
544
                         self.bzr_home + '/bazaar.conf')
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
545
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
546
    def test_locations_config_filename(self):
2991.2.4 by Vincent Ladeuil
Various fixes following local testing environment rebuild.
547
        self.assertEqual(config.locations_config_filename(),
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
548
                         self.bzr_home + '/locations.conf')
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
549
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
550
    def test_authentication_config_filename(self):
2991.2.4 by Vincent Ladeuil
Various fixes following local testing environment rebuild.
551
        self.assertEqual(config.authentication_config_filename(),
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
552
                         self.bzr_home + '/authentication.conf')
553
4584.3.23 by Martin Pool
Correction to xdg_cache_dir and add a simple test
554
    def test_xdg_cache_dir(self):
555
        self.assertEqual(config.xdg_cache_dir(),
556
            '/home/bogus/.cache')
557
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
558
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
559
class TestXDGConfigDir(tests.TestCaseInTempDir):
560
    # must be in temp dir because config tests for the existence of the bazaar
561
    # subdirectory of $XDG_CONFIG_HOME
562
5519.4.9 by Neil Martinsen-Burrell
working tests
563
    def setUp(self):
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
564
        if sys.platform in ('darwin', 'win32'):
565
            raise tests.TestNotApplicable(
566
                'XDG config dir not used on this platform')
5519.4.9 by Neil Martinsen-Burrell
working tests
567
        super(TestXDGConfigDir, self).setUp()
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
568
        self.overrideEnv('HOME', self.test_home_dir)
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
569
        # BZR_HOME overrides everything we want to test so unset it.
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
570
        self.overrideEnv('BZR_HOME', None)
5519.4.9 by Neil Martinsen-Burrell
working tests
571
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
572
    def test_xdg_config_dir_exists(self):
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
573
        """When ~/.config/bazaar exists, use it as the config dir."""
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
574
        newdir = osutils.pathjoin(self.test_home_dir, '.config', 'bazaar')
575
        os.makedirs(newdir)
576
        self.assertEqual(config.config_dir(), newdir)
577
578
    def test_xdg_config_home(self):
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
579
        """When XDG_CONFIG_HOME is set, use it."""
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
580
        xdgconfigdir = osutils.pathjoin(self.test_home_dir, 'xdgconfig')
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
581
        self.overrideEnv('XDG_CONFIG_HOME', xdgconfigdir)
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
582
        newdir = osutils.pathjoin(xdgconfigdir, 'bazaar')
583
        os.makedirs(newdir)
584
        self.assertEqual(config.config_dir(), newdir)
585
586
5050.13.2 by Parth Malwankar
copy config file ownership only if a new file is created
587
class TestIniConfig(tests.TestCaseInTempDir):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
588
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
589
    def make_config_parser(self, s):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
590
        conf = config.IniBasedConfig.from_string(s)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
591
        return conf, conf._get_parser()
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
592
5050.13.2 by Parth Malwankar
copy config file ownership only if a new file is created
593
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
594
class TestIniConfigBuilding(TestIniConfig):
595
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
596
    def test_contructs(self):
5345.1.1 by Vincent Ladeuil
Deprecate the get_filename parameter in IniBasedConfig.
597
        my_config = config.IniBasedConfig()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
598
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
599
    def test_from_fp(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
600
        my_config = config.IniBasedConfig.from_string(sample_config_text)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
601
        self.assertIsInstance(my_config._get_parser(), configobj.ConfigObj)
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
602
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
603
    def test_cached(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
604
        my_config = config.IniBasedConfig.from_string(sample_config_text)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
605
        parser = my_config._get_parser()
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
606
        self.assertTrue(my_config._get_parser() is parser)
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
607
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
608
    def _dummy_chown(self, path, uid, gid):
609
        self.path, self.uid, self.gid = path, uid, gid
610
611
    def test_ini_config_ownership(self):
5345.5.8 by Vincent Ladeuil
More doc and ensure that the config is locked when _write_config_file is called.
612
        """Ensure that chown is happening during _write_config_file"""
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
613
        self.requireFeature(features.chown_feature)
614
        self.overrideAttr(os, 'chown', self._dummy_chown)
615
        self.path = self.uid = self.gid = None
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
616
        conf = config.IniBasedConfig(file_name='./foo.conf')
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
617
        conf._write_config_file()
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
618
        self.assertEquals(self.path, './foo.conf')
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
619
        self.assertTrue(isinstance(self.uid, int))
620
        self.assertTrue(isinstance(self.gid, int))
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
621
5345.1.1 by Vincent Ladeuil
Deprecate the get_filename parameter in IniBasedConfig.
622
    def test_get_filename_parameter_is_deprecated_(self):
623
        conf = self.callDeprecated([
624
            'IniBasedConfig.__init__(get_filename) was deprecated in 2.3.'
625
            ' Use file_name instead.'],
626
            config.IniBasedConfig, lambda: 'ini.conf')
5345.3.1 by Vincent Ladeuil
Check that _get_filename() is called and produces the desired side effect.
627
        self.assertEqual('ini.conf', conf.file_name)
5345.1.1 by Vincent Ladeuil
Deprecate the get_filename parameter in IniBasedConfig.
628
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
629
    def test_get_parser_file_parameter_is_deprecated_(self):
630
        config_file = StringIO(sample_config_text.encode('utf-8'))
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
631
        conf = config.IniBasedConfig.from_string(sample_config_text)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
632
        conf = self.callDeprecated([
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
633
            'IniBasedConfig._get_parser(file=xxx) was deprecated in 2.3.'
634
            ' Use IniBasedConfig(_content=xxx) instead.'],
635
            conf._get_parser, file=config_file)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
636
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
637
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
638
class TestIniConfigSaving(tests.TestCaseInTempDir):
639
5345.1.1 by Vincent Ladeuil
Deprecate the get_filename parameter in IniBasedConfig.
640
    def test_cant_save_without_a_file_name(self):
641
        conf = config.IniBasedConfig()
642
        self.assertRaises(AssertionError, conf._write_config_file)
643
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
644
    def test_saved_with_content(self):
645
        content = 'foo = bar\n'
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
646
        conf = config.IniBasedConfig.from_string(
5345.1.25 by Vincent Ladeuil
Move the '_save' parameter from '__init__' to 'from_bytes', fix fallouts.
647
            content, file_name='./test.conf', save=True)
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
648
        self.assertFileEqual(content, 'test.conf')
649
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
650
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
651
class TestIniConfigOptionExpansionDefaultValue(tests.TestCaseInTempDir):
652
    """What is the default value of expand for config options.
653
654
    This is an opt-in beta feature used to evaluate whether or not option
655
    references can appear in dangerous place raising exceptions, disapearing
656
    (and as such corrupting data) or if it's safe to activate the option by
657
    default.
658
659
    Note that these tests relies on config._expand_default_value being already
660
    overwritten in the parent class setUp.
661
    """
662
663
    def setUp(self):
664
        super(TestIniConfigOptionExpansionDefaultValue, self).setUp()
665
        self.config = None
666
        self.warnings = []
667
        def warning(*args):
668
            self.warnings.append(args[0] % args[1:])
669
        self.overrideAttr(trace, 'warning', warning)
670
671
    def get_config(self, expand):
672
        c = config.GlobalConfig.from_string('bzr.config.expand=%s' % (expand,),
673
                                            save=True)
674
        return c
675
676
    def assertExpandIs(self, expected):
677
        actual = config._get_expand_default_value()
678
        #self.config.get_user_option_as_bool('bzr.config.expand')
679
        self.assertEquals(expected, actual)
680
681
    def test_default_is_None(self):
682
        self.assertEquals(None, config._expand_default_value)
683
684
    def test_default_is_False_even_if_None(self):
685
        self.config = self.get_config(None)
686
        self.assertExpandIs(False)
687
688
    def test_default_is_False_even_if_invalid(self):
689
        self.config = self.get_config('<your choice>')
690
        self.assertExpandIs(False)
691
        # ...
692
        # Huh ? My choice is False ? Thanks, always happy to hear that :D
693
        # Wait, you've been warned !
694
        self.assertLength(1, self.warnings)
695
        self.assertEquals(
696
            'Value "<your choice>" is not a boolean for "bzr.config.expand"',
697
            self.warnings[0])
698
699
    def test_default_is_True(self):
700
        self.config = self.get_config(True)
701
        self.assertExpandIs(True)
5743.10.10 by Vincent Ladeuil
Remove spurious space
702
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
703
    def test_default_is_False(self):
704
        self.config = self.get_config(False)
705
        self.assertExpandIs(False)
5743.10.10 by Vincent Ladeuil
Remove spurious space
706
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
707
708
class TestIniConfigOptionExpansion(tests.TestCase):
709
    """Test option expansion from the IniConfig level.
710
711
    What we really want here is to test the Config level, but the class being
712
    abstract as far as storing values is concerned, this can't be done
713
    properly (yet).
714
    """
715
    # FIXME: This should be rewritten when all configs share a storage
716
    # implementation -- vila 2011-02-18
717
718
    def get_config(self, string=None):
719
        if string is None:
720
            string = ''
721
        c = config.IniBasedConfig.from_string(string)
722
        return c
723
724
    def assertExpansion(self, expected, conf, string, env=None):
725
        self.assertEquals(expected, conf.expand_options(string, env))
726
727
    def test_no_expansion(self):
728
        c = self.get_config('')
729
        self.assertExpansion('foo', c, 'foo')
730
731
    def test_env_adding_options(self):
732
        c = self.get_config('')
733
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
734
735
    def test_env_overriding_options(self):
736
        c = self.get_config('foo=baz')
737
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
738
739
    def test_simple_ref(self):
740
        c = self.get_config('foo=xxx')
741
        self.assertExpansion('xxx', c, '{foo}')
742
743
    def test_unknown_ref(self):
744
        c = self.get_config('')
745
        self.assertRaises(errors.ExpandingUnknownOption,
746
                          c.expand_options, '{foo}')
747
748
    def test_indirect_ref(self):
749
        c = self.get_config('''
750
foo=xxx
751
bar={foo}
752
''')
753
        self.assertExpansion('xxx', c, '{bar}')
754
755
    def test_embedded_ref(self):
756
        c = self.get_config('''
757
foo=xxx
758
bar=foo
759
''')
760
        self.assertExpansion('xxx', c, '{{bar}}')
761
762
    def test_simple_loop(self):
763
        c = self.get_config('foo={foo}')
764
        self.assertRaises(errors.OptionExpansionLoop, c.expand_options, '{foo}')
765
766
    def test_indirect_loop(self):
767
        c = self.get_config('''
768
foo={bar}
769
bar={baz}
770
baz={foo}''')
771
        e = self.assertRaises(errors.OptionExpansionLoop,
772
                              c.expand_options, '{foo}')
773
        self.assertEquals('foo->bar->baz', e.refs)
774
        self.assertEquals('{foo}', e.string)
775
776
    def test_list(self):
777
        conf = self.get_config('''
778
foo=start
779
bar=middle
780
baz=end
781
list={foo},{bar},{baz}
782
''')
783
        self.assertEquals(['start', 'middle', 'end'],
784
                           conf.get_user_option('list', expand=True))
785
786
    def test_cascading_list(self):
787
        conf = self.get_config('''
788
foo=start,{bar}
789
bar=middle,{baz}
790
baz=end
791
list={foo}
792
''')
793
        self.assertEquals(['start', 'middle', 'end'],
794
                           conf.get_user_option('list', expand=True))
795
796
    def test_pathological_hidden_list(self):
797
        conf = self.get_config('''
798
foo=bin
799
bar=go
800
start={foo
801
middle=},{
802
end=bar}
803
hidden={start}{middle}{end}
804
''')
805
        # Nope, it's either a string or a list, and the list wins as soon as a
806
        # ',' appears, so the string concatenation never occur.
807
        self.assertEquals(['{foo', '}', '{', 'bar}'],
808
                          conf.get_user_option('hidden', expand=True))
809
810
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
811
812
    def get_config(self, location, string=None):
813
        if string is None:
814
            string = ''
815
        # Since we don't save the config we won't strictly require to inherit
816
        # from TestCaseInTempDir, but an error occurs so quickly...
817
        c = config.LocationConfig.from_string(string, location)
818
        return c
819
820
    def test_dont_cross_unrelated_section(self):
821
        c = self.get_config('/another/branch/path','''
822
[/one/branch/path]
823
foo = hello
824
bar = {foo}/2
825
826
[/another/branch/path]
827
bar = {foo}/2
828
''')
829
        self.assertRaises(errors.ExpandingUnknownOption,
830
                          c.get_user_option, 'bar', expand=True)
831
832
    def test_cross_related_sections(self):
833
        c = self.get_config('/project/branch/path','''
834
[/project]
835
foo = qu
836
837
[/project/branch/path]
838
bar = {foo}ux
839
''')
840
        self.assertEquals('quux', c.get_user_option('bar', expand=True))
841
842
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
843
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
844
845
    def test_cannot_reload_without_name(self):
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
846
        conf = config.IniBasedConfig.from_string(sample_config_text)
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
847
        self.assertRaises(AssertionError, conf.reload)
848
849
    def test_reload_see_new_value(self):
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
850
        c1 = config.IniBasedConfig.from_string('editor=vim\n',
851
                                               file_name='./test/conf')
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
852
        c1._write_config_file()
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
853
        c2 = config.IniBasedConfig.from_string('editor=emacs\n',
854
                                               file_name='./test/conf')
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
855
        c2._write_config_file()
856
        self.assertEqual('vim', c1.get_user_option('editor'))
857
        self.assertEqual('emacs', c2.get_user_option('editor'))
858
        # Make sure we get the Right value
859
        c1.reload()
860
        self.assertEqual('emacs', c1.get_user_option('editor'))
861
862
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
863
class TestLockableConfig(tests.TestCaseInTempDir):
864
5506.2.1 by Vincent Ladeuil
Implements ``bzr config --active option`` displaying only the value.
865
    scenarios = lockable_config_scenarios()
866
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
867
    # Set by load_tests
868
    config_class = None
869
    config_args = None
870
    config_section = None
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
871
872
    def setUp(self):
873
        super(TestLockableConfig, self).setUp()
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
874
        self._content = '[%s]\none=1\ntwo=2\n' % (self.config_section,)
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
875
        self.config = self.create_config(self._content)
876
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
877
    def get_existing_config(self):
878
        return self.config_class(*self.config_args)
879
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
880
    def create_config(self, content):
5396.1.1 by Vincent Ladeuil
Fix python-2.6-ism.
881
        kwargs = dict(save=True)
882
        c = self.config_class.from_string(content, *self.config_args, **kwargs)
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
883
        return c
884
885
    def test_simple_read_access(self):
886
        self.assertEquals('1', self.config.get_user_option('one'))
887
888
    def test_simple_write_access(self):
889
        self.config.set_user_option('one', 'one')
890
        self.assertEquals('one', self.config.get_user_option('one'))
891
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
892
    def test_listen_to_the_last_speaker(self):
893
        c1 = self.config
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
894
        c2 = self.get_existing_config()
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
895
        c1.set_user_option('one', 'ONE')
896
        c2.set_user_option('two', 'TWO')
897
        self.assertEquals('ONE', c1.get_user_option('one'))
898
        self.assertEquals('TWO', c2.get_user_option('two'))
899
        # The second update respect the first one
900
        self.assertEquals('ONE', c2.get_user_option('one'))
901
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
902
    def test_last_speaker_wins(self):
903
        # If the same config is not shared, the same variable modified twice
904
        # can only see a single result.
905
        c1 = self.config
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
906
        c2 = self.get_existing_config()
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
907
        c1.set_user_option('one', 'c1')
908
        c2.set_user_option('one', 'c2')
909
        self.assertEquals('c2', c2._get_user_option('one'))
910
        # The first modification is still available until another refresh
911
        # occur
912
        self.assertEquals('c1', c1._get_user_option('one'))
913
        c1.set_user_option('two', 'done')
914
        self.assertEquals('c2', c1._get_user_option('one'))
915
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
916
    def test_writes_are_serialized(self):
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
917
        c1 = self.config
918
        c2 = self.get_existing_config()
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
919
920
        # We spawn a thread that will pause *during* the write
921
        before_writing = threading.Event()
922
        after_writing = threading.Event()
923
        writing_done = threading.Event()
924
        c1_orig = c1._write_config_file
925
        def c1_write_config_file():
926
            before_writing.set()
927
            c1_orig()
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
928
            # The lock is held. We wait for the main thread to decide when to
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
929
            # continue
930
            after_writing.wait()
931
        c1._write_config_file = c1_write_config_file
932
        def c1_set_option():
933
            c1.set_user_option('one', 'c1')
934
            writing_done.set()
935
        t1 = threading.Thread(target=c1_set_option)
936
        # Collect the thread after the test
937
        self.addCleanup(t1.join)
938
        # Be ready to unblock the thread if the test goes wrong
939
        self.addCleanup(after_writing.set)
940
        t1.start()
941
        before_writing.wait()
942
        self.assertTrue(c1._lock.is_held)
943
        self.assertRaises(errors.LockContention,
944
                          c2.set_user_option, 'one', 'c2')
945
        self.assertEquals('c1', c1.get_user_option('one'))
946
        # Let the lock be released
947
        after_writing.set()
948
        writing_done.wait()
949
        c2.set_user_option('one', 'c2')
950
        self.assertEquals('c2', c2.get_user_option('one'))
951
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
952
    def test_read_while_writing(self):
953
       c1 = self.config
954
       # We spawn a thread that will pause *during* the write
955
       ready_to_write = threading.Event()
956
       do_writing = threading.Event()
957
       writing_done = threading.Event()
958
       c1_orig = c1._write_config_file
959
       def c1_write_config_file():
960
           ready_to_write.set()
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
961
           # The lock is held. We wait for the main thread to decide when to
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
962
           # continue
963
           do_writing.wait()
964
           c1_orig()
965
           writing_done.set()
966
       c1._write_config_file = c1_write_config_file
967
       def c1_set_option():
968
           c1.set_user_option('one', 'c1')
969
       t1 = threading.Thread(target=c1_set_option)
970
       # Collect the thread after the test
971
       self.addCleanup(t1.join)
972
       # Be ready to unblock the thread if the test goes wrong
973
       self.addCleanup(do_writing.set)
974
       t1.start()
975
       # Ensure the thread is ready to write
976
       ready_to_write.wait()
977
       self.assertTrue(c1._lock.is_held)
978
       self.assertEquals('c1', c1.get_user_option('one'))
979
       # If we read during the write, we get the old value
980
       c2 = self.get_existing_config()
981
       self.assertEquals('1', c2.get_user_option('one'))
982
       # Let the writing occur and ensure it occurred
983
       do_writing.set()
984
       writing_done.wait()
985
       # Now we get the updated value
986
       c3 = self.get_existing_config()
987
       self.assertEquals('c1', c3.get_user_option('one'))
988
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
989
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
990
class TestGetUserOptionAs(TestIniConfig):
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
991
4503.2.2 by Vincent Ladeuil
Get a bool or none from a config file.
992
    def test_get_user_option_as_bool(self):
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
993
        conf, parser = self.make_config_parser("""
4503.2.2 by Vincent Ladeuil
Get a bool or none from a config file.
994
a_true_bool = true
995
a_false_bool = 0
996
an_invalid_bool = maybe
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
997
a_list = hmm, who knows ? # This is interpreted as a list !
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
998
""")
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
999
        get_bool = conf.get_user_option_as_bool
1000
        self.assertEqual(True, get_bool('a_true_bool'))
1001
        self.assertEqual(False, get_bool('a_false_bool'))
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
1002
        warnings = []
1003
        def warning(*args):
1004
            warnings.append(args[0] % args[1:])
1005
        self.overrideAttr(trace, 'warning', warning)
1006
        msg = 'Value "%s" is not a boolean for "%s"'
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1007
        self.assertIs(None, get_bool('an_invalid_bool'))
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
1008
        self.assertEquals(msg % ('maybe', 'an_invalid_bool'), warnings[0])
1009
        warnings = []
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1010
        self.assertIs(None, get_bool('not_defined_in_this_config'))
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
1011
        self.assertEquals([], warnings)
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
1012
1013
    def test_get_user_option_as_list(self):
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1014
        conf, parser = self.make_config_parser("""
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
1015
a_list = a,b,c
1016
length_1 = 1,
1017
one_item = x
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1018
""")
1019
        get_list = conf.get_user_option_as_list
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
1020
        self.assertEqual(['a', 'b', 'c'], get_list('a_list'))
1021
        self.assertEqual(['1'], get_list('length_1'))
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1022
        self.assertEqual('x', conf.get_user_option('one_item'))
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
1023
        # automatically cast to list
1024
        self.assertEqual(['x'], get_list('one_item'))
1025
1026
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
1027
class TestSupressWarning(TestIniConfig):
1028
1029
    def make_warnings_config(self, s):
1030
        conf, parser = self.make_config_parser(s)
1031
        return conf.suppress_warning
1032
1033
    def test_suppress_warning_unknown(self):
1034
        suppress_warning = self.make_warnings_config('')
1035
        self.assertEqual(False, suppress_warning('unknown_warning'))
1036
1037
    def test_suppress_warning_known(self):
1038
        suppress_warning = self.make_warnings_config('suppress_warnings=a,b')
1039
        self.assertEqual(False, suppress_warning('c'))
1040
        self.assertEqual(True, suppress_warning('a'))
1041
        self.assertEqual(True, suppress_warning('b'))
1042
1043
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1044
class TestGetConfig(tests.TestCase):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1045
1046
    def test_constructs(self):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1047
        my_config = config.GlobalConfig()
1048
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1049
    def test_calls_read_filenames(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1050
        # replace the class that is constructed, to check its parameters
1474 by Robert Collins
Merge from Aaron Bentley.
1051
        oldparserclass = config.ConfigObj
1052
        config.ConfigObj = InstrumentedConfigObj
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1053
        my_config = config.GlobalConfig()
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1054
        try:
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1055
            parser = my_config._get_parser()
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1056
        finally:
1474 by Robert Collins
Merge from Aaron Bentley.
1057
            config.ConfigObj = oldparserclass
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1058
        self.assertIsInstance(parser, InstrumentedConfigObj)
1551.2.20 by Aaron Bentley
Treated config files as utf-8
1059
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
1060
                                          'utf-8')])
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1061
1062
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1063
class TestBranchConfig(tests.TestCaseWithTransport):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1064
1065
    def test_constructs(self):
1066
        branch = FakeBranch()
1067
        my_config = config.BranchConfig(branch)
1068
        self.assertRaises(TypeError, config.BranchConfig)
1069
1070
    def test_get_location_config(self):
1071
        branch = FakeBranch()
1072
        my_config = config.BranchConfig(branch)
1073
        location_config = my_config._get_location_config()
1074
        self.assertEqual(branch.base, location_config.location)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1075
        self.assertIs(location_config, my_config._get_location_config())
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1076
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1077
    def test_get_config(self):
1078
        """The Branch.get_config method works properly"""
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1079
        b = bzrdir.BzrDir.create_standalone_workingtree('.').branch
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1080
        my_config = b.get_config()
1081
        self.assertIs(my_config.get_user_option('wacky'), None)
1082
        my_config.set_user_option('wacky', 'unlikely')
1083
        self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
1084
1085
        # Ensure we get the same thing if we start again
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1086
        b2 = branch.Branch.open('.')
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1087
        my_config2 = b2.get_config()
1088
        self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
1089
1824.1.1 by Robert Collins
Add BranchConfig.has_explicit_nickname call.
1090
    def test_has_explicit_nickname(self):
1091
        b = self.make_branch('.')
1092
        self.assertFalse(b.get_config().has_explicit_nickname())
1093
        b.nick = 'foo'
1094
        self.assertTrue(b.get_config().has_explicit_nickname())
1095
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1096
    def test_config_url(self):
1097
        """The Branch.get_config will use section that uses a local url"""
1098
        branch = self.make_branch('branch')
1099
        self.assertEqual('branch', branch.nick)
1100
1101
        local_url = urlutils.local_path_to_url('branch')
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
1102
        conf = config.LocationConfig.from_string(
5345.1.25 by Vincent Ladeuil
Move the '_save' parameter from '__init__' to 'from_bytes', fix fallouts.
1103
            '[%s]\nnickname = foobar' % (local_url,),
1104
            local_url, save=True)
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1105
        self.assertEqual('foobar', branch.nick)
1106
1107
    def test_config_local_path(self):
1108
        """The Branch.get_config will use a local system path"""
1109
        branch = self.make_branch('branch')
1110
        self.assertEqual('branch', branch.nick)
1111
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1112
        local_path = osutils.getcwd().encode('utf8')
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
1113
        conf = config.LocationConfig.from_string(
5345.1.25 by Vincent Ladeuil
Move the '_save' parameter from '__init__' to 'from_bytes', fix fallouts.
1114
            '[%s/branch]\nnickname = barry' % (local_path,),
1115
            'branch',  save=True)
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1116
        self.assertEqual('barry', branch.nick)
1117
1878.1.2 by John Arbash Meinel
Add a test that new locations.conf entries are created with a local path, rather than a URL
1118
    def test_config_creates_local(self):
1119
        """Creating a new entry in config uses a local path."""
2230.3.6 by Aaron Bentley
work in progress bind stuff
1120
        branch = self.make_branch('branch', format='knit')
1878.1.2 by John Arbash Meinel
Add a test that new locations.conf entries are created with a local path, rather than a URL
1121
        branch.set_push_location('http://foobar')
1122
        local_path = osutils.getcwd().encode('utf8')
1123
        # Surprisingly ConfigObj doesn't create a trailing newline
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1124
        self.check_file_contents(config.locations_config_filename(),
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1125
                                 '[%s/branch]\n'
1126
                                 'push_location = http://foobar\n'
3221.7.1 by Matt Nordhoff
Upgrade ConfigObj to version 4.5.1.
1127
                                 'push_location:policy = norecurse\n'
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1128
                                 % (local_path,))
1878.1.2 by John Arbash Meinel
Add a test that new locations.conf entries are created with a local path, rather than a URL
1129
2120.5.4 by Alexander Belchenko
Whitebox test for Config.get_nickname (req. by Aaron Bentley)
1130
    def test_autonick_urlencoded(self):
1131
        b = self.make_branch('!repo')
1132
        self.assertEqual('!repo', b.get_config().get_nickname())
1133
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1134
    def test_warn_if_masked(self):
1135
        warnings = []
1136
        def warning(*args):
1137
            warnings.append(args[0] % args[1:])
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1138
        self.overrideAttr(trace, 'warning', warning)
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1139
1140
        def set_option(store, warn_masked=True):
1141
            warnings[:] = []
1142
            conf.set_user_option('example_option', repr(store), store=store,
1143
                                 warn_masked=warn_masked)
1144
        def assertWarning(warning):
1145
            if warning is None:
1146
                self.assertEqual(0, len(warnings))
1147
            else:
1148
                self.assertEqual(1, len(warnings))
1149
                self.assertEqual(warning, warnings[0])
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1150
        branch = self.make_branch('.')
1151
        conf = branch.get_config()
1152
        set_option(config.STORE_GLOBAL)
1153
        assertWarning(None)
1154
        set_option(config.STORE_BRANCH)
1155
        assertWarning(None)
1156
        set_option(config.STORE_GLOBAL)
1157
        assertWarning('Value "4" is masked by "3" from branch.conf')
1158
        set_option(config.STORE_GLOBAL, warn_masked=False)
1159
        assertWarning(None)
1160
        set_option(config.STORE_LOCATION)
1161
        assertWarning(None)
1162
        set_option(config.STORE_BRANCH)
1163
        assertWarning('Value "3" is masked by "0" from locations.conf')
1164
        set_option(config.STORE_BRANCH, warn_masked=False)
1165
        assertWarning(None)
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1166
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1167
5448.1.1 by Vincent Ladeuil
Use TestCaseInTempDir for tests requiring disk resources
1168
class TestGlobalConfigItems(tests.TestCaseInTempDir):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1169
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1170
    def test_user_id(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1171
        my_config = config.GlobalConfig.from_string(sample_config_text)
1551.2.21 by Aaron Bentley
Formatted unicode config tests as ASCII
1172
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1173
                         my_config._get_user_id())
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1174
1175
    def test_absent_user_id(self):
5345.2.2 by Vincent Ladeuil
Simplify test config building.
1176
        my_config = config.GlobalConfig()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1177
        self.assertEqual(None, my_config._get_user_id())
1178
1179
    def test_configured_editor(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1180
        my_config = config.GlobalConfig.from_string(sample_config_text)
5743.13.1 by Vincent Ladeuil
Deprecate _get_editor to identify its usages.
1181
        editor = self.applyDeprecated(
1182
            deprecated_in((2, 4, 0)), my_config.get_editor)
1183
        self.assertEqual('vim', editor)
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1184
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
1185
    def test_signatures_always(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1186
        my_config = config.GlobalConfig.from_string(sample_always_signatures)
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1187
        self.assertEqual(config.CHECK_NEVER,
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
1188
                         my_config.signature_checking())
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1189
        self.assertEqual(config.SIGN_ALWAYS,
1190
                         my_config.signing_policy())
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
1191
        self.assertEqual(True, my_config.signature_needed())
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
1192
1193
    def test_signatures_if_possible(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1194
        my_config = config.GlobalConfig.from_string(sample_maybe_signatures)
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1195
        self.assertEqual(config.CHECK_NEVER,
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
1196
                         my_config.signature_checking())
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1197
        self.assertEqual(config.SIGN_WHEN_REQUIRED,
1198
                         my_config.signing_policy())
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
1199
        self.assertEqual(False, my_config.signature_needed())
1442.1.17 by Robert Collins
allow global overriding of signature policy to force checking, or (pointless but allowed) to set auto checking
1200
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1201
    def test_signatures_ignore(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1202
        my_config = config.GlobalConfig.from_string(sample_ignore_signatures)
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1203
        self.assertEqual(config.CHECK_ALWAYS,
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1204
                         my_config.signature_checking())
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1205
        self.assertEqual(config.SIGN_NEVER,
1206
                         my_config.signing_policy())
1442.1.21 by Robert Collins
create signature_needed() call for commit to trigger creating signatures
1207
        self.assertEqual(False, my_config.signature_needed())
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1208
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1209
    def _get_sample_config(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1210
        my_config = config.GlobalConfig.from_string(sample_config_text)
1534.7.154 by Aaron Bentley
Removed changes from bzr.ab 1529..1536
1211
        return my_config
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1212
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1213
    def test_gpg_signing_command(self):
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1214
        my_config = self._get_sample_config()
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1215
        self.assertEqual("gnome-gpg", my_config.gpg_signing_command())
1216
        self.assertEqual(False, my_config.signature_needed())
1217
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1218
    def _get_empty_config(self):
5345.2.2 by Vincent Ladeuil
Simplify test config building.
1219
        my_config = config.GlobalConfig()
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1220
        return my_config
1221
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
1222
    def test_gpg_signing_command_unset(self):
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1223
        my_config = self._get_empty_config()
1442.1.59 by Robert Collins
Add re-sign command to generate a digital signature on a single revision.
1224
        self.assertEqual("gpg", my_config.gpg_signing_command())
1225
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1226
    def test_get_user_option_default(self):
1227
        my_config = self._get_empty_config()
1228
        self.assertEqual(None, my_config.get_user_option('no_option'))
1229
1230
    def test_get_user_option_global(self):
1231
        my_config = self._get_sample_config()
1232
        self.assertEqual("something",
1233
                         my_config.get_user_option('user_global_option'))
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1234
1472 by Robert Collins
post commit hook, first pass implementation
1235
    def test_post_commit_default(self):
1236
        my_config = self._get_sample_config()
1237
        self.assertEqual(None, my_config.post_commit())
1238
1553.2.9 by Erik Bågfors
log_formatter => log_format for "named" formatters
1239
    def test_configured_logformat(self):
1553.2.8 by Erik Bågfors
tests for config log_formatter
1240
        my_config = self._get_sample_config()
1553.2.9 by Erik Bågfors
log_formatter => log_format for "named" formatters
1241
        self.assertEqual("short", my_config.log_format())
1553.2.8 by Erik Bågfors
tests for config log_formatter
1242
1553.6.12 by Erik Bågfors
remove AliasConfig, based on input from abentley
1243
    def test_get_alias(self):
1244
        my_config = self._get_sample_config()
1245
        self.assertEqual('help', my_config.get_alias('h'))
1246
2900.3.6 by Tim Penhey
Added tests.
1247
    def test_get_aliases(self):
1248
        my_config = self._get_sample_config()
1249
        aliases = my_config.get_aliases()
1250
        self.assertEqual(2, len(aliases))
1251
        sorted_keys = sorted(aliases)
1252
        self.assertEqual('help', aliases[sorted_keys[0]])
1253
        self.assertEqual(sample_long_alias, aliases[sorted_keys[1]])
1254
1553.6.12 by Erik Bågfors
remove AliasConfig, based on input from abentley
1255
    def test_get_no_alias(self):
1256
        my_config = self._get_sample_config()
1257
        self.assertEqual(None, my_config.get_alias('foo'))
1258
1259
    def test_get_long_alias(self):
1260
        my_config = self._get_sample_config()
1261
        self.assertEqual(sample_long_alias, my_config.get_alias('ll'))
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1262
4603.1.10 by Aaron Bentley
Provide change editor via config.
1263
    def test_get_change_editor(self):
1264
        my_config = self._get_sample_config()
1265
        change_editor = my_config.get_change_editor('old', 'new')
1266
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
1267
        self.assertEqual('vimdiff -of @new_path @old_path',
4603.1.10 by Aaron Bentley
Provide change editor via config.
1268
                         ' '.join(change_editor.command_template))
1269
1270
    def test_get_no_change_editor(self):
1271
        my_config = self._get_empty_config()
1272
        change_editor = my_config.get_change_editor('old', 'new')
1273
        self.assertIs(None, change_editor)
1274
5321.1.89 by Gordon Tyler
Moved mergetools config tests to bzrlib.tests.test_config.
1275
    def test_get_merge_tools(self):
1276
        conf = self._get_sample_config()
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1277
        tools = conf.get_merge_tools()
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
1278
        self.log(repr(tools))
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1279
        self.assertEqual(
1280
            {u'funkytool' : u'funkytool "arg with spaces" {this_temp}',
1281
            u'sometool' : u'sometool {base} {this} {other} -o {result}'},
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
1282
            tools)
5321.1.89 by Gordon Tyler
Moved mergetools config tests to bzrlib.tests.test_config.
1283
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1284
    def test_get_merge_tools_empty(self):
5321.1.93 by Gordon Tyler
Added tests for get_default_merge_tool.
1285
        conf = self._get_empty_config()
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1286
        tools = conf.get_merge_tools()
1287
        self.assertEqual({}, tools)
5321.1.103 by Gordon Tyler
Renamed _find_merge_tool back to find_merge_tool since it must be public for UI code to lookup merge tools by name, and added tests for it.
1288
1289
    def test_find_merge_tool(self):
1290
        conf = self._get_sample_config()
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1291
        cmdline = conf.find_merge_tool('sometool')
1292
        self.assertEqual('sometool {base} {this} {other} -o {result}', cmdline)
5321.1.103 by Gordon Tyler
Renamed _find_merge_tool back to find_merge_tool since it must be public for UI code to lookup merge tools by name, and added tests for it.
1293
1294
    def test_find_merge_tool_not_found(self):
1295
        conf = self._get_sample_config()
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1296
        cmdline = conf.find_merge_tool('DOES NOT EXIST')
1297
        self.assertIs(cmdline, None)
5321.1.93 by Gordon Tyler
Added tests for get_default_merge_tool.
1298
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
1299
    def test_find_merge_tool_known(self):
1300
        conf = self._get_empty_config()
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1301
        cmdline = conf.find_merge_tool('kdiff3')
1302
        self.assertEquals('kdiff3 {base} {this} {other} -o {result}', cmdline)
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
1303
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
1304
    def test_find_merge_tool_override_known(self):
1305
        conf = self._get_empty_config()
5321.1.112 by Gordon Tyler
Removed set_merge_tool, remove_merge_tool and set_default_merge_tool from Config.
1306
        conf.set_user_option('bzr.mergetool.kdiff3', 'kdiff3 blah')
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1307
        cmdline = conf.find_merge_tool('kdiff3')
1308
        self.assertEqual('kdiff3 blah', cmdline)
5321.1.108 by Gordon Tyler
Changed known merge tools into a default set of merge tools that are always defined but can be overridden by user-defined merge tools.
1309
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1310
2900.3.6 by Tim Penhey
Added tests.
1311
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
1312
1313
    def test_empty(self):
1314
        my_config = config.GlobalConfig()
1315
        self.assertEqual(0, len(my_config.get_aliases()))
1316
1317
    def test_set_alias(self):
1318
        my_config = config.GlobalConfig()
1319
        alias_value = 'commit --strict'
1320
        my_config.set_alias('commit', alias_value)
1321
        new_config = config.GlobalConfig()
1322
        self.assertEqual(alias_value, new_config.get_alias('commit'))
1323
1324
    def test_remove_alias(self):
1325
        my_config = config.GlobalConfig()
1326
        my_config.set_alias('commit', 'commit --strict')
1327
        # Now remove the alias again.
1328
        my_config.unset_alias('commit')
1329
        new_config = config.GlobalConfig()
1330
        self.assertIs(None, new_config.get_alias('commit'))
1331
1332
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1333
class TestLocationConfig(tests.TestCaseInTempDir, TestOptionsMixin):
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1334
1335
    def test_constructs(self):
1336
        my_config = config.LocationConfig('http://example.com')
1337
        self.assertRaises(TypeError, config.LocationConfig)
1338
1339
    def test_branch_calls_read_filenames(self):
1474 by Robert Collins
Merge from Aaron Bentley.
1340
        # This is testing the correct file names are provided.
1341
        # TODO: consolidate with the test for GlobalConfigs filename checks.
1342
        #
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1343
        # replace the class that is constructed, to check its parameters
1474 by Robert Collins
Merge from Aaron Bentley.
1344
        oldparserclass = config.ConfigObj
1345
        config.ConfigObj = InstrumentedConfigObj
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1346
        try:
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
1347
            my_config = config.LocationConfig('http://www.example.com')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1348
            parser = my_config._get_parser()
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1349
        finally:
1474 by Robert Collins
Merge from Aaron Bentley.
1350
            config.ConfigObj = oldparserclass
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1351
        self.assertIsInstance(parser, InstrumentedConfigObj)
1474 by Robert Collins
Merge from Aaron Bentley.
1352
        self.assertEqual(parser._calls,
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
1353
                         [('__init__', config.locations_config_filename(),
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1354
                           'utf-8')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1355
1356
    def test_get_global_config(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1357
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1358
        global_config = my_config._get_global_config()
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1359
        self.assertIsInstance(global_config, config.GlobalConfig)
1360
        self.assertIs(global_config, my_config._get_global_config())
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1361
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1362
    def assertLocationMatching(self, expected):
1363
        self.assertEqual(expected,
1364
                         list(self.my_location_config._get_matching_sections()))
1365
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1366
    def test__get_matching_sections_no_match(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1367
        self.get_branch_config('/')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1368
        self.assertLocationMatching([])
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1369
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1370
    def test__get_matching_sections_exact(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1371
        self.get_branch_config('http://www.example.com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1372
        self.assertLocationMatching([('http://www.example.com', '')])
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1373
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1374
    def test__get_matching_sections_suffix_does_not(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1375
        self.get_branch_config('http://www.example.com-com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1376
        self.assertLocationMatching([])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1377
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1378
    def test__get_matching_sections_subdir_recursive(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1379
        self.get_branch_config('http://www.example.com/com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1380
        self.assertLocationMatching([('http://www.example.com', 'com')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1381
1993.3.5 by James Henstridge
add back recurse=False option to config file
1382
    def test__get_matching_sections_ignoreparent(self):
1993.3.3 by James Henstridge
make _get_matching_sections() return (section, extra_path) tuples, and adjust other code to match
1383
        self.get_branch_config('http://www.example.com/ignoreparent')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1384
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
1385
                                      '')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1386
1993.3.5 by James Henstridge
add back recurse=False option to config file
1387
    def test__get_matching_sections_ignoreparent_subdir(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1388
        self.get_branch_config(
1993.3.3 by James Henstridge
make _get_matching_sections() return (section, extra_path) tuples, and adjust other code to match
1389
            'http://www.example.com/ignoreparent/childbranch')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1390
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
1391
                                      'childbranch')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1392
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1393
    def test__get_matching_sections_subdir_trailing_slash(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1394
        self.get_branch_config('/b')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1395
        self.assertLocationMatching([('/b/', '')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1396
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1397
    def test__get_matching_sections_subdir_child(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1398
        self.get_branch_config('/a/foo')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1399
        self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1400
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1401
    def test__get_matching_sections_subdir_child_child(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1402
        self.get_branch_config('/a/foo/bar')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1403
        self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1404
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1405
    def test__get_matching_sections_trailing_slash_with_children(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1406
        self.get_branch_config('/a/')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1407
        self.assertLocationMatching([('/a/', '')])
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1408
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1409
    def test__get_matching_sections_explicit_over_glob(self):
1410
        # XXX: 2006-09-08 jamesh
1411
        # This test only passes because ord('c') > ord('*').  If there
1412
        # was a config section for '/a/?', it would get precedence
1413
        # over '/a/c'.
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1414
        self.get_branch_config('/a/c')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1415
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1416
2120.6.3 by James Henstridge
add some more tests for getting policy options, and behaviour of get_user_option in the presence of config policies
1417
    def test__get_option_policy_normal(self):
1418
        self.get_branch_config('http://www.example.com')
1419
        self.assertEqual(
1420
            self.my_location_config._get_config_policy(
1421
            'http://www.example.com', 'normal_option'),
1422
            config.POLICY_NONE)
1423
1424
    def test__get_option_policy_norecurse(self):
1425
        self.get_branch_config('http://www.example.com')
1426
        self.assertEqual(
1427
            self.my_location_config._get_option_policy(
1428
            'http://www.example.com', 'norecurse_option'),
1429
            config.POLICY_NORECURSE)
1430
        # Test old recurse=False setting:
1431
        self.assertEqual(
1432
            self.my_location_config._get_option_policy(
1433
            'http://www.example.com/norecurse', 'normal_option'),
1434
            config.POLICY_NORECURSE)
1435
1436
    def test__get_option_policy_normal(self):
1437
        self.get_branch_config('http://www.example.com')
1438
        self.assertEqual(
1439
            self.my_location_config._get_option_policy(
1440
            'http://www.example.com', 'appendpath_option'),
1441
            config.POLICY_APPENDPATH)
1442
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1443
    def test__get_options_with_policy(self):
1444
        self.get_branch_config('/dir/subdir',
1445
                               location_config="""\
1446
[/dir]
1447
other_url = /other-dir
1448
other_url:policy = appendpath
1449
[/dir/subdir]
1450
other_url = /other-subdir
1451
""")
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1452
        self.assertOptions(
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1453
            [(u'other_url', u'/other-subdir', u'/dir/subdir', 'locations'),
1454
             (u'other_url', u'/other-dir', u'/dir', 'locations'),
1455
             (u'other_url:policy', u'appendpath', u'/dir', 'locations')],
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1456
            self.my_location_config)
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1457
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1458
    def test_location_without_username(self):
1993.3.3 by James Henstridge
make _get_matching_sections() return (section, extra_path) tuples, and adjust other code to match
1459
        self.get_branch_config('http://www.example.com/ignoreparent')
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1460
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1461
                         self.my_config.username())
1462
1463
    def test_location_not_listed(self):
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1464
        """Test that the global username is used when no location matches"""
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1465
        self.get_branch_config('/home/robertc/sources')
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1466
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1467
                         self.my_config.username())
1468
1442.1.13 by Robert Collins
branches.conf is now able to override the users email
1469
    def test_overriding_location(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1470
        self.get_branch_config('http://www.example.com/foo')
1442.1.13 by Robert Collins
branches.conf is now able to override the users email
1471
        self.assertEqual('Robert Collins <robertc@example.org>',
1472
                         self.my_config.username())
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1473
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1474
    def test_signatures_not_set(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1475
        self.get_branch_config('http://www.example.com',
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1476
                                 global_config=sample_ignore_signatures)
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1477
        self.assertEqual(config.CHECK_ALWAYS,
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1478
                         self.my_config.signature_checking())
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1479
        self.assertEqual(config.SIGN_NEVER,
1480
                         self.my_config.signing_policy())
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1481
1482
    def test_signatures_never(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1483
        self.get_branch_config('/a/c')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1484
        self.assertEqual(config.CHECK_NEVER,
1485
                         self.my_config.signature_checking())
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1486
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1487
    def test_signatures_when_available(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1488
        self.get_branch_config('/a/', global_config=sample_ignore_signatures)
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1489
        self.assertEqual(config.CHECK_IF_POSSIBLE,
1490
                         self.my_config.signature_checking())
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1491
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1492
    def test_signatures_always(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1493
        self.get_branch_config('/b')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1494
        self.assertEqual(config.CHECK_ALWAYS,
1495
                         self.my_config.signature_checking())
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1496
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1497
    def test_gpg_signing_command(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1498
        self.get_branch_config('/b')
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1499
        self.assertEqual("gnome-gpg", self.my_config.gpg_signing_command())
1500
1501
    def test_gpg_signing_command_missing(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1502
        self.get_branch_config('/a')
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1503
        self.assertEqual("false", self.my_config.gpg_signing_command())
1504
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1505
    def test_get_user_option_global(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1506
        self.get_branch_config('/a')
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1507
        self.assertEqual('something',
1508
                         self.my_config.get_user_option('user_global_option'))
1509
1510
    def test_get_user_option_local(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1511
        self.get_branch_config('/a')
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1512
        self.assertEqual('local',
1513
                         self.my_config.get_user_option('user_local_option'))
1993.3.3 by James Henstridge
make _get_matching_sections() return (section, extra_path) tuples, and adjust other code to match
1514
2120.6.3 by James Henstridge
add some more tests for getting policy options, and behaviour of get_user_option in the presence of config policies
1515
    def test_get_user_option_appendpath(self):
1516
        # returned as is for the base path:
1517
        self.get_branch_config('http://www.example.com')
1518
        self.assertEqual('append',
1519
                         self.my_config.get_user_option('appendpath_option'))
1520
        # Extra path components get appended:
1521
        self.get_branch_config('http://www.example.com/a/b/c')
1522
        self.assertEqual('append/a/b/c',
1523
                         self.my_config.get_user_option('appendpath_option'))
1524
        # Overriden for http://www.example.com/dir, where it is a
1525
        # normal option:
1526
        self.get_branch_config('http://www.example.com/dir/a/b/c')
1527
        self.assertEqual('normal',
1528
                         self.my_config.get_user_option('appendpath_option'))
1529
1530
    def test_get_user_option_norecurse(self):
1531
        self.get_branch_config('http://www.example.com')
1532
        self.assertEqual('norecurse',
1533
                         self.my_config.get_user_option('norecurse_option'))
1534
        self.get_branch_config('http://www.example.com/dir')
1535
        self.assertEqual(None,
1536
                         self.my_config.get_user_option('norecurse_option'))
1537
        # http://www.example.com/norecurse is a recurse=False section
1538
        # that redefines normal_option.  Subdirectories do not pick up
1539
        # this redefinition.
1540
        self.get_branch_config('http://www.example.com/norecurse')
1541
        self.assertEqual('norecurse',
1542
                         self.my_config.get_user_option('normal_option'))
1543
        self.get_branch_config('http://www.example.com/norecurse/subdir')
1544
        self.assertEqual('normal',
1545
                         self.my_config.get_user_option('normal_option'))
1546
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1547
    def test_set_user_option_norecurse(self):
1548
        self.get_branch_config('http://www.example.com')
1549
        self.my_config.set_user_option('foo', 'bar',
1550
                                       store=config.STORE_LOCATION_NORECURSE)
1551
        self.assertEqual(
1552
            self.my_location_config._get_option_policy(
1553
            'http://www.example.com', 'foo'),
1554
            config.POLICY_NORECURSE)
1555
1556
    def test_set_user_option_appendpath(self):
1557
        self.get_branch_config('http://www.example.com')
1558
        self.my_config.set_user_option('foo', 'bar',
1559
                                       store=config.STORE_LOCATION_APPENDPATH)
1560
        self.assertEqual(
1561
            self.my_location_config._get_option_policy(
1562
            'http://www.example.com', 'foo'),
1563
            config.POLICY_APPENDPATH)
1564
1565
    def test_set_user_option_change_policy(self):
1566
        self.get_branch_config('http://www.example.com')
1567
        self.my_config.set_user_option('norecurse_option', 'normal',
1568
                                       store=config.STORE_LOCATION)
1569
        self.assertEqual(
1570
            self.my_location_config._get_option_policy(
1571
            'http://www.example.com', 'norecurse_option'),
1572
            config.POLICY_NONE)
1573
1574
    def test_set_user_option_recurse_false_section(self):
2120.6.9 by James Henstridge
Fixes for issues brought up in John's review
1575
        # The following section has recurse=False set.  The test is to
1576
        # make sure that a normal option can be added to the section,
1577
        # converting recurse=False to the norecurse policy.
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1578
        self.get_branch_config('http://www.example.com/norecurse')
2120.6.11 by James Henstridge
s/0.13/0.14/ in deprecation warning
1579
        self.callDeprecated(['The recurse option is deprecated as of 0.14.  '
2120.6.9 by James Henstridge
Fixes for issues brought up in John's review
1580
                             'The section "http://www.example.com/norecurse" '
1581
                             'has been converted to use policies.'],
1582
                            self.my_config.set_user_option,
1583
                            'foo', 'bar', store=config.STORE_LOCATION)
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1584
        self.assertEqual(
1585
            self.my_location_config._get_option_policy(
1586
            'http://www.example.com/norecurse', 'foo'),
1587
            config.POLICY_NONE)
1588
        # The previously existing option is still norecurse:
1589
        self.assertEqual(
1590
            self.my_location_config._get_option_policy(
1591
            'http://www.example.com/norecurse', 'normal_option'),
1592
            config.POLICY_NORECURSE)
1593
1472 by Robert Collins
post commit hook, first pass implementation
1594
    def test_post_commit_default(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1595
        self.get_branch_config('/a/c')
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
1596
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1472 by Robert Collins
post commit hook, first pass implementation
1597
                         self.my_config.post_commit())
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1598
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1599
    def get_branch_config(self, location, global_config=None,
1600
                          location_config=None):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1601
        my_branch = FakeBranch(location)
1502 by Robert Collins
Bugfix the config test suite to not create .bazaar in the dir where it is run.
1602
        if global_config is None:
5345.2.2 by Vincent Ladeuil
Simplify test config building.
1603
            global_config = sample_config_text
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1604
        if location_config is None:
1605
            location_config = sample_branches_text
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1606
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
1607
        my_global_config = config.GlobalConfig.from_string(global_config,
1608
                                                           save=True)
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1609
        my_location_config = config.LocationConfig.from_string(
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1610
            location_config, my_branch.base, save=True)
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1611
        my_config = config.BranchConfig(my_branch)
1612
        self.my_config = my_config
1613
        self.my_location_config = my_config._get_location_config()
1502 by Robert Collins
Bugfix the config test suite to not create .bazaar in the dir where it is run.
1614
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1615
    def test_set_user_setting_sets_and_saves(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1616
        self.get_branch_config('/a/c')
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1617
        record = InstrumentedConfigObj("foo")
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1618
        self.my_location_config._parser = record
1185.62.6 by John Arbash Meinel
Updated test_set_user_setting_sets_and_saves to remove the print statement, and make sure it is doing the right thing
1619
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1620
        self.callDeprecated(['The recurse option is deprecated as of '
1621
                             '0.14.  The section "/a/c" has been '
1622
                             'converted to use policies.'],
1623
                            self.my_config.set_user_option,
1624
                            'foo', 'bar', store=config.STORE_LOCATION)
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
1625
        self.assertEqual([('reload',),
1626
                          ('__contains__', '/a/c'),
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1627
                          ('__contains__', '/a/c/'),
1628
                          ('__setitem__', '/a/c', {}),
1629
                          ('__getitem__', '/a/c'),
1630
                          ('__setitem__', 'foo', 'bar'),
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1631
                          ('__getitem__', '/a/c'),
1632
                          ('as_bool', 'recurse'),
1633
                          ('__getitem__', '/a/c'),
1634
                          ('__delitem__', 'recurse'),
1635
                          ('__getitem__', '/a/c'),
1636
                          ('keys',),
2120.6.8 by James Henstridge
Change syntax for setting config option policies. Rather than
1637
                          ('__getitem__', '/a/c'),
1638
                          ('__contains__', 'foo:policy'),
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
1639
                          ('write',)],
1640
                         record._calls[1:])
1641
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1642
    def test_set_user_setting_sets_and_saves2(self):
1643
        self.get_branch_config('/a/c')
1644
        self.assertIs(self.my_config.get_user_option('foo'), None)
1645
        self.my_config.set_user_option('foo', 'bar')
1646
        self.assertEqual(
3616.2.6 by Mark Hammond
Fix test_set_user_setting_sets_and_saves2 on windows by stripping EOL
1647
            self.my_config.branch.control_files.files['branch.conf'].strip(),
1648
            'foo = bar')
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1649
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1650
        self.my_config.set_user_option('foo', 'baz',
1651
                                       store=config.STORE_LOCATION)
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1652
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1653
        self.my_config.set_user_option('foo', 'qux')
1654
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1655
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
1656
    def test_get_bzr_remote_path(self):
1657
        my_config = config.LocationConfig('/a/c')
1658
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1659
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
1660
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
5570.3.9 by Vincent Ladeuil
More use cases for overrideEnv, _cleanEnvironment *may* contain too much variables now.
1661
        self.overrideEnv('BZR_REMOTE_PATH', '/environ-bzr')
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
1662
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
1663
1185.62.7 by John Arbash Meinel
Whitespace cleanup.
1664
1770.2.8 by Aaron Bentley
Add precedence test
1665
precedence_global = 'option = global'
1666
precedence_branch = 'option = branch'
1667
precedence_location = """
1668
[http://]
1669
recurse = true
1670
option = recurse
1671
[http://example.com/specific]
1672
option = exact
1673
"""
1674
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1675
class TestBranchConfigItems(tests.TestCaseInTempDir):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1676
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1677
    def get_branch_config(self, global_config=None, location=None,
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1678
                          location_config=None, branch_data_config=None):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1679
        my_branch = FakeBranch(location)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1680
        if global_config is not None:
5345.1.26 by Vincent Ladeuil
Merge lockable-config-files into remove-gratuitous-ensure-config-dir-exist-calls resolving conflicts
1681
            my_global_config = config.GlobalConfig.from_string(global_config,
1682
                                                               save=True)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1683
        if location_config is not None:
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1684
            my_location_config = config.LocationConfig.from_string(
5345.1.25 by Vincent Ladeuil
Move the '_save' parameter from '__init__' to 'from_bytes', fix fallouts.
1685
                location_config, my_branch.base, save=True)
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1686
        my_config = config.BranchConfig(my_branch)
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1687
        if branch_data_config is not None:
1688
            my_config.branch.control_files.files['branch.conf'] = \
1689
                branch_data_config
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1690
        return my_config
1691
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1692
    def test_user_id(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1693
        branch = FakeBranch(user_id='Robert Collins <robertc@example.net>')
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1694
        my_config = config.BranchConfig(branch)
1695
        self.assertEqual("Robert Collins <robertc@example.net>",
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1696
                         my_config.username())
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
1697
        my_config.branch.control_files.files['email'] = "John"
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1698
        my_config.set_user_option('email',
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1699
                                  "Robert Collins <robertc@example.org>")
1700
        self.assertEqual("John", my_config.username())
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
1701
        del my_config.branch.control_files.files['email']
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1702
        self.assertEqual("Robert Collins <robertc@example.org>",
1703
                         my_config.username())
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1704
1705
    def test_not_set_in_branch(self):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1706
        my_config = self.get_branch_config(global_config=sample_config_text)
1551.2.21 by Aaron Bentley
Formatted unicode config tests as ASCII
1707
        self.assertEqual(u"Erik B\u00e5gfors <erik@bagfors.nu>",
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1708
                         my_config._get_user_id())
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
1709
        my_config.branch.control_files.files['email'] = "John"
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1710
        self.assertEqual("John", my_config._get_user_id())
1711
1861.4.1 by Matthieu Moy
BZREMAIL renamed to BZR_EMAIL.
1712
    def test_BZR_EMAIL_OVERRIDES(self):
5570.3.9 by Vincent Ladeuil
More use cases for overrideEnv, _cleanEnvironment *may* contain too much variables now.
1713
        self.overrideEnv('BZR_EMAIL', "Robert Collins <robertc@example.org>")
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1714
        branch = FakeBranch()
1715
        my_config = config.BranchConfig(branch)
1716
        self.assertEqual("Robert Collins <robertc@example.org>",
1717
                         my_config.username())
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1718
1442.1.19 by Robert Collins
BranchConfigs inherit signature_checking policy from their LocationConfig.
1719
    def test_signatures_forced(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1720
        my_config = self.get_branch_config(
1721
            global_config=sample_always_signatures)
1770.2.1 by Aaron Bentley
Use create_signature for signing policy, deprecate check_signatures for this
1722
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1723
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1724
        self.assertTrue(my_config.signature_needed())
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1725
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1726
    def test_signatures_forced_branch(self):
1727
        my_config = self.get_branch_config(
1728
            global_config=sample_ignore_signatures,
1729
            branch_data_config=sample_always_signatures)
1730
        self.assertEqual(config.CHECK_NEVER, my_config.signature_checking())
1731
        self.assertEqual(config.SIGN_ALWAYS, my_config.signing_policy())
1732
        self.assertTrue(my_config.signature_needed())
1733
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1734
    def test_gpg_signing_command(self):
1770.2.10 by Aaron Bentley
Added test that branch_config can't influence gpg_signing_command
1735
        my_config = self.get_branch_config(
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1736
            global_config=sample_config_text,
1770.2.10 by Aaron Bentley
Added test that branch_config can't influence gpg_signing_command
1737
            # branch data cannot set gpg_signing_command
1738
            branch_data_config="gpg_signing_command=pgp")
1442.1.56 by Robert Collins
gpg_signing_command configuration item
1739
        self.assertEqual('gnome-gpg', my_config.gpg_signing_command())
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1740
1741
    def test_get_user_option_global(self):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1742
        my_config = self.get_branch_config(global_config=sample_config_text)
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1743
        self.assertEqual('something',
1744
                         my_config.get_user_option('user_global_option'))
1472 by Robert Collins
post commit hook, first pass implementation
1745
1746
    def test_post_commit_default(self):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1747
        my_config = self.get_branch_config(global_config=sample_config_text,
1748
                                      location='/a/c',
1749
                                      location_config=sample_branches_text)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1750
        self.assertEqual(my_config.branch.base, '/a/c')
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
1751
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1472 by Robert Collins
post commit hook, first pass implementation
1752
                         my_config.post_commit())
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1753
        my_config.set_user_option('post_commit', 'rmtree_root')
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1754
        # post-commit is ignored when present in branch data
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1755
        self.assertEqual('bzrlib.tests.test_config.post_commit',
1756
                         my_config.post_commit())
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1757
        my_config.set_user_option('post_commit', 'rmtree_root',
1758
                                  store=config.STORE_LOCATION)
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1759
        self.assertEqual('rmtree_root', my_config.post_commit())
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1760
1770.2.8 by Aaron Bentley
Add precedence test
1761
    def test_config_precedence(self):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1762
        # FIXME: eager test, luckily no persitent config file makes it fail
1763
        # -- vila 20100716
1770.2.8 by Aaron Bentley
Add precedence test
1764
        my_config = self.get_branch_config(global_config=precedence_global)
1765
        self.assertEqual(my_config.get_user_option('option'), 'global')
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1766
        my_config = self.get_branch_config(global_config=precedence_global,
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1767
                                           branch_data_config=precedence_branch)
1770.2.8 by Aaron Bentley
Add precedence test
1768
        self.assertEqual(my_config.get_user_option('option'), 'branch')
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1769
        my_config = self.get_branch_config(
1770
            global_config=precedence_global,
1771
            branch_data_config=precedence_branch,
1772
            location_config=precedence_location)
1770.2.8 by Aaron Bentley
Add precedence test
1773
        self.assertEqual(my_config.get_user_option('option'), 'recurse')
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1774
        my_config = self.get_branch_config(
1775
            global_config=precedence_global,
1776
            branch_data_config=precedence_branch,
1777
            location_config=precedence_location,
1778
            location='http://example.com/specific')
1770.2.8 by Aaron Bentley
Add precedence test
1779
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1780
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
1781
    def test_get_mail_client(self):
1782
        config = self.get_branch_config()
1783
        client = config.get_mail_client()
2681.1.24 by Aaron Bentley
Handle default mail client by trying xdg-email, falling back to editor
1784
        self.assertIsInstance(client, mail_client.DefaultMail)
1785
2790.2.2 by Keir Mierle
Change alphabetic ordering into two categories; one for specific clients the other for generic options.
1786
        # Specific clients
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
1787
        config.set_user_option('mail_client', 'evolution')
1788
        client = config.get_mail_client()
1789
        self.assertIsInstance(client, mail_client.Evolution)
1790
2681.5.1 by ghigo
Add KMail support to bzr send
1791
        config.set_user_option('mail_client', 'kmail')
1792
        client = config.get_mail_client()
1793
        self.assertIsInstance(client, mail_client.KMail)
1794
2790.2.1 by Keir Mierle
Add Mutt as a supported client email program. Also rearranges various listings
1795
        config.set_user_option('mail_client', 'mutt')
1796
        client = config.get_mail_client()
1797
        self.assertIsInstance(client, mail_client.Mutt)
1798
1799
        config.set_user_option('mail_client', 'thunderbird')
1800
        client = config.get_mail_client()
1801
        self.assertIsInstance(client, mail_client.Thunderbird)
1802
2790.2.2 by Keir Mierle
Change alphabetic ordering into two categories; one for specific clients the other for generic options.
1803
        # Generic options
1804
        config.set_user_option('mail_client', 'default')
1805
        client = config.get_mail_client()
1806
        self.assertIsInstance(client, mail_client.DefaultMail)
1807
1808
        config.set_user_option('mail_client', 'editor')
1809
        client = config.get_mail_client()
1810
        self.assertIsInstance(client, mail_client.Editor)
1811
1812
        config.set_user_option('mail_client', 'mapi')
1813
        client = config.get_mail_client()
1814
        self.assertIsInstance(client, mail_client.MAPIClient)
1815
2681.1.23 by Aaron Bentley
Add support for xdg-email
1816
        config.set_user_option('mail_client', 'xdg-email')
1817
        client = config.get_mail_client()
1818
        self.assertIsInstance(client, mail_client.XDGEmail)
1819
2681.1.10 by Aaron Bentley
Clean up handling of unknown mail clients
1820
        config.set_user_option('mail_client', 'firebird')
1821
        self.assertRaises(errors.UnknownMailClient, config.get_mail_client)
1822
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1823
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1824
class TestMailAddressExtraction(tests.TestCase):
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1825
1826
    def test_extract_email_address(self):
1827
        self.assertEqual('jane@test.com',
1828
                         config.extract_email_address('Jane <jane@test.com>'))
2055.2.2 by John Arbash Meinel
Switch extract_email_address() to use a more specific exception
1829
        self.assertRaises(errors.NoEmailInUsername,
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1830
                          config.extract_email_address, 'Jane Tester')
2533.1.1 by James Westby
Fix TreeConfig to return values from sections.
1831
3063.3.2 by Lukáš Lalinský
Move the name and e-mail address extraction logic to config.parse_username.
1832
    def test_parse_username(self):
1833
        self.assertEqual(('', 'jdoe@example.com'),
1834
                         config.parse_username('jdoe@example.com'))
1835
        self.assertEqual(('', 'jdoe@example.com'),
1836
                         config.parse_username('<jdoe@example.com>'))
1837
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1838
                         config.parse_username('John Doe <jdoe@example.com>'))
1839
        self.assertEqual(('John Doe', ''),
1840
                         config.parse_username('John Doe'))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1841
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1842
                         config.parse_username('John Doe jdoe@example.com'))
2562.1.2 by John Arbash Meinel
Clean up whitespace
1843
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1844
class TestTreeConfig(tests.TestCaseWithTransport):
2533.1.1 by James Westby
Fix TreeConfig to return values from sections.
1845
1846
    def test_get_value(self):
1847
        """Test that retreiving a value from a section is possible"""
1848
        branch = self.make_branch('.')
1849
        tree_config = config.TreeConfig(branch)
1850
        tree_config.set_option('value', 'key', 'SECTION')
1851
        tree_config.set_option('value2', 'key2')
1852
        tree_config.set_option('value3-top', 'key3')
1853
        tree_config.set_option('value3-section', 'key3', 'SECTION')
1854
        value = tree_config.get_option('key', 'SECTION')
1855
        self.assertEqual(value, 'value')
1856
        value = tree_config.get_option('key2')
1857
        self.assertEqual(value, 'value2')
1858
        self.assertEqual(tree_config.get_option('non-existant'), None)
1859
        value = tree_config.get_option('non-existant', 'SECTION')
1860
        self.assertEqual(value, None)
1861
        value = tree_config.get_option('non-existant', default='default')
1862
        self.assertEqual(value, 'default')
1863
        self.assertEqual(tree_config.get_option('key2', 'NOSECTION'), None)
1864
        value = tree_config.get_option('key2', 'NOSECTION', default='default')
1865
        self.assertEqual(value, 'default')
1866
        value = tree_config.get_option('key3')
1867
        self.assertEqual(value, 'value3-top')
1868
        value = tree_config.get_option('key3', 'SECTION')
1869
        self.assertEqual(value, 'value3-section')
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
1870
1871
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
1872
class TestTransportConfig(tests.TestCaseWithTransport):
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1873
1874
    def test_get_value(self):
1875
        """Test that retreiving a value from a section is possible"""
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
1876
        bzrdir_config = config.TransportConfig(transport.get_transport('.'),
1877
                                               'control.conf')
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1878
        bzrdir_config.set_option('value', 'key', 'SECTION')
1879
        bzrdir_config.set_option('value2', 'key2')
1880
        bzrdir_config.set_option('value3-top', 'key3')
1881
        bzrdir_config.set_option('value3-section', 'key3', 'SECTION')
1882
        value = bzrdir_config.get_option('key', 'SECTION')
1883
        self.assertEqual(value, 'value')
1884
        value = bzrdir_config.get_option('key2')
1885
        self.assertEqual(value, 'value2')
1886
        self.assertEqual(bzrdir_config.get_option('non-existant'), None)
1887
        value = bzrdir_config.get_option('non-existant', 'SECTION')
1888
        self.assertEqual(value, None)
1889
        value = bzrdir_config.get_option('non-existant', default='default')
1890
        self.assertEqual(value, 'default')
1891
        self.assertEqual(bzrdir_config.get_option('key2', 'NOSECTION'), None)
1892
        value = bzrdir_config.get_option('key2', 'NOSECTION',
1893
                                         default='default')
1894
        self.assertEqual(value, 'default')
1895
        value = bzrdir_config.get_option('key3')
1896
        self.assertEqual(value, 'value3-top')
1897
        value = bzrdir_config.get_option('key3', 'SECTION')
1898
        self.assertEqual(value, 'value3-section')
1899
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1900
    def test_set_unset_default_stack_on(self):
1901
        my_dir = self.make_bzrdir('.')
4288.1.3 by Robert Collins
Fix BzrDirConfig tests.
1902
        bzrdir_config = config.BzrDirConfig(my_dir)
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1903
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1904
        bzrdir_config.set_default_stack_on('Foo')
3242.3.14 by Aaron Bentley
Make BzrDirConfig use TransportConfig
1905
        self.assertEqual('Foo', bzrdir_config._config.get_option(
1906
                         'default_stack_on'))
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1907
        self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
1908
        bzrdir_config.set_default_stack_on(None)
1909
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1910
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1911
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1912
class TestOldConfigHooks(tests.TestCaseWithTransport):
1913
1914
    def setUp(self):
1915
        super(TestOldConfigHooks, self).setUp()
1916
        create_configs_with_file_option(self)
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1917
1918
    def assertGetHook(self, conf, name, value):
1919
        calls = []
1920
        def hook(*args):
1921
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1922
        config.OldConfigHooks.install_named_hook('get', hook, None)
5743.8.23 by Vincent Ladeuil
Don't publicize the hooks yet and add proper cleanups to avoid hook leaks (or hooks triggering during tests cleanup).
1923
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1924
            config.OldConfigHooks.uninstall_named_hook, 'get', None)
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1925
        self.assertLength(0, calls)
1926
        actual_value = conf.get_user_option(name)
1927
        self.assertEquals(value, actual_value)
1928
        self.assertLength(1, calls)
1929
        self.assertEquals((conf, name, value), calls[0])
1930
1931
    def test_get_hook_bazaar(self):
1932
        self.assertGetHook(self.bazaar_config, 'file', 'bazaar')
1933
1934
    def test_get_hook_locations(self):
1935
        self.assertGetHook(self.locations_config, 'file', 'locations')
1936
1937
    def test_get_hook_branch(self):
1938
        # Since locations masks branch, we define a different option
1939
        self.branch_config.set_user_option('file2', 'branch')
1940
        self.assertGetHook(self.branch_config, 'file2', 'branch')
1941
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1942
    def assertSetHook(self, conf, name, value):
1943
        calls = []
1944
        def hook(*args):
1945
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1946
        config.OldConfigHooks.install_named_hook('set', hook, None)
5743.8.23 by Vincent Ladeuil
Don't publicize the hooks yet and add proper cleanups to avoid hook leaks (or hooks triggering during tests cleanup).
1947
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1948
            config.OldConfigHooks.uninstall_named_hook, 'set', None)
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1949
        self.assertLength(0, calls)
1950
        conf.set_user_option(name, value)
1951
        self.assertLength(1, calls)
1952
        # We can't assert the conf object below as different configs use
1953
        # different means to implement set_user_option and we care only about
1954
        # coverage here.
1955
        self.assertEquals((name, value), calls[0][1:])
1956
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1957
    def test_set_hook_bazaar(self):
1958
        self.assertSetHook(self.bazaar_config, 'foo', 'bazaar')
1959
1960
    def test_set_hook_locations(self):
1961
        self.assertSetHook(self.locations_config, 'foo', 'locations')
1962
1963
    def test_set_hook_branch(self):
1964
        self.assertSetHook(self.branch_config, 'foo', 'branch')
1965
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1966
    def assertRemoveHook(self, conf, name, section_name=None):
1967
        calls = []
1968
        def hook(*args):
1969
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1970
        config.OldConfigHooks.install_named_hook('remove', hook, None)
5743.8.23 by Vincent Ladeuil
Don't publicize the hooks yet and add proper cleanups to avoid hook leaks (or hooks triggering during tests cleanup).
1971
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1972
            config.OldConfigHooks.uninstall_named_hook, 'remove', None)
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1973
        self.assertLength(0, calls)
1974
        conf.remove_user_option(name, section_name)
1975
        self.assertLength(1, calls)
1976
        # We can't assert the conf object below as different configs use
1977
        # different means to implement remove_user_option and we care only about
1978
        # coverage here.
1979
        self.assertEquals((name,), calls[0][1:])
1980
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1981
    def test_remove_hook_bazaar(self):
1982
        self.assertRemoveHook(self.bazaar_config, 'file')
1983
1984
    def test_remove_hook_locations(self):
1985
        self.assertRemoveHook(self.locations_config, 'file',
1986
                              self.locations_config.location)
1987
1988
    def test_remove_hook_branch(self):
1989
        self.assertRemoveHook(self.branch_config, 'file')
1990
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1991
    def assertLoadHook(self, name, conf_class, *conf_args):
1992
        calls = []
1993
        def hook(*args):
1994
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1995
        config.OldConfigHooks.install_named_hook('load', hook, None)
5743.8.23 by Vincent Ladeuil
Don't publicize the hooks yet and add proper cleanups to avoid hook leaks (or hooks triggering during tests cleanup).
1996
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1997
            config.OldConfigHooks.uninstall_named_hook, 'load', None)
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1998
        self.assertLength(0, calls)
1999
        # Build a config
2000
        conf = conf_class(*conf_args)
2001
        # Access an option to trigger a load
2002
        conf.get_user_option(name)
2003
        self.assertLength(1, calls)
2004
        # Since we can't assert about conf, we just use the number of calls ;-/
2005
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
2006
    def test_load_hook_bazaar(self):
2007
        self.assertLoadHook('file', config.GlobalConfig)
2008
2009
    def test_load_hook_locations(self):
2010
        self.assertLoadHook('file', config.LocationConfig, self.tree.basedir)
2011
2012
    def test_load_hook_branch(self):
2013
        self.assertLoadHook('file', config.BranchConfig, self.tree.branch)
2014
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
2015
    def assertSaveHook(self, conf):
2016
        calls = []
2017
        def hook(*args):
2018
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2019
        config.OldConfigHooks.install_named_hook('save', hook, None)
5743.8.23 by Vincent Ladeuil
Don't publicize the hooks yet and add proper cleanups to avoid hook leaks (or hooks triggering during tests cleanup).
2020
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2021
            config.OldConfigHooks.uninstall_named_hook, 'save', None)
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
2022
        self.assertLength(0, calls)
2023
        # Setting an option triggers a save
2024
        conf.set_user_option('foo', 'bar')
2025
        self.assertLength(1, calls)
2026
        # Since we can't assert about conf, we just use the number of calls ;-/
2027
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
2028
    def test_save_hook_bazaar(self):
2029
        self.assertSaveHook(self.bazaar_config)
2030
2031
    def test_save_hook_locations(self):
2032
        self.assertSaveHook(self.locations_config)
2033
2034
    def test_save_hook_branch(self):
2035
        self.assertSaveHook(self.branch_config)
2036
2037
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
2038
class TestOldConfigHooksForRemote(tests.TestCaseWithTransport):
2039
    """Tests config hooks for remote configs.
2040
2041
    No tests for the remove hook as this is not implemented there.
2042
    """
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
2043
2044
    def setUp(self):
2045
        super(TestOldConfigHooksForRemote, self).setUp()
2046
        self.transport_server = test_server.SmartTCPServer_for_testing
2047
        create_configs_with_file_option(self)
2048
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
2049
    def assertGetHook(self, conf, name, value):
2050
        calls = []
2051
        def hook(*args):
2052
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2053
        config.OldConfigHooks.install_named_hook('get', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
2054
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2055
            config.OldConfigHooks.uninstall_named_hook, 'get', None)
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
2056
        self.assertLength(0, calls)
2057
        actual_value = conf.get_option(name)
2058
        self.assertEquals(value, actual_value)
2059
        self.assertLength(1, calls)
2060
        self.assertEquals((conf, name, value), calls[0])
2061
2062
    def test_get_hook_remote_branch(self):
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
2063
        remote_branch = branch.Branch.open(self.get_url('tree'))
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
2064
        self.assertGetHook(remote_branch._get_config(), 'file', 'branch')
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
2065
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
2066
    def test_get_hook_remote_bzrdir(self):
2067
        remote_bzrdir = bzrdir.BzrDir.open(self.get_url('tree'))
2068
        conf = remote_bzrdir._get_config()
2069
        conf.set_option('remotedir', 'file')
2070
        self.assertGetHook(conf, 'file', 'remotedir')
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
2071
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
2072
    def assertSetHook(self, conf, name, value):
2073
        calls = []
2074
        def hook(*args):
2075
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2076
        config.OldConfigHooks.install_named_hook('set', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
2077
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2078
            config.OldConfigHooks.uninstall_named_hook, 'set', None)
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
2079
        self.assertLength(0, calls)
2080
        conf.set_option(value, name)
2081
        self.assertLength(1, calls)
2082
        # We can't assert the conf object below as different configs use
2083
        # different means to implement set_user_option and we care only about
2084
        # coverage here.
2085
        self.assertEquals((name, value), calls[0][1:])
2086
2087
    def test_set_hook_remote_branch(self):
2088
        remote_branch = branch.Branch.open(self.get_url('tree'))
2089
        self.addCleanup(remote_branch.lock_write().unlock)
2090
        self.assertSetHook(remote_branch._get_config(), 'file', 'remote')
2091
2092
    def test_set_hook_remote_bzrdir(self):
2093
        remote_branch = branch.Branch.open(self.get_url('tree'))
2094
        self.addCleanup(remote_branch.lock_write().unlock)
2095
        remote_bzrdir = bzrdir.BzrDir.open(self.get_url('tree'))
2096
        self.assertSetHook(remote_bzrdir._get_config(), 'file', 'remotedir')
2097
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
2098
    def assertLoadHook(self, expected_nb_calls, name, conf_class, *conf_args):
2099
        calls = []
2100
        def hook(*args):
2101
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2102
        config.OldConfigHooks.install_named_hook('load', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
2103
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2104
            config.OldConfigHooks.uninstall_named_hook, 'load', None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
2105
        self.assertLength(0, calls)
2106
        # Build a config
2107
        conf = conf_class(*conf_args)
2108
        # Access an option to trigger a load
2109
        conf.get_option(name)
2110
        self.assertLength(expected_nb_calls, calls)
2111
        # Since we can't assert about conf, we just use the number of calls ;-/
2112
2113
    def test_load_hook_remote_branch(self):
2114
        remote_branch = branch.Branch.open(self.get_url('tree'))
2115
        self.assertLoadHook(1, 'file', remote.RemoteBranchConfig, remote_branch)
2116
2117
    def test_load_hook_remote_bzrdir(self):
2118
        remote_bzrdir = bzrdir.BzrDir.open(self.get_url('tree'))
2119
        # The config file doesn't exist, set an option to force its creation
2120
        conf = remote_bzrdir._get_config()
2121
        conf.set_option('remotedir', 'file')
2122
        # We get one call for the server and one call for the client, this is
2123
        # caused by the differences in implementations betwen
2124
        # SmartServerBzrDirRequestConfigFile (in smart/bzrdir.py) and
2125
        # SmartServerBranchGetConfigFile (in smart/branch.py)
2126
        self.assertLoadHook(2 ,'file', remote.RemoteBzrDirConfig, remote_bzrdir)
2127
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
2128
    def assertSaveHook(self, conf):
2129
        calls = []
2130
        def hook(*args):
2131
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2132
        config.OldConfigHooks.install_named_hook('save', hook, None)
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
2133
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
2134
            config.OldConfigHooks.uninstall_named_hook, 'save', None)
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
2135
        self.assertLength(0, calls)
2136
        # Setting an option triggers a save
2137
        conf.set_option('foo', 'bar')
2138
        self.assertLength(1, calls)
2139
        # Since we can't assert about conf, we just use the number of calls ;-/
2140
2141
    def test_save_hook_remote_branch(self):
2142
        remote_branch = branch.Branch.open(self.get_url('tree'))
2143
        self.addCleanup(remote_branch.lock_write().unlock)
2144
        self.assertSaveHook(remote_branch._get_config())
2145
2146
    def test_save_hook_remote_bzrdir(self):
2147
        remote_branch = branch.Branch.open(self.get_url('tree'))
2148
        self.addCleanup(remote_branch.lock_write().unlock)
2149
        remote_bzrdir = bzrdir.BzrDir.open(self.get_url('tree'))
2150
        self.assertSaveHook(remote_bzrdir._get_config())
2151
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
2152
5743.12.4 by Vincent Ladeuil
An option can provide a default value.
2153
class TestOption(tests.TestCase):
2154
2155
    def test_default_value(self):
2156
        opt = config.Option('foo', default='bar')
2157
        self.assertEquals('bar', opt.get_default())
5743.12.5 by Vincent Ladeuil
Remove spurious spaces.
2158
5743.12.4 by Vincent Ladeuil
An option can provide a default value.
2159
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2160
class TestOptionRegistry(tests.TestCase):
5743.12.5 by Vincent Ladeuil
Remove spurious spaces.
2161
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2162
    def setUp(self):
2163
        super(TestOptionRegistry, self).setUp()
2164
        # Always start with an empty registry
2165
        self.overrideAttr(config, 'option_registry', registry.Registry())
2166
        self.registry = config.option_registry
2167
2168
    def test_register(self):
2169
        opt = config.Option('foo')
2170
        self.registry.register('foo', opt)
2171
        self.assertIs(opt, self.registry.get('foo'))
2172
2173
    lazy_option = config.Option('lazy_foo')
2174
2175
    def test_register_lazy(self):
2176
        self.registry.register_lazy('foo', self.__module__,
2177
                                    'TestOptionRegistry.lazy_option')
2178
        self.assertIs(self.lazy_option, self.registry.get('foo'))
2179
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2180
    def test_registered_help(self):
2181
        opt = config.Option('foo')
2182
        self.registry.register('foo', opt, help='A simple option')
2183
        self.assertEquals('A simple option', self.registry.get_help('foo'))
2184
2185
2186
class TestRegisteredOptions(tests.TestCase):
2187
    """All registered options should verify some constraints."""
2188
2189
    scenarios = [(key, {'option_name': key, 'option': option}) for key, option
2190
                 in config.option_registry.iteritems()]
2191
2192
    def setUp(self):
2193
        super(TestRegisteredOptions, self).setUp()
2194
        self.registry = config.option_registry
2195
2196
    def test_proper_name(self):
2197
        # An option should be registered under its own name, this can't be
2198
        # checked at registration time for the lazy ones.
2199
        self.assertEquals(self.option_name, self.option.name)
2200
2201
    def test_help_is_set(self):
2202
        option_help = self.registry.get_help(self.option_name)
2203
        self.assertNotEquals(None, option_help)
2204
        # Come on, think about the user, he really wants to know whst the
2205
        # option is about
2206
        self.assertNotEquals('', option_help)
2207
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2208
5743.3.12 by Vincent Ladeuil
Add an ad-hoc __repr__.
2209
class TestSection(tests.TestCase):
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2210
2211
    # FIXME: Parametrize so that all sections produced by Stores run these
5743.3.1 by Vincent Ladeuil
Add a docstring and dates to FIXMEs.
2212
    # tests -- vila 2011-04-01
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2213
2214
    def test_get_a_value(self):
2215
        a_dict = dict(foo='bar')
5743.3.11 by Vincent Ladeuil
Config sections only implement read access.
2216
        section = config.Section('myID', a_dict)
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2217
        self.assertEquals('bar', section.get('foo'))
2218
5743.3.10 by Vincent Ladeuil
Fix typos mentioned in reviews.
2219
    def test_get_unknown_option(self):
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2220
        a_dict = dict()
5743.5.13 by Vincent Ladeuil
Merge config-abstract-store into config-concrete-stores resolving conflicts
2221
        section = config.Section(None, a_dict)
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2222
        self.assertEquals('out of thin air',
2223
                          section.get('foo', 'out of thin air'))
2224
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2225
    def test_options_is_shared(self):
2226
        a_dict = dict()
5743.5.13 by Vincent Ladeuil
Merge config-abstract-store into config-concrete-stores resolving conflicts
2227
        section = config.Section(None, a_dict)
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2228
        self.assertIs(a_dict, section.options)
2229
2230
5743.3.12 by Vincent Ladeuil
Add an ad-hoc __repr__.
2231
class TestMutableSection(tests.TestCase):
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2232
5743.4.20 by Vincent Ladeuil
Fix typo.
2233
    # FIXME: Parametrize so that all sections (including os.environ and the
5743.3.1 by Vincent Ladeuil
Add a docstring and dates to FIXMEs.
2234
    # ones produced by Stores) run these tests -- vila 2011-04-01
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2235
2236
    def test_set(self):
2237
        a_dict = dict(foo='bar')
2238
        section = config.MutableSection('myID', a_dict)
2239
        section.set('foo', 'new_value')
2240
        self.assertEquals('new_value', section.get('foo'))
2241
        # The change appears in the shared section
2242
        self.assertEquals('new_value', a_dict.get('foo'))
2243
        # We keep track of the change
2244
        self.assertTrue('foo' in section.orig)
2245
        self.assertEquals('bar', section.orig.get('foo'))
2246
2247
    def test_set_preserve_original_once(self):
2248
        a_dict = dict(foo='bar')
2249
        section = config.MutableSection('myID', a_dict)
2250
        section.set('foo', 'first_value')
2251
        section.set('foo', 'second_value')
2252
        # We keep track of the original value
2253
        self.assertTrue('foo' in section.orig)
2254
        self.assertEquals('bar', section.orig.get('foo'))
2255
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2256
    def test_remove(self):
2257
        a_dict = dict(foo='bar')
2258
        section = config.MutableSection('myID', a_dict)
2259
        section.remove('foo')
2260
        # We get None for unknown options via the default value
2261
        self.assertEquals(None, section.get('foo'))
2262
        # Or we just get the default value
2263
        self.assertEquals('unknown', section.get('foo', 'unknown'))
2264
        self.assertFalse('foo' in section.options)
2265
        # We keep track of the deletion
2266
        self.assertTrue('foo' in section.orig)
2267
        self.assertEquals('bar', section.orig.get('foo'))
2268
2269
    def test_remove_new_option(self):
2270
        a_dict = dict()
2271
        section = config.MutableSection('myID', a_dict)
2272
        section.set('foo', 'bar')
2273
        section.remove('foo')
2274
        self.assertFalse('foo' in section.options)
2275
        # The option didn't exist initially so it we need to keep track of it
2276
        # with a special value
2277
        self.assertTrue('foo' in section.orig)
5743.3.6 by Vincent Ladeuil
Use a name less likely to be reused.
2278
        self.assertEquals(config._NewlyCreatedOption, section.orig['foo'])
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2279
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2280
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2281
class TestStore(tests.TestCaseWithTransport):
2282
2283
    def assertSectionContent(self, expected, section):
2284
        """Assert that some options have the proper values in a section."""
2285
        expected_name, expected_options = expected
2286
        self.assertEquals(expected_name, section.id)
2287
        self.assertEquals(
2288
            expected_options,
2289
            dict([(k, section.get(k)) for k in expected_options.keys()]))
2290
2291
2292
class TestReadonlyStore(TestStore):
2293
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2294
    scenarios = [(key, {'get_store': builder}) for key, builder
2295
                 in config.test_store_builder_registry.iteritems()]
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2296
2297
    def setUp(self):
2298
        super(TestReadonlyStore, self).setUp()
2299
2300
    def test_building_delays_load(self):
2301
        store = self.get_store(self)
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2302
        self.assertEquals(False, store.is_loaded())
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2303
        store._load_from_string('')
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2304
        self.assertEquals(True, store.is_loaded())
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2305
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2306
    def test_get_no_sections_for_empty(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2307
        store = self.get_store(self)
2308
        store._load_from_string('')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2309
        self.assertEquals([], list(store.get_sections()))
2310
2311
    def test_get_default_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2312
        store = self.get_store(self)
2313
        store._load_from_string('foo=bar')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2314
        sections = list(store.get_sections())
2315
        self.assertLength(1, sections)
2316
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2317
2318
    def test_get_named_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2319
        store = self.get_store(self)
2320
        store._load_from_string('[baz]\nfoo=bar')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2321
        sections = list(store.get_sections())
2322
        self.assertLength(1, sections)
2323
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
2324
5743.4.21 by Vincent Ladeuil
All stores should provide _load_from_string to reuse the existing tests.
2325
    def test_load_from_string_fails_for_non_empty_store(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2326
        store = self.get_store(self)
2327
        store._load_from_string('foo=bar')
5743.4.21 by Vincent Ladeuil
All stores should provide _load_from_string to reuse the existing tests.
2328
        self.assertRaises(AssertionError, store._load_from_string, 'bar=baz')
2329
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2330
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2331
class TestBug799212(TestStore):
2332
2333
   def test_load_utf8(self):
2334
        t = self.get_transport()
2335
        # From http://pad.lv/799212
2336
        unicode_user = u'Piotr O\u017carowski'
2337
        unicode_content = u'user=%s' % (unicode_user,)
2338
        utf8_content = unicode_content.encode('utf8')
2339
        # Store the raw content in the config file
2340
        t.put_bytes('foo.conf', utf8_content)
2341
        store = config.IniFileStore(t, 'foo.conf')
2342
        store.load()
2343
        stack = config.Stack([store.get_sections], store)
2344
        self.assertEquals(unicode_user, stack.get('user'))
2345
2346
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2347
class TestMutableStore(TestStore):
2348
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2349
    scenarios = [(key, {'store_id': key, 'get_store': builder}) for key, builder
2350
                 in config.test_store_builder_registry.iteritems()]
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2351
2352
    def setUp(self):
2353
        super(TestMutableStore, self).setUp()
2354
        self.transport = self.get_transport()
2355
2356
    def has_store(self, store):
2357
        store_basename = urlutils.relative_url(self.transport.external_url(),
2358
                                               store.external_url())
2359
        return self.transport.has(store_basename)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2360
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2361
    def test_save_empty_creates_no_file(self):
5743.10.4 by Vincent Ladeuil
Add FIXME.
2362
        # FIXME: There should be a better way than relying on the test
2363
        # parametrization to identify branch.conf -- vila 2011-0526
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
2364
        if self.store_id in ('branch', 'remote_branch'):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2365
            raise tests.TestNotApplicable(
2366
                'branch.conf is *always* created when a branch is initialized')
2367
        store = self.get_store(self)
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2368
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2369
        self.assertEquals(False, self.has_store(store))
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2370
2371
    def test_save_emptied_succeeds(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2372
        store = self.get_store(self)
2373
        store._load_from_string('foo=bar\n')
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2374
        section = store.get_mutable_section(None)
2375
        section.remove('foo')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2376
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2377
        self.assertEquals(True, self.has_store(store))
2378
        modified_store = self.get_store(self)
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2379
        sections = list(modified_store.get_sections())
2380
        self.assertLength(0, sections)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2381
2382
    def test_save_with_content_succeeds(self):
5743.10.4 by Vincent Ladeuil
Add FIXME.
2383
        # FIXME: There should be a better way than relying on the test
2384
        # parametrization to identify branch.conf -- vila 2011-0526
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
2385
        if self.store_id in ('branch', 'remote_branch'):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2386
            raise tests.TestNotApplicable(
2387
                'branch.conf is *always* created when a branch is initialized')
2388
        store = self.get_store(self)
2389
        store._load_from_string('foo=bar\n')
2390
        self.assertEquals(False, self.has_store(store))
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2391
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2392
        self.assertEquals(True, self.has_store(store))
2393
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2394
        sections = list(modified_store.get_sections())
2395
        self.assertLength(1, sections)
2396
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2397
2398
    def test_set_option_in_empty_store(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2399
        store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2400
        section = store.get_mutable_section(None)
2401
        section.set('foo', 'bar')
2402
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2403
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2404
        sections = list(modified_store.get_sections())
2405
        self.assertLength(1, sections)
2406
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2407
2408
    def test_set_option_in_default_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2409
        store = self.get_store(self)
2410
        store._load_from_string('')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2411
        section = store.get_mutable_section(None)
2412
        section.set('foo', 'bar')
2413
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2414
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2415
        sections = list(modified_store.get_sections())
2416
        self.assertLength(1, sections)
2417
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2418
2419
    def test_set_option_in_named_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2420
        store = self.get_store(self)
2421
        store._load_from_string('')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2422
        section = store.get_mutable_section('baz')
2423
        section.set('foo', 'bar')
2424
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2425
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2426
        sections = list(modified_store.get_sections())
2427
        self.assertLength(1, sections)
2428
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
2429
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2430
    def test_load_hook(self):
2431
        # We first needs to ensure that the store exists
2432
        store = self.get_store(self)
2433
        section = store.get_mutable_section('baz')
2434
        section.set('foo', 'bar')
2435
        store.save()
2436
        # Now we can try to load it
5743.8.11 by Vincent Ladeuil
Restrict the scope when testing hooks to avoid spurious failures.
2437
        store = self.get_store(self)
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2438
        calls = []
2439
        def hook(*args):
2440
            calls.append(args)
5743.8.10 by Vincent Ladeuil
We don't need (nor want) to tie the config hooks to a particular class. Especially when we want to use the same hooks on both implementations.
2441
        config.ConfigHooks.install_named_hook('load', hook, None)
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2442
        self.assertLength(0, calls)
2443
        store.load()
2444
        self.assertLength(1, calls)
2445
        self.assertEquals((store,), calls[0])
2446
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2447
    def test_save_hook(self):
2448
        calls = []
2449
        def hook(*args):
2450
            calls.append(args)
5743.8.10 by Vincent Ladeuil
We don't need (nor want) to tie the config hooks to a particular class. Especially when we want to use the same hooks on both implementations.
2451
        config.ConfigHooks.install_named_hook('save', hook, None)
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2452
        self.assertLength(0, calls)
2453
        store = self.get_store(self)
2454
        section = store.get_mutable_section('baz')
2455
        section.set('foo', 'bar')
2456
        store.save()
2457
        self.assertLength(1, calls)
2458
        self.assertEquals((store,), calls[0])
2459
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2460
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2461
class TestIniFileStore(TestStore):
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2462
5743.4.3 by Vincent Ladeuil
Implement get_mutable_section.
2463
    def test_loading_unknown_file_fails(self):
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2464
        store = config.IniFileStore(self.get_transport(), 'I-do-not-exist')
5743.4.3 by Vincent Ladeuil
Implement get_mutable_section.
2465
        self.assertRaises(errors.NoSuchFile, store.load)
2466
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2467
    def test_invalid_content(self):
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2468
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
2469
        self.assertEquals(False, store.is_loaded())
5743.4.18 by Vincent Ladeuil
Replace class.from_string with self._load_from_string to all stores can use it.
2470
        exc = self.assertRaises(
2471
            errors.ParseConfigError, store._load_from_string,
2472
            'this is invalid !')
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2473
        self.assertEndsWith(exc.filename, 'foo.conf')
2474
        # And the load failed
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2475
        self.assertEquals(False, store.is_loaded())
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2476
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2477
    def test_get_embedded_sections(self):
5743.2.11 by Vincent Ladeuil
Basic store.set implementation.
2478
        # A more complicated example (which also shows that section names and
2479
        # option names share the same name space...)
5743.4.7 by Vincent Ladeuil
The test is now specific to ConfigObjStore and highlight a pending problem there.
2480
        # FIXME: This should be fixed by forbidding dicts as values ?
2481
        # -- vila 2011-04-05
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2482
        store = config.IniFileStore(self.get_transport(), 'foo.conf', )
5743.4.18 by Vincent Ladeuil
Replace class.from_string with self._load_from_string to all stores can use it.
2483
        store._load_from_string('''
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2484
foo=bar
2485
l=1,2
2486
[DEFAULT]
2487
foo_in_DEFAULT=foo_DEFAULT
2488
[bar]
2489
foo_in_bar=barbar
2490
[baz]
2491
foo_in_baz=barbaz
2492
[[qux]]
2493
foo_in_qux=quux
5743.4.18 by Vincent Ladeuil
Replace class.from_string with self._load_from_string to all stores can use it.
2494
''')
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2495
        sections = list(store.get_sections())
2496
        self.assertLength(4, sections)
2497
        # The default section has no name.
2498
        # List values are provided as lists
5743.4.1 by Vincent Ladeuil
Use proper ReadOnly sections in ConfigObjStore.get_sections().
2499
        self.assertSectionContent((None, {'foo': 'bar', 'l': ['1', '2']}),
2500
                                  sections[0])
2501
        self.assertSectionContent(
2502
            ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
2503
        self.assertSectionContent(
2504
            ('bar', {'foo_in_bar': 'barbar'}), sections[2])
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2505
        # sub sections are provided as embedded dicts.
5743.4.1 by Vincent Ladeuil
Use proper ReadOnly sections in ConfigObjStore.get_sections().
2506
        self.assertSectionContent(
2507
            ('baz', {'foo_in_baz': 'barbaz', 'qux': {'foo_in_qux': 'quux'}}),
2508
            sections[3])
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2509
5743.4.5 by Vincent Ladeuil
Split store tests between readonly and mutable ones.
2510
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2511
class TestLockableIniFileStore(TestStore):
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2512
2513
    def test_create_store_in_created_dir(self):
5743.6.21 by Vincent Ladeuil
Tighten the test.
2514
        self.assertPathDoesNotExist('dir')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2515
        t = self.get_transport('dir/subdir')
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2516
        store = config.LockableIniFileStore(t, 'foo.conf')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2517
        store.get_mutable_section(None).set('foo', 'bar')
2518
        store.save()
5743.6.21 by Vincent Ladeuil
Tighten the test.
2519
        self.assertPathExists('dir/subdir')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2520
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
2521
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2522
class TestConcurrentStoreUpdates(TestStore):
5743.10.13 by Vincent Ladeuil
Mention that the the concurrent update tests are not targeted at *all* Store implementations.
2523
    """Test that Stores properly handle conccurent updates.
2524
2525
    New Store implementation may fail some of these tests but until such
2526
    implementations exist it's hard to properly filter them from the scenarios
2527
    applied here. If you encounter such a case, contact the bzr devs.
2528
    """
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2529
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2530
    scenarios = [(key, {'get_stack': builder}) for key, builder
2531
                 in config.test_stack_builder_registry.iteritems()]
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2532
2533
    def setUp(self):
2534
        super(TestConcurrentStoreUpdates, self).setUp()
2535
        self._content = 'one=1\ntwo=2\n'
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
2536
        self.stack = self.get_stack(self)
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2537
        if not isinstance(self.stack, config._CompatibleStack):
2538
            raise tests.TestNotApplicable(
2539
                '%s is not meant to be compatible with the old config design'
2540
                % (self.stack,))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
2541
        self.stack.store._load_from_string(self._content)
2542
        # Flush the store
2543
        self.stack.store.save()
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2544
2545
    def test_simple_read_access(self):
2546
        self.assertEquals('1', self.stack.get('one'))
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2547
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2548
    def test_simple_write_access(self):
2549
        self.stack.set('one', 'one')
2550
        self.assertEquals('one', self.stack.get('one'))
2551
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
2552
    def test_listen_to_the_last_speaker(self):
2553
        c1 = self.stack
2554
        c2 = self.get_stack(self)
2555
        c1.set('one', 'ONE')
2556
        c2.set('two', 'TWO')
2557
        self.assertEquals('ONE', c1.get('one'))
2558
        self.assertEquals('TWO', c2.get('two'))
2559
        # The second update respect the first one
2560
        self.assertEquals('ONE', c2.get('one'))
2561
2562
    def test_last_speaker_wins(self):
2563
        # If the same config is not shared, the same variable modified twice
2564
        # can only see a single result.
2565
        c1 = self.stack
2566
        c2 = self.get_stack(self)
2567
        c1.set('one', 'c1')
2568
        c2.set('one', 'c2')
2569
        self.assertEquals('c2', c2.get('one'))
2570
        # The first modification is still available until another refresh
2571
        # occur
2572
        self.assertEquals('c1', c1.get('one'))
2573
        c1.set('two', 'done')
2574
        self.assertEquals('c2', c1.get('one'))
2575
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
2576
    def test_writes_are_serialized(self):
2577
        c1 = self.stack
2578
        c2 = self.get_stack(self)
2579
5743.6.25 by Vincent Ladeuil
Last test rewritten.
2580
        # We spawn a thread that will pause *during* the config saving.
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
2581
        before_writing = threading.Event()
2582
        after_writing = threading.Event()
2583
        writing_done = threading.Event()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2584
        c1_save_without_locking_orig = c1.store.save_without_locking
2585
        def c1_save_without_locking():
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
2586
            before_writing.set()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2587
            c1_save_without_locking_orig()
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
2588
            # The lock is held. We wait for the main thread to decide when to
2589
            # continue
2590
            after_writing.wait()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2591
        c1.store.save_without_locking = c1_save_without_locking
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
2592
        def c1_set():
2593
            c1.set('one', 'c1')
2594
            writing_done.set()
2595
        t1 = threading.Thread(target=c1_set)
2596
        # Collect the thread after the test
2597
        self.addCleanup(t1.join)
2598
        # Be ready to unblock the thread if the test goes wrong
2599
        self.addCleanup(after_writing.set)
2600
        t1.start()
2601
        before_writing.wait()
2602
        self.assertRaises(errors.LockContention,
2603
                          c2.set, 'one', 'c2')
2604
        self.assertEquals('c1', c1.get('one'))
2605
        # Let the lock be released
2606
        after_writing.set()
2607
        writing_done.wait()
2608
        c2.set('one', 'c2')
2609
        self.assertEquals('c2', c2.get('one'))
2610
5743.6.25 by Vincent Ladeuil
Last test rewritten.
2611
    def test_read_while_writing(self):
2612
       c1 = self.stack
2613
       # We spawn a thread that will pause *during* the write
2614
       ready_to_write = threading.Event()
2615
       do_writing = threading.Event()
2616
       writing_done = threading.Event()
2617
       # We override the _save implementation so we know the store is locked
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2618
       c1_save_without_locking_orig = c1.store.save_without_locking
2619
       def c1_save_without_locking():
5743.6.25 by Vincent Ladeuil
Last test rewritten.
2620
           ready_to_write.set()
2621
           # The lock is held. We wait for the main thread to decide when to
2622
           # continue
2623
           do_writing.wait()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2624
           c1_save_without_locking_orig()
5743.6.25 by Vincent Ladeuil
Last test rewritten.
2625
           writing_done.set()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
2626
       c1.store.save_without_locking = c1_save_without_locking
5743.6.25 by Vincent Ladeuil
Last test rewritten.
2627
       def c1_set():
2628
           c1.set('one', 'c1')
2629
       t1 = threading.Thread(target=c1_set)
2630
       # Collect the thread after the test
2631
       self.addCleanup(t1.join)
2632
       # Be ready to unblock the thread if the test goes wrong
2633
       self.addCleanup(do_writing.set)
2634
       t1.start()
2635
       # Ensure the thread is ready to write
2636
       ready_to_write.wait()
2637
       self.assertEquals('c1', c1.get('one'))
2638
       # If we read during the write, we get the old value
2639
       c2 = self.get_stack(self)
2640
       self.assertEquals('1', c2.get('one'))
2641
       # Let the writing occur and ensure it occurred
2642
       do_writing.set()
2643
       writing_done.wait()
2644
       # Now we get the updated value
2645
       c3 = self.get_stack(self)
2646
       self.assertEquals('c1', c3.get('one'))
2647
2648
    # FIXME: It may be worth looking into removing the lock dir when it's not
2649
    # needed anymore and look at possible fallouts for concurrent lockers. This
2650
    # will matter if/when we use config files outside of bazaar directories
2651
    # (.bazaar or .bzr) -- vila 20110-04-11
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2652
2653
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
2654
class TestSectionMatcher(TestStore):
2655
2656
    scenarios = [('location', {'matcher': config.LocationMatcher})]
2657
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2658
    def get_store(self, file_name):
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
2659
        return config.IniFileStore(self.get_readonly_transport(), file_name)
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
2660
2661
    def test_no_matches_for_empty_stores(self):
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2662
        store = self.get_store('foo.conf')
2663
        store._load_from_string('')
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2664
        matcher = self.matcher(store, '/bar')
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
2665
        self.assertEquals([], list(matcher.get_sections()))
2666
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2667
    def test_build_doesnt_load_store(self):
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2668
        store = self.get_store('foo.conf')
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2669
        matcher = self.matcher(store, '/bar')
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
2670
        self.assertFalse(store.is_loaded())
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2671
2672
2673
class TestLocationSection(tests.TestCase):
2674
2675
    def get_section(self, options, extra_path):
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
2676
        section = config.Section('foo', options)
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2677
        # We don't care about the length so we use '0'
2678
        return config.LocationSection(section, 0, extra_path)
2679
2680
    def test_simple_option(self):
2681
        section = self.get_section({'foo': 'bar'}, '')
2682
        self.assertEquals('bar', section.get('foo'))
2683
2684
    def test_option_with_extra_path(self):
2685
        section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
2686
                                   'baz')
2687
        self.assertEquals('bar/baz', section.get('foo'))
2688
2689
    def test_invalid_policy(self):
2690
        section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
2691
                                   'baz')
2692
        # invalid policies are ignored
2693
        self.assertEquals('bar', section.get('foo'))
2694
2695
2696
class TestLocationMatcher(TestStore):
2697
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2698
    def get_store(self, file_name):
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
2699
        return config.IniFileStore(self.get_readonly_transport(), file_name)
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2700
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2701
    def test_more_specific_sections_first(self):
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2702
        store = self.get_store('foo.conf')
2703
        store._load_from_string('''
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2704
[/foo]
2705
section=/foo
2706
[/foo/bar]
2707
section=/foo/bar
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
2708
''')
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
2709
        self.assertEquals(['/foo', '/foo/bar'],
2710
                          [section.id for section in store.get_sections()])
2711
        matcher = config.LocationMatcher(store, '/foo/bar/baz')
2712
        sections = list(matcher.get_sections())
2713
        self.assertEquals([3, 2],
2714
                          [section.length for section in sections])
2715
        self.assertEquals(['/foo/bar', '/foo'],
2716
                          [section.id for section in sections])
2717
        self.assertEquals(['baz', 'bar/baz'],
2718
                          [section.extra_path for section in sections])
2719
5743.6.18 by Vincent Ladeuil
Add a test for appendpath support in no-name section.
2720
    def test_appendpath_in_no_name_section(self):
2721
        # It's a bit weird to allow appendpath in a no-name section, but
2722
        # someone may found a use for it
2723
        store = self.get_store('foo.conf')
2724
        store._load_from_string('''
2725
foo=bar
2726
foo:policy = appendpath
2727
''')
2728
        matcher = config.LocationMatcher(store, 'dir/subdir')
2729
        sections = list(matcher.get_sections())
2730
        self.assertLength(1, sections)
2731
        self.assertEquals('bar/dir/subdir', sections[0].get('foo'))
2732
5743.6.19 by Vincent Ladeuil
Clarify comments about section names for Location-related objects (also fix LocationMatcher and add tests).
2733
    def test_file_urls_are_normalized(self):
2734
        store = self.get_store('foo.conf')
5912.3.1 by Vincent Ladeuil
Fix spurious windows-specific test failure
2735
        if sys.platform == 'win32':
2736
            expected_url = 'file:///C:/dir/subdir'
2737
            expected_location = 'C:/dir/subdir'
2738
        else:
2739
            expected_url = 'file:///dir/subdir'
2740
            expected_location = '/dir/subdir'
2741
        matcher = config.LocationMatcher(store, expected_url)
2742
        self.assertEquals(expected_location, matcher.location)
5743.6.19 by Vincent Ladeuil
Clarify comments about section names for Location-related objects (also fix LocationMatcher and add tests).
2743
5743.1.20 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
2744
5743.1.35 by Vincent Ladeuil
Address some review comments from jelmer and poolie.
2745
class TestStackGet(tests.TestCase):
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
2746
5743.1.35 by Vincent Ladeuil
Address some review comments from jelmer and poolie.
2747
    # FIXME: This should be parametrized for all known Stack or dedicated
5743.1.3 by Vincent Ladeuil
Don't forget to parametrized for people *providing* new stacks.
2748
    # paramerized tests created to avoid bloating -- vila 2011-03-31
2749
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
2750
    def test_single_config_get(self):
2751
        conf = dict(foo='bar')
5743.1.34 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
2752
        conf_stack = config.Stack([conf])
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
2753
        self.assertEquals('bar', conf_stack.get('foo'))
2754
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
2755
    def test_get_with_registered_default_value(self):
5743.12.6 by Vincent Ladeuil
Stack.get() provides the registered option default value.
2756
        conf_stack = config.Stack([dict()])
2757
        opt = config.Option('foo', default='bar')
2758
        self.overrideAttr(config, 'option_registry', registry.Registry())
2759
        config.option_registry.register('foo', opt)
2760
        self.assertEquals('bar', conf_stack.get('foo'))
2761
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
2762
    def test_get_without_registered_default_value(self):
2763
        conf_stack = config.Stack([dict()])
2764
        opt = config.Option('foo')
2765
        self.overrideAttr(config, 'option_registry', registry.Registry())
2766
        config.option_registry.register('foo', opt)
2767
        self.assertEquals(None, conf_stack.get('foo'))
2768
2769
    def test_get_without_default_value_for_not_registered(self):
2770
        conf_stack = config.Stack([dict()])
2771
        opt = config.Option('foo')
2772
        self.overrideAttr(config, 'option_registry', registry.Registry())
2773
        self.assertEquals(None, conf_stack.get('foo'))
2774
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
2775
    def test_get_first_definition(self):
2776
        conf1 = dict(foo='bar')
2777
        conf2 = dict(foo='baz')
5743.1.34 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
2778
        conf_stack = config.Stack([conf1, conf2])
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
2779
        self.assertEquals('bar', conf_stack.get('foo'))
2780
5743.1.2 by Vincent Ladeuil
Stacks can be used as read-only sections.
2781
    def test_get_embedded_definition(self):
2782
        conf1 = dict(yy='12')
5743.1.34 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
2783
        conf2 = config.Stack([dict(xx='42'), dict(foo='baz')])
2784
        conf_stack = config.Stack([conf1, conf2])
5743.1.2 by Vincent Ladeuil
Stacks can be used as read-only sections.
2785
        self.assertEquals('baz', conf_stack.get('foo'))
2786
5743.1.16 by Vincent Ladeuil
Allows empty sections and empty section callables.
2787
    def test_get_for_empty_section_callable(self):
5743.1.34 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
2788
        conf_stack = config.Stack([lambda : []])
5743.1.16 by Vincent Ladeuil
Allows empty sections and empty section callables.
2789
        self.assertEquals(None, conf_stack.get('foo'))
2790
5743.1.35 by Vincent Ladeuil
Address some review comments from jelmer and poolie.
2791
    def test_get_for_broken_callable(self):
2792
        # Trying to use and invalid callable raises an exception on first use
2793
        conf_stack = config.Stack([lambda : object()])
2794
        self.assertRaises(TypeError, conf_stack.get, 'foo')
2795
2796
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2797
class TestStackWithTransport(tests.TestCaseWithTransport):
2798
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2799
    scenarios = [(key, {'get_stack': builder}) for key, builder
2800
                 in config.test_stack_builder_registry.iteritems()]
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2801
2802
5743.11.1 by Vincent Ladeuil
Add a note about config store builders being called several times by some tests.
2803
class TestConcreteStacks(TestStackWithTransport):
2804
2805
    def test_build_stack(self):
2806
        # Just a smoke test to help debug builders
2807
        stack = self.get_stack(self)
2808
2809
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2810
class TestStackGet(TestStackWithTransport):
2811
2812
    def test_get_for_empty_stack(self):
2813
        conf = self.get_stack(self)
2814
        self.assertEquals(None, conf.get('foo'))
2815
2816
    def test_get_hook(self):
5743.8.11 by Vincent Ladeuil
Restrict the scope when testing hooks to avoid spurious failures.
2817
        conf = self.get_stack(self)
2818
        conf.store._load_from_string('foo=bar')
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2819
        calls = []
2820
        def hook(*args):
2821
            calls.append(args)
5743.8.10 by Vincent Ladeuil
We don't need (nor want) to tie the config hooks to a particular class. Especially when we want to use the same hooks on both implementations.
2822
        config.ConfigHooks.install_named_hook('get', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2823
        self.assertLength(0, calls)
2824
        value = conf.get('foo')
2825
        self.assertEquals('bar', value)
2826
        self.assertLength(1, calls)
2827
        self.assertEquals((conf, 'foo', 'bar'), calls[0])
2828
2829
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2830
class TestStackSet(TestStackWithTransport):
2831
5743.1.7 by Vincent Ladeuil
Simple set implementation.
2832
    def test_simple_set(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2833
        conf = self.get_stack(self)
2834
        conf.store._load_from_string('foo=bar')
5743.1.7 by Vincent Ladeuil
Simple set implementation.
2835
        self.assertEquals('bar', conf.get('foo'))
2836
        conf.set('foo', 'baz')
2837
        # Did we get it back ?
2838
        self.assertEquals('baz', conf.get('foo'))
2839
5743.1.8 by Vincent Ladeuil
Damn, the sections can't be pre-loaded or need to be reloaded on modifications or even better lazily iterated instead.
2840
    def test_set_creates_a_new_section(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2841
        conf = self.get_stack(self)
5743.1.8 by Vincent Ladeuil
Damn, the sections can't be pre-loaded or need to be reloaded on modifications or even better lazily iterated instead.
2842
        conf.set('foo', 'baz')
5743.1.9 by Vincent Ladeuil
Fix the issue by allowing delayed section acquisition.
2843
        self.assertEquals, 'baz', conf.get('foo')
5743.1.8 by Vincent Ladeuil
Damn, the sections can't be pre-loaded or need to be reloaded on modifications or even better lazily iterated instead.
2844
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2845
    def test_set_hook(self):
2846
        calls = []
2847
        def hook(*args):
2848
            calls.append(args)
5743.8.10 by Vincent Ladeuil
We don't need (nor want) to tie the config hooks to a particular class. Especially when we want to use the same hooks on both implementations.
2849
        config.ConfigHooks.install_named_hook('set', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2850
        self.assertLength(0, calls)
2851
        conf = self.get_stack(self)
2852
        conf.set('foo', 'bar')
2853
        self.assertLength(1, calls)
2854
        self.assertEquals((conf, 'foo', 'bar'), calls[0])
2855
5743.1.7 by Vincent Ladeuil
Simple set implementation.
2856
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2857
class TestStackRemove(TestStackWithTransport):
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
2858
2859
    def test_remove_existing(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2860
        conf = self.get_stack(self)
2861
        conf.store._load_from_string('foo=bar')
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
2862
        self.assertEquals('bar', conf.get('foo'))
2863
        conf.remove('foo')
2864
        # Did we get it back ?
2865
        self.assertEquals(None, conf.get('foo'))
2866
2867
    def test_remove_unknown(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
2868
        conf = self.get_stack(self)
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
2869
        self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
2870
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2871
    def test_remove_hook(self):
2872
        calls = []
2873
        def hook(*args):
2874
            calls.append(args)
5743.8.10 by Vincent Ladeuil
We don't need (nor want) to tie the config hooks to a particular class. Especially when we want to use the same hooks on both implementations.
2875
        config.ConfigHooks.install_named_hook('remove', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
2876
        self.assertLength(0, calls)
2877
        conf = self.get_stack(self)
2878
        conf.store._load_from_string('foo=bar')
2879
        conf.remove('foo')
2880
        self.assertLength(1, calls)
2881
        self.assertEquals((conf, 'foo'), calls[0])
2882
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
2883
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
2884
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2885
2886
    def setUp(self):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2887
        super(TestConfigGetOptions, self).setUp()
2888
        create_configs(self)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
2889
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2890
    def test_no_variable(self):
2891
        # Using branch should query branch, locations and bazaar
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2892
        self.assertOptions([], self.branch_config)
2893
2894
    def test_option_in_bazaar(self):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2895
        self.bazaar_config.set_user_option('file', 'bazaar')
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2896
        self.assertOptions([('file', 'bazaar', 'DEFAULT', 'bazaar')],
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2897
                           self.bazaar_config)
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2898
2899
    def test_option_in_locations(self):
2900
        self.locations_config.set_user_option('file', 'locations')
2901
        self.assertOptions(
2902
            [('file', 'locations', self.tree.basedir, 'locations')],
2903
            self.locations_config)
2904
2905
    def test_option_in_branch(self):
2906
        self.branch_config.set_user_option('file', 'branch')
2907
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
2908
                           self.branch_config)
2909
2910
    def test_option_in_bazaar_and_branch(self):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2911
        self.bazaar_config.set_user_option('file', 'bazaar')
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2912
        self.branch_config.set_user_option('file', 'branch')
2913
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
2914
                            ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
2915
                           self.branch_config)
2916
2917
    def test_option_in_branch_and_locations(self):
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2918
        # Hmm, locations override branch :-/
2919
        self.locations_config.set_user_option('file', 'locations')
2920
        self.branch_config.set_user_option('file', 'branch')
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2921
        self.assertOptions(
2922
            [('file', 'locations', self.tree.basedir, 'locations'),
2923
             ('file', 'branch', 'DEFAULT', 'branch'),],
2924
            self.branch_config)
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2925
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2926
    def test_option_in_bazaar_locations_and_branch(self):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2927
        self.bazaar_config.set_user_option('file', 'bazaar')
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2928
        self.locations_config.set_user_option('file', 'locations')
2929
        self.branch_config.set_user_option('file', 'branch')
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
2930
        self.assertOptions(
2931
            [('file', 'locations', self.tree.basedir, 'locations'),
2932
             ('file', 'branch', 'DEFAULT', 'branch'),
2933
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
2934
            self.branch_config)
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
2935
2936
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
2937
class TestConfigRemoveOption(tests.TestCaseWithTransport, TestOptionsMixin):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2938
2939
    def setUp(self):
2940
        super(TestConfigRemoveOption, self).setUp()
2941
        create_configs_with_file_option(self)
2942
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
2943
    def test_remove_in_locations(self):
2944
        self.locations_config.remove_user_option('file', self.tree.basedir)
2945
        self.assertOptions(
2946
            [('file', 'branch', 'DEFAULT', 'branch'),
2947
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
2948
            self.branch_config)
2949
2950
    def test_remove_in_branch(self):
2951
        self.branch_config.remove_user_option('file')
2952
        self.assertOptions(
2953
            [('file', 'locations', self.tree.basedir, 'locations'),
2954
             ('file', 'bazaar', 'DEFAULT', 'bazaar'),],
2955
            self.branch_config)
2956
2957
    def test_remove_in_bazaar(self):
2958
        self.bazaar_config.remove_user_option('file')
2959
        self.assertOptions(
2960
            [('file', 'locations', self.tree.basedir, 'locations'),
2961
             ('file', 'branch', 'DEFAULT', 'branch'),],
2962
            self.branch_config)
2963
5447.4.7 by Vincent Ladeuil
Check error message if the test is checking for errors or we have unexpected success for wrong errors.
2964
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2965
class TestConfigGetSections(tests.TestCaseWithTransport):
2966
2967
    def setUp(self):
2968
        super(TestConfigGetSections, self).setUp()
2969
        create_configs(self)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
2970
2971
    def assertSectionNames(self, expected, conf, name=None):
2972
        """Check which sections are returned for a given config.
2973
2974
        If fallback configurations exist their sections can be included.
2975
2976
        :param expected: A list of section names.
2977
2978
        :param conf: The configuration that will be queried.
2979
2980
        :param name: An optional section name that will be passed to
2981
            get_sections().
2982
        """
5447.4.12 by Vincent Ladeuil
Turn get_options() and get_sections() into private methods because section handling is too messy and needs to be discussed and settled.
2983
        sections = list(conf._get_sections(name))
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
2984
        self.assertLength(len(expected), sections)
5447.4.12 by Vincent Ladeuil
Turn get_options() and get_sections() into private methods because section handling is too messy and needs to be discussed and settled.
2985
        self.assertEqual(expected, [name for name, _, _ in sections])
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
2986
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
2987
    def test_bazaar_default_section(self):
2988
        self.assertSectionNames(['DEFAULT'], self.bazaar_config)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
2989
2990
    def test_locations_default_section(self):
2991
        # No sections are defined in an empty file
2992
        self.assertSectionNames([], self.locations_config)
2993
2994
    def test_locations_named_section(self):
2995
        self.locations_config.set_user_option('file', 'locations')
2996
        self.assertSectionNames([self.tree.basedir], self.locations_config)
2997
2998
    def test_locations_matching_sections(self):
2999
        loc_config = self.locations_config
3000
        loc_config.set_user_option('file', 'locations')
3001
        # We need to cheat a bit here to create an option in sections above and
3002
        # below the 'location' one.
3003
        parser = loc_config._get_parser()
3004
        # locations.cong deals with '/' ignoring native os.sep
3005
        location_names = self.tree.basedir.split('/')
3006
        parent = '/'.join(location_names[:-1])
3007
        child = '/'.join(location_names + ['child'])
3008
        parser[parent] = {}
3009
        parser[parent]['file'] = 'parent'
3010
        parser[child] = {}
3011
        parser[child]['file'] = 'child'
3012
        self.assertSectionNames([self.tree.basedir, parent], loc_config)
3013
3014
    def test_branch_data_default_section(self):
3015
        self.assertSectionNames([None],
3016
                                self.branch_config._get_branch_data_config())
3017
3018
    def test_branch_default_sections(self):
3019
        # No sections are defined in an empty locations file
3020
        self.assertSectionNames([None, 'DEFAULT'],
3021
                                self.branch_config)
3022
        # Unless we define an option
3023
        self.branch_config._get_location_config().set_user_option(
3024
            'file', 'locations')
3025
        self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
3026
                                self.branch_config)
3027
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
3028
    def test_bazaar_named_section(self):
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
3029
        # We need to cheat as the API doesn't give direct access to sections
3030
        # other than DEFAULT.
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
3031
        self.bazaar_config.set_alias('bazaar', 'bzr')
3032
        self.assertSectionNames(['ALIASES'], self.bazaar_config, 'ALIASES')
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
3033
3034
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
3035
class TestAuthenticationConfigFile(tests.TestCase):
2900.2.14 by Vincent Ladeuil
More tests.
3036
    """Test the authentication.conf file matching"""
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3037
3038
    def _got_user_passwd(self, expected_user, expected_password,
3039
                         config, *args, **kwargs):
3040
        credentials = config.get_credentials(*args, **kwargs)
3041
        if credentials is None:
3042
            user = None
3043
            password = None
3044
        else:
3045
            user = credentials['user']
3046
            password = credentials['password']
3047
        self.assertEquals(expected_user, user)
3048
        self.assertEquals(expected_password, password)
3049
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
3050
    def test_empty_config(self):
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3051
        conf = config.AuthenticationConfig(_file=StringIO())
3052
        self.assertEquals({}, conf._get_config())
3053
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
3054
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
3055
    def test_missing_auth_section_header(self):
3056
        conf = config.AuthenticationConfig(_file=StringIO('foo = bar'))
3057
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
3058
3059
    def test_auth_section_header_not_closed(self):
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3060
        conf = config.AuthenticationConfig(_file=StringIO('[DEF'))
3061
        self.assertRaises(errors.ParseConfigError, conf._get_config)
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
3062
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
3063
    def test_auth_value_not_boolean(self):
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
3064
        conf = config.AuthenticationConfig(_file=StringIO(
3065
                """[broken]
3066
scheme=ftp
3067
user=joe
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
3068
verify_certificates=askme # Error: Not a boolean
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
3069
"""))
3070
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
3071
3072
    def test_auth_value_not_int(self):
2900.2.22 by Vincent Ladeuil
Polishing.
3073
        conf = config.AuthenticationConfig(_file=StringIO(
3074
                """[broken]
3075
scheme=ftp
3076
user=joe
3077
port=port # Error: Not an int
3078
"""))
3079
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3080
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
3081
    def test_unknown_password_encoding(self):
3082
        conf = config.AuthenticationConfig(_file=StringIO(
3083
                """[broken]
3084
scheme=ftp
3085
user=joe
3086
password_encoding=unknown
3087
"""))
3088
        self.assertRaises(ValueError, conf.get_password,
3089
                          'ftp', 'foo.net', 'joe')
3090
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3091
    def test_credentials_for_scheme_host(self):
3092
        conf = config.AuthenticationConfig(_file=StringIO(
3093
                """# Identity on foo.net
3094
[ftp definition]
3095
scheme=ftp
3096
host=foo.net
3097
user=joe
3098
password=secret-pass
3099
"""))
3100
        # Basic matching
3101
        self._got_user_passwd('joe', 'secret-pass', conf, 'ftp', 'foo.net')
3102
        # different scheme
3103
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
3104
        # different host
3105
        self._got_user_passwd(None, None, conf, 'ftp', 'bar.net')
3106
3107
    def test_credentials_for_host_port(self):
3108
        conf = config.AuthenticationConfig(_file=StringIO(
3109
                """# Identity on foo.net
3110
[ftp definition]
3111
scheme=ftp
3112
port=10021
3113
host=foo.net
3114
user=joe
3115
password=secret-pass
3116
"""))
3117
        # No port
3118
        self._got_user_passwd('joe', 'secret-pass',
3119
                              conf, 'ftp', 'foo.net', port=10021)
3120
        # different port
3121
        self._got_user_passwd(None, None, conf, 'ftp', 'foo.net')
3122
3123
    def test_for_matching_host(self):
3124
        conf = config.AuthenticationConfig(_file=StringIO(
3125
                """# Identity on foo.net
3126
[sourceforge]
3127
scheme=bzr
3128
host=bzr.sf.net
3129
user=joe
3130
password=joepass
3131
[sourceforge domain]
3132
scheme=bzr
3133
host=.bzr.sf.net
3134
user=georges
3135
password=bendover
3136
"""))
3137
        # matching domain
3138
        self._got_user_passwd('georges', 'bendover',
3139
                              conf, 'bzr', 'foo.bzr.sf.net')
3140
        # phishing attempt
3141
        self._got_user_passwd(None, None,
3142
                              conf, 'bzr', 'bbzr.sf.net')
3143
3144
    def test_for_matching_host_None(self):
3145
        conf = config.AuthenticationConfig(_file=StringIO(
3146
                """# Identity on foo.net
3147
[catchup bzr]
3148
scheme=bzr
3149
user=joe
3150
password=joepass
3151
[DEFAULT]
3152
user=georges
3153
password=bendover
3154
"""))
3155
        # match no host
3156
        self._got_user_passwd('joe', 'joepass',
3157
                              conf, 'bzr', 'quux.net')
3158
        # no host but different scheme
3159
        self._got_user_passwd('georges', 'bendover',
3160
                              conf, 'ftp', 'quux.net')
3161
3162
    def test_credentials_for_path(self):
3163
        conf = config.AuthenticationConfig(_file=StringIO(
3164
                """
3165
[http dir1]
3166
scheme=http
3167
host=bar.org
3168
path=/dir1
3169
user=jim
3170
password=jimpass
3171
[http dir2]
3172
scheme=http
3173
host=bar.org
3174
path=/dir2
3175
user=georges
3176
password=bendover
3177
"""))
3178
        # no path no dice
3179
        self._got_user_passwd(None, None,
3180
                              conf, 'http', host='bar.org', path='/dir3')
3181
        # matching path
3182
        self._got_user_passwd('georges', 'bendover',
3183
                              conf, 'http', host='bar.org', path='/dir2')
3184
        # matching subdir
3185
        self._got_user_passwd('jim', 'jimpass',
3186
                              conf, 'http', host='bar.org',path='/dir1/subdir')
3187
3188
    def test_credentials_for_user(self):
3189
        conf = config.AuthenticationConfig(_file=StringIO(
3190
                """
3191
[with user]
3192
scheme=http
3193
host=bar.org
3194
user=jim
3195
password=jimpass
3196
"""))
3197
        # Get user
3198
        self._got_user_passwd('jim', 'jimpass',
3199
                              conf, 'http', 'bar.org')
3200
        # Get same user
3201
        self._got_user_passwd('jim', 'jimpass',
3202
                              conf, 'http', 'bar.org', user='jim')
3203
        # Don't get a different user if one is specified
3204
        self._got_user_passwd(None, None,
3205
                              conf, 'http', 'bar.org', user='georges')
3206
3418.4.1 by Vincent Ladeuil
Reproduce bug 199440.
3207
    def test_credentials_for_user_without_password(self):
3208
        conf = config.AuthenticationConfig(_file=StringIO(
3209
                """
3210
[without password]
3211
scheme=http
3212
host=bar.org
3213
user=jim
3214
"""))
3215
        # Get user but no password
3216
        self._got_user_passwd('jim', None,
3217
                              conf, 'http', 'bar.org')
3218
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
3219
    def test_verify_certificates(self):
3220
        conf = config.AuthenticationConfig(_file=StringIO(
3221
                """
3222
[self-signed]
3223
scheme=https
3224
host=bar.org
3225
user=jim
3226
password=jimpass
3227
verify_certificates=False
3228
[normal]
3229
scheme=https
3230
host=foo.net
3231
user=georges
3232
password=bendover
3233
"""))
3234
        credentials = conf.get_credentials('https', 'bar.org')
3235
        self.assertEquals(False, credentials.get('verify_certificates'))
3236
        credentials = conf.get_credentials('https', 'foo.net')
3237
        self.assertEquals(True, credentials.get('verify_certificates'))
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
3238
3777.1.10 by Aaron Bentley
Ensure credentials are stored
3239
3240
class TestAuthenticationStorage(tests.TestCaseInTempDir):
3241
3777.1.8 by Aaron Bentley
Commit work-in-progress
3242
    def test_set_credentials(self):
3777.1.10 by Aaron Bentley
Ensure credentials are stored
3243
        conf = config.AuthenticationConfig()
3777.3.2 by Aaron Bentley
Reverse order of scheme and password
3244
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password',
4081.1.1 by Jean-Francois Roy
A 'realm' optional argument was added to the get_credentials and set_credentials
3245
        99, path='/foo', verify_certificates=False, realm='realm')
3777.1.8 by Aaron Bentley
Commit work-in-progress
3246
        credentials = conf.get_credentials(host='host', scheme='scheme',
4081.1.1 by Jean-Francois Roy
A 'realm' optional argument was added to the get_credentials and set_credentials
3247
                                           port=99, path='/foo',
3248
                                           realm='realm')
3777.1.10 by Aaron Bentley
Ensure credentials are stored
3249
        CREDENTIALS = {'name': 'name', 'user': 'user', 'password': 'password',
4107.1.8 by Jean-Francois Roy
Updated test_config to account for the new credentials keys.
3250
                       'verify_certificates': False, 'scheme': 'scheme', 
3251
                       'host': 'host', 'port': 99, 'path': '/foo', 
3252
                       'realm': 'realm'}
3777.1.10 by Aaron Bentley
Ensure credentials are stored
3253
        self.assertEqual(CREDENTIALS, credentials)
3254
        credentials_from_disk = config.AuthenticationConfig().get_credentials(
4081.1.1 by Jean-Francois Roy
A 'realm' optional argument was added to the get_credentials and set_credentials
3255
            host='host', scheme='scheme', port=99, path='/foo', realm='realm')
3777.1.10 by Aaron Bentley
Ensure credentials are stored
3256
        self.assertEqual(CREDENTIALS, credentials_from_disk)
3777.1.8 by Aaron Bentley
Commit work-in-progress
3257
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
3258
    def test_reset_credentials_different_name(self):
3259
        conf = config.AuthenticationConfig()
3777.3.2 by Aaron Bentley
Reverse order of scheme and password
3260
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password'),
3261
        conf.set_credentials('name2', 'host', 'user2', 'scheme', 'password'),
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
3262
        self.assertIs(None, conf._get_config().get('name'))
3263
        credentials = conf.get_credentials(host='host', scheme='scheme')
3264
        CREDENTIALS = {'name': 'name2', 'user': 'user2', 'password':
4107.1.8 by Jean-Francois Roy
Updated test_config to account for the new credentials keys.
3265
                       'password', 'verify_certificates': True, 
3266
                       'scheme': 'scheme', 'host': 'host', 'port': None, 
3267
                       'path': None, 'realm': None}
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
3268
        self.assertEqual(CREDENTIALS, credentials)
3269
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
3270
2900.2.14 by Vincent Ladeuil
More tests.
3271
class TestAuthenticationConfig(tests.TestCase):
3272
    """Test AuthenticationConfig behaviour"""
3273
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
3274
    def _check_default_password_prompt(self, expected_prompt_format, scheme,
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3275
                                       host=None, port=None, realm=None,
3276
                                       path=None):
2900.2.14 by Vincent Ladeuil
More tests.
3277
        if host is None:
3278
            host = 'bar.org'
3279
        user, password = 'jim', 'precious'
3280
        expected_prompt = expected_prompt_format % {
3281
            'scheme': scheme, 'host': host, 'port': port,
3282
            'user': user, 'realm': realm}
3283
3284
        stdout = tests.StringIOWrapper()
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3285
        stderr = tests.StringIOWrapper()
2900.2.14 by Vincent Ladeuil
More tests.
3286
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n',
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3287
                                            stdout=stdout, stderr=stderr)
2900.2.14 by Vincent Ladeuil
More tests.
3288
        # We use an empty conf so that the user is always prompted
3289
        conf = config.AuthenticationConfig()
3290
        self.assertEquals(password,
3291
                          conf.get_password(scheme, host, user, port=port,
3292
                                            realm=realm, path=path))
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3293
        self.assertEquals(expected_prompt, stderr.getvalue())
3294
        self.assertEquals('', stdout.getvalue())
2900.2.14 by Vincent Ladeuil
More tests.
3295
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3296
    def _check_default_username_prompt(self, expected_prompt_format, scheme,
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3297
                                       host=None, port=None, realm=None,
3298
                                       path=None):
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3299
        if host is None:
3300
            host = 'bar.org'
3301
        username = 'jim'
3302
        expected_prompt = expected_prompt_format % {
3303
            'scheme': scheme, 'host': host, 'port': port,
3304
            'realm': realm}
3305
        stdout = tests.StringIOWrapper()
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3306
        stderr = tests.StringIOWrapper()
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3307
        ui.ui_factory = tests.TestUIFactory(stdin=username+ '\n',
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3308
                                            stdout=stdout, stderr=stderr)
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3309
        # We use an empty conf so that the user is always prompted
3310
        conf = config.AuthenticationConfig()
4222.3.5 by Jelmer Vernooij
Fix test.
3311
        self.assertEquals(username, conf.get_user(scheme, host, port=port,
3312
                          realm=realm, path=path, ask=True))
4368.3.1 by Vincent Ladeuil
Use stderr for UI prompt to address bug #376582.
3313
        self.assertEquals(expected_prompt, stderr.getvalue())
3314
        self.assertEquals('', stdout.getvalue())
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3315
3316
    def test_username_defaults_prompts(self):
3317
        # HTTP prompts can't be tested here, see test_http.py
5923.1.3 by Vincent Ladeuil
Even more unicode prompts fixes revealed by pqm.
3318
        self._check_default_username_prompt(u'FTP %(host)s username: ', 'ftp')
3319
        self._check_default_username_prompt(
3320
            u'FTP %(host)s:%(port)d username: ', 'ftp', port=10020)
3321
        self._check_default_username_prompt(
3322
            u'SSH %(host)s:%(port)d username: ', 'ssh', port=12345)
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
3323
4222.3.11 by Jelmer Vernooij
Add test to make sure the default= parameter works.
3324
    def test_username_default_no_prompt(self):
3325
        conf = config.AuthenticationConfig()
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
3326
        self.assertEquals(None,
4222.3.11 by Jelmer Vernooij
Add test to make sure the default= parameter works.
3327
            conf.get_user('ftp', 'example.com'))
4304.2.1 by Vincent Ladeuil
Fix bug #367726 by reverting some default user handling introduced
3328
        self.assertEquals("explicitdefault",
4222.3.11 by Jelmer Vernooij
Add test to make sure the default= parameter works.
3329
            conf.get_user('ftp', 'example.com', default="explicitdefault"))
3330
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
3331
    def test_password_default_prompts(self):
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
3332
        # HTTP prompts can't be tested here, see test_http.py
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
3333
        self._check_default_password_prompt(
5923.1.3 by Vincent Ladeuil
Even more unicode prompts fixes revealed by pqm.
3334
            u'FTP %(user)s@%(host)s password: ', 'ftp')
3335
        self._check_default_password_prompt(
3336
            u'FTP %(user)s@%(host)s:%(port)d password: ', 'ftp', port=10020)
3337
        self._check_default_password_prompt(
3338
            u'SSH %(user)s@%(host)s:%(port)d password: ', 'ssh', port=12345)
2900.2.14 by Vincent Ladeuil
More tests.
3339
        # SMTP port handling is a bit special (it's handled if embedded in the
3340
        # host too)
2900.2.22 by Vincent Ladeuil
Polishing.
3341
        # FIXME: should we: forbid that, extend it to other schemes, leave
3342
        # things as they are that's fine thank you ?
5923.1.3 by Vincent Ladeuil
Even more unicode prompts fixes revealed by pqm.
3343
        self._check_default_password_prompt(
3344
            u'SMTP %(user)s@%(host)s password: ', 'smtp')
3345
        self._check_default_password_prompt(
3346
            u'SMTP %(user)s@%(host)s password: ', 'smtp', host='bar.org:10025')
3347
        self._check_default_password_prompt(
3348
            u'SMTP %(user)s@%(host)s:%(port)d password: ', 'smtp', port=10025)
2900.2.14 by Vincent Ladeuil
More tests.
3349
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
3350
    def test_ssh_password_emits_warning(self):
3351
        conf = config.AuthenticationConfig(_file=StringIO(
3352
                """
3353
[ssh with password]
3354
scheme=ssh
3355
host=bar.org
3356
user=jim
3357
password=jimpass
3358
"""))
3359
        entered_password = 'typed-by-hand'
3360
        stdout = tests.StringIOWrapper()
4449.3.30 by Martin Pool
Tweaks to test_config ui factory use
3361
        stderr = tests.StringIOWrapper()
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
3362
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
4449.3.30 by Martin Pool
Tweaks to test_config ui factory use
3363
                                            stdout=stdout, stderr=stderr)
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
3364
3365
        # Since the password defined in the authentication config is ignored,
3366
        # the user is prompted
3367
        self.assertEquals(entered_password,
3368
                          conf.get_password('ssh', 'bar.org', user='jim'))
3369
        self.assertContainsRe(
4794.1.17 by Robert Collins
Fix from vila for type log_log.
3370
            self.get_log(),
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
3371
            'password ignored in section \[ssh with password\]')
3372
3420.1.3 by Vincent Ladeuil
John's review feedback.
3373
    def test_ssh_without_password_doesnt_emit_warning(self):
3374
        conf = config.AuthenticationConfig(_file=StringIO(
3375
                """
3376
[ssh with password]
3377
scheme=ssh
3378
host=bar.org
3379
user=jim
3380
"""))
3381
        entered_password = 'typed-by-hand'
3382
        stdout = tests.StringIOWrapper()
4449.3.30 by Martin Pool
Tweaks to test_config ui factory use
3383
        stderr = tests.StringIOWrapper()
3420.1.3 by Vincent Ladeuil
John's review feedback.
3384
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n',
4449.3.30 by Martin Pool
Tweaks to test_config ui factory use
3385
                                            stdout=stdout,
3386
                                            stderr=stderr)
3420.1.3 by Vincent Ladeuil
John's review feedback.
3387
3388
        # Since the password defined in the authentication config is ignored,
3389
        # the user is prompted
3390
        self.assertEquals(entered_password,
3391
                          conf.get_password('ssh', 'bar.org', user='jim'))
3420.1.4 by Vincent Ladeuil
Fix comment.
3392
        # No warning shoud be emitted since there is no password. We are only
3393
        # providing "user".
3420.1.3 by Vincent Ladeuil
John's review feedback.
3394
        self.assertNotContainsRe(
4794.1.15 by Robert Collins
Review feedback.
3395
            self.get_log(),
3420.1.3 by Vincent Ladeuil
John's review feedback.
3396
            'password ignored in section \[ssh with password\]')
3397
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
3398
    def test_uses_fallback_stores(self):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
3399
        self.overrideAttr(config, 'credential_store_registry',
3400
                          config.CredentialStoreRegistry())
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
3401
        store = StubCredentialStore()
3402
        store.add_credentials("http", "example.com", "joe", "secret")
3403
        config.credential_store_registry.register("stub", store, fallback=True)
3404
        conf = config.AuthenticationConfig(_file=StringIO())
3405
        creds = conf.get_credentials("http", "example.com")
3406
        self.assertEquals("joe", creds["user"])
3407
        self.assertEquals("secret", creds["password"])
3408
2900.2.14 by Vincent Ladeuil
More tests.
3409
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3410
class StubCredentialStore(config.CredentialStore):
3411
3412
    def __init__(self):
3413
        self._username = {}
3414
        self._password = {}
3415
3416
    def add_credentials(self, scheme, host, user, password=None):
3417
        self._username[(scheme, host)] = user
3418
        self._password[(scheme, host)] = password
3419
3420
    def get_credentials(self, scheme, host, port=None, user=None,
3421
        path=None, realm=None):
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3422
        key = (scheme, host)
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3423
        if not key in self._username:
3424
            return None
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3425
        return { "scheme": scheme, "host": host, "port": port,
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3426
                "user": self._username[key], "password": self._password[key]}
3427
3428
3429
class CountingCredentialStore(config.CredentialStore):
3430
3431
    def __init__(self):
3432
        self._calls = 0
3433
3434
    def get_credentials(self, scheme, host, port=None, user=None,
3435
        path=None, realm=None):
3436
        self._calls += 1
3437
        return None
3438
3439
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
3440
class TestCredentialStoreRegistry(tests.TestCase):
3441
3442
    def _get_cs_registry(self):
3443
        return config.credential_store_registry
3444
3445
    def test_default_credential_store(self):
3446
        r = self._get_cs_registry()
3447
        default = r.get_credential_store(None)
3448
        self.assertIsInstance(default, config.PlainTextCredentialStore)
3449
3450
    def test_unknown_credential_store(self):
3451
        r = self._get_cs_registry()
3452
        # It's hard to imagine someone creating a credential store named
3453
        # 'unknown' so we use that as an never registered key.
3454
        self.assertRaises(KeyError, r.get_credential_store, 'unknown')
3455
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3456
    def test_fallback_none_registered(self):
3457
        r = config.CredentialStoreRegistry()
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3458
        self.assertEquals(None,
3459
                          r.get_fallback_credentials("http", "example.com"))
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3460
3461
    def test_register(self):
3462
        r = config.CredentialStoreRegistry()
3463
        r.register("stub", StubCredentialStore(), fallback=False)
3464
        r.register("another", StubCredentialStore(), fallback=True)
3465
        self.assertEquals(["another", "stub"], r.keys())
3466
3467
    def test_register_lazy(self):
3468
        r = config.CredentialStoreRegistry()
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3469
        r.register_lazy("stub", "bzrlib.tests.test_config",
3470
                        "StubCredentialStore", fallback=False)
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3471
        self.assertEquals(["stub"], r.keys())
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3472
        self.assertIsInstance(r.get_credential_store("stub"),
3473
                              StubCredentialStore)
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3474
3475
    def test_is_fallback(self):
3476
        r = config.CredentialStoreRegistry()
3477
        r.register("stub1", None, fallback=False)
3478
        r.register("stub2", None, fallback=True)
3479
        self.assertEquals(False, r.is_fallback("stub1"))
3480
        self.assertEquals(True, r.is_fallback("stub2"))
3481
3482
    def test_no_fallback(self):
3483
        r = config.CredentialStoreRegistry()
3484
        store = CountingCredentialStore()
3485
        r.register("count", store, fallback=False)
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3486
        self.assertEquals(None,
3487
                          r.get_fallback_credentials("http", "example.com"))
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3488
        self.assertEquals(0, store._calls)
3489
3490
    def test_fallback_credentials(self):
3491
        r = config.CredentialStoreRegistry()
3492
        store = StubCredentialStore()
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3493
        store.add_credentials("http", "example.com",
3494
                              "somebody", "geheim")
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
3495
        r.register("stub", store, fallback=True)
3496
        creds = r.get_fallback_credentials("http", "example.com")
3497
        self.assertEquals("somebody", creds["user"])
3498
        self.assertEquals("geheim", creds["password"])
3499
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
3500
    def test_fallback_first_wins(self):
3501
        r = config.CredentialStoreRegistry()
3502
        stub1 = StubCredentialStore()
3503
        stub1.add_credentials("http", "example.com",
3504
                              "somebody", "stub1")
3505
        r.register("stub1", stub1, fallback=True)
3506
        stub2 = StubCredentialStore()
3507
        stub2.add_credentials("http", "example.com",
3508
                              "somebody", "stub2")
3509
        r.register("stub2", stub1, fallback=True)
3510
        creds = r.get_fallback_credentials("http", "example.com")
3511
        self.assertEquals("somebody", creds["user"])
3512
        self.assertEquals("stub1", creds["password"])
3513
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
3514
3515
class TestPlainTextCredentialStore(tests.TestCase):
3516
3517
    def test_decode_password(self):
3518
        r = config.credential_store_registry
3519
        plain_text = r.get_credential_store()
3520
        decoded = plain_text.decode_password(dict(password='secret'))
3521
        self.assertEquals('secret', decoded)
3522
3523
2900.2.14 by Vincent Ladeuil
More tests.
3524
# FIXME: Once we have a way to declare authentication to all test servers, we
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
3525
# can implement generic tests.
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
3526
# test_user_password_in_url
3527
# test_user_in_url_password_from_config
3528
# test_user_in_url_password_prompted
3529
# test_user_in_config
3530
# test_user_getpass.getuser
3531
# test_user_prompted ?
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
3532
class TestAuthenticationRing(tests.TestCaseWithTransport):
3533
    pass
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
3534
3535
3536
class TestAutoUserId(tests.TestCase):
3537
    """Test inferring an automatic user name."""
3538
3539
    def test_auto_user_id(self):
3540
        """Automatic inference of user name.
3541
        
3542
        This is a bit hard to test in an isolated way, because it depends on
3543
        system functions that go direct to /etc or perhaps somewhere else.
3544
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
3545
        to be able to choose a user name with no configuration.
3546
        """
3547
        if sys.platform == 'win32':
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
3548
            raise tests.TestSkipped(
3549
                "User name inference not implemented on win32")
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
3550
        realname, address = config._auto_user_id()
3551
        if os.path.exists('/etc/mailname'):
5813.1.1 by Jelmer Vernooij
Allow realname to be empty in tests.
3552
            self.assertIsNot(None, realname)
3553
            self.assertIsNot(None, address)
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
3554
        else:
3555
            self.assertEquals((None, None), (realname, address))
3556