/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
1
# Copyright (C) 2005-2014, 2016 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]."""
5912.5.7 by Martin
Minor cleanups and note about error case
18
6524.2.2 by Aaron Bentley
Test branchname config var.
19
from textwrap import dedent
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
6621.5.1 by Martin
Remove internal copy of configobj and add workarounds for bugs in latest version
24
import configobj
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
25
from testtools import matchers
26
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
27
from .. import (
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
28
    branch,
1878.1.3 by John Arbash Meinel
some test cleanups
29
    config,
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
30
    controldir,
4603.1.10 by Aaron Bentley
Provide change editor via config.
31
    diff,
1878.1.3 by John Arbash Meinel
some test cleanups
32
    errors,
6754.8.12 by Jelmer Vernooij
FIx remaining tests.
33
    lock,
1878.1.3 by John Arbash Meinel
some test cleanups
34
    osutils,
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
35
    mail_client,
2900.2.14 by Vincent Ladeuil
More tests.
36
    ui,
1878.1.3 by John Arbash Meinel
some test cleanups
37
    urlutils,
6449.2.1 by Jelmer Vernooij
Add bzrlib.config.RegistryOption.
38
    registry as _mod_registry,
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
39
    tests,
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
40
    trace,
1878.1.3 by John Arbash Meinel
some test cleanups
41
    )
6670.4.14 by Jelmer Vernooij
Move remote to breezy.bzr.
42
from ..bzr import (
43
    remote,
44
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
45
from ..sixish import (
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
46
    BytesIO,
6973.6.2 by Jelmer Vernooij
Fix more tests.
47
    text_type,
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
48
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
49
from ..transport import remote as transport_remote
50
from . import (
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
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
    )
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
55
56
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
57
def lockable_config_scenarios():
58
    return [
59
        ('global',
60
         {'config_class': config.GlobalConfig,
61
          'config_args': [],
62
          'config_section': 'DEFAULT'}),
63
        ('locations',
64
         {'config_class': config.LocationConfig,
65
          'config_args': ['.'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
66
          'config_section': '.'}), ]
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
67
68
5506.2.1 by Vincent Ladeuil
Implements ``bzr config --active option`` displaying only the value.
69
load_tests = scenarios.load_tests_apply_scenarios
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
70
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
71
# Register helpers to build stores
72
config.test_store_builder_registry.register(
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
73
    'configobj', lambda test: config.TransportIniFileStore(
74
        test.get_transport(), 'configobj.conf'))
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
75
config.test_store_builder_registry.register(
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
76
    'breezy', lambda test: config.GlobalStore())
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
77
config.test_store_builder_registry.register(
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
78
    '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
79
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
80
81
def build_backing_branch(test, relpath,
82
                         transport_class=None, server_class=None):
83
    """Test helper to create a backing branch only once.
84
85
    Some tests needs multiple stores/stacks to check concurrent update
86
    behaviours. As such, they need to build different branch *objects* even if
87
    they share the branch on disk.
88
89
    :param relpath: The relative path to the branch. (Note that the helper
90
        should always specify the same relpath).
91
92
    :param transport_class: The Transport class the test needs to use.
93
94
    :param server_class: The server associated with the ``transport_class``
95
        above.
96
5743.10.9 by Vincent Ladeuil
Fix use of none where neither is required.
97
    Either both or neither of ``transport_class`` and ``server_class`` should
98
    be specified.
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
99
    """
100
    if transport_class is not None and server_class is not None:
101
        test.transport_class = transport_class
102
        test.transport_server = server_class
103
    elif not (transport_class is None and server_class is None):
104
        raise AssertionError('Specify both ``transport_class`` and '
5743.10.9 by Vincent Ladeuil
Fix use of none where neither is required.
105
                             '``server_class`` or neither of them')
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
106
    if getattr(test, 'backing_branch', None) is None:
107
        # First call, let's build the branch on disk
108
        test.backing_branch = test.make_branch(relpath)
109
110
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
111
def build_branch_store(test):
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
112
    build_backing_branch(test, 'branch')
113
    b = branch.Branch.open('branch')
114
    return config.BranchStore(b)
7143.15.2 by Jelmer Vernooij
Run autopep8.
115
116
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
117
config.test_store_builder_registry.register('branch', build_branch_store)
118
119
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
120
def build_control_store(test):
121
    build_backing_branch(test, 'branch')
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
122
    b = controldir.ControlDir.open('branch')
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
123
    return config.ControlStore(b)
7143.15.2 by Jelmer Vernooij
Run autopep8.
124
125
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
126
config.test_store_builder_registry.register('control', build_control_store)
127
128
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
129
def build_remote_branch_store(test):
130
    # There is only one permutation (but we won't be able to handle more with
131
    # this design anyway)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
132
    (transport_class,
133
     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.
134
    build_backing_branch(test, 'branch', transport_class, server_class)
135
    b = branch.Branch.open(test.get_url('branch'))
136
    return config.BranchStore(b)
7143.15.2 by Jelmer Vernooij
Run autopep8.
137
138
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
139
config.test_store_builder_registry.register('remote_branch',
140
                                            build_remote_branch_store)
141
142
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
143
config.test_stack_builder_registry.register(
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
144
    'breezy', lambda test: config.GlobalStack())
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
145
config.test_stack_builder_registry.register(
146
    'location', lambda test: config.LocationStack('.'))
147
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
148
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
149
def build_branch_stack(test):
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
150
    build_backing_branch(test, 'branch')
151
    b = branch.Branch.open('branch')
152
    return config.BranchStack(b)
7143.15.2 by Jelmer Vernooij
Run autopep8.
153
154
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
155
config.test_stack_builder_registry.register('branch', build_branch_stack)
156
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
157
6379.11.1 by Vincent Ladeuil
Migrate location options to config stacks.
158
def build_branch_only_stack(test):
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
159
    # There is only one permutation (but we won't be able to handle more with
160
    # this design anyway)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
161
    (transport_class,
162
     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.
163
    build_backing_branch(test, 'branch', transport_class, server_class)
164
    b = branch.Branch.open(test.get_url('branch'))
6379.11.2 by Vincent Ladeuil
No matter how weird BranchOnlyStack is, it's public, the FIXMEs should be enough for devs to notice.
165
    return config.BranchOnlyStack(b)
7143.15.2 by Jelmer Vernooij
Run autopep8.
166
167
6379.11.1 by Vincent Ladeuil
Migrate location options to config stacks.
168
config.test_stack_builder_registry.register('branch_only',
169
                                            build_branch_only_stack)
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
170
7143.15.2 by Jelmer Vernooij
Run autopep8.
171
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
172
def build_remote_control_stack(test):
173
    # There is only one permutation (but we won't be able to handle more with
174
    # this design anyway)
175
    (transport_class,
176
     server_class) = transport_remote.get_test_permutations()[0]
177
    # We need only a bzrdir for this, not a full branch, but it's not worth
178
    # creating a dedicated helper to create only the bzrdir
179
    build_backing_branch(test, 'branch', transport_class, server_class)
180
    b = branch.Branch.open(test.get_url('branch'))
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
181
    return config.RemoteControlStack(b.controldir)
7143.15.2 by Jelmer Vernooij
Run autopep8.
182
183
6076.1.1 by Vincent Ladeuil
Add the missing config stacks and store
184
config.test_stack_builder_registry.register('remote_control',
185
                                            build_remote_control_stack)
186
5743.10.2 by Vincent Ladeuil
Make sure RemoteBranch are supported as well, relying on the vfs API.
187
7143.15.2 by Jelmer Vernooij
Run autopep8.
188
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
189
sample_config_text = u"""
190
[DEFAULT]
191
email=Erik B\u00e5gfors <erik@bagfors.nu>
192
editor=vim
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
193
change_editor=vimdiff -of @new_path @old_path
6012.2.11 by Jonathan Riddell
rename config option signing_key to gpg_signing_key
194
gpg_signing_key=DD4D5088
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
195
log_format=short
5971.1.58 by Jonathan Riddell
more tests for new config options
196
validate_signatures_in_log=true
197
acceptable_keys=amy
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
198
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.
199
bzr.mergetool.sometool=sometool {base} {this} {other} -o {result}
5321.2.3 by Vincent Ladeuil
Prefix mergetools option names with 'bzr.'.
200
bzr.mergetool.funkytool=funkytool "arg with spaces" {this_temp}
6091.4.2 by Gordon Tyler
Updated TestGlobalConfigItems.test_get_merge_tools for new config quoting behaviour.
201
bzr.mergetool.newtool='"newtool 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.
202
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
203
[ALIASES]
204
h=help
6973.10.4 by Jelmer Vernooij
Update python3.passing.
205
ll=""".encode('utf-8') + sample_long_alias.encode('utf-8') + b"\n"
206
207
208
sample_always_signatures = b"""
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
209
[DEFAULT]
210
check_signatures=ignore
211
create_signatures=always
212
"""
213
6973.10.4 by Jelmer Vernooij
Update python3.passing.
214
sample_ignore_signatures = b"""
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
215
[DEFAULT]
216
check_signatures=require
217
create_signatures=never
218
"""
219
6973.10.4 by Jelmer Vernooij
Update python3.passing.
220
sample_maybe_signatures = b"""
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
221
[DEFAULT]
222
check_signatures=ignore
223
create_signatures=when-required
224
"""
225
6973.10.4 by Jelmer Vernooij
Update python3.passing.
226
sample_branches_text = b"""
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
227
[http://www.example.com]
228
# Top level policy
229
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
230
normal_option = normal
231
appendpath_option = append
2120.6.8 by James Henstridge
Change syntax for setting config option policies. Rather than
232
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
233
norecurse_option = norecurse
2120.6.8 by James Henstridge
Change syntax for setting config option policies. Rather than
234
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
235
[http://www.example.com/ignoreparent]
236
# different project: ignore parent dir config
237
ignore_parents=true
238
[http://www.example.com/norecurse]
239
# configuration items that only apply to this dir
240
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
241
normal_option = norecurse
242
[http://www.example.com/dir]
243
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
244
[/b/]
245
check_signatures=require
246
# test trailing / matching with no children
247
[/a/]
248
check_signatures=check-available
6012.2.11 by Jonathan Riddell
rename config option signing_key to gpg_signing_key
249
gpg_signing_key=default
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
250
user_local_option=local
251
# test trailing / matching
252
[/a/*]
253
#subdirs will match but not the parent
254
[/a/c]
255
check_signatures=ignore
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
256
post_commit=breezy.tests.test_config.post_commit
2120.6.2 by James Henstridge
remove get_matching_sections() norecurse tests, since that feature is handled in the config policy code now
257
#testing explicit beats globs
258
"""
1553.6.3 by Erik Bågfors
tests for AliasesConfig
259
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
260
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
261
def create_configs(test):
262
    """Create configuration files for a given test.
263
264
    This requires creating a tree (and populate the ``test.tree`` attribute)
265
    and its associated branch and will populate the following attributes:
266
267
    - branch_config: A BranchConfig for the associated branch.
268
269
    - locations_config : A LocationConfig for the associated branch
270
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
271
    - breezy_config: A GlobalConfig.
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
272
273
    The tree and branch are created in a 'tree' subdirectory so the tests can
274
    still use the test directory to stay outside of the branch.
275
    """
276
    tree = test.make_branch_and_tree('tree')
277
    test.tree = tree
278
    test.branch_config = config.BranchConfig(tree.branch)
279
    test.locations_config = config.LocationConfig(tree.basedir)
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
280
    test.breezy_config = config.GlobalConfig()
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
281
5533.2.4 by Vincent Ladeuil
Fix whitespace issue.
282
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
283
def create_configs_with_file_option(test):
284
    """Create configuration files with a ``file`` option set in each.
285
286
    This builds on ``create_configs`` and add one ``file`` option in each
287
    configuration with a value which allows identifying the configuration file.
288
    """
289
    create_configs(test)
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
290
    test.breezy_config.set_user_option('file', 'breezy')
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
291
    test.locations_config.set_user_option('file', 'locations')
292
    test.branch_config.set_user_option('file', 'branch')
293
294
295
class TestOptionsMixin:
296
297
    def assertOptions(self, expected, conf):
298
        # We don't care about the parser (as it will make tests hard to write
299
        # and error-prone anyway)
300
        self.assertThat([opt[:4] for opt in conf._get_options()],
301
                        matchers.Equals(expected))
302
303
1474 by Robert Collins
Merge from Aaron Bentley.
304
class InstrumentedConfigObj(object):
305
    """A config obj look-enough-alike to record calls made to it."""
306
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
307
    def __contains__(self, thing):
308
        self._calls.append(('__contains__', thing))
309
        return False
310
311
    def __getitem__(self, key):
312
        self._calls.append(('__getitem__', key))
313
        return self
314
1551.2.20 by Aaron Bentley
Treated config files as utf-8
315
    def __init__(self, input, encoding=None):
316
        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.
317
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
318
    def __setitem__(self, key, value):
319
        self._calls.append(('__setitem__', key, value))
320
2120.6.4 by James Henstridge
add support for specifying policy when storing options
321
    def __delitem__(self, key):
322
        self._calls.append(('__delitem__', key))
323
324
    def keys(self):
325
        self._calls.append(('keys',))
326
        return []
327
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
328
    def reload(self):
329
        self._calls.append(('reload',))
330
1551.2.49 by abentley
Made ConfigObj output binary-identical files on win32 and *nix
331
    def write(self, arg):
1490 by Robert Collins
Implement a 'bzr push' command, with saved locations; update diff to return 1.
332
        self._calls.append(('write',))
333
2120.6.4 by James Henstridge
add support for specifying policy when storing options
334
    def as_bool(self, value):
335
        self._calls.append(('as_bool', value))
336
        return False
337
338
    def get_value(self, section, name):
339
        self._calls.append(('get_value', section, name))
340
        return None
341
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
342
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
343
class FakeBranch(object):
344
6362.1.4 by Jelmer Vernooij
Fix tests.
345
    def __init__(self, base=None):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
346
        if base is None:
347
            self.base = "http://example.com/branches/demo"
348
        else:
349
            self.base = base
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
350
        self._transport = self.control_files = \
6362.1.4 by Jelmer Vernooij
Fix tests.
351
            FakeControlFilesAndTransport()
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
352
4226.1.7 by Robert Collins
Alter test_config.FakeBranch in accordance with the Branch change to have a _get_config.
353
    def _get_config(self):
354
        return config.TransportConfig(self._transport, 'branch.conf')
355
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
356
    def lock_write(self):
6754.8.12 by Jelmer Vernooij
FIx remaining tests.
357
        return lock.LogicalLockResult(self.unlock)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
358
359
    def unlock(self):
360
        pass
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
361
362
3407.2.13 by Martin Pool
Remove indirection through control_files to get transports
363
class FakeControlFilesAndTransport(object):
1185.65.11 by Robert Collins
Disable inheritance for getting at LockableFiles, rather use composition.
364
6362.1.4 by Jelmer Vernooij
Fix tests.
365
    def __init__(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
366
        self.files = {}
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
367
        self._transport = self
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
368
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
369
    def get(self, filename):
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
370
        # from Transport
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
371
        try:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
372
            return BytesIO(self.files[filename])
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
373
        except KeyError:
374
            raise errors.NoSuchFile(filename)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
375
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
376
    def get_bytes(self, filename):
377
        # from Transport
378
        try:
379
            return self.files[filename]
380
        except KeyError:
381
            raise errors.NoSuchFile(filename)
382
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
383
    def put(self, filename, fileobj):
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
384
        self.files[filename] = fileobj.read()
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
385
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
386
    def put_file(self, filename, fileobj):
387
        return self.put(filename, fileobj)
388
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
389
390
class InstrumentedConfig(config.Config):
391
    """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.
392
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
393
    def __init__(self):
394
        super(InstrumentedConfig, self).__init__()
395
        self._calls = []
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
396
        self._signatures = config.CHECK_NEVER
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
397
398
    def _get_user_id(self):
399
        self._calls.append('_get_user_id')
400
        return "Robert Collins <robert.collins@example.org>"
401
1442.1.15 by Robert Collins
make getting the signature checking policy a template method
402
    def _get_signature_checking(self):
403
        self._calls.append('_get_signature_checking')
404
        return self._signatures
405
4603.1.10 by Aaron Bentley
Provide change editor via config.
406
    def _get_change_editor(self):
407
        self._calls.append('_get_change_editor')
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
408
        return 'vimdiff -fo @new_path @old_path'
4603.1.10 by Aaron Bentley
Provide change editor via config.
409
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
410
6973.10.4 by Jelmer Vernooij
Update python3.passing.
411
bool_config = b"""[DEFAULT]
1556.2.2 by Aaron Bentley
Fixed get_bool
412
active = true
413
inactive = false
414
[UPPERCASE]
415
active = True
416
nonactive = False
417
"""
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
418
419
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
420
class TestConfigObj(tests.TestCase):
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
421
1556.2.2 by Aaron Bentley
Fixed get_bool
422
    def test_get_bool(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
423
        co = config.ConfigObj(BytesIO(bool_config))
1556.2.2 by Aaron Bentley
Fixed get_bool
424
        self.assertIs(co.get_bool('DEFAULT', 'active'), True)
425
        self.assertIs(co.get_bool('DEFAULT', 'inactive'), False)
426
        self.assertIs(co.get_bool('UPPERCASE', 'active'), True)
427
        self.assertIs(co.get_bool('UPPERCASE', 'nonactive'), False)
428
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
429
    def test_hash_sign_in_value(self):
430
        """
431
        Before 4.5.0, ConfigObj did not quote # signs in values, so they'd be
432
        treated as comments when read in again. (#86838)
433
        """
434
        co = config.ConfigObj()
435
        co['test'] = 'foo#bar'
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
436
        outfile = BytesIO()
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.
437
        co.write(outfile=outfile)
438
        lines = outfile.getvalue().splitlines()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
439
        self.assertEqual(lines, [b'test = "foo#bar"'])
3221.7.4 by Matt Nordhoff
Add test for bug #86838.
440
        co2 = config.ConfigObj(lines)
441
        self.assertEqual(co2['test'], 'foo#bar')
442
5050.62.10 by Alexander Belchenko
test to illustrate the problem
443
    def test_triple_quotes(self):
444
        # Bug #710410: if the value string has triple quotes
445
        # then ConfigObj versions up to 4.7.2 will quote them wrong
5050.62.12 by Alexander Belchenko
added NEWS entry
446
        # and won't able to read them back
5050.62.10 by Alexander Belchenko
test to illustrate the problem
447
        triple_quotes_value = '''spam
448
""" that's my spam """
449
eggs'''
450
        co = config.ConfigObj()
451
        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.
452
        # While writing this test another bug in ConfigObj has been found:
5050.62.10 by Alexander Belchenko
test to illustrate the problem
453
        # method co.write() without arguments produces list of lines
454
        # one option per line, and multiline values are not split
455
        # 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.
456
        # and that breaks the parsing these lines back by ConfigObj.
457
        # This issue only affects test, but it's better to avoid
458
        # `co.write()` construct at all.
459
        # [bialix 20110222] bug report sent to ConfigObj's author
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
460
        outfile = BytesIO()
5050.62.10 by Alexander Belchenko
test to illustrate the problem
461
        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.
462
        output = outfile.getvalue()
5050.62.10 by Alexander Belchenko
test to illustrate the problem
463
        # now we're trying to read it back
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
464
        co2 = config.ConfigObj(BytesIO(output))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
465
        self.assertEqual(triple_quotes_value, co2['test'])
5050.62.10 by Alexander Belchenko
test to illustrate the problem
466
1556.2.2 by Aaron Bentley
Fixed get_bool
467
6973.10.4 by Jelmer Vernooij
Update python3.passing.
468
erroneous_config = b"""[section] # line 1
2900.1.1 by Vincent Ladeuil
469
good=good # line 2
470
[section] # line 3
471
whocares=notme # line 4
472
"""
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
473
474
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
475
class TestConfigObjErrors(tests.TestCase):
2900.1.1 by Vincent Ladeuil
476
477
    def test_duplicate_section_name_error_line(self):
478
        try:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
479
            co = configobj.ConfigObj(BytesIO(erroneous_config),
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
480
                                     raise_errors=True)
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
481
        except config.configobj.DuplicateError as e:
2900.1.1 by Vincent Ladeuil
482
            self.assertEqual(3, e.line_number)
483
        else:
484
            self.fail('Error in config file not detected')
485
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
486
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
487
class TestConfig(tests.TestCase):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
488
489
    def test_constructs(self):
490
        config.Config()
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
491
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
492
    def test_user_email(self):
493
        my_config = InstrumentedConfig()
494
        self.assertEqual('robert.collins@example.org', my_config.user_email())
495
        self.assertEqual(['_get_user_id'], my_config._calls)
496
497
    def test_username(self):
498
        my_config = InstrumentedConfig()
499
        self.assertEqual('Robert Collins <robert.collins@example.org>',
500
                         my_config.username())
501
        self.assertEqual(['_get_user_id'], my_config._calls)
1442.1.14 by Robert Collins
Create a default signature checking policy of CHECK_IF_POSSIBLE
502
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
503
    def test_get_user_option_default(self):
504
        my_config = config.Config()
505
        self.assertEqual(None, my_config.get_user_option('no_option'))
506
5971.1.57 by Jonathan Riddell
tests for new config options
507
    def test_validate_signatures_in_log_default(self):
508
        my_config = config.Config()
509
        self.assertEqual(False, my_config.validate_signatures_in_log())
510
4603.1.10 by Aaron Bentley
Provide change editor via config.
511
    def test_get_change_editor(self):
512
        my_config = InstrumentedConfig()
513
        change_editor = my_config.get_change_editor('old_tree', 'new_tree')
514
        self.assertEqual(['_get_change_editor'], my_config._calls)
515
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
516
        self.assertEqual(['vimdiff', '-fo', '@new_path', '@old_path'],
4603.1.10 by Aaron Bentley
Provide change editor via config.
517
                         change_editor.command_template)
518
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
519
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
520
class TestConfigPath(tests.TestCase):
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
521
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
522
    def setUp(self):
523
        super(TestConfigPath, self).setUp()
5570.3.9 by Vincent Ladeuil
More use cases for overrideEnv, _cleanEnvironment *may* contain too much variables now.
524
        self.overrideEnv('HOME', '/home/bogus')
6589.2.1 by Andrew Starr-Bochicchio
The XDG Base Directory Specification uses the XDG_CACHE_HOME XDG_CACHE_HOME, not XDG_CACHE_DIR.
525
        self.overrideEnv('XDG_CACHE_HOME', '')
2309.2.6 by Alexander Belchenko
bzr now use Win32 API to determine Application Data location, and don't rely solely on $APPDATA
526
        if sys.platform == 'win32':
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
527
            self.overrideEnv(
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
528
                'BRZ_HOME',
529
                r'C:\Documents and Settings\bogus\Application Data')
530
            self.brz_home = \
531
                'C:/Documents and Settings/bogus/Application Data/breezy'
5519.4.3 by Neil Martinsen-Burrell
be permissive about using $XDG_CONFIG_HOME/bazaar, but dont complain
532
        else:
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
533
            self.brz_home = '/home/bogus/.config/breezy'
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
534
1442.1.1 by Robert Collins
move config_dir into bzrlib.config
535
    def test_config_dir(self):
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
536
        self.assertEqual(config.config_dir(), self.brz_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.
537
6437.27.5 by Martin Packman
Document and test that config_dir now always returns unicode
538
    def test_config_dir_is_unicode(self):
6973.6.2 by Jelmer Vernooij
Fix more tests.
539
        self.assertIsInstance(config.config_dir(), text_type)
6437.27.5 by Martin Packman
Document and test that config_dir now always returns unicode
540
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
    def test_config_filename(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
542
        self.assertEqual(config.config_filename(),
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
543
                         self.brz_home + '/breezy.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.
544
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
545
    def test_locations_config_filename(self):
2991.2.4 by Vincent Ladeuil
Various fixes following local testing environment rebuild.
546
        self.assertEqual(config.locations_config_filename(),
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
547
                         self.brz_home + '/locations.conf')
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
548
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
549
    def test_authentication_config_filename(self):
2991.2.4 by Vincent Ladeuil
Various fixes following local testing environment rebuild.
550
        self.assertEqual(config.authentication_config_filename(),
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
551
                         self.brz_home + '/authentication.conf')
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
552
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
553
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
554
class TestConfigPathFallback(tests.TestCaseInTempDir):
555
556
    def setUp(self):
557
        super(TestConfigPathFallback, self).setUp()
558
        self.overrideEnv('HOME', self.test_dir)
559
        self.overrideEnv('XDG_CACHE_HOME', '')
560
        self.bzr_home = os.path.join(self.test_dir, '.bazaar')
561
        os.mkdir(self.bzr_home)
562
563
    def test_config_dir(self):
564
        self.assertEqual(config.config_dir(), self.bzr_home)
565
566
    def test_config_dir_is_unicode(self):
6973.6.2 by Jelmer Vernooij
Fix more tests.
567
        self.assertIsInstance(config.config_dir(), text_type)
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
568
569
    def test_config_filename(self):
570
        self.assertEqual(config.config_filename(),
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
571
                         self.bzr_home + '/bazaar.conf')
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
572
573
    def test_locations_config_filename(self):
574
        self.assertEqual(config.locations_config_filename(),
575
                         self.bzr_home + '/locations.conf')
576
577
    def test_authentication_config_filename(self):
578
        self.assertEqual(config.authentication_config_filename(),
579
                         self.bzr_home + '/authentication.conf')
580
581
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
582
class TestXDGConfigDir(tests.TestCaseInTempDir):
583
    # must be in temp dir because config tests for the existence of the bazaar
584
    # subdirectory of $XDG_CONFIG_HOME
585
5519.4.9 by Neil Martinsen-Burrell
working tests
586
    def setUp(self):
6591.2.1 by Fabien Meghazi
Also honor $XDG_CONFIG_HOME specification on Mac OS X platform
587
        if sys.platform == 'win32':
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
588
            raise tests.TestNotApplicable(
589
                'XDG config dir not used on this platform')
5519.4.9 by Neil Martinsen-Burrell
working tests
590
        super(TestXDGConfigDir, self).setUp()
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
591
        self.overrideEnv('HOME', self.test_home_dir)
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
592
        # BRZ_HOME overrides everything we want to test so unset it.
593
        self.overrideEnv('BRZ_HOME', None)
5519.4.9 by Neil Martinsen-Burrell
working tests
594
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
595
    def test_xdg_config_dir_exists(self):
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
596
        """When ~/.config/bazaar exists, use it as the config dir."""
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
597
        newdir = osutils.pathjoin(self.test_home_dir, '.config', 'bazaar')
598
        os.makedirs(newdir)
599
        self.assertEqual(config.config_dir(), newdir)
600
601
    def test_xdg_config_home(self):
5519.4.10 by Andrew Bennetts
Cosmetic tweaks to TestXDGConfigDir.
602
        """When XDG_CONFIG_HOME is set, use it."""
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
603
        xdgconfigdir = osutils.pathjoin(self.test_home_dir, 'xdgconfig')
5570.3.8 by Vincent Ladeuil
More use cases for overrideEnv.
604
        self.overrideEnv('XDG_CONFIG_HOME', xdgconfigdir)
5519.4.8 by Neil Martinsen-Burrell
some tests and mention in Whats New
605
        newdir = osutils.pathjoin(xdgconfigdir, 'bazaar')
606
        os.makedirs(newdir)
607
        self.assertEqual(config.config_dir(), newdir)
608
609
5050.13.2 by Parth Malwankar
copy config file ownership only if a new file is created
610
class TestIniConfig(tests.TestCaseInTempDir):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
611
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
612
    def make_config_parser(self, s):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
613
        conf = config.IniBasedConfig.from_string(s)
5345.1.4 by Vincent Ladeuil
Deprecate the ``file`` parameter of the ``config._get_parser()`` method.
614
        return conf, conf._get_parser()
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
615
5050.13.2 by Parth Malwankar
copy config file ownership only if a new file is created
616
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
617
class TestIniConfigBuilding(TestIniConfig):
618
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
619
    def test_contructs(self):
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
620
        config.IniBasedConfig()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
621
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
622
    def test_from_fp(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
623
        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.
624
        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.
625
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
626
    def test_cached(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
627
        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.
628
        parser = my_config._get_parser()
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
629
        self.assertTrue(my_config._get_parser() is parser)
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
630
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
631
    def _dummy_chown(self, path, uid, gid):
632
        self.path, self.uid, self.gid = path, uid, gid
633
634
    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.
635
        """Ensure that chown is happening during _write_config_file"""
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
636
        self.requireFeature(features.chown_feature)
637
        self.overrideAttr(os, 'chown', self._dummy_chown)
638
        self.path = self.uid = self.gid = None
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
639
        conf = config.IniBasedConfig(file_name='./foo.conf')
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
640
        conf._write_config_file()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
641
        self.assertEqual(self.path, './foo.conf')
5050.13.1 by Parth Malwankar
fixed .bazaar ownership regression
642
        self.assertTrue(isinstance(self.uid, int))
643
        self.assertTrue(isinstance(self.gid, int))
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
644
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
645
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
646
class TestIniConfigSaving(tests.TestCaseInTempDir):
647
5345.1.1 by Vincent Ladeuil
Deprecate the get_filename parameter in IniBasedConfig.
648
    def test_cant_save_without_a_file_name(self):
649
        conf = config.IniBasedConfig()
650
        self.assertRaises(AssertionError, conf._write_config_file)
651
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
652
    def test_saved_with_content(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
653
        content = b'foo = bar\n'
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
654
        config.IniBasedConfig.from_string(content, file_name='./test.conf',
655
                                          save=True)
5345.1.16 by Vincent Ladeuil
Allows tests to save the config file at build time.
656
        self.assertFileEqual(content, 'test.conf')
657
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
658
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
659
class TestIniConfigOptionExpansion(tests.TestCase):
660
    """Test option expansion from the IniConfig level.
661
662
    What we really want here is to test the Config level, but the class being
663
    abstract as far as storing values is concerned, this can't be done
664
    properly (yet).
665
    """
666
    # FIXME: This should be rewritten when all configs share a storage
667
    # implementation -- vila 2011-02-18
668
669
    def get_config(self, string=None):
670
        if string is None:
6973.10.4 by Jelmer Vernooij
Update python3.passing.
671
            string = b''
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
672
        c = config.IniBasedConfig.from_string(string)
673
        return c
674
675
    def assertExpansion(self, expected, conf, string, env=None):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
676
        self.assertEqual(expected, conf.expand_options(string, env))
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
677
678
    def test_no_expansion(self):
679
        c = self.get_config('')
680
        self.assertExpansion('foo', c, 'foo')
681
682
    def test_env_adding_options(self):
683
        c = self.get_config('')
684
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
685
686
    def test_env_overriding_options(self):
687
        c = self.get_config('foo=baz')
688
        self.assertExpansion('bar', c, '{foo}', {'foo': 'bar'})
689
690
    def test_simple_ref(self):
691
        c = self.get_config('foo=xxx')
692
        self.assertExpansion('xxx', c, '{foo}')
693
694
    def test_unknown_ref(self):
695
        c = self.get_config('')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
696
        self.assertRaises(config.ExpandingUnknownOption,
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
697
                          c.expand_options, '{foo}')
698
699
    def test_indirect_ref(self):
700
        c = self.get_config('''
701
foo=xxx
702
bar={foo}
703
''')
704
        self.assertExpansion('xxx', c, '{bar}')
705
706
    def test_embedded_ref(self):
707
        c = self.get_config('''
708
foo=xxx
709
bar=foo
710
''')
711
        self.assertExpansion('xxx', c, '{{bar}}')
712
713
    def test_simple_loop(self):
714
        c = self.get_config('foo={foo}')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
715
        self.assertRaises(config.OptionExpansionLoop, c.expand_options,
716
                          '{foo}')
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
717
718
    def test_indirect_loop(self):
719
        c = self.get_config('''
720
foo={bar}
721
bar={baz}
722
baz={foo}''')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
723
        e = self.assertRaises(config.OptionExpansionLoop,
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
724
                              c.expand_options, '{foo}')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
725
        self.assertEqual('foo->bar->baz', e.refs)
726
        self.assertEqual('{foo}', e.string)
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
727
728
    def test_list(self):
729
        conf = self.get_config('''
730
foo=start
731
bar=middle
732
baz=end
733
list={foo},{bar},{baz}
734
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
735
        self.assertEqual(['start', 'middle', 'end'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
736
                         conf.get_user_option('list', expand=True))
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
737
738
    def test_cascading_list(self):
739
        conf = self.get_config('''
740
foo=start,{bar}
741
bar=middle,{baz}
742
baz=end
743
list={foo}
744
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
745
        self.assertEqual(['start', 'middle', 'end'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
746
                         conf.get_user_option('list', expand=True))
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
747
748
    def test_pathological_hidden_list(self):
749
        conf = self.get_config('''
750
foo=bin
751
bar=go
752
start={foo
753
middle=},{
754
end=bar}
755
hidden={start}{middle}{end}
756
''')
757
        # Nope, it's either a string or a list, and the list wins as soon as a
758
        # ',' appears, so the string concatenation never occur.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
759
        self.assertEqual(['{foo', '}', '{', 'bar}'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
760
                         conf.get_user_option('hidden', expand=True))
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
761
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
762
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
763
class TestLocationConfigOptionExpansion(tests.TestCaseInTempDir):
764
765
    def get_config(self, location, string=None):
766
        if string is None:
767
            string = ''
768
        # Since we don't save the config we won't strictly require to inherit
769
        # from TestCaseInTempDir, but an error occurs so quickly...
770
        c = config.LocationConfig.from_string(string, location)
771
        return c
772
773
    def test_dont_cross_unrelated_section(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
774
        c = self.get_config('/another/branch/path', '''
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
775
[/one/branch/path]
776
foo = hello
777
bar = {foo}/2
778
779
[/another/branch/path]
780
bar = {foo}/2
781
''')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
782
        self.assertRaises(config.ExpandingUnknownOption,
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
783
                          c.get_user_option, 'bar', expand=True)
784
785
    def test_cross_related_sections(self):
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
786
        c = self.get_config('/project/branch/path', '''
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
787
[/project]
788
foo = qu
789
790
[/project/branch/path]
791
bar = {foo}ux
792
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
793
        self.assertEqual('quux', c.get_user_option('bar', expand=True))
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
794
795
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
796
class TestIniBaseConfigOnDisk(tests.TestCaseInTempDir):
797
798
    def test_cannot_reload_without_name(self):
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
799
        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.
800
        self.assertRaises(AssertionError, conf.reload)
801
802
    def test_reload_see_new_value(self):
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
803
        c1 = config.IniBasedConfig.from_string('editor=vim\n',
804
                                               file_name='./test/conf')
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
805
        c1._write_config_file()
5345.5.13 by Vincent Ladeuil
Merge simplify-test-config-building into lockable-config-files resolving conflicts
806
        c2 = config.IniBasedConfig.from_string('editor=emacs\n',
807
                                               file_name='./test/conf')
5345.5.1 by Vincent Ladeuil
Implement config.reload and make sure we have a file name when using it.
808
        c2._write_config_file()
809
        self.assertEqual('vim', c1.get_user_option('editor'))
810
        self.assertEqual('emacs', c2.get_user_option('editor'))
811
        # Make sure we get the Right value
812
        c1.reload()
813
        self.assertEqual('emacs', c1.get_user_option('editor'))
814
815
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
816
class TestLockableConfig(tests.TestCaseInTempDir):
817
5506.2.1 by Vincent Ladeuil
Implements ``bzr config --active option`` displaying only the value.
818
    scenarios = lockable_config_scenarios()
819
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
820
    # Set by load_tests
821
    config_class = None
822
    config_args = None
823
    config_section = None
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
824
825
    def setUp(self):
826
        super(TestLockableConfig, self).setUp()
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
827
        self._content = '[%s]\none=1\ntwo=2\n' % (self.config_section,)
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
828
        self.config = self.create_config(self._content)
829
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
830
    def get_existing_config(self):
831
        return self.config_class(*self.config_args)
832
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
833
    def create_config(self, content):
5396.1.1 by Vincent Ladeuil
Fix python-2.6-ism.
834
        kwargs = dict(save=True)
835
        c = self.config_class.from_string(content, *self.config_args, **kwargs)
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
836
        return c
837
838
    def test_simple_read_access(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
839
        self.assertEqual('1', self.config.get_user_option('one'))
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
840
841
    def test_simple_write_access(self):
842
        self.config.set_user_option('one', 'one')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
843
        self.assertEqual('one', self.config.get_user_option('one'))
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
844
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
845
    def test_listen_to_the_last_speaker(self):
846
        c1 = self.config
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
847
        c2 = self.get_existing_config()
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
848
        c1.set_user_option('one', 'ONE')
849
        c2.set_user_option('two', 'TWO')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
850
        self.assertEqual('ONE', c1.get_user_option('one'))
851
        self.assertEqual('TWO', c2.get_user_option('two'))
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
852
        # The second update respect the first one
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
853
        self.assertEqual('ONE', c2.get_user_option('one'))
5345.1.8 by Vincent Ladeuil
Make the test_listen_to_the_last_speaker pass and fix fallouts.
854
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
855
    def test_last_speaker_wins(self):
856
        # If the same config is not shared, the same variable modified twice
857
        # can only see a single result.
858
        c1 = self.config
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
859
        c2 = self.get_existing_config()
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
860
        c1.set_user_option('one', 'c1')
861
        c2.set_user_option('one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
862
        self.assertEqual('c2', c2._get_user_option('one'))
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
863
        # The first modification is still available until another refresh
864
        # occur
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
865
        self.assertEqual('c1', c1._get_user_option('one'))
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
866
        c1.set_user_option('two', 'done')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
867
        self.assertEqual('c2', c1._get_user_option('one'))
5345.5.3 by Vincent Ladeuil
Add a test for concurrent writers ensuring the values propagate.
868
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
869
    def test_writes_are_serialized(self):
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
870
        c1 = self.config
871
        c2 = self.get_existing_config()
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
872
873
        # We spawn a thread that will pause *during* the write
874
        before_writing = threading.Event()
875
        after_writing = threading.Event()
876
        writing_done = threading.Event()
877
        c1_orig = c1._write_config_file
7143.15.2 by Jelmer Vernooij
Run autopep8.
878
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
879
        def c1_write_config_file():
880
            before_writing.set()
881
            c1_orig()
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
882
            # 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.
883
            # continue
884
            after_writing.wait()
885
        c1._write_config_file = c1_write_config_file
7143.15.2 by Jelmer Vernooij
Run autopep8.
886
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
887
        def c1_set_option():
888
            c1.set_user_option('one', 'c1')
889
            writing_done.set()
890
        t1 = threading.Thread(target=c1_set_option)
891
        # Collect the thread after the test
892
        self.addCleanup(t1.join)
893
        # Be ready to unblock the thread if the test goes wrong
894
        self.addCleanup(after_writing.set)
895
        t1.start()
896
        before_writing.wait()
897
        self.assertTrue(c1._lock.is_held)
898
        self.assertRaises(errors.LockContention,
899
                          c2.set_user_option, 'one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
900
        self.assertEqual('c1', c1.get_user_option('one'))
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
901
        # Let the lock be released
902
        after_writing.set()
903
        writing_done.wait()
904
        c2.set_user_option('one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
905
        self.assertEqual('c2', c2.get_user_option('one'))
5345.5.4 by Vincent Ladeuil
Start implementing config files locking.
906
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
907
    def test_read_while_writing(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
908
        c1 = self.config
909
        # We spawn a thread that will pause *during* the write
910
        ready_to_write = threading.Event()
911
        do_writing = threading.Event()
912
        writing_done = threading.Event()
913
        c1_orig = c1._write_config_file
914
915
        def c1_write_config_file():
916
            ready_to_write.set()
917
            # The lock is held. We wait for the main thread to decide when to
918
            # continue
919
            do_writing.wait()
920
            c1_orig()
921
            writing_done.set()
922
        c1._write_config_file = c1_write_config_file
923
924
        def c1_set_option():
925
            c1.set_user_option('one', 'c1')
926
        t1 = threading.Thread(target=c1_set_option)
927
        # Collect the thread after the test
928
        self.addCleanup(t1.join)
929
        # Be ready to unblock the thread if the test goes wrong
930
        self.addCleanup(do_writing.set)
931
        t1.start()
932
        # Ensure the thread is ready to write
933
        ready_to_write.wait()
934
        self.assertTrue(c1._lock.is_held)
935
        self.assertEqual('c1', c1.get_user_option('one'))
936
        # If we read during the write, we get the old value
937
        c2 = self.get_existing_config()
938
        self.assertEqual('1', c2.get_user_option('one'))
939
        # Let the writing occur and ensure it occurred
940
        do_writing.set()
941
        writing_done.wait()
942
        # Now we get the updated value
943
        c3 = self.get_existing_config()
944
        self.assertEqual('c1', c3.get_user_option('one'))
5345.5.7 by Vincent Ladeuil
Make LocationConfig use a lock too.
945
5345.1.7 by Vincent Ladeuil
Start LockableConfig tests.
946
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
947
class TestGetUserOptionAs(TestIniConfig):
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
948
4503.2.2 by Vincent Ladeuil
Get a bool or none from a config file.
949
    def test_get_user_option_as_bool(self):
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
950
        conf, parser = self.make_config_parser("""
4503.2.2 by Vincent Ladeuil
Get a bool or none from a config file.
951
a_true_bool = true
952
a_false_bool = 0
953
an_invalid_bool = maybe
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
954
a_list = hmm, who knows ? # This is interpreted as a list !
4840.2.5 by Vincent Ladeuil
Refactor get_user_option_as_* tests.
955
""")
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
956
        get_bool = conf.get_user_option_as_bool
957
        self.assertEqual(True, get_bool('a_true_bool'))
958
        self.assertEqual(False, get_bool('a_false_bool'))
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
959
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
960
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
961
        def warning(*args):
962
            warnings.append(args[0] % args[1:])
963
        self.overrideAttr(trace, 'warning', warning)
964
        msg = 'Value "%s" is not a boolean for "%s"'
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
965
        self.assertIs(None, get_bool('an_invalid_bool'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
966
        self.assertEqual(msg % ('maybe', 'an_invalid_bool'), warnings[0])
4989.2.12 by Vincent Ladeuil
Display a warning if an option value is not boolean.
967
        warnings = []
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
968
        self.assertIs(None, get_bool('not_defined_in_this_config'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
969
        self.assertEqual([], warnings)
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
970
971
    def test_get_user_option_as_list(self):
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
972
        conf, parser = self.make_config_parser("""
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
973
a_list = a,b,c
974
length_1 = 1,
975
one_item = x
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
976
""")
977
        get_list = conf.get_user_option_as_list
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
978
        self.assertEqual(['a', 'b', 'c'], get_list('a_list'))
979
        self.assertEqual(['1'], get_list('length_1'))
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
980
        self.assertEqual('x', conf.get_user_option('one_item'))
4840.2.4 by Vincent Ladeuil
Implement config.get_user_option_as_list.
981
        # automatically cast to list
982
        self.assertEqual(['x'], get_list('one_item'))
983
6378.1.1 by Vincent Ladeuil
Add int_SI_from_store as a config option helper
984
4840.2.6 by Vincent Ladeuil
Implement config.suppress_warning.
985
class TestSupressWarning(TestIniConfig):
986
987
    def make_warnings_config(self, s):
988
        conf, parser = self.make_config_parser(s)
989
        return conf.suppress_warning
990
991
    def test_suppress_warning_unknown(self):
992
        suppress_warning = self.make_warnings_config('')
993
        self.assertEqual(False, suppress_warning('unknown_warning'))
994
995
    def test_suppress_warning_known(self):
996
        suppress_warning = self.make_warnings_config('suppress_warnings=a,b')
997
        self.assertEqual(False, suppress_warning('c'))
998
        self.assertEqual(True, suppress_warning('a'))
999
        self.assertEqual(True, suppress_warning('b'))
1000
1001
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
1002
class TestGetConfig(tests.TestCaseInTempDir):
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1003
1004
    def test_constructs(self):
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1005
        config.GlobalConfig()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1006
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1007
    def test_calls_read_filenames(self):
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1008
        # replace the class that is constructed, to check its parameters
1474 by Robert Collins
Merge from Aaron Bentley.
1009
        oldparserclass = config.ConfigObj
1010
        config.ConfigObj = InstrumentedConfigObj
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1011
        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.
1012
        try:
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1013
            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.
1014
        finally:
1474 by Robert Collins
Merge from Aaron Bentley.
1015
            config.ConfigObj = oldparserclass
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1016
        self.assertIsInstance(parser, InstrumentedConfigObj)
1551.2.20 by Aaron Bentley
Treated config files as utf-8
1017
        self.assertEqual(parser._calls, [('__init__', config.config_filename(),
1018
                                          '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.
1019
1020
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1021
class TestBranchConfig(tests.TestCaseWithTransport):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1022
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1023
    def test_constructs_valid(self):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1024
        branch = FakeBranch()
1025
        my_config = config.BranchConfig(branch)
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1026
        self.assertIsNot(None, my_config)
1027
1028
    def test_constructs_error(self):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1029
        self.assertRaises(TypeError, config.BranchConfig)
1030
1031
    def test_get_location_config(self):
1032
        branch = FakeBranch()
1033
        my_config = config.BranchConfig(branch)
1034
        location_config = my_config._get_location_config()
1035
        self.assertEqual(branch.base, location_config.location)
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1036
        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
1037
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1038
    def test_get_config(self):
1039
        """The Branch.get_config method works properly"""
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1040
        b = controldir.ControlDir.create_standalone_workingtree('.').branch
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1041
        my_config = b.get_config()
1042
        self.assertIs(my_config.get_user_option('wacky'), None)
1043
        my_config.set_user_option('wacky', 'unlikely')
1044
        self.assertEqual(my_config.get_user_option('wacky'), 'unlikely')
1045
1046
        # Ensure we get the same thing if we start again
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1047
        b2 = branch.Branch.open('.')
1770.2.9 by Aaron Bentley
Add Branch.get_config, update BranchConfig() callers
1048
        my_config2 = b2.get_config()
1049
        self.assertEqual(my_config2.get_user_option('wacky'), 'unlikely')
1050
1824.1.1 by Robert Collins
Add BranchConfig.has_explicit_nickname call.
1051
    def test_has_explicit_nickname(self):
1052
        b = self.make_branch('.')
1053
        self.assertFalse(b.get_config().has_explicit_nickname())
1054
        b.nick = 'foo'
1055
        self.assertTrue(b.get_config().has_explicit_nickname())
1056
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1057
    def test_config_url(self):
1058
        """The Branch.get_config will use section that uses a local url"""
1059
        branch = self.make_branch('branch')
1060
        self.assertEqual('branch', branch.nick)
1061
1062
        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
1063
        conf = config.LocationConfig.from_string(
5345.1.25 by Vincent Ladeuil
Move the '_save' parameter from '__init__' to 'from_bytes', fix fallouts.
1064
            '[%s]\nnickname = foobar' % (local_url,),
1065
            local_url, save=True)
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1066
        self.assertIsNot(None, conf)
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1067
        self.assertEqual('foobar', branch.nick)
1068
1069
    def test_config_local_path(self):
1070
        """The Branch.get_config will use a local system path"""
1071
        branch = self.make_branch('branch')
1072
        self.assertEqual('branch', branch.nick)
1073
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1074
        local_path = osutils.getcwd().encode('utf8')
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1075
        config.LocationConfig.from_string(
6973.10.4 by Jelmer Vernooij
Update python3.passing.
1076
            b'[%s/branch]\nnickname = barry' % (local_path,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1077
            'branch', save=True)
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1078
        # Now the branch will find its nick via the location config
1878.1.1 by John Arbash Meinel
Entries in locations.conf should prefer local paths if available (bug #53653)
1079
        self.assertEqual('barry', branch.nick)
1080
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
1081
    def test_config_creates_local(self):
1082
        """Creating a new entry in config uses a local path."""
2230.3.6 by Aaron Bentley
work in progress bind stuff
1083
        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
1084
        branch.set_push_location('http://foobar')
1085
        local_path = osutils.getcwd().encode('utf8')
1086
        # Surprisingly ConfigObj doesn't create a trailing newline
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1087
        self.check_file_contents(config.locations_config_filename(),
6973.10.4 by Jelmer Vernooij
Update python3.passing.
1088
                                 b'[%s/branch]\n'
1089
                                 b'push_location = http://foobar\n'
1090
                                 b'push_location:policy = norecurse\n'
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1091
                                 % (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
1092
2120.5.4 by Alexander Belchenko
Whitebox test for Config.get_nickname (req. by Aaron Bentley)
1093
    def test_autonick_urlencoded(self):
1094
        b = self.make_branch('!repo')
1095
        self.assertEqual('!repo', b.get_config().get_nickname())
1096
6437.32.1 by Aaron Bentley
Use colocated branch names as nicknames.
1097
    def test_autonick_uses_branch_name(self):
1098
        b = self.make_branch('foo', name='bar')
1099
        self.assertEqual('bar', b.get_config().get_nickname())
1100
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1101
    def test_warn_if_masked(self):
1102
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1103
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1104
        def warning(*args):
1105
            warnings.append(args[0] % args[1:])
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1106
        self.overrideAttr(trace, 'warning', warning)
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1107
1108
        def set_option(store, warn_masked=True):
1109
            warnings[:] = []
1110
            conf.set_user_option('example_option', repr(store), store=store,
1111
                                 warn_masked=warn_masked)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1112
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1113
        def assertWarning(warning):
1114
            if warning is None:
1115
                self.assertEqual(0, len(warnings))
1116
            else:
1117
                self.assertEqual(1, len(warnings))
1118
                self.assertEqual(warning, warnings[0])
5345.1.12 by Vincent Ladeuil
Cleanup test_config some more.
1119
        branch = self.make_branch('.')
1120
        conf = branch.get_config()
1121
        set_option(config.STORE_GLOBAL)
1122
        assertWarning(None)
1123
        set_option(config.STORE_BRANCH)
1124
        assertWarning(None)
1125
        set_option(config.STORE_GLOBAL)
1126
        assertWarning('Value "4" is masked by "3" from branch.conf')
1127
        set_option(config.STORE_GLOBAL, warn_masked=False)
1128
        assertWarning(None)
1129
        set_option(config.STORE_LOCATION)
1130
        assertWarning(None)
1131
        set_option(config.STORE_BRANCH)
1132
        assertWarning('Value "3" is masked by "0" from locations.conf')
1133
        set_option(config.STORE_BRANCH, warn_masked=False)
1134
        assertWarning(None)
1551.15.35 by Aaron Bentley
Warn when setting config values that will be masked (#122286)
1135
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1136
5448.1.1 by Vincent Ladeuil
Use TestCaseInTempDir for tests requiring disk resources
1137
class TestGlobalConfigItems(tests.TestCaseInTempDir):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1138
6630.1.1 by Jelmer Vernooij
Remove deprecated functionality.
1139
    def _get_empty_config(self):
1140
        my_config = config.GlobalConfig()
1141
        return my_config
1142
1143
    def _get_sample_config(self):
1144
        my_config = config.GlobalConfig.from_string(sample_config_text)
1145
        return my_config
1146
1442.1.2 by Robert Collins
create a config module - there is enough config logic to make this worthwhile, and start testing config processing.
1147
    def test_user_id(self):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
1148
        my_config = config.GlobalConfig.from_string(sample_config_text)
1551.2.21 by Aaron Bentley
Formatted unicode config tests as ASCII
1149
        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
1150
                         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.
1151
1152
    def test_absent_user_id(self):
5345.2.2 by Vincent Ladeuil
Simplify test config building.
1153
        my_config = config.GlobalConfig()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1154
        self.assertEqual(None, my_config._get_user_id())
1155
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1156
    def test_get_user_option_default(self):
1157
        my_config = self._get_empty_config()
1158
        self.assertEqual(None, my_config.get_user_option('no_option'))
1159
1160
    def test_get_user_option_global(self):
1161
        my_config = self._get_sample_config()
1162
        self.assertEqual("something",
1163
                         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.
1164
5971.1.58 by Jonathan Riddell
more tests for new config options
1165
    def test_configured_validate_signatures_in_log(self):
1166
        my_config = self._get_sample_config()
1167
        self.assertEqual(True, my_config.validate_signatures_in_log())
1168
1553.6.12 by Erik Bågfors
remove AliasConfig, based on input from abentley
1169
    def test_get_alias(self):
1170
        my_config = self._get_sample_config()
1171
        self.assertEqual('help', my_config.get_alias('h'))
1172
2900.3.6 by Tim Penhey
Added tests.
1173
    def test_get_aliases(self):
1174
        my_config = self._get_sample_config()
1175
        aliases = my_config.get_aliases()
1176
        self.assertEqual(2, len(aliases))
1177
        sorted_keys = sorted(aliases)
1178
        self.assertEqual('help', aliases[sorted_keys[0]])
1179
        self.assertEqual(sample_long_alias, aliases[sorted_keys[1]])
1180
1553.6.12 by Erik Bågfors
remove AliasConfig, based on input from abentley
1181
    def test_get_no_alias(self):
1182
        my_config = self._get_sample_config()
1183
        self.assertEqual(None, my_config.get_alias('foo'))
1184
1185
    def test_get_long_alias(self):
1186
        my_config = self._get_sample_config()
1187
        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.
1188
4603.1.10 by Aaron Bentley
Provide change editor via config.
1189
    def test_get_change_editor(self):
1190
        my_config = self._get_sample_config()
1191
        change_editor = my_config.get_change_editor('old', 'new')
1192
        self.assertIs(diff.DiffFromTool, change_editor.__class__)
4603.1.20 by Aaron Bentley
Use string.Template substitution with @ as delimiter.
1193
        self.assertEqual('vimdiff -of @new_path @old_path',
4603.1.10 by Aaron Bentley
Provide change editor via config.
1194
                         ' '.join(change_editor.command_template))
1195
1196
    def test_get_no_change_editor(self):
1197
        my_config = self._get_empty_config()
1198
        change_editor = my_config.get_change_editor('old', 'new')
1199
        self.assertIs(None, change_editor)
1200
5321.1.89 by Gordon Tyler
Moved mergetools config tests to bzrlib.tests.test_config.
1201
    def test_get_merge_tools(self):
1202
        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.
1203
        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.
1204
        self.log(repr(tools))
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1205
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1206
            {u'funkytool': u'funkytool "arg with spaces" {this_temp}',
1207
             u'sometool': u'sometool {base} {this} {other} -o {result}',
1208
             u'newtool': u'"newtool 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.
1209
            tools)
5321.1.89 by Gordon Tyler
Moved mergetools config tests to bzrlib.tests.test_config.
1210
5321.1.116 by Gordon Tyler
Simplified mergetools module down to functions which deal with command lines -- no MergeTool class.
1211
    def test_get_merge_tools_empty(self):
5321.1.93 by Gordon Tyler
Added tests for get_default_merge_tool.
1212
        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.
1213
        tools = conf.get_merge_tools()
1214
        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.
1215
1216
    def test_find_merge_tool(self):
1217
        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.
1218
        cmdline = conf.find_merge_tool('sometool')
1219
        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.
1220
1221
    def test_find_merge_tool_not_found(self):
1222
        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.
1223
        cmdline = conf.find_merge_tool('DOES NOT EXIST')
1224
        self.assertIs(cmdline, None)
5321.1.93 by Gordon Tyler
Added tests for get_default_merge_tool.
1225
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.
1226
    def test_find_merge_tool_known(self):
1227
        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.
1228
        cmdline = conf.find_merge_tool('kdiff3')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1229
        self.assertEqual('kdiff3 {base} {this} {other} -o {result}', cmdline)
5676.1.4 by Jelmer Vernooij
merge bzr.dev.
1230
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.
1231
    def test_find_merge_tool_override_known(self):
1232
        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.
1233
        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.
1234
        cmdline = conf.find_merge_tool('kdiff3')
1235
        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.
1236
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1237
2900.3.6 by Tim Penhey
Added tests.
1238
class TestGlobalConfigSavingOptions(tests.TestCaseInTempDir):
1239
1240
    def test_empty(self):
1241
        my_config = config.GlobalConfig()
1242
        self.assertEqual(0, len(my_config.get_aliases()))
1243
1244
    def test_set_alias(self):
1245
        my_config = config.GlobalConfig()
1246
        alias_value = 'commit --strict'
1247
        my_config.set_alias('commit', alias_value)
1248
        new_config = config.GlobalConfig()
1249
        self.assertEqual(alias_value, new_config.get_alias('commit'))
1250
1251
    def test_remove_alias(self):
1252
        my_config = config.GlobalConfig()
1253
        my_config.set_alias('commit', 'commit --strict')
1254
        # Now remove the alias again.
1255
        my_config.unset_alias('commit')
1256
        new_config = config.GlobalConfig()
1257
        self.assertIs(None, new_config.get_alias('commit'))
1258
1259
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1260
class TestLocationConfig(tests.TestCaseInTempDir, TestOptionsMixin):
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1261
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1262
    def test_constructs_valid(self):
1263
        config.LocationConfig('http://example.com')
1264
1265
    def test_constructs_error(self):
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1266
        self.assertRaises(TypeError, config.LocationConfig)
1267
1268
    def test_branch_calls_read_filenames(self):
1474 by Robert Collins
Merge from Aaron Bentley.
1269
        # This is testing the correct file names are provided.
1270
        # TODO: consolidate with the test for GlobalConfigs filename checks.
1271
        #
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1272
        # replace the class that is constructed, to check its parameters
1474 by Robert Collins
Merge from Aaron Bentley.
1273
        oldparserclass = config.ConfigObj
1274
        config.ConfigObj = InstrumentedConfigObj
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1275
        try:
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
1276
            my_config = config.LocationConfig('http://www.example.com')
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1277
            parser = my_config._get_parser()
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1278
        finally:
1474 by Robert Collins
Merge from Aaron Bentley.
1279
            config.ConfigObj = oldparserclass
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1280
        self.assertIsInstance(parser, InstrumentedConfigObj)
1474 by Robert Collins
Merge from Aaron Bentley.
1281
        self.assertEqual(parser._calls,
1770.2.2 by Aaron Bentley
Rename branches.conf to locations.conf
1282
                         [('__init__', config.locations_config_filename(),
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1283
                           'utf-8')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1284
1285
    def test_get_global_config(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1286
        my_config = config.BranchConfig(FakeBranch('http://example.com'))
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1287
        global_config = my_config._get_global_config()
5784.1.1 by Martin Pool
Stop using failIf, failUnless, etc
1288
        self.assertIsInstance(global_config, config.GlobalConfig)
1289
        self.assertIs(global_config, my_config._get_global_config())
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1290
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1291
    def assertLocationMatching(self, expected):
1292
        self.assertEqual(expected,
1293
                         list(self.my_location_config._get_matching_sections()))
1294
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1295
    def test__get_matching_sections_no_match(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1296
        self.get_branch_config('/')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1297
        self.assertLocationMatching([])
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1298
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1299
    def test__get_matching_sections_exact(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1300
        self.get_branch_config('http://www.example.com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1301
        self.assertLocationMatching([('http://www.example.com', '')])
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1302
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1303
    def test__get_matching_sections_suffix_does_not(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1304
        self.get_branch_config('http://www.example.com-com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1305
        self.assertLocationMatching([])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1306
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1307
    def test__get_matching_sections_subdir_recursive(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1308
        self.get_branch_config('http://www.example.com/com')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1309
        self.assertLocationMatching([('http://www.example.com', 'com')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1310
1993.3.5 by James Henstridge
add back recurse=False option to config file
1311
    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
1312
        self.get_branch_config('http://www.example.com/ignoreparent')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1313
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
1314
                                      '')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1315
1993.3.5 by James Henstridge
add back recurse=False option to config file
1316
    def test__get_matching_sections_ignoreparent_subdir(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1317
        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
1318
            'http://www.example.com/ignoreparent/childbranch')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1319
        self.assertLocationMatching([('http://www.example.com/ignoreparent',
1320
                                      'childbranch')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1321
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1322
    def test__get_matching_sections_subdir_trailing_slash(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1323
        self.get_branch_config('/b')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1324
        self.assertLocationMatching([('/b/', '')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1325
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1326
    def test__get_matching_sections_subdir_child(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1327
        self.get_branch_config('/a/foo')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1328
        self.assertLocationMatching([('/a/*', ''), ('/a/', 'foo')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1329
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1330
    def test__get_matching_sections_subdir_child_child(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1331
        self.get_branch_config('/a/foo/bar')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1332
        self.assertLocationMatching([('/a/*', 'bar'), ('/a/', 'foo/bar')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1333
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1334
    def test__get_matching_sections_trailing_slash_with_children(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1335
        self.get_branch_config('/a/')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1336
        self.assertLocationMatching([('/a/', '')])
1442.1.18 by Robert Collins
permit per branch location overriding of signature checking policy
1337
1993.3.1 by James Henstridge
first go at making location config lookup recursive
1338
    def test__get_matching_sections_explicit_over_glob(self):
1339
        # XXX: 2006-09-08 jamesh
1340
        # This test only passes because ord('c') > ord('*').  If there
1341
        # was a config section for '/a/?', it would get precedence
1342
        # over '/a/c'.
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1343
        self.get_branch_config('/a/c')
5764.1.4 by Vincent Ladeuil
Using iterators is even clearer.
1344
        self.assertLocationMatching([('/a/c', ''), ('/a/*', ''), ('/a/', 'c')])
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1345
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
1346
    def test__get_option_policy_normal(self):
1347
        self.get_branch_config('http://www.example.com')
1348
        self.assertEqual(
1349
            self.my_location_config._get_config_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1350
                'http://www.example.com', 'normal_option'),
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
1351
            config.POLICY_NONE)
1352
1353
    def test__get_option_policy_norecurse(self):
1354
        self.get_branch_config('http://www.example.com')
1355
        self.assertEqual(
1356
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1357
                'http://www.example.com', 'norecurse_option'),
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
1358
            config.POLICY_NORECURSE)
1359
        # Test old recurse=False setting:
1360
        self.assertEqual(
1361
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1362
                'http://www.example.com/norecurse', 'normal_option'),
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
1363
            config.POLICY_NORECURSE)
1364
1365
    def test__get_option_policy_normal(self):
1366
        self.get_branch_config('http://www.example.com')
1367
        self.assertEqual(
1368
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1369
                'http://www.example.com', 'appendpath_option'),
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
1370
            config.POLICY_APPENDPATH)
1371
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1372
    def test__get_options_with_policy(self):
1373
        self.get_branch_config('/dir/subdir',
1374
                               location_config="""\
1375
[/dir]
1376
other_url = /other-dir
1377
other_url:policy = appendpath
1378
[/dir/subdir]
1379
other_url = /other-subdir
1380
""")
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1381
        self.assertOptions(
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1382
            [(u'other_url', u'/other-subdir', u'/dir/subdir', 'locations'),
1383
             (u'other_url', u'/other-dir', u'/dir', 'locations'),
1384
             (u'other_url:policy', u'appendpath', u'/dir', 'locations')],
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
1385
            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.
1386
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1387
    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
1388
        self.get_branch_config('http://www.example.com/ignoreparent')
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1389
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1390
                         self.my_config.username())
1391
1392
    def test_location_not_listed(self):
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1393
        """Test that the global username is used when no location matches"""
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1394
        self.get_branch_config('/home/robertc/sources')
1704.2.18 by Martin Pool
Remove duplicated TestLocationConfig and update previously hidden tests. (#32587)
1395
        self.assertEqual(u'Erik B\u00e5gfors <erik@bagfors.nu>',
1442.1.8 by Robert Collins
preparing some tests for LocationConfig
1396
                         self.my_config.username())
1397
1442.1.13 by Robert Collins
branches.conf is now able to override the users email
1398
    def test_overriding_location(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1399
        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
1400
        self.assertEqual('Robert Collins <robertc@example.org>',
1401
                         self.my_config.username())
1442.1.16 by Robert Collins
allow global overriding of signature policy to never check
1402
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1403
    def test_get_user_option_global(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1404
        self.get_branch_config('/a')
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1405
        self.assertEqual('something',
1406
                         self.my_config.get_user_option('user_global_option'))
1407
1408
    def test_get_user_option_local(self):
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1409
        self.get_branch_config('/a')
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1410
        self.assertEqual('local',
1411
                         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
1412
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
1413
    def test_get_user_option_appendpath(self):
1414
        # returned as is for the base path:
1415
        self.get_branch_config('http://www.example.com')
1416
        self.assertEqual('append',
1417
                         self.my_config.get_user_option('appendpath_option'))
1418
        # Extra path components get appended:
1419
        self.get_branch_config('http://www.example.com/a/b/c')
1420
        self.assertEqual('append/a/b/c',
1421
                         self.my_config.get_user_option('appendpath_option'))
1422
        # Overriden for http://www.example.com/dir, where it is a
1423
        # normal option:
1424
        self.get_branch_config('http://www.example.com/dir/a/b/c')
1425
        self.assertEqual('normal',
1426
                         self.my_config.get_user_option('appendpath_option'))
1427
1428
    def test_get_user_option_norecurse(self):
1429
        self.get_branch_config('http://www.example.com')
1430
        self.assertEqual('norecurse',
1431
                         self.my_config.get_user_option('norecurse_option'))
1432
        self.get_branch_config('http://www.example.com/dir')
1433
        self.assertEqual(None,
1434
                         self.my_config.get_user_option('norecurse_option'))
1435
        # http://www.example.com/norecurse is a recurse=False section
1436
        # that redefines normal_option.  Subdirectories do not pick up
1437
        # this redefinition.
1438
        self.get_branch_config('http://www.example.com/norecurse')
1439
        self.assertEqual('norecurse',
1440
                         self.my_config.get_user_option('normal_option'))
1441
        self.get_branch_config('http://www.example.com/norecurse/subdir')
1442
        self.assertEqual('normal',
1443
                         self.my_config.get_user_option('normal_option'))
1444
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1445
    def test_set_user_option_norecurse(self):
1446
        self.get_branch_config('http://www.example.com')
1447
        self.my_config.set_user_option('foo', 'bar',
1448
                                       store=config.STORE_LOCATION_NORECURSE)
1449
        self.assertEqual(
1450
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1451
                'http://www.example.com', 'foo'),
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1452
            config.POLICY_NORECURSE)
1453
1454
    def test_set_user_option_appendpath(self):
1455
        self.get_branch_config('http://www.example.com')
1456
        self.my_config.set_user_option('foo', 'bar',
1457
                                       store=config.STORE_LOCATION_APPENDPATH)
1458
        self.assertEqual(
1459
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1460
                'http://www.example.com', 'foo'),
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1461
            config.POLICY_APPENDPATH)
1462
1463
    def test_set_user_option_change_policy(self):
1464
        self.get_branch_config('http://www.example.com')
1465
        self.my_config.set_user_option('norecurse_option', 'normal',
1466
                                       store=config.STORE_LOCATION)
1467
        self.assertEqual(
1468
            self.my_location_config._get_option_policy(
7143.15.2 by Jelmer Vernooij
Run autopep8.
1469
                'http://www.example.com', 'norecurse_option'),
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1470
            config.POLICY_NONE)
1471
5533.1.1 by Vincent Ladeuil
Fix ``bzr config`` to respect policies when displaying values and also display sections when appropriate.
1472
    def get_branch_config(self, location, global_config=None,
1473
                          location_config=None):
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1474
        my_branch = FakeBranch(location)
1502 by Robert Collins
Bugfix the config test suite to not create .bazaar in the dir where it is run.
1475
        if global_config is None:
5345.2.2 by Vincent Ladeuil
Simplify test config building.
1476
            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.
1477
        if location_config is None:
1478
            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.
1479
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1480
        config.GlobalConfig.from_string(global_config, save=True)
1481
        config.LocationConfig.from_string(location_config, my_branch.base,
1482
                                          save=True)
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1483
        my_config = config.BranchConfig(my_branch)
1484
        self.my_config = my_config
1485
        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.
1486
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1487
    def test_set_user_setting_sets_and_saves2(self):
1488
        self.get_branch_config('/a/c')
1489
        self.assertIs(self.my_config.get_user_option('foo'), None)
1490
        self.my_config.set_user_option('foo', 'bar')
1491
        self.assertEqual(
3616.2.6 by Mark Hammond
Fix test_set_user_setting_sets_and_saves2 on windows by stripping EOL
1492
            self.my_config.branch.control_files.files['branch.conf'].strip(),
6973.10.4 by Jelmer Vernooij
Update python3.passing.
1493
            b'foo = bar')
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1494
        self.assertEqual(self.my_config.get_user_option('foo'), 'bar')
2120.6.4 by James Henstridge
add support for specifying policy when storing options
1495
        self.my_config.set_user_option('foo', 'baz',
1496
                                       store=config.STORE_LOCATION)
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1497
        self.assertEqual(self.my_config.get_user_option('foo'), 'baz')
1498
        self.my_config.set_user_option('foo', 'qux')
1499
        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.
1500
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
1501
    def test_get_bzr_remote_path(self):
1502
        my_config = config.LocationConfig('/a/c')
1503
        self.assertEqual('bzr', my_config.get_bzr_remote_path())
1504
        my_config.set_user_option('bzr_remote_path', '/path-bzr')
1505
        self.assertEqual('/path-bzr', my_config.get_bzr_remote_path())
6622.1.33 by Jelmer Vernooij
Fix more tests (all?)
1506
        self.overrideEnv('BZR_REMOTE_PATH', '/environ-bzr')
1551.18.17 by Aaron Bentley
Introduce bzr_remote_path configuration variable
1507
        self.assertEqual('/environ-bzr', my_config.get_bzr_remote_path())
1508
1185.62.7 by John Arbash Meinel
Whitespace cleanup.
1509
7058.4.16 by Jelmer Vernooij
Fix a config test.
1510
precedence_global = b'option = global'
1511
precedence_branch = b'option = branch'
1512
precedence_location = b"""
1770.2.8 by Aaron Bentley
Add precedence test
1513
[http://]
1514
recurse = true
1515
option = recurse
1516
[http://example.com/specific]
1517
option = exact
1518
"""
1519
7143.15.2 by Jelmer Vernooij
Run autopep8.
1520
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1521
class TestBranchConfigItems(tests.TestCaseInTempDir):
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1522
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1523
    def get_branch_config(self, global_config=None, location=None,
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1524
                          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.
1525
        my_branch = FakeBranch(location)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1526
        if global_config is not None:
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1527
            config.GlobalConfig.from_string(global_config, save=True)
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1528
        if location_config is not None:
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
1529
            config.LocationConfig.from_string(location_config, my_branch.base,
1530
                                              save=True)
5345.1.5 by Vincent Ladeuil
Fix fallouts by slightly editing the tests. More refactoring avoided to keep the review light.
1531
        my_config = config.BranchConfig(my_branch)
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1532
        if branch_data_config is not None:
1533
            my_config.branch.control_files.files['branch.conf'] = \
1534
                branch_data_config
1770.2.5 by Aaron Bentley
Integrate branch.conf into BranchConfig
1535
        return my_config
1536
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1537
    def test_user_id(self):
6362.1.4 by Jelmer Vernooij
Fix tests.
1538
        branch = FakeBranch()
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1539
        my_config = config.BranchConfig(branch)
6362.1.4 by Jelmer Vernooij
Fix tests.
1540
        self.assertIsNot(None, my_config.username())
3388.2.3 by Martin Pool
Fix up more uses of LockableFiles.get_utf8 in tests
1541
        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.
1542
        my_config.set_user_option('email',
1770.2.6 by Aaron Bentley
Ensure branch.conf works properly
1543
                                  "Robert Collins <robertc@example.org>")
1544
        self.assertEqual("Robert Collins <robertc@example.org>",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1545
                         my_config.username())
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1546
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
1547
    def test_BRZ_EMAIL_OVERRIDES(self):
1548
        self.overrideEnv('BRZ_EMAIL', "Robert Collins <robertc@example.org>")
1442.1.6 by Robert Collins
first stage major overhaul of configs, giving use BranchConfigs, LocationConfigs and GlobalConfigs
1549
        branch = FakeBranch()
1550
        my_config = config.BranchConfig(branch)
1551
        self.assertEqual("Robert Collins <robertc@example.org>",
1552
                         my_config.username())
2991.2.2 by Vincent Ladeuil
No tests worth adding after upgrading to configobj-4.4.0.
1553
1442.1.69 by Robert Collins
config.Config has a 'get_user_option' call that accepts an option name.
1554
    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.
1555
        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.
1556
        self.assertEqual('something',
1557
                         my_config.get_user_option('user_global_option'))
1472 by Robert Collins
post commit hook, first pass implementation
1558
1770.2.8 by Aaron Bentley
Add precedence test
1559
    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.
1560
        # FIXME: eager test, luckily no persitent config file makes it fail
1561
        # -- vila 20100716
1770.2.8 by Aaron Bentley
Add precedence test
1562
        my_config = self.get_branch_config(global_config=precedence_global)
1563
        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.
1564
        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.
1565
                                           branch_data_config=precedence_branch)
1770.2.8 by Aaron Bentley
Add precedence test
1566
        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.
1567
        my_config = self.get_branch_config(
1568
            global_config=precedence_global,
1569
            branch_data_config=precedence_branch,
1570
            location_config=precedence_location)
1770.2.8 by Aaron Bentley
Add precedence test
1571
        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.
1572
        my_config = self.get_branch_config(
1573
            global_config=precedence_global,
1574
            branch_data_config=precedence_branch,
1575
            location_config=precedence_location,
1576
            location='http://example.com/specific')
1770.2.8 by Aaron Bentley
Add precedence test
1577
        self.assertEqual(my_config.get_user_option('option'), 'exact')
1578
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1579
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1580
class TestMailAddressExtraction(tests.TestCase):
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1581
1582
    def test_extract_email_address(self):
1583
        self.assertEqual('jane@test.com',
1584
                         config.extract_email_address('Jane <jane@test.com>'))
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
1585
        self.assertRaises(config.NoEmailInUsername,
1185.33.31 by Martin Pool
Make annotate cope better with revisions committed without a valid
1586
                          config.extract_email_address, 'Jane Tester')
2533.1.1 by James Westby
Fix TreeConfig to return values from sections.
1587
3063.3.2 by Lukáš Lalinský
Move the name and e-mail address extraction logic to config.parse_username.
1588
    def test_parse_username(self):
1589
        self.assertEqual(('', 'jdoe@example.com'),
1590
                         config.parse_username('jdoe@example.com'))
1591
        self.assertEqual(('', 'jdoe@example.com'),
1592
                         config.parse_username('<jdoe@example.com>'))
1593
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1594
                         config.parse_username('John Doe <jdoe@example.com>'))
1595
        self.assertEqual(('John Doe', ''),
1596
                         config.parse_username('John Doe'))
3063.3.3 by Lukáš Lalinský
Add one more test for config.parse_username().
1597
        self.assertEqual(('John Doe', 'jdoe@example.com'),
1598
                         config.parse_username('John Doe jdoe@example.com'))
2562.1.2 by John Arbash Meinel
Clean up whitespace
1599
7143.15.2 by Jelmer Vernooij
Run autopep8.
1600
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
1601
class TestTreeConfig(tests.TestCaseWithTransport):
2533.1.1 by James Westby
Fix TreeConfig to return values from sections.
1602
1603
    def test_get_value(self):
1604
        """Test that retreiving a value from a section is possible"""
1605
        branch = self.make_branch('.')
1606
        tree_config = config.TreeConfig(branch)
1607
        tree_config.set_option('value', 'key', 'SECTION')
1608
        tree_config.set_option('value2', 'key2')
1609
        tree_config.set_option('value3-top', 'key3')
1610
        tree_config.set_option('value3-section', 'key3', 'SECTION')
1611
        value = tree_config.get_option('key', 'SECTION')
1612
        self.assertEqual(value, 'value')
1613
        value = tree_config.get_option('key2')
1614
        self.assertEqual(value, 'value2')
1615
        self.assertEqual(tree_config.get_option('non-existant'), None)
1616
        value = tree_config.get_option('non-existant', 'SECTION')
1617
        self.assertEqual(value, None)
1618
        value = tree_config.get_option('non-existant', default='default')
1619
        self.assertEqual(value, 'default')
1620
        self.assertEqual(tree_config.get_option('key2', 'NOSECTION'), None)
1621
        value = tree_config.get_option('key2', 'NOSECTION', default='default')
1622
        self.assertEqual(value, 'default')
1623
        value = tree_config.get_option('key3')
1624
        self.assertEqual(value, 'value3-top')
1625
        value = tree_config.get_option('key3', 'SECTION')
1626
        self.assertEqual(value, 'value3-section')
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
1627
1628
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
1629
class TestTransportConfig(tests.TestCaseWithTransport):
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1630
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1631
    def test_load_utf8(self):
1632
        """Ensure we can load an utf8-encoded file."""
1633
        t = self.get_transport()
1634
        unicode_user = u'b\N{Euro Sign}ar'
1635
        unicode_content = u'user=%s' % (unicode_user,)
1636
        utf8_content = unicode_content.encode('utf8')
1637
        # Store the raw content in the config file
1638
        t.put_bytes('foo.conf', utf8_content)
1639
        conf = config.TransportConfig(t, 'foo.conf')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1640
        self.assertEqual(unicode_user, conf.get_option('user'))
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1641
1642
    def test_load_non_ascii(self):
1643
        """Ensure we display a proper error on non-ascii, non utf-8 content."""
1644
        t = self.get_transport()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
1645
        t.put_bytes('foo.conf', b'user=foo\n#\xff\n')
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1646
        conf = config.TransportConfig(t, 'foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
1647
        self.assertRaises(config.ConfigContentError, conf._get_configobj)
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1648
1649
    def test_load_erroneous_content(self):
1650
        """Ensure we display a proper error on content that can't be parsed."""
1651
        t = self.get_transport()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
1652
        t.put_bytes('foo.conf', b'[open_section\n')
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1653
        conf = config.TransportConfig(t, 'foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
1654
        self.assertRaises(config.ParseConfigError, conf._get_configobj)
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1655
6110.5.1 by Jelmer Vernooij
Warn when a configuration file can not be opened.
1656
    def test_load_permission_denied(self):
1657
        """Ensure we get an empty config file if the file is inaccessible."""
1658
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1659
6110.5.1 by Jelmer Vernooij
Warn when a configuration file can not be opened.
1660
        def warning(*args):
1661
            warnings.append(args[0] % args[1:])
1662
        self.overrideAttr(trace, 'warning', warning)
1663
1664
        class DenyingTransport(object):
1665
1666
            def __init__(self, base):
1667
                self.base = base
1668
1669
            def get_bytes(self, relpath):
1670
                raise errors.PermissionDenied(relpath, "")
1671
1672
        cfg = config.TransportConfig(
1673
            DenyingTransport("nonexisting://"), 'control.conf')
1674
        self.assertIs(None, cfg.get_option('non-existant', 'SECTION'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1675
        self.assertEqual(
6110.5.1 by Jelmer Vernooij
Warn when a configuration file can not be opened.
1676
            warnings,
1677
            [u'Permission denied while trying to open configuration file '
1678
             u'nonexisting:///control.conf.'])
1679
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1680
    def test_get_value(self):
1681
        """Test that retreiving a value from a section is possible"""
5987.1.4 by Vincent Ladeuil
Proper error messages for config files with content in non-utf encoding or that cannot be parsed
1682
        bzrdir_config = config.TransportConfig(self.get_transport('.'),
3242.1.2 by Aaron Bentley
Turn BzrDirConfig into TransportConfig, reduce code duplication
1683
                                               'control.conf')
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1684
        bzrdir_config.set_option('value', 'key', 'SECTION')
1685
        bzrdir_config.set_option('value2', 'key2')
1686
        bzrdir_config.set_option('value3-top', 'key3')
1687
        bzrdir_config.set_option('value3-section', 'key3', 'SECTION')
1688
        value = bzrdir_config.get_option('key', 'SECTION')
1689
        self.assertEqual(value, 'value')
1690
        value = bzrdir_config.get_option('key2')
1691
        self.assertEqual(value, 'value2')
1692
        self.assertEqual(bzrdir_config.get_option('non-existant'), None)
1693
        value = bzrdir_config.get_option('non-existant', 'SECTION')
1694
        self.assertEqual(value, None)
1695
        value = bzrdir_config.get_option('non-existant', default='default')
1696
        self.assertEqual(value, 'default')
1697
        self.assertEqual(bzrdir_config.get_option('key2', 'NOSECTION'), None)
1698
        value = bzrdir_config.get_option('key2', 'NOSECTION',
1699
                                         default='default')
1700
        self.assertEqual(value, 'default')
1701
        value = bzrdir_config.get_option('key3')
1702
        self.assertEqual(value, 'value3-top')
1703
        value = bzrdir_config.get_option('key3', 'SECTION')
1704
        self.assertEqual(value, 'value3-section')
1705
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1706
    def test_set_unset_default_stack_on(self):
6653.6.5 by Jelmer Vernooij
Rename make_bzrdir to make_controldir.
1707
        my_dir = self.make_controldir('.')
4288.1.3 by Robert Collins
Fix BzrDirConfig tests.
1708
        bzrdir_config = config.BzrDirConfig(my_dir)
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1709
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1710
        bzrdir_config.set_default_stack_on('Foo')
3242.3.14 by Aaron Bentley
Make BzrDirConfig use TransportConfig
1711
        self.assertEqual('Foo', bzrdir_config._config.get_option(
1712
                         'default_stack_on'))
3242.3.11 by Aaron Bentley
Clean up BzrDirConfig usage
1713
        self.assertEqual('Foo', bzrdir_config.get_default_stack_on())
1714
        bzrdir_config.set_default_stack_on(None)
1715
        self.assertIs(None, bzrdir_config.get_default_stack_on())
1716
3242.1.1 by Aaron Bentley
Implement BzrDir configuration
1717
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1718
class TestOldConfigHooks(tests.TestCaseWithTransport):
1719
1720
    def setUp(self):
1721
        super(TestOldConfigHooks, self).setUp()
1722
        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.
1723
1724
    def assertGetHook(self, conf, name, value):
1725
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1726
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1727
        def hook(*args):
1728
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1729
        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).
1730
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1731
            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.
1732
        self.assertLength(0, calls)
1733
        actual_value = conf.get_user_option(name)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1734
        self.assertEqual(value, actual_value)
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1735
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1736
        self.assertEqual((conf, name, value), calls[0])
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1737
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
1738
    def test_get_hook_breezy(self):
1739
        self.assertGetHook(self.breezy_config, 'file', 'breezy')
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1740
1741
    def test_get_hook_locations(self):
1742
        self.assertGetHook(self.locations_config, 'file', 'locations')
1743
1744
    def test_get_hook_branch(self):
1745
        # Since locations masks branch, we define a different option
1746
        self.branch_config.set_user_option('file2', 'branch')
1747
        self.assertGetHook(self.branch_config, 'file2', 'branch')
1748
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1749
    def assertSetHook(self, conf, name, value):
1750
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1751
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1752
        def hook(*args):
1753
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1754
        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).
1755
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1756
            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.
1757
        self.assertLength(0, calls)
1758
        conf.set_user_option(name, value)
1759
        self.assertLength(1, calls)
1760
        # We can't assert the conf object below as different configs use
1761
        # different means to implement set_user_option and we care only about
1762
        # coverage here.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1763
        self.assertEqual((name, value), calls[0][1:])
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1764
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
1765
    def test_set_hook_breezy(self):
1766
        self.assertSetHook(self.breezy_config, 'foo', 'breezy')
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1767
1768
    def test_set_hook_locations(self):
1769
        self.assertSetHook(self.locations_config, 'foo', 'locations')
1770
1771
    def test_set_hook_branch(self):
1772
        self.assertSetHook(self.branch_config, 'foo', 'branch')
1773
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1774
    def assertRemoveHook(self, conf, name, section_name=None):
1775
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1776
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1777
        def hook(*args):
1778
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1779
        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).
1780
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1781
            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.
1782
        self.assertLength(0, calls)
1783
        conf.remove_user_option(name, section_name)
1784
        self.assertLength(1, calls)
1785
        # We can't assert the conf object below as different configs use
1786
        # different means to implement remove_user_option and we care only about
1787
        # coverage here.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1788
        self.assertEqual((name,), calls[0][1:])
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1789
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
1790
    def test_remove_hook_breezy(self):
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
1791
        self.assertRemoveHook(self.breezy_config, 'file')
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1792
1793
    def test_remove_hook_locations(self):
1794
        self.assertRemoveHook(self.locations_config, 'file',
1795
                              self.locations_config.location)
1796
1797
    def test_remove_hook_branch(self):
1798
        self.assertRemoveHook(self.branch_config, 'file')
1799
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1800
    def assertLoadHook(self, name, conf_class, *conf_args):
1801
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1802
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1803
        def hook(*args):
1804
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1805
        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).
1806
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1807
            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.
1808
        self.assertLength(0, calls)
1809
        # Build a config
1810
        conf = conf_class(*conf_args)
1811
        # Access an option to trigger a load
1812
        conf.get_user_option(name)
1813
        self.assertLength(1, calls)
1814
        # Since we can't assert about conf, we just use the number of calls ;-/
1815
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
1816
    def test_load_hook_breezy(self):
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1817
        self.assertLoadHook('file', config.GlobalConfig)
1818
1819
    def test_load_hook_locations(self):
1820
        self.assertLoadHook('file', config.LocationConfig, self.tree.basedir)
1821
1822
    def test_load_hook_branch(self):
1823
        self.assertLoadHook('file', config.BranchConfig, self.tree.branch)
1824
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1825
    def assertSaveHook(self, conf):
1826
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1827
5743.8.19 by Vincent Ladeuil
Revert the mixin addition, no way to share with remote configs which implements a different API.
1828
        def hook(*args):
1829
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1830
        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).
1831
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1832
            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.
1833
        self.assertLength(0, calls)
1834
        # Setting an option triggers a save
1835
        conf.set_user_option('foo', 'bar')
1836
        self.assertLength(1, calls)
1837
        # Since we can't assert about conf, we just use the number of calls ;-/
1838
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
1839
    def test_save_hook_breezy(self):
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
1840
        self.assertSaveHook(self.breezy_config)
5743.8.15 by Vincent Ladeuil
Add tests for old config hooks covering bazaar.conf, locations.conf and branch.conf.
1841
1842
    def test_save_hook_locations(self):
1843
        self.assertSaveHook(self.locations_config)
1844
1845
    def test_save_hook_branch(self):
1846
        self.assertSaveHook(self.branch_config)
1847
1848
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1849
class TestOldConfigHooksForRemote(tests.TestCaseWithTransport):
1850
    """Tests config hooks for remote configs.
1851
1852
    No tests for the remove hook as this is not implemented there.
1853
    """
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
1854
1855
    def setUp(self):
1856
        super(TestOldConfigHooksForRemote, self).setUp()
1857
        self.transport_server = test_server.SmartTCPServer_for_testing
1858
        create_configs_with_file_option(self)
1859
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1860
    def assertGetHook(self, conf, name, value):
1861
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1862
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1863
        def hook(*args):
1864
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1865
        config.OldConfigHooks.install_named_hook('get', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1866
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1867
            config.OldConfigHooks.uninstall_named_hook, 'get', None)
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1868
        self.assertLength(0, calls)
1869
        actual_value = conf.get_option(name)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1870
        self.assertEqual(value, actual_value)
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1871
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1872
        self.assertEqual((conf, name, value), calls[0])
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1873
1874
    def test_get_hook_remote_branch(self):
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
1875
        remote_branch = branch.Branch.open(self.get_url('tree'))
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1876
        self.assertGetHook(remote_branch._get_config(), 'file', 'branch')
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
1877
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1878
    def test_get_hook_remote_bzrdir(self):
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1879
        remote_bzrdir = controldir.ControlDir.open(self.get_url('tree'))
5743.8.18 by Vincent Ladeuil
Add a test for remote bzr dir.
1880
        conf = remote_bzrdir._get_config()
1881
        conf.set_option('remotedir', 'file')
1882
        self.assertGetHook(conf, 'file', 'remotedir')
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
1883
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1884
    def assertSetHook(self, conf, name, value):
1885
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1886
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1887
        def hook(*args):
1888
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1889
        config.OldConfigHooks.install_named_hook('set', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1890
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1891
            config.OldConfigHooks.uninstall_named_hook, 'set', None)
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1892
        self.assertLength(0, calls)
1893
        conf.set_option(value, name)
1894
        self.assertLength(1, calls)
1895
        # We can't assert the conf object below as different configs use
1896
        # different means to implement set_user_option and we care only about
1897
        # coverage here.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1898
        self.assertEqual((name, value), calls[0][1:])
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1899
1900
    def test_set_hook_remote_branch(self):
1901
        remote_branch = branch.Branch.open(self.get_url('tree'))
1902
        self.addCleanup(remote_branch.lock_write().unlock)
1903
        self.assertSetHook(remote_branch._get_config(), 'file', 'remote')
1904
1905
    def test_set_hook_remote_bzrdir(self):
1906
        remote_branch = branch.Branch.open(self.get_url('tree'))
1907
        self.addCleanup(remote_branch.lock_write().unlock)
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1908
        remote_bzrdir = controldir.ControlDir.open(self.get_url('tree'))
5743.8.20 by Vincent Ladeuil
Add tests for set hook.
1909
        self.assertSetHook(remote_bzrdir._get_config(), 'file', 'remotedir')
1910
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1911
    def assertLoadHook(self, expected_nb_calls, name, conf_class, *conf_args):
1912
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1913
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1914
        def hook(*args):
1915
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1916
        config.OldConfigHooks.install_named_hook('load', hook, None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1917
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1918
            config.OldConfigHooks.uninstall_named_hook, 'load', None)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1919
        self.assertLength(0, calls)
1920
        # Build a config
1921
        conf = conf_class(*conf_args)
1922
        # Access an option to trigger a load
1923
        conf.get_option(name)
1924
        self.assertLength(expected_nb_calls, calls)
1925
        # Since we can't assert about conf, we just use the number of calls ;-/
1926
1927
    def test_load_hook_remote_branch(self):
1928
        remote_branch = branch.Branch.open(self.get_url('tree'))
7143.15.2 by Jelmer Vernooij
Run autopep8.
1929
        self.assertLoadHook(
1930
            1, 'file', remote.RemoteBranchConfig, remote_branch)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1931
1932
    def test_load_hook_remote_bzrdir(self):
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1933
        remote_bzrdir = controldir.ControlDir.open(self.get_url('tree'))
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1934
        # The config file doesn't exist, set an option to force its creation
1935
        conf = remote_bzrdir._get_config()
1936
        conf.set_option('remotedir', 'file')
1937
        # We get one call for the server and one call for the client, this is
1938
        # caused by the differences in implementations betwen
1939
        # SmartServerBzrDirRequestConfigFile (in smart/bzrdir.py) and
1940
        # SmartServerBranchGetConfigFile (in smart/branch.py)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1941
        self.assertLoadHook(
1942
            2, 'file', remote.RemoteBzrDirConfig, remote_bzrdir)
5743.8.21 by Vincent Ladeuil
Add test for config load hook for remote configs.
1943
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
1944
    def assertSaveHook(self, conf):
1945
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
1946
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
1947
        def hook(*args):
1948
            calls.append(args)
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1949
        config.OldConfigHooks.install_named_hook('save', hook, None)
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
1950
        self.addCleanup(
5743.8.24 by Vincent Ladeuil
Clearly seaparate both sets of hooks for the old and new config implementations.
1951
            config.OldConfigHooks.uninstall_named_hook, 'save', None)
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
1952
        self.assertLength(0, calls)
1953
        # Setting an option triggers a save
1954
        conf.set_option('foo', 'bar')
1955
        self.assertLength(1, calls)
1956
        # Since we can't assert about conf, we just use the number of calls ;-/
1957
1958
    def test_save_hook_remote_branch(self):
1959
        remote_branch = branch.Branch.open(self.get_url('tree'))
1960
        self.addCleanup(remote_branch.lock_write().unlock)
1961
        self.assertSaveHook(remote_branch._get_config())
1962
1963
    def test_save_hook_remote_bzrdir(self):
1964
        remote_branch = branch.Branch.open(self.get_url('tree'))
1965
        self.addCleanup(remote_branch.lock_write().unlock)
6472.2.2 by Jelmer Vernooij
Use controldir rather than bzrdir in a couple more places.
1966
        remote_bzrdir = controldir.ControlDir.open(self.get_url('tree'))
5743.8.22 by Vincent Ladeuil
Add tests for config save hook for remote configs.
1967
        self.assertSaveHook(remote_bzrdir._get_config())
1968
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
1969
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
1970
class TestOptionNames(tests.TestCase):
1971
1972
    def is_valid(self, name):
1973
        return config._option_ref_re.match('{%s}' % name) is not None
1974
1975
    def test_valid_names(self):
1976
        self.assertTrue(self.is_valid('foo'))
1977
        self.assertTrue(self.is_valid('foo.bar'))
1978
        self.assertTrue(self.is_valid('f1'))
1979
        self.assertTrue(self.is_valid('_'))
1980
        self.assertTrue(self.is_valid('__bar__'))
1981
        self.assertTrue(self.is_valid('a_'))
1982
        self.assertTrue(self.is_valid('a1'))
6587.2.4 by Vincent Ladeuil
Allow hyphens in option names to unbreak compatibility.
1983
        # Don't break bzr-svn for no good reason
1984
        self.assertTrue(self.is_valid('guessed-layout'))
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
1985
1986
    def test_invalid_names(self):
1987
        self.assertFalse(self.is_valid(' foo'))
1988
        self.assertFalse(self.is_valid('foo '))
1989
        self.assertFalse(self.is_valid('1'))
1990
        self.assertFalse(self.is_valid('1,2'))
1991
        self.assertFalse(self.is_valid('foo$'))
1992
        self.assertFalse(self.is_valid('!foo'))
1993
        self.assertFalse(self.is_valid('foo.'))
1994
        self.assertFalse(self.is_valid('foo..bar'))
1995
        self.assertFalse(self.is_valid('{}'))
1996
        self.assertFalse(self.is_valid('{a}'))
1997
        self.assertFalse(self.is_valid('a\n'))
6587.2.4 by Vincent Ladeuil
Allow hyphens in option names to unbreak compatibility.
1998
        self.assertFalse(self.is_valid('-'))
1999
        self.assertFalse(self.is_valid('-a'))
2000
        self.assertFalse(self.is_valid('a-'))
2001
        self.assertFalse(self.is_valid('a--a'))
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2002
2003
    def assertSingleGroup(self, reference):
2004
        # the regexp is used with split and as such should match the reference
2005
        # *only*, if more groups needs to be defined, (?:...) should be used.
2006
        m = config._option_ref_re.match('{a}')
2007
        self.assertLength(1, m.groups())
2008
2009
    def test_valid_references(self):
2010
        self.assertSingleGroup('{a}')
2011
        self.assertSingleGroup('{{a}}')
2012
2013
5743.12.4 by Vincent Ladeuil
An option can provide a default value.
2014
class TestOption(tests.TestCase):
2015
2016
    def test_default_value(self):
2017
        opt = config.Option('foo', default='bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2018
        self.assertEqual('bar', opt.get_default())
5743.12.5 by Vincent Ladeuil
Remove spurious spaces.
2019
6349.3.1 by Vincent Ladeuil
Allow config option default value to be a python callable
2020
    def test_callable_default_value(self):
2021
        def bar_as_unicode():
2022
            return u'bar'
2023
        opt = config.Option('foo', default=bar_as_unicode)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2024
        self.assertEqual('bar', opt.get_default())
6349.3.1 by Vincent Ladeuil
Allow config option default value to be a python callable
2025
6082.2.1 by Vincent Ladeuil
Implement default values from environment for config options
2026
    def test_default_value_from_env(self):
2027
        opt = config.Option('foo', default='bar', default_from_env=['FOO'])
2028
        self.overrideEnv('FOO', 'quux')
2029
        # Env variable provides a default taking over the option one
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2030
        self.assertEqual('quux', opt.get_default())
6091.3.1 by Vincent Ladeuil
Add convert_from_unicode to Option and rewrite the tests to need only an
2031
6082.2.1 by Vincent Ladeuil
Implement default values from environment for config options
2032
    def test_first_default_value_from_env_wins(self):
2033
        opt = config.Option('foo', default='bar',
2034
                            default_from_env=['NO_VALUE', 'FOO', 'BAZ'])
2035
        self.overrideEnv('FOO', 'foo')
2036
        self.overrideEnv('BAZ', 'baz')
2037
        # The first env var set wins
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2038
        self.assertEqual('foo', opt.get_default())
6082.2.1 by Vincent Ladeuil
Implement default values from environment for config options
2039
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
2040
    def test_not_supported_list_default_value(self):
2041
        self.assertRaises(AssertionError, config.Option, 'foo', default=[1])
2042
2043
    def test_not_supported_object_default_value(self):
2044
        self.assertRaises(AssertionError, config.Option, 'foo',
2045
                          default=object())
2046
6349.3.1 by Vincent Ladeuil
Allow config option default value to be a python callable
2047
    def test_not_supported_callable_default_value_not_unicode(self):
2048
        def bar_not_unicode():
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2049
            return b'bar'
6349.3.1 by Vincent Ladeuil
Allow config option default value to be a python callable
2050
        opt = config.Option('foo', default=bar_not_unicode)
2051
        self.assertRaises(AssertionError, opt.get_default)
2052
6437.42.1 by Jelmer Vernooij
Make sure help options can provide their own help topic.
2053
    def test_get_help_topic(self):
2054
        opt = config.Option('foo')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2055
        self.assertEqual('foo', opt.get_help_topic())
6437.42.1 by Jelmer Vernooij
Make sure help options can provide their own help topic.
2056
5743.12.4 by Vincent Ladeuil
An option can provide a default value.
2057
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2058
class TestOptionConverter(tests.TestCase):
6091.3.1 by Vincent Ladeuil
Add convert_from_unicode to Option and rewrite the tests to need only an
2059
2060
    def assertConverted(self, expected, opt, value):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2061
        self.assertEqual(expected, opt.convert_from_unicode(None, value))
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2062
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2063
    def assertCallsWarning(self, opt, value):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2064
        warnings = []
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2065
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2066
        def warning(*args):
2067
            warnings.append(args[0] % args[1:])
2068
        self.overrideAttr(trace, 'warning', warning)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2069
        self.assertEqual(None, opt.convert_from_unicode(None, value))
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2070
        self.assertLength(1, warnings)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2071
        self.assertEqual(
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2072
            'Value "%s" is not valid for "%s"' % (value, opt.name),
2073
            warnings[0])
2074
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2075
    def assertCallsError(self, opt, value):
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2076
        self.assertRaises(config.ConfigOptionValueError,
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2077
                          opt.convert_from_unicode, None, value)
2078
2079
    def assertConvertInvalid(self, opt, invalid_value):
2080
        opt.invalid = None
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2081
        self.assertEqual(None, opt.convert_from_unicode(None, invalid_value))
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2082
        opt.invalid = 'warning'
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2083
        self.assertCallsWarning(opt, invalid_value)
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2084
        opt.invalid = 'error'
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2085
        self.assertCallsError(opt, invalid_value)
2086
2087
2088
class TestOptionWithBooleanConverter(TestOptionConverter):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2089
2090
    def get_option(self):
2091
        return config.Option('foo', help='A boolean.',
2092
                             from_unicode=config.bool_from_store)
2093
2094
    def test_convert_invalid(self):
2095
        opt = self.get_option()
2096
        # A string that is not recognized as a boolean
2097
        self.assertConvertInvalid(opt, u'invalid-boolean')
2098
        # A list of strings is never recognized as a boolean
2099
        self.assertConvertInvalid(opt, [u'not', u'a', u'boolean'])
2100
2101
    def test_convert_valid(self):
2102
        opt = self.get_option()
2103
        self.assertConverted(True, opt, u'True')
2104
        self.assertConverted(True, opt, u'1')
2105
        self.assertConverted(False, opt, u'False')
2106
2107
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2108
class TestOptionWithIntegerConverter(TestOptionConverter):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2109
2110
    def get_option(self):
2111
        return config.Option('foo', help='An integer.',
2112
                             from_unicode=config.int_from_store)
2113
2114
    def test_convert_invalid(self):
2115
        opt = self.get_option()
2116
        # A string that is not recognized as an integer
2117
        self.assertConvertInvalid(opt, u'forty-two')
2118
        # A list of strings is never recognized as an integer
2119
        self.assertConvertInvalid(opt, [u'a', u'list'])
2120
2121
    def test_convert_valid(self):
2122
        opt = self.get_option()
2123
        self.assertConverted(16, opt, u'16')
2124
2125
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2126
class TestOptionWithSIUnitConverter(TestOptionConverter):
6378.1.1 by Vincent Ladeuil
Add int_SI_from_store as a config option helper
2127
2128
    def get_option(self):
2129
        return config.Option('foo', help='An integer in SI units.',
2130
                             from_unicode=config.int_SI_from_store)
2131
2132
    def test_convert_invalid(self):
2133
        opt = self.get_option()
2134
        self.assertConvertInvalid(opt, u'not-a-unit')
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2135
        self.assertConvertInvalid(opt, u'Gb')  # Forgot the value
2136
        self.assertConvertInvalid(opt, u'1b')  # Forgot the unit
6378.1.1 by Vincent Ladeuil
Add int_SI_from_store as a config option helper
2137
        self.assertConvertInvalid(opt, u'1GG')
2138
        self.assertConvertInvalid(opt, u'1Mbb')
2139
        self.assertConvertInvalid(opt, u'1MM')
2140
2141
    def test_convert_valid(self):
2142
        opt = self.get_option()
2143
        self.assertConverted(int(5e3), opt, u'5kb')
2144
        self.assertConverted(int(5e6), opt, u'5M')
2145
        self.assertConverted(int(5e6), opt, u'5MB')
2146
        self.assertConverted(int(5e9), opt, u'5g')
2147
        self.assertConverted(int(5e9), opt, u'5gB')
2148
        self.assertConverted(100, opt, u'100')
2149
2150
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2151
class TestListOption(TestOptionConverter):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2152
2153
    def get_option(self):
2154
        return config.ListOption('foo', help='A list.')
6091.3.1 by Vincent Ladeuil
Add convert_from_unicode to Option and rewrite the tests to need only an
2155
2156
    def test_convert_invalid(self):
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
2157
        opt = self.get_option()
2158
        # We don't even try to convert a list into a list, we only expect
2159
        # strings
2160
        self.assertConvertInvalid(opt, [1])
6091.3.1 by Vincent Ladeuil
Add convert_from_unicode to Option and rewrite the tests to need only an
2161
        # No string is invalid as all forms can be converted to a list
2162
2163
    def test_convert_valid(self):
2164
        opt = self.get_option()
2165
        # An empty string is an empty list
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2166
        self.assertConverted([], opt, '')  # Using a bare str() just in case
6091.3.1 by Vincent Ladeuil
Add convert_from_unicode to Option and rewrite the tests to need only an
2167
        self.assertConverted([], opt, u'')
2168
        # A boolean
2169
        self.assertConverted([u'True'], opt, u'True')
2170
        # An integer
2171
        self.assertConverted([u'42'], opt, u'42')
2172
        # A single string
2173
        self.assertConverted([u'bar'], opt, u'bar')
2174
2175
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2176
class TestRegistryOption(TestOptionConverter):
6449.2.1 by Jelmer Vernooij
Add bzrlib.config.RegistryOption.
2177
2178
    def get_option(self, registry):
2179
        return config.RegistryOption('foo', registry,
6607.1.1 by Vincent Ladeuil
Rename assertWarns in test_config to avoid clashing with unittest2 assertWarns
2180
                                     help='A registry option.')
6449.2.1 by Jelmer Vernooij
Add bzrlib.config.RegistryOption.
2181
2182
    def test_convert_invalid(self):
2183
        registry = _mod_registry.Registry()
2184
        opt = self.get_option(registry)
2185
        self.assertConvertInvalid(opt, [1])
2186
        self.assertConvertInvalid(opt, u"notregistered")
2187
2188
    def test_convert_valid(self):
2189
        registry = _mod_registry.Registry()
2190
        registry.register("someval", 1234)
2191
        opt = self.get_option(registry)
2192
        # Using a bare str() just in case
2193
        self.assertConverted(1234, opt, "someval")
2194
        self.assertConverted(1234, opt, u'someval')
2195
        self.assertConverted(None, opt, None)
2196
2197
    def test_help(self):
2198
        registry = _mod_registry.Registry()
2199
        registry.register("someval", 1234, help="some option")
2200
        registry.register("dunno", 1234, help="some other option")
2201
        opt = self.get_option(registry)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2202
        self.assertEqual(
6449.2.1 by Jelmer Vernooij
Add bzrlib.config.RegistryOption.
2203
            'A registry option.\n'
2204
            '\n'
2205
            'The following values are supported:\n'
2206
            ' dunno - some other option\n'
2207
            ' someval - some option\n',
6449.2.2 by Jelmer Vernooij
Moar tests.
2208
            opt.help)
2209
2210
    def test_get_help_text(self):
2211
        registry = _mod_registry.Registry()
2212
        registry.register("someval", 1234, help="some option")
2213
        registry.register("dunno", 1234, help="some other option")
2214
        opt = self.get_option(registry)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2215
        self.assertEqual(
6449.2.2 by Jelmer Vernooij
Moar tests.
2216
            'A registry option.\n'
2217
            '\n'
2218
            'The following values are supported:\n'
2219
            ' dunno - some other option\n'
2220
            ' someval - some option\n',
2221
            opt.get_help_text())
6449.2.1 by Jelmer Vernooij
Add bzrlib.config.RegistryOption.
2222
2223
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2224
class TestOptionRegistry(tests.TestCase):
5743.12.5 by Vincent Ladeuil
Remove spurious spaces.
2225
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2226
    def setUp(self):
2227
        super(TestOptionRegistry, self).setUp()
2228
        # Always start with an empty registry
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
2229
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2230
        self.registry = config.option_registry
2231
2232
    def test_register(self):
2233
        opt = config.Option('foo')
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
2234
        self.registry.register(opt)
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2235
        self.assertIs(opt, self.registry.get('foo'))
2236
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2237
    def test_registered_help(self):
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
2238
        opt = config.Option('foo', help='A simple option')
2239
        self.registry.register(opt)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2240
        self.assertEqual('A simple option', self.registry.get_help('foo'))
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2241
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2242
    def test_dont_register_illegal_name(self):
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2243
        self.assertRaises(config.IllegalOptionName,
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2244
                          self.registry.register, config.Option(' foo'))
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2245
        self.assertRaises(config.IllegalOptionName,
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2246
                          self.registry.register, config.Option('bar,'))
2247
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
2248
    lazy_option = config.Option('lazy_foo', help='Lazy help')
2249
2250
    def test_register_lazy(self):
2251
        self.registry.register_lazy('lazy_foo', self.__module__,
2252
                                    'TestOptionRegistry.lazy_option')
2253
        self.assertIs(self.lazy_option, self.registry.get('lazy_foo'))
2254
2255
    def test_registered_lazy_help(self):
2256
        self.registry.register_lazy('lazy_foo', self.__module__,
2257
                                    'TestOptionRegistry.lazy_option')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2258
        self.assertEqual('Lazy help', self.registry.get_help('lazy_foo'))
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
2259
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2260
    def test_dont_lazy_register_illegal_name(self):
2261
        # This is where the root cause of http://pad.lv/1235099 is better
2262
        # understood: 'register_lazy' doc string mentions that key should match
2263
        # the option name which indirectly requires that the option name is a
2264
        # valid python identifier. We violate that rule here (using a key that
2265
        # doesn't match the option name) to test the option name checking.
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2266
        self.assertRaises(config.IllegalOptionName,
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2267
                          self.registry.register_lazy, ' foo', self.__module__,
2268
                          'TestOptionRegistry.lazy_option')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2269
        self.assertRaises(config.IllegalOptionName,
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
2270
                          self.registry.register_lazy, '1,2', self.__module__,
2271
                          'TestOptionRegistry.lazy_option')
2272
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2273
2274
class TestRegisteredOptions(tests.TestCase):
2275
    """All registered options should verify some constraints."""
2276
2277
    scenarios = [(key, {'option_name': key, 'option': option}) for key, option
2278
                 in config.option_registry.iteritems()]
2279
2280
    def setUp(self):
2281
        super(TestRegisteredOptions, self).setUp()
2282
        self.registry = config.option_registry
2283
2284
    def test_proper_name(self):
2285
        # An option should be registered under its own name, this can't be
2286
        # checked at registration time for the lazy ones.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2287
        self.assertEqual(self.option_name, self.option.name)
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2288
2289
    def test_help_is_set(self):
2290
        option_help = self.registry.get_help(self.option_name)
6056.2.5 by Vincent Ladeuil
Fix typos caught by jelmer.
2291
        # Come on, think about the user, he really wants to know what the
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2292
        # option is about
6056.2.5 by Vincent Ladeuil
Fix typos caught by jelmer.
2293
        self.assertIsNot(None, option_help)
6614.1.2 by Vincent Ladeuil
Fix assertNotEquals being deprecated by using assertNotEqual.
2294
        self.assertNotEqual('', option_help)
5743.12.3 by Vincent Ladeuil
More basic tests for options. Start tests for all registered options.
2295
5743.12.2 by Vincent Ladeuil
Basic registry for options.
2296
5743.3.12 by Vincent Ladeuil
Add an ad-hoc __repr__.
2297
class TestSection(tests.TestCase):
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2298
2299
    # FIXME: Parametrize so that all sections produced by Stores run these
5743.3.1 by Vincent Ladeuil
Add a docstring and dates to FIXMEs.
2300
    # tests -- vila 2011-04-01
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2301
2302
    def test_get_a_value(self):
2303
        a_dict = dict(foo='bar')
5743.3.11 by Vincent Ladeuil
Config sections only implement read access.
2304
        section = config.Section('myID', a_dict)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2305
        self.assertEqual('bar', section.get('foo'))
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2306
5743.3.10 by Vincent Ladeuil
Fix typos mentioned in reviews.
2307
    def test_get_unknown_option(self):
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2308
        a_dict = dict()
5743.5.13 by Vincent Ladeuil
Merge config-abstract-store into config-concrete-stores resolving conflicts
2309
        section = config.Section(None, a_dict)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2310
        self.assertEqual('out of thin air',
7143.15.2 by Jelmer Vernooij
Run autopep8.
2311
                         section.get('foo', 'out of thin air'))
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2312
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2313
    def test_options_is_shared(self):
2314
        a_dict = dict()
5743.5.13 by Vincent Ladeuil
Merge config-abstract-store into config-concrete-stores resolving conflicts
2315
        section = config.Section(None, a_dict)
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2316
        self.assertIs(a_dict, section.options)
2317
2318
5743.3.12 by Vincent Ladeuil
Add an ad-hoc __repr__.
2319
class TestMutableSection(tests.TestCase):
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2320
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2321
    scenarios = [('mutable',
2322
                  {'get_section':
7143.15.2 by Jelmer Vernooij
Run autopep8.
2323
                   lambda opts: config.MutableSection('myID', opts)},),
2324
                 ]
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2325
2326
    def test_set(self):
2327
        a_dict = dict(foo='bar')
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2328
        section = self.get_section(a_dict)
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2329
        section.set('foo', 'new_value')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2330
        self.assertEqual('new_value', section.get('foo'))
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2331
        # The change appears in the shared section
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2332
        self.assertEqual('new_value', a_dict.get('foo'))
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2333
        # We keep track of the change
2334
        self.assertTrue('foo' in section.orig)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2335
        self.assertEqual('bar', section.orig.get('foo'))
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2336
2337
    def test_set_preserve_original_once(self):
2338
        a_dict = dict(foo='bar')
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2339
        section = self.get_section(a_dict)
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2340
        section.set('foo', 'first_value')
2341
        section.set('foo', 'second_value')
2342
        # We keep track of the original value
2343
        self.assertTrue('foo' in section.orig)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2344
        self.assertEqual('bar', section.orig.get('foo'))
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2345
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2346
    def test_remove(self):
2347
        a_dict = dict(foo='bar')
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2348
        section = self.get_section(a_dict)
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2349
        section.remove('foo')
2350
        # We get None for unknown options via the default value
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2351
        self.assertEqual(None, section.get('foo'))
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2352
        # Or we just get the default value
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2353
        self.assertEqual('unknown', section.get('foo', 'unknown'))
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2354
        self.assertFalse('foo' in section.options)
2355
        # We keep track of the deletion
2356
        self.assertTrue('foo' in section.orig)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2357
        self.assertEqual('bar', section.orig.get('foo'))
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2358
2359
    def test_remove_new_option(self):
2360
        a_dict = dict()
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2361
        section = self.get_section(a_dict)
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2362
        section.set('foo', 'bar')
2363
        section.remove('foo')
2364
        self.assertFalse('foo' in section.options)
2365
        # The option didn't exist initially so it we need to keep track of it
2366
        # with a special value
2367
        self.assertTrue('foo' in section.orig)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2368
        self.assertEqual(config._NewlyCreatedOption, section.orig['foo'])
5743.2.2 by Vincent Ladeuil
Add tests for remove.
2369
5743.2.1 by Vincent Ladeuil
Basic tests and implementations for read-only and mutable sections.
2370
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2371
class TestCommandLineStore(tests.TestCase):
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2372
2373
    def setUp(self):
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2374
        super(TestCommandLineStore, self).setUp()
2375
        self.store = config.CommandLineStore()
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2376
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2377
2378
    def get_section(self):
2379
        """Get the unique section for the command line overrides."""
2380
        sections = list(self.store.get_sections())
2381
        self.assertLength(1, sections)
2382
        store, section = sections[0]
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2383
        self.assertEqual(self.store, store)
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2384
        return section
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2385
2386
    def test_no_override(self):
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2387
        self.store._from_cmdline([])
2388
        section = self.get_section()
2389
        self.assertLength(0, list(section.iter_option_names()))
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2390
2391
    def test_simple_override(self):
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2392
        self.store._from_cmdline(['a=b'])
2393
        section = self.get_section()
2394
        self.assertEqual('b', section.get('a'))
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2395
2396
    def test_list_override(self):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2397
        opt = config.ListOption('l')
2398
        config.option_registry.register(opt)
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2399
        self.store._from_cmdline(['l=1,2,3'])
2400
        val = self.get_section().get('l')
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2401
        self.assertEqual('1,2,3', val)
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2402
        # Reminder: lists should be registered as such explicitely, otherwise
2403
        # the conversion needs to be done afterwards.
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2404
        self.assertEqual(['1', '2', '3'],
2405
                         opt.convert_from_unicode(self.store, val))
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2406
2407
    def test_multiple_overrides(self):
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2408
        self.store._from_cmdline(['a=b', 'x=y'])
2409
        section = self.get_section()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2410
        self.assertEqual('b', section.get('a'))
2411
        self.assertEqual('y', section.get('x'))
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2412
2413
    def test_wrong_syntax(self):
2414
        self.assertRaises(errors.BzrCommandError,
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
2415
                          self.store._from_cmdline, ['a=b', 'c'])
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2416
7143.15.2 by Jelmer Vernooij
Run autopep8.
2417
6404.4.1 by Vincent Ladeuil
Properly support config.CommandLineStore in ``bzr config``
2418
class TestStoreMinimalAPI(tests.TestCaseWithTransport):
2419
2420
    scenarios = [(key, {'get_store': builder}) for key, builder
2421
                 in config.test_store_builder_registry.iteritems()] + [
2422
        ('cmdline', {'get_store': lambda test: config.CommandLineStore()})]
2423
2424
    def test_id(self):
2425
        store = self.get_store(self)
6619.3.18 by Jelmer Vernooij
Run 2to3 idioms fixer.
2426
        if isinstance(store, config.TransportIniFileStore):
6404.4.2 by Vincent Ladeuil
test_id is not applicable (which is why is it skipped) to TransportIniFileStore.
2427
            raise tests.TestNotApplicable(
6404.4.1 by Vincent Ladeuil
Properly support config.CommandLineStore in ``bzr config``
2428
                "%s is not a concrete Store implementation"
2429
                " so it doesn't need an id" % (store.__class__.__name__,))
2430
        self.assertIsNot(None, store.id)
2431
6161.1.1 by Vincent Ladeuil
Allow config options to be overridden from the command line
2432
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2433
class TestStore(tests.TestCaseWithTransport):
2434
6621.20.1 by Martin
Run 2to3 tuple_params fixer and tidy up.
2435
    def assertSectionContent(self, expected, store_and_section):
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2436
        """Assert that some options have the proper values in a section."""
6621.20.1 by Martin
Run 2to3 tuple_params fixer and tidy up.
2437
        _, section = store_and_section
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2438
        expected_name, expected_options = expected
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2439
        self.assertEqual(expected_name, section.id)
2440
        self.assertEqual(
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2441
            expected_options,
2442
            dict([(k, section.get(k)) for k in expected_options.keys()]))
2443
2444
2445
class TestReadonlyStore(TestStore):
2446
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2447
    scenarios = [(key, {'get_store': builder}) for key, builder
2448
                 in config.test_store_builder_registry.iteritems()]
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2449
2450
    def test_building_delays_load(self):
2451
        store = self.get_store(self)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2452
        self.assertEqual(False, store.is_loaded())
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2453
        store._load_from_string(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2454
        self.assertEqual(True, store.is_loaded())
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2455
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2456
    def test_get_no_sections_for_empty(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2457
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2458
        store._load_from_string(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2459
        self.assertEqual([], list(store.get_sections()))
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2460
2461
    def test_get_default_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2462
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2463
        store._load_from_string(b'foo=bar')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2464
        sections = list(store.get_sections())
2465
        self.assertLength(1, sections)
2466
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2467
2468
    def test_get_named_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2469
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2470
        store._load_from_string(b'[baz]\nfoo=bar')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2471
        sections = list(store.get_sections())
2472
        self.assertLength(1, sections)
2473
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
2474
5743.4.21 by Vincent Ladeuil
All stores should provide _load_from_string to reuse the existing tests.
2475
    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.
2476
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2477
        store._load_from_string(b'foo=bar')
2478
        self.assertRaises(AssertionError, store._load_from_string, b'bar=baz')
5743.4.21 by Vincent Ladeuil
All stores should provide _load_from_string to reuse the existing tests.
2479
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2480
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2481
class TestStoreQuoting(TestStore):
2482
2483
    scenarios = [(key, {'get_store': builder}) for key, builder
2484
                 in config.test_store_builder_registry.iteritems()]
2485
2486
    def setUp(self):
2487
        super(TestStoreQuoting, self).setUp()
2488
        self.store = self.get_store(self)
2489
        # We need a loaded store but any content will do
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2490
        self.store._load_from_string(b'')
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2491
2492
    def assertIdempotent(self, s):
2493
        """Assert that quoting an unquoted string is a no-op and vice-versa.
2494
2495
        What matters here is that option values, as they appear in a store, can
2496
        be safely round-tripped out of the store and back.
2497
2498
        :param s: A string, quoted if required.
2499
        """
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2500
        self.assertEqual(s, self.store.quote(self.store.unquote(s)))
2501
        self.assertEqual(s, self.store.unquote(self.store.quote(s)))
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2502
2503
    def test_empty_string(self):
2504
        if isinstance(self.store, config.IniFileStore):
2505
            # configobj._quote doesn't handle empty values
6385.1.4 by Vincent Ladeuil
Cannot use ExpectedException as pqm provides only testtools-0.9.8, 0.9.9 needed
2506
            self.assertRaises(AssertionError,
2507
                              self.assertIdempotent, '')
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2508
        else:
2509
            self.assertIdempotent('')
2510
        # But quoted empty strings are ok
2511
        self.assertIdempotent('""')
2512
2513
    def test_embedded_spaces(self):
2514
        self.assertIdempotent('" a b c "')
2515
2516
    def test_embedded_commas(self):
2517
        self.assertIdempotent('" a , b c "')
2518
2519
    def test_simple_comma(self):
2520
        if isinstance(self.store, config.IniFileStore):
2521
            # configobj requires that lists are special-cased
7143.15.2 by Jelmer Vernooij
Run autopep8.
2522
            self.assertRaises(AssertionError,
2523
                              self.assertIdempotent, ',')
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2524
        else:
2525
            self.assertIdempotent(',')
2526
        # When a single comma is required, quoting is also required
2527
        self.assertIdempotent('","')
2528
2529
    def test_list(self):
2530
        if isinstance(self.store, config.IniFileStore):
2531
            # configobj requires that lists are special-cased
6385.1.4 by Vincent Ladeuil
Cannot use ExpectedException as pqm provides only testtools-0.9.8, 0.9.9 needed
2532
            self.assertRaises(AssertionError,
2533
                              self.assertIdempotent, 'a,b')
6385.1.2 by Vincent Ladeuil
Add tests for Store quoting/unquoting
2534
        else:
2535
            self.assertIdempotent('a,b')
2536
2537
6404.3.1 by Vincent Ladeuil
Robustly unquote configuration values (workaround configobj presenting a section as a dict in weird edge cases)
2538
class TestDictFromStore(tests.TestCase):
2539
2540
    def test_unquote_not_string(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2541
        conf = config.MemoryStack(b'x=2\n[a_section]\na=1\n')
6404.3.1 by Vincent Ladeuil
Robustly unquote configuration values (workaround configobj presenting a section as a dict in weird edge cases)
2542
        value = conf.get('a_section')
2543
        # Urgh, despite 'conf' asking for the no-name section, we get the
2544
        # content of another section as a dict o_O
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2545
        self.assertEqual({'a': '1'}, value)
6404.3.1 by Vincent Ladeuil
Robustly unquote configuration values (workaround configobj presenting a section as a dict in weird edge cases)
2546
        unquoted = conf.store.unquote(value)
2547
        # Which cannot be unquoted but shouldn't crash either (the use cases
2548
        # are getting the value or displaying it. In the later case, '%s' will
2549
        # do).
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2550
        self.assertEqual({'a': '1'}, unquoted)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2551
        self.assertIn('%s' % (unquoted,), ("{u'a': u'1'}", "{'a': '1'}"))
6404.3.1 by Vincent Ladeuil
Robustly unquote configuration values (workaround configobj presenting a section as a dict in weird edge cases)
2552
2553
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2554
class TestIniFileStoreContent(tests.TestCaseWithTransport):
6082.5.13 by Vincent Ladeuil
Fix typos.
2555
    """Simulate loading a config store with content of various encodings.
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2556
2557
    All files produced by bzr are in utf8 content.
2558
2559
    Users may modify them manually and end up with a file that can't be
2560
    loaded. We need to issue proper error messages in this case.
2561
    """
2562
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2563
    invalid_utf8_char = b'\xff'
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2564
2565
    def test_load_utf8(self):
2566
        """Ensure we can load an utf8-encoded file."""
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2567
        t = self.get_transport()
2568
        # From http://pad.lv/799212
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2569
        unicode_user = u'b\N{Euro Sign}ar'
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2570
        unicode_content = u'user=%s' % (unicode_user,)
2571
        utf8_content = unicode_content.encode('utf8')
2572
        # Store the raw content in the config file
2573
        t.put_bytes('foo.conf', utf8_content)
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2574
        store = config.TransportIniFileStore(t, 'foo.conf')
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2575
        store.load()
2576
        stack = config.Stack([store.get_sections], store)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2577
        self.assertEqual(unicode_user, stack.get('user'))
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2578
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2579
    def test_load_non_ascii(self):
2580
        """Ensure we display a proper error on non-ascii, non utf-8 content."""
2581
        t = self.get_transport()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2582
        t.put_bytes('foo.conf', b'user=foo\n#%s\n' % (self.invalid_utf8_char,))
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2583
        store = config.TransportIniFileStore(t, 'foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2584
        self.assertRaises(config.ConfigContentError, store.load)
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2585
2586
    def test_load_erroneous_content(self):
2587
        """Ensure we display a proper error on content that can't be parsed."""
2588
        t = self.get_transport()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2589
        t.put_bytes('foo.conf', b'[open_section\n')
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2590
        store = config.TransportIniFileStore(t, 'foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2591
        self.assertRaises(config.ParseConfigError, store.load)
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2592
6110.5.3 by Jelmer Vernooij
Add test for IniFileStore.
2593
    def test_load_permission_denied(self):
6110.5.5 by Vincent Ladeuil
Warn when loading, fail if saving will occur later
2594
        """Ensure we get warned when trying to load an inaccessible file."""
6110.5.3 by Jelmer Vernooij
Add test for IniFileStore.
2595
        warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
2596
6110.5.3 by Jelmer Vernooij
Add test for IniFileStore.
2597
        def warning(*args):
2598
            warnings.append(args[0] % args[1:])
2599
        self.overrideAttr(trace, 'warning', warning)
2600
6110.5.5 by Vincent Ladeuil
Warn when loading, fail if saving will occur later
2601
        t = self.get_transport()
2602
2603
        def get_bytes(relpath):
2604
            raise errors.PermissionDenied(relpath, "")
2605
        t.get_bytes = get_bytes
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2606
        store = config.TransportIniFileStore(t, 'foo.conf')
6110.5.5 by Vincent Ladeuil
Warn when loading, fail if saving will occur later
2607
        self.assertRaises(errors.PermissionDenied, store.load)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2608
        self.assertEqual(
6110.5.3 by Jelmer Vernooij
Add test for IniFileStore.
2609
            warnings,
6110.5.5 by Vincent Ladeuil
Warn when loading, fail if saving will occur later
2610
            [u'Permission denied while trying to load configuration store %s.'
2611
             % store.external_url()])
6110.5.3 by Jelmer Vernooij
Add test for IniFileStore.
2612
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2613
2614
class TestIniConfigContent(tests.TestCaseWithTransport):
6082.5.13 by Vincent Ladeuil
Fix typos.
2615
    """Simulate loading a IniBasedConfig with content of various encodings.
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2616
2617
    All files produced by bzr are in utf8 content.
2618
2619
    Users may modify them manually and end up with a file that can't be
2620
    loaded. We need to issue proper error messages in this case.
2621
    """
2622
6973.7.5 by Jelmer Vernooij
s/file/open.
2623
    invalid_utf8_char = b'\xff'
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2624
2625
    def test_load_utf8(self):
2626
        """Ensure we can load an utf8-encoded file."""
2627
        # From http://pad.lv/799212
2628
        unicode_user = u'b\N{Euro Sign}ar'
2629
        unicode_content = u'user=%s' % (unicode_user,)
2630
        utf8_content = unicode_content.encode('utf8')
2631
        # Store the raw content in the config file
2632
        with open('foo.conf', 'wb') as f:
2633
            f.write(utf8_content)
2634
        conf = config.IniBasedConfig(file_name='foo.conf')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2635
        self.assertEqual(unicode_user, conf.get_user_option('user'))
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2636
2637
    def test_load_badly_encoded_content(self):
2638
        """Ensure we display a proper error on non-ascii, non utf-8 content."""
2639
        with open('foo.conf', 'wb') as f:
6973.7.5 by Jelmer Vernooij
s/file/open.
2640
            f.write(b'user=foo\n#%s\n' % (self.invalid_utf8_char,))
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2641
        conf = config.IniBasedConfig(file_name='foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2642
        self.assertRaises(config.ConfigContentError, conf._get_parser)
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2643
2644
    def test_load_erroneous_content(self):
2645
        """Ensure we display a proper error on content that can't be parsed."""
2646
        with open('foo.conf', 'wb') as f:
6973.7.5 by Jelmer Vernooij
s/file/open.
2647
            f.write(b'[open_section\n')
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2648
        conf = config.IniBasedConfig(file_name='foo.conf')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2649
        self.assertRaises(config.ParseConfigError, conf._get_parser)
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
2650
5987.1.1 by Vincent Ladeuil
Properly load utf8-encoded config files
2651
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2652
class TestMutableStore(TestStore):
2653
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2654
    scenarios = [(key, {'store_id': key, 'get_store': builder}) for key, builder
2655
                 in config.test_store_builder_registry.iteritems()]
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2656
2657
    def setUp(self):
2658
        super(TestMutableStore, self).setUp()
2659
        self.transport = self.get_transport()
2660
2661
    def has_store(self, store):
2662
        store_basename = urlutils.relative_url(self.transport.external_url(),
2663
                                               store.external_url())
2664
        return self.transport.has(store_basename)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2665
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2666
    def test_save_empty_creates_no_file(self):
5743.10.4 by Vincent Ladeuil
Add FIXME.
2667
        # FIXME: There should be a better way than relying on the test
2668
        # 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.
2669
        if self.store_id in ('branch', 'remote_branch'):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2670
            raise tests.TestNotApplicable(
2671
                'branch.conf is *always* created when a branch is initialized')
2672
        store = self.get_store(self)
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2673
        store.save()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2674
        self.assertEqual(False, self.has_store(store))
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2675
6499.2.1 by Vincent Ladeuil
Save branch config options only during the final unlock
2676
    def test_mutable_section_shared(self):
2677
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2678
        store._load_from_string(b'foo=bar\n')
6499.2.1 by Vincent Ladeuil
Save branch config options only during the final unlock
2679
        # FIXME: There should be a better way than relying on the test
2680
        # parametrization to identify branch.conf -- vila 2011-0526
2681
        if self.store_id in ('branch', 'remote_branch'):
2682
            # branch stores requires write locked branches
2683
            self.addCleanup(store.branch.lock_write().unlock)
2684
        section1 = store.get_mutable_section(None)
2685
        section2 = store.get_mutable_section(None)
2686
        # If we get different sections, different callers won't share the
2687
        # modification
2688
        self.assertIs(section1, section2)
2689
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2690
    def test_save_emptied_succeeds(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2691
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2692
        store._load_from_string(b'foo=bar\n')
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2693
        # FIXME: There should be a better way than relying on the test
2694
        # parametrization to identify branch.conf -- vila 2011-0526
2695
        if self.store_id in ('branch', 'remote_branch'):
2696
            # branch stores requires write locked branches
2697
            self.addCleanup(store.branch.lock_write().unlock)
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2698
        section = store.get_mutable_section(None)
2699
        section.remove('foo')
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2700
        store.save()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2701
        self.assertEqual(True, self.has_store(store))
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2702
        modified_store = self.get_store(self)
5743.4.19 by Vincent Ladeuil
Clarify that only Store.get_mutable_section() can accept an empty file.
2703
        sections = list(modified_store.get_sections())
2704
        self.assertLength(0, sections)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2705
2706
    def test_save_with_content_succeeds(self):
5743.10.4 by Vincent Ladeuil
Add FIXME.
2707
        # FIXME: There should be a better way than relying on the test
2708
        # 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.
2709
        if self.store_id in ('branch', 'remote_branch'):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2710
            raise tests.TestNotApplicable(
2711
                'branch.conf is *always* created when a branch is initialized')
2712
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2713
        store._load_from_string(b'foo=bar\n')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2714
        self.assertEqual(False, self.has_store(store))
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2715
        store.save()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2716
        self.assertEqual(True, self.has_store(store))
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2717
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2718
        sections = list(modified_store.get_sections())
2719
        self.assertLength(1, sections)
2720
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2721
2722
    def test_set_option_in_empty_store(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2723
        store = self.get_store(self)
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2724
        # FIXME: There should be a better way than relying on the test
2725
        # parametrization to identify branch.conf -- vila 2011-0526
2726
        if self.store_id in ('branch', 'remote_branch'):
2727
            # branch stores requires write locked branches
2728
            self.addCleanup(store.branch.lock_write().unlock)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2729
        section = store.get_mutable_section(None)
2730
        section.set('foo', 'bar')
2731
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2732
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2733
        sections = list(modified_store.get_sections())
2734
        self.assertLength(1, sections)
2735
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2736
2737
    def test_set_option_in_default_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2738
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2739
        store._load_from_string(b'')
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2740
        # FIXME: There should be a better way than relying on the test
2741
        # parametrization to identify branch.conf -- vila 2011-0526
2742
        if self.store_id in ('branch', 'remote_branch'):
2743
            # branch stores requires write locked branches
2744
            self.addCleanup(store.branch.lock_write().unlock)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2745
        section = store.get_mutable_section(None)
2746
        section.set('foo', 'bar')
2747
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2748
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2749
        sections = list(modified_store.get_sections())
2750
        self.assertLength(1, sections)
2751
        self.assertSectionContent((None, {'foo': 'bar'}), sections[0])
2752
2753
    def test_set_option_in_named_section(self):
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2754
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2755
        store._load_from_string(b'')
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2756
        # FIXME: There should be a better way than relying on the test
2757
        # parametrization to identify branch.conf -- vila 2011-0526
2758
        if self.store_id in ('branch', 'remote_branch'):
2759
            # branch stores requires write locked branches
2760
            self.addCleanup(store.branch.lock_write().unlock)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2761
        section = store.get_mutable_section('baz')
2762
        section.set('foo', 'bar')
2763
        store.save()
5743.5.10 by Vincent Ladeuil
Parametrize the generic tests against the concrete stores.
2764
        modified_store = self.get_store(self)
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2765
        sections = list(modified_store.get_sections())
2766
        self.assertLength(1, sections)
2767
        self.assertSectionContent(('baz', {'foo': 'bar'}), sections[0])
2768
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2769
    def test_load_hook(self):
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2770
        # First, we need to ensure that the store exists
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2771
        store = self.get_store(self)
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2772
        # FIXME: There should be a better way than relying on the test
2773
        # parametrization to identify branch.conf -- vila 2011-0526
2774
        if self.store_id in ('branch', 'remote_branch'):
2775
            # branch stores requires write locked branches
2776
            self.addCleanup(store.branch.lock_write().unlock)
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2777
        section = store.get_mutable_section('baz')
2778
        section.set('foo', 'bar')
2779
        store.save()
2780
        # Now we can try to load it
5743.8.11 by Vincent Ladeuil
Restrict the scope when testing hooks to avoid spurious failures.
2781
        store = self.get_store(self)
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2782
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
2783
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2784
        def hook(*args):
2785
            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.
2786
        config.ConfigHooks.install_named_hook('load', hook, None)
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2787
        self.assertLength(0, calls)
2788
        store.load()
2789
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2790
        self.assertEqual((store,), calls[0])
5743.8.8 by Vincent Ladeuil
Puth the load hook in the right place.
2791
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2792
    def test_save_hook(self):
2793
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
2794
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2795
        def hook(*args):
2796
            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.
2797
        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).
2798
        self.assertLength(0, calls)
2799
        store = self.get_store(self)
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
2800
        # FIXME: There should be a better way than relying on the test
2801
        # parametrization to identify branch.conf -- vila 2011-0526
2802
        if self.store_id in ('branch', 'remote_branch'):
2803
            # branch stores requires write locked branches
2804
            self.addCleanup(store.branch.lock_write().unlock)
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2805
        section = store.get_mutable_section('baz')
2806
        section.set('foo', 'bar')
2807
        store.save()
2808
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2809
        self.assertEqual((store,), calls[0])
5743.8.7 by Vincent Ladeuil
Add hooks for config stores (but the load one is not in the right place).
2810
6404.5.1 by Vincent Ladeuil
Setting or removing an option records the section as dirty
2811
    def test_set_mark_dirty(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2812
        stack = config.MemoryStack(b'')
6404.5.1 by Vincent Ladeuil
Setting or removing an option records the section as dirty
2813
        self.assertLength(0, stack.store.dirty_sections)
2814
        stack.set('foo', 'baz')
2815
        self.assertLength(1, stack.store.dirty_sections)
6404.5.3 by Vincent Ladeuil
If at least one mutable section contain a change, the store needs to be saved
2816
        self.assertTrue(stack.store._need_saving())
6404.5.1 by Vincent Ladeuil
Setting or removing an option records the section as dirty
2817
2818
    def test_remove_mark_dirty(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2819
        stack = config.MemoryStack(b'foo=bar')
6404.5.1 by Vincent Ladeuil
Setting or removing an option records the section as dirty
2820
        self.assertLength(0, stack.store.dirty_sections)
2821
        stack.remove('foo')
2822
        self.assertLength(1, stack.store.dirty_sections)
6404.5.3 by Vincent Ladeuil
If at least one mutable section contain a change, the store needs to be saved
2823
        self.assertTrue(stack.store._need_saving())
6404.5.1 by Vincent Ladeuil
Setting or removing an option records the section as dirty
2824
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2825
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2826
class TestStoreSaveChanges(tests.TestCaseWithTransport):
2827
    """Tests that config changes are kept in memory and saved on-demand."""
2828
2829
    def setUp(self):
2830
        super(TestStoreSaveChanges, self).setUp()
2831
        self.transport = self.get_transport()
2832
        # Most of the tests involve two stores pointing to the same persistent
2833
        # storage to observe the effects of concurrent changes
2834
        self.st1 = config.TransportIniFileStore(self.transport, 'foo.conf')
2835
        self.st2 = config.TransportIniFileStore(self.transport, 'foo.conf')
6404.5.5 by Vincent Ladeuil
Refine implementations and add more precise tests. More tests can be added for more scenarios if it doesn't seem worth it until we encounter them in real life (which is unlikely so far)
2836
        self.warnings = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
2837
6404.5.5 by Vincent Ladeuil
Refine implementations and add more precise tests. More tests can be added for more scenarios if it doesn't seem worth it until we encounter them in real life (which is unlikely so far)
2838
        def warning(*args):
2839
            self.warnings.append(args[0] % args[1:])
2840
        self.overrideAttr(trace, 'warning', warning)
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2841
2842
    def has_store(self, store):
2843
        store_basename = urlutils.relative_url(self.transport.external_url(),
2844
                                               store.external_url())
2845
        return self.transport.has(store_basename)
2846
2847
    def get_stack(self, store):
2848
        # Any stack will do as long as it uses the right store, just a single
2849
        # no-name section is enough
2850
        return config.Stack([store.get_sections], store)
2851
2852
    def test_no_changes_no_save(self):
2853
        s = self.get_stack(self.st1)
2854
        s.store.save_changes()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2855
        self.assertEqual(False, self.has_store(self.st1))
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2856
2857
    def test_unrelated_concurrent_update(self):
2858
        s1 = self.get_stack(self.st1)
2859
        s2 = self.get_stack(self.st2)
2860
        s1.set('foo', 'bar')
2861
        s2.set('baz', 'quux')
2862
        s1.store.save()
2863
        # Changes don't propagate magically
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2864
        self.assertEqual(None, s1.get('baz'))
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2865
        s2.store.save_changes()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2866
        self.assertEqual('quux', s2.get('baz'))
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2867
        # Changes are acquired when saving
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2868
        self.assertEqual('bar', s2.get('foo'))
6404.5.5 by Vincent Ladeuil
Refine implementations and add more precise tests. More tests can be added for more scenarios if it doesn't seem worth it until we encounter them in real life (which is unlikely so far)
2869
        # Since there is no overlap, no warnings are emitted
2870
        self.assertLength(0, self.warnings)
2871
2872
    def test_concurrent_update_modified(self):
2873
        s1 = self.get_stack(self.st1)
2874
        s2 = self.get_stack(self.st2)
2875
        s1.set('foo', 'bar')
2876
        s2.set('foo', 'baz')
2877
        s1.store.save()
2878
        # Last speaker wins
2879
        s2.store.save_changes()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2880
        self.assertEqual('baz', s2.get('foo'))
6404.5.5 by Vincent Ladeuil
Refine implementations and add more precise tests. More tests can be added for more scenarios if it doesn't seem worth it until we encounter them in real life (which is unlikely so far)
2881
        # But the user get a warning
2882
        self.assertLength(1, self.warnings)
2883
        warning = self.warnings[0]
2884
        self.assertStartsWith(warning, 'Option foo in section None')
2885
        self.assertEndsWith(warning, 'was changed from <CREATED> to bar.'
2886
                            ' The baz value will be saved.')
2887
2888
    def test_concurrent_deletion(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2889
        self.st1._load_from_string(b'foo=bar')
6404.5.5 by Vincent Ladeuil
Refine implementations and add more precise tests. More tests can be added for more scenarios if it doesn't seem worth it until we encounter them in real life (which is unlikely so far)
2890
        self.st1.save()
2891
        s1 = self.get_stack(self.st1)
2892
        s2 = self.get_stack(self.st2)
2893
        s1.remove('foo')
2894
        s2.remove('foo')
2895
        s1.store.save_changes()
2896
        # No warning yet
2897
        self.assertLength(0, self.warnings)
2898
        s2.store.save_changes()
2899
        # Now we get one
2900
        self.assertLength(1, self.warnings)
2901
        warning = self.warnings[0]
2902
        self.assertStartsWith(warning, 'Option foo in section None')
2903
        self.assertEndsWith(warning, 'was changed from bar to <CREATED>.'
2904
                            ' The <DELETED> value will be saved.')
6404.5.4 by Vincent Ladeuil
Saving changes is incremental and brings back updates from concurrent users
2905
2906
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2907
class TestQuotingIniFileStore(tests.TestCaseWithTransport):
2908
2909
    def get_store(self):
2910
        return config.TransportIniFileStore(self.get_transport(), 'foo.conf')
2911
2912
    def test_get_quoted_string(self):
2913
        store = self.get_store()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2914
        store._load_from_string(b'foo= " abc "')
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2915
        stack = config.Stack([store.get_sections])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2916
        self.assertEqual(' abc ', stack.get('foo'))
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2917
2918
    def test_set_quoted_string(self):
2919
        store = self.get_store()
2920
        stack = config.Stack([store.get_sections], store)
2921
        stack.set('foo', ' a b c ')
2922
        store.save()
7143.15.2 by Jelmer Vernooij
Run autopep8.
2923
        self.assertFileEqual(b'foo = " a b c "' +
2924
                             os.linesep.encode('ascii'), 'foo.conf')
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
2925
2926
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2927
class TestTransportIniFileStore(TestStore):
5743.4.6 by Vincent Ladeuil
Parametrize Store tests and isolate the ConfigObjStore specific ones.
2928
5743.4.3 by Vincent Ladeuil
Implement get_mutable_section.
2929
    def test_loading_unknown_file_fails(self):
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2930
        store = config.TransportIniFileStore(self.get_transport(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2931
                                             'I-do-not-exist')
5743.4.3 by Vincent Ladeuil
Implement get_mutable_section.
2932
        self.assertRaises(errors.NoSuchFile, store.load)
2933
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2934
    def test_invalid_content(self):
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2935
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2936
        self.assertEqual(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.
2937
        exc = self.assertRaises(
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
2938
            config.ParseConfigError, store._load_from_string,
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2939
            b'this is invalid !')
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2940
        self.assertEndsWith(exc.filename, 'foo.conf')
2941
        # And the load failed
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
2942
        self.assertEqual(False, store.is_loaded())
5743.2.7 by Vincent Ladeuil
Implement loading a config store from a string or a file.
2943
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2944
    def test_get_embedded_sections(self):
5743.2.11 by Vincent Ladeuil
Basic store.set implementation.
2945
        # A more complicated example (which also shows that section names and
2946
        # 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.
2947
        # FIXME: This should be fixed by forbidding dicts as values ?
2948
        # -- vila 2011-04-05
6270.1.5 by Jelmer Vernooij
Add TransportIniFileStore.
2949
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
2950
        store._load_from_string(b'''
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2951
foo=bar
2952
l=1,2
2953
[DEFAULT]
2954
foo_in_DEFAULT=foo_DEFAULT
2955
[bar]
2956
foo_in_bar=barbar
2957
[baz]
2958
foo_in_baz=barbaz
2959
[[qux]]
2960
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.
2961
''')
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2962
        sections = list(store.get_sections())
2963
        self.assertLength(4, sections)
2964
        # The default section has no name.
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
2965
        # List values are provided as strings and need to be explicitly
2966
        # converted by specifying from_unicode=list_from_store at option
2967
        # registration
2968
        self.assertSectionContent((None, {'foo': 'bar', 'l': u'1,2'}),
5743.4.1 by Vincent Ladeuil
Use proper ReadOnly sections in ConfigObjStore.get_sections().
2969
                                  sections[0])
2970
        self.assertSectionContent(
2971
            ('DEFAULT', {'foo_in_DEFAULT': 'foo_DEFAULT'}), sections[1])
2972
        self.assertSectionContent(
2973
            ('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.
2974
        # sub sections are provided as embedded dicts.
5743.4.1 by Vincent Ladeuil
Use proper ReadOnly sections in ConfigObjStore.get_sections().
2975
        self.assertSectionContent(
2976
            ('baz', {'foo_in_baz': 'barbaz', 'qux': {'foo_in_qux': 'quux'}}),
2977
            sections[3])
5743.2.10 by Vincent Ladeuil
Implement store.get_sections() as an iterator and provides the configobj implementation.
2978
5743.4.5 by Vincent Ladeuil
Split store tests between readonly and mutable ones.
2979
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2980
class TestLockableIniFileStore(TestStore):
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2981
2982
    def test_create_store_in_created_dir(self):
5743.6.21 by Vincent Ladeuil
Tighten the test.
2983
        self.assertPathDoesNotExist('dir')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2984
        t = self.get_transport('dir/subdir')
5743.4.25 by Vincent Ladeuil
Address review comments by jelmer and poolie.
2985
        store = config.LockableIniFileStore(t, 'foo.conf')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2986
        store.get_mutable_section(None).set('foo', 'bar')
2987
        store.save()
5743.6.21 by Vincent Ladeuil
Tighten the test.
2988
        self.assertPathExists('dir/subdir')
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
2989
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
2990
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2991
class TestConcurrentStoreUpdates(TestStore):
5743.10.13 by Vincent Ladeuil
Mention that the the concurrent update tests are not targeted at *all* Store implementations.
2992
    """Test that Stores properly handle conccurent updates.
2993
2994
    New Store implementation may fail some of these tests but until such
2995
    implementations exist it's hard to properly filter them from the scenarios
2996
    applied here. If you encounter such a case, contact the bzr devs.
2997
    """
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
2998
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
2999
    scenarios = [(key, {'get_stack': builder}) for key, builder
3000
                 in config.test_stack_builder_registry.iteritems()]
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
3001
3002
    def setUp(self):
3003
        super(TestConcurrentStoreUpdates, self).setUp()
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3004
        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
3005
        if not isinstance(self.stack, config._CompatibleStack):
3006
            raise tests.TestNotApplicable(
3007
                '%s is not meant to be compatible with the old config design'
3008
                % (self.stack,))
6260.3.1 by Vincent Ladeuil
Switch ``bzr config`` to the new config implementation
3009
        self.stack.set('one', '1')
3010
        self.stack.set('two', '2')
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3011
        # Flush the store
3012
        self.stack.store.save()
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
3013
3014
    def test_simple_read_access(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3015
        self.assertEqual('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
3016
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
3017
    def test_simple_write_access(self):
3018
        self.stack.set('one', 'one')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3019
        self.assertEqual('one', self.stack.get('one'))
5743.6.22 by Vincent Ladeuil
Start writing tests for lockable stores.
3020
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3021
    def test_listen_to_the_last_speaker(self):
3022
        c1 = self.stack
3023
        c2 = self.get_stack(self)
3024
        c1.set('one', 'ONE')
3025
        c2.set('two', 'TWO')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3026
        self.assertEqual('ONE', c1.get('one'))
3027
        self.assertEqual('TWO', c2.get('two'))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3028
        # The second update respect the first one
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3029
        self.assertEqual('ONE', c2.get('one'))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3030
3031
    def test_last_speaker_wins(self):
3032
        # If the same config is not shared, the same variable modified twice
3033
        # can only see a single result.
3034
        c1 = self.stack
3035
        c2 = self.get_stack(self)
3036
        c1.set('one', 'c1')
3037
        c2.set('one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3038
        self.assertEqual('c2', c2.get('one'))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3039
        # The first modification is still available until another refresh
3040
        # occur
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3041
        self.assertEqual('c1', c1.get('one'))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3042
        c1.set('two', 'done')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3043
        self.assertEqual('c2', c1.get('one'))
5743.6.23 by Vincent Ladeuil
More config concurrent updates tests.
3044
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
3045
    def test_writes_are_serialized(self):
3046
        c1 = self.stack
3047
        c2 = self.get_stack(self)
3048
5743.6.25 by Vincent Ladeuil
Last test rewritten.
3049
        # 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.
3050
        before_writing = threading.Event()
3051
        after_writing = threading.Event()
3052
        writing_done = threading.Event()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
3053
        c1_save_without_locking_orig = c1.store.save_without_locking
7143.15.2 by Jelmer Vernooij
Run autopep8.
3054
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
3055
        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.
3056
            before_writing.set()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
3057
            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.
3058
            # The lock is held. We wait for the main thread to decide when to
3059
            # continue
3060
            after_writing.wait()
5743.6.32 by Vincent Ladeuil
Address poolie's review comments.
3061
        c1.store.save_without_locking = c1_save_without_locking
7143.15.2 by Jelmer Vernooij
Run autopep8.
3062
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
3063
        def c1_set():
3064
            c1.set('one', 'c1')
3065
            writing_done.set()
3066
        t1 = threading.Thread(target=c1_set)
3067
        # Collect the thread after the test
3068
        self.addCleanup(t1.join)
3069
        # Be ready to unblock the thread if the test goes wrong
3070
        self.addCleanup(after_writing.set)
3071
        t1.start()
3072
        before_writing.wait()
3073
        self.assertRaises(errors.LockContention,
3074
                          c2.set, 'one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3075
        self.assertEqual('c1', c1.get('one'))
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
3076
        # Let the lock be released
3077
        after_writing.set()
3078
        writing_done.wait()
3079
        c2.set('one', 'c2')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3080
        self.assertEqual('c2', c2.get('one'))
5743.6.24 by Vincent Ladeuil
One more test with a ugly hack to allow the test to stop in the right place.
3081
5743.6.25 by Vincent Ladeuil
Last test rewritten.
3082
    def test_read_while_writing(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
3083
        c1 = self.stack
3084
        # We spawn a thread that will pause *during* the write
3085
        ready_to_write = threading.Event()
3086
        do_writing = threading.Event()
3087
        writing_done = threading.Event()
3088
        # We override the _save implementation so we know the store is locked
3089
        c1_save_without_locking_orig = c1.store.save_without_locking
3090
3091
        def c1_save_without_locking():
3092
            ready_to_write.set()
3093
            # The lock is held. We wait for the main thread to decide when to
3094
            # continue
3095
            do_writing.wait()
3096
            c1_save_without_locking_orig()
3097
            writing_done.set()
3098
        c1.store.save_without_locking = c1_save_without_locking
3099
3100
        def c1_set():
3101
            c1.set('one', 'c1')
3102
        t1 = threading.Thread(target=c1_set)
3103
        # Collect the thread after the test
3104
        self.addCleanup(t1.join)
3105
        # Be ready to unblock the thread if the test goes wrong
3106
        self.addCleanup(do_writing.set)
3107
        t1.start()
3108
        # Ensure the thread is ready to write
3109
        ready_to_write.wait()
3110
        self.assertEqual('c1', c1.get('one'))
3111
        # If we read during the write, we get the old value
3112
        c2 = self.get_stack(self)
3113
        self.assertEqual('1', c2.get('one'))
3114
        # Let the writing occur and ensure it occurred
3115
        do_writing.set()
3116
        writing_done.wait()
3117
        # Now we get the updated value
3118
        c3 = self.get_stack(self)
3119
        self.assertEqual('c1', c3.get('one'))
5743.6.25 by Vincent Ladeuil
Last test rewritten.
3120
3121
    # FIXME: It may be worth looking into removing the lock dir when it's not
3122
    # needed anymore and look at possible fallouts for concurrent lockers. This
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
3123
    # will matter if/when we use config files outside of breezy directories
3124
    # (.config/breezy or .bzr) -- vila 20110-04-111
5743.4.9 by Vincent Ladeuil
Implement a LockableConfigObjStore to be able to mimick the actual behaviour.
3125
3126
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
3127
class TestSectionMatcher(TestStore):
3128
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3129
    scenarios = [('location', {'matcher': config.LocationMatcher}),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3130
                 ('id', {'matcher': config.NameMatcher}), ]
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
3131
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3132
    def setUp(self):
3133
        super(TestSectionMatcher, self).setUp()
3134
        # Any simple store is good enough
3135
        self.get_store = config.test_store_builder_registry.get('configobj')
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
3136
3137
    def test_no_matches_for_empty_stores(self):
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3138
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3139
        store._load_from_string(b'')
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3140
        matcher = self.matcher(store, '/bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3141
        self.assertEqual([], list(matcher.get_sections()))
5743.2.22 by Vincent Ladeuil
Some minimal SectionMatcher implementation to setup the test infrastucture.
3142
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3143
    def test_build_doesnt_load_store(self):
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3144
        store = self.get_store(self)
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
3145
        self.matcher(store, '/bar')
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
3146
        self.assertFalse(store.is_loaded())
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3147
3148
3149
class TestLocationSection(tests.TestCase):
3150
3151
    def get_section(self, options, extra_path):
5743.2.37 by Vincent Ladeuil
Merge config-concrete-stores into config-section-matchers resolving conflicts
3152
        section = config.Section('foo', options)
6402.2.1 by Vincent Ladeuil
Get rid of LocationSection.length as its not needed in the general case.
3153
        return config.LocationSection(section, extra_path)
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3154
3155
    def test_simple_option(self):
3156
        section = self.get_section({'foo': 'bar'}, '')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3157
        self.assertEqual('bar', section.get('foo'))
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3158
3159
    def test_option_with_extra_path(self):
3160
        section = self.get_section({'foo': 'bar', 'foo:policy': 'appendpath'},
3161
                                   'baz')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3162
        self.assertEqual('bar/baz', section.get('foo'))
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3163
3164
    def test_invalid_policy(self):
3165
        section = self.get_section({'foo': 'bar', 'foo:policy': 'die'},
3166
                                   'baz')
3167
        # invalid policies are ignored
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3168
        self.assertEqual('bar', section.get('foo'))
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3169
3170
3171
class TestLocationMatcher(TestStore):
3172
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3173
    def setUp(self):
3174
        super(TestLocationMatcher, self).setUp()
3175
        # Any simple store is good enough
3176
        self.get_store = config.test_store_builder_registry.get('configobj')
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
3177
6015.22.1 by Vincent Ladeuil
config.LocationMatcher properly excludes unrelated sections
3178
    def test_unrelated_section_excluded(self):
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3179
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3180
        store._load_from_string(b'''
6015.22.1 by Vincent Ladeuil
config.LocationMatcher properly excludes unrelated sections
3181
[/foo]
3182
section=/foo
3183
[/foo/baz]
3184
section=/foo/baz
3185
[/foo/bar]
3186
section=/foo/bar
3187
[/foo/bar/baz]
3188
section=/foo/bar/baz
3189
[/quux/quux]
3190
section=/quux/quux
3191
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3192
        self.assertEqual(['/foo', '/foo/baz', '/foo/bar', '/foo/bar/baz',
7143.15.2 by Jelmer Vernooij
Run autopep8.
3193
                          '/quux/quux'],
3194
                         [section.id for _, section in store.get_sections()])
6015.22.1 by Vincent Ladeuil
config.LocationMatcher properly excludes unrelated sections
3195
        matcher = config.LocationMatcher(store, '/foo/bar/quux')
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3196
        sections = [section for _, section in matcher.get_sections()]
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3197
        self.assertEqual(['/foo/bar', '/foo'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3198
                         [section.id for section in sections])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3199
        self.assertEqual(['quux', 'bar/quux'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3200
                         [section.extra_path for section in sections])
6015.22.1 by Vincent Ladeuil
config.LocationMatcher properly excludes unrelated sections
3201
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3202
    def test_more_specific_sections_first(self):
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3203
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3204
        store._load_from_string(b'''
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3205
[/foo]
3206
section=/foo
3207
[/foo/bar]
3208
section=/foo/bar
5743.2.33 by Vincent Ladeuil
Stop using get_ConfigObjStore.
3209
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3210
        self.assertEqual(['/foo', '/foo/bar'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3211
                         [section.id for _, section in store.get_sections()])
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3212
        matcher = config.LocationMatcher(store, '/foo/bar/baz')
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3213
        sections = [section for _, section in matcher.get_sections()]
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3214
        self.assertEqual(['/foo/bar', '/foo'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3215
                         [section.id for section in sections])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3216
        self.assertEqual(['baz', 'bar/baz'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3217
                         [section.extra_path for section in sections])
5743.2.24 by Vincent Ladeuil
Complete location config helpers with basic tests.
3218
5743.6.18 by Vincent Ladeuil
Add a test for appendpath support in no-name section.
3219
    def test_appendpath_in_no_name_section(self):
3220
        # It's a bit weird to allow appendpath in a no-name section, but
3221
        # someone may found a use for it
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3222
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3223
        store._load_from_string(b'''
5743.6.18 by Vincent Ladeuil
Add a test for appendpath support in no-name section.
3224
foo=bar
3225
foo:policy = appendpath
3226
''')
3227
        matcher = config.LocationMatcher(store, 'dir/subdir')
3228
        sections = list(matcher.get_sections())
3229
        self.assertLength(1, sections)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3230
        self.assertEqual('bar/dir/subdir', sections[0][1].get('foo'))
5743.6.18 by Vincent Ladeuil
Add a test for appendpath support in no-name section.
3231
5743.6.19 by Vincent Ladeuil
Clarify comments about section names for Location-related objects (also fix LocationMatcher and add tests).
3232
    def test_file_urls_are_normalized(self):
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3233
        store = self.get_store(self)
5912.3.1 by Vincent Ladeuil
Fix spurious windows-specific test failure
3234
        if sys.platform == 'win32':
3235
            expected_url = 'file:///C:/dir/subdir'
3236
            expected_location = 'C:/dir/subdir'
3237
        else:
3238
            expected_url = 'file:///dir/subdir'
3239
            expected_location = '/dir/subdir'
3240
        matcher = config.LocationMatcher(store, expected_url)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3241
        self.assertEqual(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).
3242
6524.2.4 by Aaron Bentley
branchname falls back to basename.
3243
    def test_branch_name_colo(self):
3244
        store = self.get_store(self)
3245
        store._load_from_string(dedent("""\
3246
            [/]
3247
            push_location=my{branchname}
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3248
        """).encode('ascii'))
6524.2.4 by Aaron Bentley
branchname falls back to basename.
3249
        matcher = config.LocationMatcher(store, 'file:///,branch=example%3c')
3250
        self.assertEqual('example<', matcher.branch_name)
3251
        ((_, section),) = matcher.get_sections()
3252
        self.assertEqual('example<', section.locals['branchname'])
3253
3254
    def test_branch_name_basename(self):
3255
        store = self.get_store(self)
3256
        store._load_from_string(dedent("""\
3257
            [/]
3258
            push_location=my{branchname}
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3259
        """).encode('ascii'))
6524.2.4 by Aaron Bentley
branchname falls back to basename.
3260
        matcher = config.LocationMatcher(store, 'file:///parent/example%3c')
3261
        self.assertEqual('example<', matcher.branch_name)
3262
        ((_, section),) = matcher.get_sections()
3263
        self.assertEqual('example<', section.locals['branchname'])
3264
5743.1.20 by Vincent Ladeuil
Merge config-section-matchers into config-stack resolving conflicts
3265
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3266
class TestStartingPathMatcher(TestStore):
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3267
3268
    def setUp(self):
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3269
        super(TestStartingPathMatcher, self).setUp()
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3270
        # Any simple store is good enough
3271
        self.store = config.IniFileStore()
3272
3273
    def assertSectionIDs(self, expected, location, content):
3274
        self.store._load_from_string(content)
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3275
        matcher = config.StartingPathMatcher(self.store, location)
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3276
        sections = list(matcher.get_sections())
3277
        self.assertLength(len(expected), sections)
3278
        self.assertEqual(expected, [section.id for _, section in sections])
3279
        return sections
3280
3281
    def test_empty(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3282
        self.assertSectionIDs([], self.get_url(), b'')
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3283
6402.2.8 by Vincent Ladeuil
Feedback from review.
3284
    def test_url_vs_local_paths(self):
3285
        # The matcher location is an url and the section names are local paths
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
3286
        self.assertSectionIDs(['/foo/bar', '/foo'],
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3287
                              'file:///foo/bar/baz', b'''\
6402.2.8 by Vincent Ladeuil
Feedback from review.
3288
[/foo]
3289
[/foo/bar]
3290
''')
3291
3292
    def test_local_path_vs_url(self):
3293
        # The matcher location is a local path and the section names are urls
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
3294
        self.assertSectionIDs(['file:///foo/bar', 'file:///foo'],
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3295
                              '/foo/bar/baz', b'''\
6402.2.8 by Vincent Ladeuil
Feedback from review.
3296
[file:///foo]
3297
[file:///foo/bar]
3298
''')
3299
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3300
    def test_no_name_section_included_when_present(self):
6402.2.5 by Vincent Ladeuil
Always return the no-name section if present.
3301
        # Note that other tests will cover the case where the no-name section
3302
        # is empty and as such, not included.
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3303
        sections = self.assertSectionIDs(['/foo/bar', '/foo', None],
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3304
                                         '/foo/bar/baz', b'''\
6402.2.5 by Vincent Ladeuil
Always return the no-name section if present.
3305
option = defined so the no-name section exists
3306
[/foo]
3307
[/foo/bar]
3308
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3309
        self.assertEqual(['baz', 'bar/baz', '/foo/bar/baz'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3310
                         [s.locals['relpath'] for _, s in sections])
6402.2.5 by Vincent Ladeuil
Always return the no-name section if present.
3311
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3312
    def test_order_reversed(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3313
        self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', b'''\
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3314
[/foo]
3315
[/foo/bar]
3316
''')
3317
3318
    def test_unrelated_section_excluded(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3319
        self.assertSectionIDs(['/foo/bar', '/foo'], '/foo/bar/baz', b'''\
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3320
[/foo]
3321
[/foo/qux]
3322
[/foo/bar]
3323
''')
3324
3325
    def test_glob_included(self):
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3326
        sections = self.assertSectionIDs(['/foo/*/baz', '/foo/b*', '/foo'],
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3327
                                         '/foo/bar/baz', b'''\
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3328
[/foo]
3329
[/foo/qux]
3330
[/foo/b*]
3331
[/foo/*/baz]
3332
''')
6402.2.6 by Vincent Ladeuil
Fix {relpath} support, realizing that when a section ends with a glob, it's not obivous to decide what should be done.
3333
        # Note that 'baz' as a relpath for /foo/b* is not fully correct, but
6402.2.8 by Vincent Ladeuil
Feedback from review.
3334
        # nothing really is... as far using {relpath} to append it to something
3335
        # else, this seems good enough though.
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3336
        self.assertEqual(['', 'baz', 'bar/baz'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3337
                         [s.locals['relpath'] for _, s in sections])
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3338
3339
    def test_respect_order(self):
3340
        self.assertSectionIDs(['/foo', '/foo/b*', '/foo/*/baz'],
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3341
                              '/foo/bar/baz', b'''\
6402.2.3 by Vincent Ladeuil
More tests, a real implementation and some tweaks.
3342
[/foo/*/baz]
3343
[/foo/qux]
3344
[/foo/b*]
3345
[/foo]
3346
''')
3347
3348
6123.7.2 by Vincent Ladeuil
Rename IdMatcher to NameMatcher.
3349
class TestNameMatcher(TestStore):
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3350
3351
    def setUp(self):
6123.7.2 by Vincent Ladeuil
Rename IdMatcher to NameMatcher.
3352
        super(TestNameMatcher, self).setUp()
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3353
        self.matcher = config.NameMatcher
3354
        # Any simple store is good enough
3355
        self.get_store = config.test_store_builder_registry.get('configobj')
3356
3357
    def get_matching_sections(self, name):
3358
        store = self.get_store(self)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3359
        store._load_from_string(b'''
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3360
[foo]
3361
option=foo
3362
[foo/baz]
3363
option=foo/baz
3364
[bar]
3365
option=bar
3366
''')
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
3367
        matcher = self.matcher(store, name)
6123.7.2 by Vincent Ladeuil
Rename IdMatcher to NameMatcher.
3368
        return list(matcher.get_sections())
3369
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3370
    def test_matching(self):
6123.7.2 by Vincent Ladeuil
Rename IdMatcher to NameMatcher.
3371
        sections = self.get_matching_sections('foo')
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3372
        self.assertLength(1, sections)
3373
        self.assertSectionContent(('foo', {'option': 'foo'}), sections[0])
3374
3375
    def test_not_matching(self):
6123.7.2 by Vincent Ladeuil
Rename IdMatcher to NameMatcher.
3376
        sections = self.get_matching_sections('baz')
6123.7.1 by Vincent Ladeuil
Provide config.IdMatcher for config files defining secion names as unique ids
3377
        self.assertLength(0, sections)
3378
3379
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3380
class TestBaseStackGet(tests.TestCase):
3381
3382
    def setUp(self):
3383
        super(TestBaseStackGet, self).setUp()
6056.2.4 by Vincent Ladeuil
Option help is now part of the object itself.
3384
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3385
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3386
    def test_get_first_definition(self):
3387
        store1 = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3388
        store1._load_from_string(b'foo=bar')
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3389
        store2 = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3390
        store2._load_from_string(b'foo=baz')
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3391
        conf = config.Stack([store1.get_sections, store2.get_sections])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3392
        self.assertEqual('bar', conf.get('foo'))
5743.1.1 by Vincent Ladeuil
Start implementing a config stack.
3393
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
3394
    def test_get_with_registered_default_value(self):
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3395
        config.option_registry.register(config.Option('foo', default='bar'))
3396
        conf_stack = config.Stack([])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3397
        self.assertEqual('bar', conf_stack.get('foo'))
5743.12.6 by Vincent Ladeuil
Stack.get() provides the registered option default value.
3398
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
3399
    def test_get_without_registered_default_value(self):
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3400
        config.option_registry.register(config.Option('foo'))
3401
        conf_stack = config.Stack([])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3402
        self.assertEqual(None, conf_stack.get('foo'))
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
3403
3404
    def test_get_without_default_value_for_not_registered(self):
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3405
        conf_stack = config.Stack([])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3406
        self.assertEqual(None, conf_stack.get('foo'))
5743.12.7 by Vincent Ladeuil
Test that providing a default value doesn't break for non-registered options.
3407
5743.1.16 by Vincent Ladeuil
Allows empty sections and empty section callables.
3408
    def test_get_for_empty_section_callable(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
3409
        conf_stack = config.Stack([lambda: []])
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3410
        self.assertEqual(None, conf_stack.get('foo'))
5743.1.16 by Vincent Ladeuil
Allows empty sections and empty section callables.
3411
5743.1.35 by Vincent Ladeuil
Address some review comments from jelmer and poolie.
3412
    def test_get_for_broken_callable(self):
3413
        # Trying to use and invalid callable raises an exception on first use
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3414
        conf_stack = config.Stack([object])
5743.1.35 by Vincent Ladeuil
Address some review comments from jelmer and poolie.
3415
        self.assertRaises(TypeError, conf_stack.get, 'foo')
3416
3417
6393.3.1 by Vincent Ladeuil
Configuration option value can be overridden by os environ variables
3418
class TestStackWithSimpleStore(tests.TestCase):
3419
3420
    def setUp(self):
3421
        super(TestStackWithSimpleStore, self).setUp()
3422
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3423
        self.registry = config.option_registry
3424
3425
    def get_conf(self, content=None):
3426
        return config.MemoryStack(content)
3427
3428
    def test_override_value_from_env(self):
6523.1.1 by Vincent Ladeuil
Fix some test issues raised by mgz.
3429
        self.overrideEnv('FOO', None)
6393.3.1 by Vincent Ladeuil
Configuration option value can be overridden by os environ variables
3430
        self.registry.register(
3431
            config.Option('foo', default='bar', override_from_env=['FOO']))
3432
        self.overrideEnv('FOO', 'quux')
3433
        # Env variable provides a default taking over the option one
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3434
        conf = self.get_conf(b'foo=store')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3435
        self.assertEqual('quux', conf.get('foo'))
6393.3.1 by Vincent Ladeuil
Configuration option value can be overridden by os environ variables
3436
3437
    def test_first_override_value_from_env_wins(self):
6523.1.1 by Vincent Ladeuil
Fix some test issues raised by mgz.
3438
        self.overrideEnv('NO_VALUE', None)
3439
        self.overrideEnv('FOO', None)
3440
        self.overrideEnv('BAZ', None)
6393.3.1 by Vincent Ladeuil
Configuration option value can be overridden by os environ variables
3441
        self.registry.register(
3442
            config.Option('foo', default='bar',
3443
                          override_from_env=['NO_VALUE', 'FOO', 'BAZ']))
3444
        self.overrideEnv('FOO', 'foo')
3445
        self.overrideEnv('BAZ', 'baz')
3446
        # The first env var set wins
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3447
        conf = self.get_conf(b'foo=store')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3448
        self.assertEqual('foo', conf.get('foo'))
6393.3.1 by Vincent Ladeuil
Configuration option value can be overridden by os environ variables
3449
3450
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3451
class TestMemoryStack(tests.TestCase):
3452
3453
    def test_get(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3454
        conf = config.MemoryStack(b'foo=bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3455
        self.assertEqual('bar', conf.get('foo'))
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3456
3457
    def test_set(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3458
        conf = config.MemoryStack(b'foo=bar')
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3459
        conf.set('foo', 'baz')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3460
        self.assertEqual('baz', conf.get('foo'))
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3461
3462
    def test_no_content(self):
3463
        conf = config.MemoryStack()
3464
        # No content means no loading
3465
        self.assertFalse(conf.store.is_loaded())
6393.1.2 by Vincent Ladeuil
Cannot use ExpectedException as pqm provides only testtools-0.9.8, 0.9.9 needed
3466
        self.assertRaises(NotImplementedError, conf.get, 'foo')
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3467
        # But a content can still be provided
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3468
        conf.store._load_from_string(b'foo=bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3469
        self.assertEqual('bar', conf.get('foo'))
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3470
3471
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3472
class TestStackIterSections(tests.TestCase):
3473
3474
    def test_empty_stack(self):
3475
        conf = config.Stack([])
3476
        sections = list(conf.iter_sections())
3477
        self.assertLength(0, sections)
3478
3479
    def test_empty_store(self):
3480
        store = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3481
        store._load_from_string(b'')
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3482
        conf = config.Stack([store.get_sections])
3483
        sections = list(conf.iter_sections())
3484
        self.assertLength(0, sections)
3485
3486
    def test_simple_store(self):
3487
        store = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3488
        store._load_from_string(b'foo=bar')
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3489
        conf = config.Stack([store.get_sections])
3490
        tuples = list(conf.iter_sections())
3491
        self.assertLength(1, tuples)
3492
        (found_store, found_section) = tuples[0]
3493
        self.assertIs(store, found_store)
3494
3495
    def test_two_stores(self):
3496
        store1 = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3497
        store1._load_from_string(b'foo=bar')
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3498
        store2 = config.IniFileStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3499
        store2._load_from_string(b'bar=qux')
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3500
        conf = config.Stack([store1.get_sections, store2.get_sections])
3501
        tuples = list(conf.iter_sections())
3502
        self.assertLength(2, tuples)
3503
        self.assertIs(store1, tuples[0][0])
3504
        self.assertIs(store2, tuples[1][0])
3505
3506
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3507
class TestStackWithTransport(tests.TestCaseWithTransport):
3508
5743.6.27 by Vincent Ladeuil
Move the test registries to bzrlib.config so plugins will be able to use
3509
    scenarios = [(key, {'get_stack': builder}) for key, builder
3510
                 in config.test_stack_builder_registry.iteritems()]
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3511
3512
5743.11.1 by Vincent Ladeuil
Add a note about config store builders being called several times by some tests.
3513
class TestConcreteStacks(TestStackWithTransport):
3514
3515
    def test_build_stack(self):
3516
        # Just a smoke test to help debug builders
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
3517
        self.get_stack(self)
5743.11.1 by Vincent Ladeuil
Add a note about config store builders being called several times by some tests.
3518
3519
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3520
class TestStackGet(TestStackWithTransport):
3521
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3522
    def setUp(self):
3523
        super(TestStackGet, self).setUp()
3524
        self.conf = self.get_stack(self)
3525
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3526
    def test_get_for_empty_stack(self):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3527
        self.assertEqual(None, self.conf.get('foo'))
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3528
3529
    def test_get_hook(self):
6260.3.2 by Vincent Ladeuil
Only the DEFAULT section is searched for the normal uses of bazaar.conf
3530
        self.conf.set('foo', 'bar')
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3531
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
3532
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3533
        def hook(*args):
3534
            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.
3535
        config.ConfigHooks.install_named_hook('get', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3536
        self.assertLength(0, calls)
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3537
        value = self.conf.get('foo')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3538
        self.assertEqual('bar', value)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3539
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3540
        self.assertEqual((self.conf, 'foo', 'bar'), calls[0])
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3541
3542
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3543
class TestStackGetWithConverter(tests.TestCase):
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3544
3545
    def setUp(self):
3546
        super(TestStackGetWithConverter, self).setUp()
3547
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3548
        self.registry = config.option_registry
6393.1.1 by Vincent Ladeuil
Provides MemoryStack to simplify configuration setup in tests
3549
3550
    def get_conf(self, content=None):
3551
        return config.MemoryStack(content)
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3552
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3553
    def register_bool_option(self, name, default=None, default_from_env=None):
3554
        b = config.Option(name, help='A boolean.',
3555
                          default=default, default_from_env=default_from_env,
3556
                          from_unicode=config.bool_from_store)
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
3557
        self.registry.register(b)
3558
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3559
    def test_get_default_bool_None(self):
3560
        self.register_bool_option('foo')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3561
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3562
        self.assertEqual(None, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3563
3564
    def test_get_default_bool_True(self):
3565
        self.register_bool_option('foo', u'True')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3566
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3567
        self.assertEqual(True, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3568
3569
    def test_get_default_bool_False(self):
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3570
        self.register_bool_option('foo', False)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3571
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3572
        self.assertEqual(False, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3573
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3574
    def test_get_default_bool_False_as_string(self):
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3575
        self.register_bool_option('foo', u'False')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3576
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3577
        self.assertEqual(False, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3578
6091.3.3 by Vincent Ladeuil
Update registered option default values and also convert the default value if the first conversion fails.
3579
    def test_get_default_bool_from_env_converted(self):
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3580
        self.register_bool_option('foo', u'True', default_from_env=['FOO'])
3581
        self.overrideEnv('FOO', 'False')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3582
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3583
        self.assertEqual(False, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3584
6091.3.3 by Vincent Ladeuil
Update registered option default values and also convert the default value if the first conversion fails.
3585
    def test_get_default_bool_when_conversion_fails(self):
3586
        self.register_bool_option('foo', default='True')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3587
        conf = self.get_conf(b'foo=invalid boolean')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3588
        self.assertEqual(True, conf.get('foo'))
6091.3.3 by Vincent Ladeuil
Update registered option default values and also convert the default value if the first conversion fails.
3589
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3590
    def register_integer_option(self, name,
3591
                                default=None, default_from_env=None):
3592
        i = config.Option(name, help='An integer.',
3593
                          default=default, default_from_env=default_from_env,
6059.1.6 by Vincent Ladeuil
Implement integer config options.
3594
                          from_unicode=config.int_from_store)
3595
        self.registry.register(i)
3596
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3597
    def test_get_default_integer_None(self):
3598
        self.register_integer_option('foo')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3599
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3600
        self.assertEqual(None, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3601
3602
    def test_get_default_integer(self):
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3603
        self.register_integer_option('foo', 42)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3604
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3605
        self.assertEqual(42, conf.get('foo'))
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3606
3607
    def test_get_default_integer_as_string(self):
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3608
        self.register_integer_option('foo', u'42')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3609
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3610
        self.assertEqual(42, conf.get('foo'))
6059.1.6 by Vincent Ladeuil
Implement integer config options.
3611
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3612
    def test_get_default_integer_from_env(self):
3613
        self.register_integer_option('foo', default_from_env=['FOO'])
3614
        self.overrideEnv('FOO', '18')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3615
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3616
        self.assertEqual(18, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3617
6091.3.3 by Vincent Ladeuil
Update registered option default values and also convert the default value if the first conversion fails.
3618
    def test_get_default_integer_when_conversion_fails(self):
3619
        self.register_integer_option('foo', default='12')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3620
        conf = self.get_conf(b'foo=invalid integer')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3621
        self.assertEqual(12, conf.get('foo'))
6091.3.3 by Vincent Ladeuil
Update registered option default values and also convert the default value if the first conversion fails.
3622
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3623
    def register_list_option(self, name, default=None, default_from_env=None):
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
3624
        l = config.ListOption(name, help='A list.', default=default,
3625
                              default_from_env=default_from_env)
6059.2.1 by Vincent Ladeuil
Implement list config options.
3626
        self.registry.register(l)
3627
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3628
    def test_get_default_list_None(self):
3629
        self.register_list_option('foo')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3630
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3631
        self.assertEqual(None, conf.get('foo'))
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3632
3633
    def test_get_default_list_empty(self):
3634
        self.register_list_option('foo', '')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3635
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3636
        self.assertEqual([], conf.get('foo'))
6059.2.1 by Vincent Ladeuil
Implement list config options.
3637
6091.3.2 by Vincent Ladeuil
Cleanup now duplicated tests, always convert default value so environment variables can be used for more option types.
3638
    def test_get_default_list_from_env(self):
3639
        self.register_list_option('foo', default_from_env=['FOO'])
3640
        self.overrideEnv('FOO', '')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3641
        conf = self.get_conf(b'')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3642
        self.assertEqual([], conf.get('foo'))
6059.2.1 by Vincent Ladeuil
Implement list config options.
3643
3644
    def test_get_with_list_converter_no_item(self):
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3645
        self.register_list_option('foo', None)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3646
        conf = self.get_conf(b'foo=,')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3647
        self.assertEqual([], conf.get('foo'))
6059.2.1 by Vincent Ladeuil
Implement list config options.
3648
3649
    def test_get_with_list_converter_many_items(self):
6091.3.6 by Vincent Ladeuil
Replace ugly default value declarations with ad-hoc and limited conversion to unicode strings.
3650
        self.register_list_option('foo', None)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3651
        conf = self.get_conf(b'foo=m,o,r,e')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3652
        self.assertEqual(['m', 'o', 'r', 'e'], conf.get('foo'))
6059.2.1 by Vincent Ladeuil
Implement list config options.
3653
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
3654
    def test_get_with_list_converter_embedded_spaces_many_items(self):
3655
        self.register_list_option('foo', None)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3656
        conf = self.get_conf(b'foo=" bar", "baz "')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3657
        self.assertEqual([' bar', 'baz '], conf.get('foo'))
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
3658
3659
    def test_get_with_list_converter_stripped_spaces_many_items(self):
3660
        self.register_list_option('foo', None)
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3661
        conf = self.get_conf(b'foo= bar ,  baz ')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3662
        self.assertEqual(['bar', 'baz'], conf.get('foo'))
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
3663
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3664
6082.5.20 by Vincent Ladeuil
Refactor iter_option_refs out of Stack so it can be reused.
3665
class TestIterOptionRefs(tests.TestCase):
3666
    """iter_option_refs is a bit unusual, document some cases."""
3667
3668
    def assertRefs(self, expected, string):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3669
        self.assertEqual(expected, list(config.iter_option_refs(string)))
6082.5.20 by Vincent Ladeuil
Refactor iter_option_refs out of Stack so it can be reused.
3670
3671
    def test_empty(self):
3672
        self.assertRefs([(False, '')], '')
3673
3674
    def test_no_refs(self):
3675
        self.assertRefs([(False, 'foo bar')], 'foo bar')
3676
3677
    def test_single_ref(self):
3678
        self.assertRefs([(False, ''), (True, '{foo}'), (False, '')], '{foo}')
3679
3680
    def test_broken_ref(self):
3681
        self.assertRefs([(False, '{foo')], '{foo')
3682
3683
    def test_embedded_ref(self):
3684
        self.assertRefs([(False, '{'), (True, '{foo}'), (False, '}')],
3685
                        '{{foo}}')
3686
3687
    def test_two_refs(self):
3688
        self.assertRefs([(False, ''), (True, '{foo}'),
3689
                         (False, ''), (True, '{bar}'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
3690
                         (False, ''), ],
6082.5.20 by Vincent Ladeuil
Refactor iter_option_refs out of Stack so it can be reused.
3691
                        '{foo}{bar}')
3692
6351.1.1 by Vincent Ladeuil
Don't accept \n as part of a config option reference
3693
    def test_newline_in_refs_are_not_matched(self):
3694
        self.assertRefs([(False, '{\nxx}{xx\n}{{\n}}')], '{\nxx}{xx\n}{{\n}}')
3695
6082.5.20 by Vincent Ladeuil
Refactor iter_option_refs out of Stack so it can be reused.
3696
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3697
class TestStackExpandOptions(tests.TestCaseWithTransport):
3698
3699
    def setUp(self):
3700
        super(TestStackExpandOptions, self).setUp()
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3701
        self.overrideAttr(config, 'option_registry', config.OptionRegistry())
3702
        self.registry = config.option_registry
6404.6.1 by Vincent Ladeuil
Tests passing for a first rough version of a cached branch config store. The changes here are too invasive and several parallel proposals have been made.
3703
        store = config.TransportIniFileStore(self.get_transport(), 'foo.conf')
3704
        self.conf = config.Stack([store.get_sections], store)
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3705
3706
    def assertExpansion(self, expected, string, env=None):
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3707
        self.assertEqual(expected, self.conf.expand_options(string, env))
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3708
3709
    def test_no_expansion(self):
3710
        self.assertExpansion('foo', 'foo')
3711
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3712
    def test_expand_default_value(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3713
        self.conf.store._load_from_string(b'bar=baz')
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3714
        self.registry.register(config.Option('foo', default=u'{bar}'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3715
        self.assertEqual('baz', self.conf.get('foo', expand=True))
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3716
3717
    def test_expand_default_from_env(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3718
        self.conf.store._load_from_string(b'bar=baz')
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3719
        self.registry.register(config.Option('foo', default_from_env=['FOO']))
3720
        self.overrideEnv('FOO', '{bar}')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3721
        self.assertEqual('baz', self.conf.get('foo', expand=True))
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3722
3723
    def test_expand_default_on_failed_conversion(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3724
        self.conf.store._load_from_string(b'baz=bogus\nbar=42\nfoo={baz}')
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3725
        self.registry.register(
3726
            config.Option('foo', default=u'{bar}',
3727
                          from_unicode=config.int_from_store))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3728
        self.assertEqual(42, self.conf.get('foo', expand=True))
6082.5.7 by Vincent Ladeuil
If conversion fails, the default value still needs to be expanded (if applicable).
3729
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3730
    def test_env_adding_options(self):
3731
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3732
3733
    def test_env_overriding_options(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3734
        self.conf.store._load_from_string(b'foo=baz')
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3735
        self.assertExpansion('bar', '{foo}', {'foo': 'bar'})
3736
3737
    def test_simple_ref(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3738
        self.conf.store._load_from_string(b'foo=xxx')
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3739
        self.assertExpansion('xxx', '{foo}')
3740
3741
    def test_unknown_ref(self):
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
3742
        self.assertRaises(config.ExpandingUnknownOption,
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3743
                          self.conf.expand_options, '{foo}')
3744
6587.2.2 by Vincent Ladeuil
Stricter checks on configuration option names
3745
    def test_illegal_def_is_ignored(self):
3746
        self.assertExpansion('{1,2}', '{1,2}')
3747
        self.assertExpansion('{ }', '{ }')
3748
        self.assertExpansion('${Foo,f}', '${Foo,f}')
3749
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3750
    def test_indirect_ref(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3751
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3752
foo=xxx
3753
bar={foo}
3754
''')
3755
        self.assertExpansion('xxx', '{bar}')
3756
3757
    def test_embedded_ref(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3758
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3759
foo=xxx
3760
bar=foo
3761
''')
3762
        self.assertExpansion('xxx', '{{bar}}')
3763
3764
    def test_simple_loop(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3765
        self.conf.store._load_from_string(b'foo={foo}')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
3766
        self.assertRaises(config.OptionExpansionLoop,
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3767
                          self.conf.expand_options, '{foo}')
3768
3769
    def test_indirect_loop(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3770
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3771
foo={bar}
3772
bar={baz}
3773
baz={foo}''')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
3774
        e = self.assertRaises(config.OptionExpansionLoop,
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3775
                              self.conf.expand_options, '{foo}')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3776
        self.assertEqual('foo->bar->baz', e.refs)
3777
        self.assertEqual('{foo}', e.string)
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3778
3779
    def test_list(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3780
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3781
foo=start
3782
bar=middle
3783
baz=end
3784
list={foo},{bar},{baz}
3785
''')
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
3786
        self.registry.register(
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
3787
            config.ListOption('list'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3788
        self.assertEqual(['start', 'middle', 'end'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3789
                         self.conf.get('list', expand=True))
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3790
3791
    def test_cascading_list(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3792
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3793
foo=start,{bar}
3794
bar=middle,{baz}
3795
baz=end
3796
list={foo}
3797
''')
6466.1.3 by Vincent Ladeuil
Values should never be converted during expansion.
3798
        self.registry.register(config.ListOption('list'))
3799
        # Register an intermediate option as a list to ensure no conversion
6466.1.4 by Vincent Ladeuil
Fix typo and add tests.
3800
        # happen while expanding. Conversion should only occur for the original
6466.1.3 by Vincent Ladeuil
Values should never be converted during expansion.
3801
        # option ('list' here).
3802
        self.registry.register(config.ListOption('baz'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3803
        self.assertEqual(['start', 'middle', 'end'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3804
                         self.conf.get('list', expand=True))
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3805
3806
    def test_pathologically_hidden_list(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3807
        self.conf.store._load_from_string(b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3808
foo=bin
3809
bar=go
3810
start={foo
3811
middle=},{
3812
end=bar}
3813
hidden={start}{middle}{end}
3814
''')
6082.5.13 by Vincent Ladeuil
Fix typos.
3815
        # What matters is what the registration says, the conversion happens
6082.5.11 by Vincent Ladeuil
Disable list_values for config.Store, using a dedicated configobj object to trigger the string -> list conversion on-demand (via the option registration) only.
3816
        # only after all expansions have been performed
6385.1.1 by Vincent Ladeuil
Stores allow Stacks to control when values are quoted/unquoted
3817
        self.registry.register(config.ListOption('hidden'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3818
        self.assertEqual(['bin', 'go'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
3819
                         self.conf.get('hidden', expand=True))
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3820
3821
3822
class TestStackCrossSectionsExpand(tests.TestCaseWithTransport):
3823
3824
    def setUp(self):
3825
        super(TestStackCrossSectionsExpand, self).setUp()
3826
3827
    def get_config(self, location, string):
3828
        if string is None:
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3829
            string = b''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3830
        # Since we don't save the config we won't strictly require to inherit
3831
        # from TestCaseInTempDir, but an error occurs so quickly...
3832
        c = config.LocationStack(location)
3833
        c.store._load_from_string(string)
3834
        return c
3835
3836
    def test_dont_cross_unrelated_section(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3837
        c = self.get_config('/another/branch/path', b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3838
[/one/branch/path]
3839
foo = hello
3840
bar = {foo}/2
3841
3842
[/another/branch/path]
3843
bar = {foo}/2
3844
''')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
3845
        self.assertRaises(config.ExpandingUnknownOption,
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3846
                          c.get, 'bar', expand=True)
3847
3848
    def test_cross_related_sections(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3849
        c = self.get_config('/project/branch/path', b'''
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3850
[/project]
3851
foo = qu
3852
3853
[/project/branch/path]
3854
bar = {foo}ux
3855
''')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3856
        self.assertEqual('quux', c.get('bar', expand=True))
6082.5.2 by Vincent Ladeuil
Cargo-cult the config option expansion implementation with tweaks from the old to the new config design.
3857
3858
6082.5.19 by Vincent Ladeuil
Bah, cross stores expansion already works of course, tests added.
3859
class TestStackCrossStoresExpand(tests.TestCaseWithTransport):
3860
3861
    def test_cross_global_locations(self):
3862
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3863
        l_store._load_from_string(b'''
6082.5.19 by Vincent Ladeuil
Bah, cross stores expansion already works of course, tests added.
3864
[/branch]
3865
lfoo = loc-foo
3866
lbar = {gbar}
3867
''')
3868
        l_store.save()
3869
        g_store = config.GlobalStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3870
        g_store._load_from_string(b'''
6082.5.19 by Vincent Ladeuil
Bah, cross stores expansion already works of course, tests added.
3871
[DEFAULT]
3872
gfoo = {lfoo}
3873
gbar = glob-bar
3874
''')
3875
        g_store.save()
3876
        stack = config.LocationStack('/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3877
        self.assertEqual('glob-bar', stack.get('lbar', expand=True))
3878
        self.assertEqual('loc-foo', stack.get('gfoo', expand=True))
6082.5.19 by Vincent Ladeuil
Bah, cross stores expansion already works of course, tests added.
3879
3880
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3881
class TestStackExpandSectionLocals(tests.TestCaseWithTransport):
3882
6082.5.25 by Vincent Ladeuil
Add ``basename`` as a section local option
3883
    def test_expand_locals_empty(self):
3884
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3885
        l_store._load_from_string(b'''
6082.5.25 by Vincent Ladeuil
Add ``basename`` as a section local option
3886
[/home/user/project]
3887
base = {basename}
3888
rel = {relpath}
3889
''')
3890
        l_store.save()
3891
        stack = config.LocationStack('/home/user/project/')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3892
        self.assertEqual('', stack.get('base', expand=True))
3893
        self.assertEqual('', stack.get('rel', expand=True))
6082.5.25 by Vincent Ladeuil
Add ``basename`` as a section local option
3894
3895
    def test_expand_basename_locally(self):
3896
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3897
        l_store._load_from_string(b'''
6082.5.25 by Vincent Ladeuil
Add ``basename`` as a section local option
3898
[/home/user/project]
3899
bfoo = {basename}
3900
''')
3901
        l_store.save()
3902
        stack = config.LocationStack('/home/user/project/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3903
        self.assertEqual('branch', stack.get('bfoo', expand=True))
6082.5.25 by Vincent Ladeuil
Add ``basename`` as a section local option
3904
6082.5.28 by Vincent Ladeuil
Add a test to better expose the feature
3905
    def test_expand_basename_locally_longer_path(self):
3906
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3907
        l_store._load_from_string(b'''
6082.5.28 by Vincent Ladeuil
Add a test to better expose the feature
3908
[/home/user]
3909
bfoo = {basename}
3910
''')
3911
        l_store.save()
3912
        stack = config.LocationStack('/home/user/project/dir/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3913
        self.assertEqual('branch', stack.get('bfoo', expand=True))
6082.5.28 by Vincent Ladeuil
Add a test to better expose the feature
3914
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3915
    def test_expand_relpath_locally(self):
3916
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3917
        l_store._load_from_string(b'''
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3918
[/home/user/project]
3919
lfoo = loc-foo/{relpath}
3920
''')
3921
        l_store.save()
3922
        stack = config.LocationStack('/home/user/project/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3923
        self.assertEqual('loc-foo/branch', stack.get('lfoo', expand=True))
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3924
3925
    def test_expand_relpath_unknonw_in_global(self):
3926
        g_store = config.GlobalStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3927
        g_store._load_from_string(b'''
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3928
[DEFAULT]
3929
gfoo = {relpath}
3930
''')
3931
        g_store.save()
3932
        stack = config.LocationStack('/home/user/project/branch')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
3933
        self.assertRaises(config.ExpandingUnknownOption,
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3934
                          stack.get, 'gfoo', expand=True)
3935
3936
    def test_expand_local_option_locally(self):
3937
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3938
        l_store._load_from_string(b'''
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3939
[/home/user/project]
3940
lfoo = loc-foo/{relpath}
3941
lbar = {gbar}
3942
''')
3943
        l_store.save()
3944
        g_store = config.GlobalStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3945
        g_store._load_from_string(b'''
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3946
[DEFAULT]
3947
gfoo = {lfoo}
3948
gbar = glob-bar
3949
''')
3950
        g_store.save()
3951
        stack = config.LocationStack('/home/user/project/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3952
        self.assertEqual('glob-bar', stack.get('lbar', expand=True))
3953
        self.assertEqual('loc-foo/branch', stack.get('gfoo', expand=True))
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3954
3955
    def test_locals_dont_leak(self):
3956
        """Make sure we chose the right local in presence of several sections.
3957
        """
3958
        l_store = config.LocationStore()
6973.10.4 by Jelmer Vernooij
Update python3.passing.
3959
        l_store._load_from_string(b'''
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3960
[/home/user]
3961
lfoo = loc-foo/{relpath}
3962
[/home/user/project]
3963
lfoo = loc-foo/{relpath}
3964
''')
3965
        l_store.save()
3966
        stack = config.LocationStack('/home/user/project/branch')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3967
        self.assertEqual('loc-foo/branch', stack.get('lfoo', expand=True))
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3968
        stack = config.LocationStack('/home/user/bar/baz')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3969
        self.assertEqual('loc-foo/bar/baz', stack.get('lfoo', expand=True))
6082.5.21 by Vincent Ladeuil
Implement 'relpath' as a section locally expanded option.
3970
3971
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3972
class TestStackSet(TestStackWithTransport):
3973
5743.1.7 by Vincent Ladeuil
Simple set implementation.
3974
    def test_simple_set(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3975
        conf = self.get_stack(self)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3976
        self.assertEqual(None, conf.get('foo'))
5743.1.7 by Vincent Ladeuil
Simple set implementation.
3977
        conf.set('foo', 'baz')
3978
        # Did we get it back ?
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3979
        self.assertEqual('baz', conf.get('foo'))
5743.1.7 by Vincent Ladeuil
Simple set implementation.
3980
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.
3981
    def test_set_creates_a_new_section(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3982
        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.
3983
        conf.set('foo', 'baz')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3984
        self.assertEqual, '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.
3985
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3986
    def test_set_hook(self):
3987
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
3988
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3989
        def hook(*args):
3990
            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.
3991
        config.ConfigHooks.install_named_hook('set', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3992
        self.assertLength(0, calls)
3993
        conf = self.get_stack(self)
3994
        conf.set('foo', 'bar')
3995
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
3996
        self.assertEqual((conf, 'foo', 'bar'), calls[0])
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
3997
5743.1.7 by Vincent Ladeuil
Simple set implementation.
3998
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
3999
class TestStackRemove(TestStackWithTransport):
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
4000
4001
    def test_remove_existing(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
4002
        conf = self.get_stack(self)
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
4003
        conf.set('foo', 'bar')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4004
        self.assertEqual('bar', conf.get('foo'))
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
4005
        conf.remove('foo')
4006
        # Did we get it back ?
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4007
        self.assertEqual(None, conf.get('foo'))
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
4008
4009
    def test_remove_unknown(self):
5743.6.14 by Vincent Ladeuil
Parametrize the Stack tests.
4010
        conf = self.get_stack(self)
5743.1.15 by Vincent Ladeuil
Test and implement ConfigStack.remove.
4011
        self.assertRaises(KeyError, conf.remove, 'I_do_not_exist')
4012
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
4013
    def test_remove_hook(self):
4014
        calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
4015
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
4016
        def hook(*args):
4017
            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.
4018
        config.ConfigHooks.install_named_hook('remove', hook, None)
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
4019
        self.assertLength(0, calls)
4020
        conf = self.get_stack(self)
6191.3.1 by Vincent Ladeuil
Fix some issues where the config tests were either making a bad use of to the parametrization or asssuming implementation details which are not guaranteed.
4021
        conf.set('foo', 'bar')
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
4022
        conf.remove('foo')
4023
        self.assertLength(1, calls)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4024
        self.assertEqual((conf, 'foo'), calls[0])
5743.8.6 by Vincent Ladeuil
Add hooks for config stacks.
4025
5743.6.1 by Vincent Ladeuil
Outline concrete stacks and basic smoke tests.
4026
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
4027
class TestConfigGetOptions(tests.TestCaseWithTransport, TestOptionsMixin):
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4028
4029
    def setUp(self):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
4030
        super(TestConfigGetOptions, self).setUp()
4031
        create_configs(self)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4032
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4033
    def test_no_variable(self):
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4034
        # Using branch should query branch, locations and breezy
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4035
        self.assertOptions([], self.branch_config)
4036
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4037
    def test_option_in_breezy(self):
4038
        self.breezy_config.set_user_option('file', 'breezy')
4039
        self.assertOptions([('file', 'breezy', 'DEFAULT', 'breezy')],
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
4040
                           self.breezy_config)
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4041
4042
    def test_option_in_locations(self):
4043
        self.locations_config.set_user_option('file', 'locations')
4044
        self.assertOptions(
4045
            [('file', 'locations', self.tree.basedir, 'locations')],
4046
            self.locations_config)
4047
4048
    def test_option_in_branch(self):
4049
        self.branch_config.set_user_option('file', 'branch')
4050
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch')],
4051
                           self.branch_config)
4052
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4053
    def test_option_in_breezy_and_branch(self):
4054
        self.breezy_config.set_user_option('file', 'breezy')
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4055
        self.branch_config.set_user_option('file', 'branch')
4056
        self.assertOptions([('file', 'branch', 'DEFAULT', 'branch'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4057
                            ('file', 'breezy', 'DEFAULT', 'breezy'), ],
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4058
                           self.branch_config)
4059
4060
    def test_option_in_branch_and_locations(self):
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4061
        # Hmm, locations override branch :-/
4062
        self.locations_config.set_user_option('file', 'locations')
4063
        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.
4064
        self.assertOptions(
4065
            [('file', 'locations', self.tree.basedir, 'locations'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4066
             ('file', 'branch', 'DEFAULT', 'branch'), ],
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4067
            self.branch_config)
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4068
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4069
    def test_option_in_breezy_locations_and_branch(self):
4070
        self.breezy_config.set_user_option('file', 'breezy')
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4071
        self.locations_config.set_user_option('file', 'locations')
4072
        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.
4073
        self.assertOptions(
4074
            [('file', 'locations', self.tree.basedir, 'locations'),
4075
             ('file', 'branch', 'DEFAULT', 'branch'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4076
             ('file', 'breezy', 'DEFAULT', 'breezy'), ],
5447.4.3 by Vincent Ladeuil
Simplify code and design by only defining get_options() where relevant.
4077
            self.branch_config)
5447.4.1 by Vincent Ladeuil
Implement config.get_options_matching_regexp.
4078
4079
5533.2.1 by Vincent Ladeuil
``bzr config`` properly displays list values
4080
class TestConfigRemoveOption(tests.TestCaseWithTransport, TestOptionsMixin):
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
4081
4082
    def setUp(self):
4083
        super(TestConfigRemoveOption, self).setUp()
4084
        create_configs_with_file_option(self)
4085
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
4086
    def test_remove_in_locations(self):
4087
        self.locations_config.remove_user_option('file', self.tree.basedir)
4088
        self.assertOptions(
4089
            [('file', 'branch', 'DEFAULT', 'branch'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4090
             ('file', 'breezy', 'DEFAULT', 'breezy'), ],
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
4091
            self.branch_config)
4092
4093
    def test_remove_in_branch(self):
4094
        self.branch_config.remove_user_option('file')
4095
        self.assertOptions(
4096
            [('file', 'locations', self.tree.basedir, 'locations'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4097
             ('file', 'breezy', 'DEFAULT', 'breezy'), ],
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
4098
            self.branch_config)
4099
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4100
    def test_remove_in_breezy(self):
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
4101
        self.breezy_config.remove_user_option('file')
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
4102
        self.assertOptions(
4103
            [('file', 'locations', self.tree.basedir, 'locations'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4104
             ('file', 'branch', 'DEFAULT', 'branch'), ],
5447.4.11 by Vincent Ladeuil
Implement ``bzr config --remove <option>``.
4105
            self.branch_config)
4106
5447.4.7 by Vincent Ladeuil
Check error message if the test is checking for errors or we have unexpected success for wrong errors.
4107
5447.4.6 by Vincent Ladeuil
Start defining fixtures but we still have an unexpected sucessful test.
4108
class TestConfigGetSections(tests.TestCaseWithTransport):
4109
4110
    def setUp(self):
4111
        super(TestConfigGetSections, self).setUp()
4112
        create_configs(self)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4113
4114
    def assertSectionNames(self, expected, conf, name=None):
4115
        """Check which sections are returned for a given config.
4116
4117
        If fallback configurations exist their sections can be included.
4118
4119
        :param expected: A list of section names.
4120
4121
        :param conf: The configuration that will be queried.
4122
4123
        :param name: An optional section name that will be passed to
4124
            get_sections().
4125
        """
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.
4126
        sections = list(conf._get_sections(name))
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4127
        self.assertLength(len(expected), sections)
6587.2.1 by Vincent Ladeuil
Fix pep8 warnings: unused import, unused variables, shadowing variables.
4128
        self.assertEqual(expected, [n for n, _, _ in sections])
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4129
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4130
    def test_breezy_default_section(self):
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
4131
        self.assertSectionNames(['DEFAULT'], self.breezy_config)
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4132
4133
    def test_locations_default_section(self):
4134
        # No sections are defined in an empty file
4135
        self.assertSectionNames([], self.locations_config)
4136
4137
    def test_locations_named_section(self):
4138
        self.locations_config.set_user_option('file', 'locations')
4139
        self.assertSectionNames([self.tree.basedir], self.locations_config)
4140
4141
    def test_locations_matching_sections(self):
4142
        loc_config = self.locations_config
4143
        loc_config.set_user_option('file', 'locations')
4144
        # We need to cheat a bit here to create an option in sections above and
4145
        # below the 'location' one.
4146
        parser = loc_config._get_parser()
4147
        # locations.cong deals with '/' ignoring native os.sep
4148
        location_names = self.tree.basedir.split('/')
4149
        parent = '/'.join(location_names[:-1])
4150
        child = '/'.join(location_names + ['child'])
4151
        parser[parent] = {}
4152
        parser[parent]['file'] = 'parent'
4153
        parser[child] = {}
4154
        parser[child]['file'] = 'child'
4155
        self.assertSectionNames([self.tree.basedir, parent], loc_config)
4156
4157
    def test_branch_data_default_section(self):
4158
        self.assertSectionNames([None],
4159
                                self.branch_config._get_branch_data_config())
4160
4161
    def test_branch_default_sections(self):
4162
        # No sections are defined in an empty locations file
4163
        self.assertSectionNames([None, 'DEFAULT'],
4164
                                self.branch_config)
4165
        # Unless we define an option
4166
        self.branch_config._get_location_config().set_user_option(
4167
            'file', 'locations')
4168
        self.assertSectionNames([self.tree.basedir, None, 'DEFAULT'],
4169
                                self.branch_config)
4170
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4171
    def test_breezy_named_section(self):
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4172
        # We need to cheat as the API doesn't give direct access to sections
4173
        # other than DEFAULT.
6741 by Jelmer Vernooij
Merge lp:~jelmer/brz/breezy-conf
4174
        self.breezy_config.set_alias('breezy', 'bzr')
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
4175
        self.assertSectionNames(['ALIASES'], self.breezy_config, 'ALIASES')
5447.4.4 by Vincent Ladeuil
Implement config.get_sections() to clarify how sections can be used.
4176
4177
6499.3.6 by Vincent Ladeuil
Add test to ensure local config files are shared.
4178
class TestSharedStores(tests.TestCaseInTempDir):
4179
6740.1.1 by Jelmer Vernooij
Rename bazaar.conf to breezy.conf.
4180
    def test_breezy_conf_shared(self):
6499.3.6 by Vincent Ladeuil
Add test to ensure local config files are shared.
4181
        g1 = config.GlobalStack()
4182
        g2 = config.GlobalStack()
4183
        # The two stacks share the same store
4184
        self.assertIs(g1.store, g2.store)
4185
4186
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4187
class TestAuthenticationConfigFilePermissions(tests.TestCaseInTempDir):
4188
    """Test warning for permissions of authentication.conf."""
4189
4190
    def setUp(self):
4191
        super(TestAuthenticationConfigFilePermissions, self).setUp()
4192
        self.path = osutils.pathjoin(self.test_dir, 'authentication.conf')
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4193
        with open(self.path, 'wb') as f:
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4194
            f.write(b"""[broken]
4195
scheme=ftp
4196
user=joe
4197
port=port # Error: Not an int
4198
""")
4199
        self.overrideAttr(config, 'authentication_config_filename',
7143.15.2 by Jelmer Vernooij
Run autopep8.
4200
                          lambda: self.path)
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4201
        osutils.chmod_if_possible(self.path, 0o755)
4202
4203
    def test_check_warning(self):
4204
        conf = config.AuthenticationConfig()
4205
        self.assertEqual(conf._filename, self.path)
4206
        self.assertContainsRe(self.get_log(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4207
                              'Saved passwords may be accessible by other users.')
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4208
4209
    def test_check_suppressed_warning(self):
4210
        global_config = config.GlobalConfig()
4211
        global_config.set_user_option('suppress_warnings',
7143.15.2 by Jelmer Vernooij
Run autopep8.
4212
                                      'insecure_permissions')
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4213
        conf = config.AuthenticationConfig()
4214
        self.assertEqual(conf._filename, self.path)
4215
        self.assertNotContainsRe(self.get_log(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
4216
                                 'Saved passwords may be accessible by other users.')
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4217
4218
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
4219
class TestAuthenticationConfigFile(tests.TestCase):
2900.2.14 by Vincent Ladeuil
More tests.
4220
    """Test the authentication.conf file matching"""
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4221
4222
    def _got_user_passwd(self, expected_user, expected_password,
4223
                         config, *args, **kwargs):
4224
        credentials = config.get_credentials(*args, **kwargs)
4225
        if credentials is None:
4226
            user = None
4227
            password = None
4228
        else:
4229
            user = credentials['user']
4230
            password = credentials['password']
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4231
        self.assertEqual(expected_user, user)
4232
        self.assertEqual(expected_password, password)
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4233
2978.5.1 by John Arbash Meinel
Fix bug #162494, 'bzr register-branch' needs proper auth handling.
4234
    def test_empty_config(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4235
        conf = config.AuthenticationConfig(_file=BytesIO())
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4236
        self.assertEqual({}, conf._get_config())
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4237
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
4238
5987.1.2 by Vincent Ladeuil
Reproduce bug #502060, bug #688677 and bug #792246.
4239
    def test_non_utf8_config(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4240
        conf = config.AuthenticationConfig(_file=BytesIO(b'foo = bar\xff'))
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
4241
        self.assertRaises(config.ConfigContentError, conf._get_config)
6059.1.1 by Vincent Ladeuil
Implement from_unicode to convert config option values from store.
4242
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
4243
    def test_missing_auth_section_header(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4244
        conf = config.AuthenticationConfig(_file=BytesIO(b'foo = bar'))
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
4245
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
4246
4247
    def test_auth_section_header_not_closed(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4248
        conf = config.AuthenticationConfig(_file=BytesIO(b'[DEF'))
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
4249
        self.assertRaises(config.ParseConfigError, conf._get_config)
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
4250
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
4251
    def test_auth_value_not_boolean(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4252
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4253
[broken]
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
4254
scheme=ftp
4255
user=joe
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
4256
verify_certificates=askme # Error: Not a boolean
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
4257
"""))
4258
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
3418.2.1 by Vincent Ladeuil
Fix #217650 by catching declarations outside sections.
4259
4260
    def test_auth_value_not_int(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4261
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4262
[broken]
2900.2.22 by Vincent Ladeuil
Polishing.
4263
scheme=ftp
4264
user=joe
4265
port=port # Error: Not an int
4266
"""))
4267
        self.assertRaises(ValueError, conf.get_credentials, 'ftp', 'foo.net')
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4268
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
4269
    def test_unknown_password_encoding(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4270
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4271
[broken]
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
4272
scheme=ftp
4273
user=joe
4274
password_encoding=unknown
4275
"""))
4276
        self.assertRaises(ValueError, conf.get_password,
4277
                          'ftp', 'foo.net', 'joe')
4278
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4279
    def test_credentials_for_scheme_host(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4280
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4281
# Identity on foo.net
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4282
[ftp definition]
4283
scheme=ftp
4284
host=foo.net
4285
user=joe
4286
password=secret-pass
4287
"""))
4288
        # Basic matching
4289
        self._got_user_passwd('joe', 'secret-pass', conf, 'ftp', 'foo.net')
4290
        # different scheme
4291
        self._got_user_passwd(None, None, conf, 'http', 'foo.net')
4292
        # different host
4293
        self._got_user_passwd(None, None, conf, 'ftp', 'bar.net')
4294
4295
    def test_credentials_for_host_port(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4296
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4297
# Identity on foo.net
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4298
[ftp definition]
4299
scheme=ftp
4300
port=10021
4301
host=foo.net
4302
user=joe
4303
password=secret-pass
4304
"""))
4305
        # No port
4306
        self._got_user_passwd('joe', 'secret-pass',
4307
                              conf, 'ftp', 'foo.net', port=10021)
4308
        # different port
4309
        self._got_user_passwd(None, None, conf, 'ftp', 'foo.net')
4310
4311
    def test_for_matching_host(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4312
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4313
# Identity on foo.net
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4314
[sourceforge]
4315
scheme=bzr
4316
host=bzr.sf.net
4317
user=joe
4318
password=joepass
4319
[sourceforge domain]
4320
scheme=bzr
4321
host=.bzr.sf.net
4322
user=georges
4323
password=bendover
4324
"""))
4325
        # matching domain
4326
        self._got_user_passwd('georges', 'bendover',
4327
                              conf, 'bzr', 'foo.bzr.sf.net')
4328
        # phishing attempt
4329
        self._got_user_passwd(None, None,
4330
                              conf, 'bzr', 'bbzr.sf.net')
4331
4332
    def test_for_matching_host_None(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4333
        conf = config.AuthenticationConfig(_file=BytesIO(b"""\
4334
# Identity on foo.net
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4335
[catchup bzr]
4336
scheme=bzr
4337
user=joe
4338
password=joepass
4339
[DEFAULT]
4340
user=georges
4341
password=bendover
4342
"""))
4343
        # match no host
4344
        self._got_user_passwd('joe', 'joepass',
4345
                              conf, 'bzr', 'quux.net')
4346
        # no host but different scheme
4347
        self._got_user_passwd('georges', 'bendover',
4348
                              conf, 'ftp', 'quux.net')
4349
4350
    def test_credentials_for_path(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4351
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4352
[http dir1]
4353
scheme=http
4354
host=bar.org
4355
path=/dir1
4356
user=jim
4357
password=jimpass
4358
[http dir2]
4359
scheme=http
4360
host=bar.org
4361
path=/dir2
4362
user=georges
4363
password=bendover
4364
"""))
4365
        # no path no dice
4366
        self._got_user_passwd(None, None,
4367
                              conf, 'http', host='bar.org', path='/dir3')
4368
        # matching path
4369
        self._got_user_passwd('georges', 'bendover',
4370
                              conf, 'http', host='bar.org', path='/dir2')
4371
        # matching subdir
4372
        self._got_user_passwd('jim', 'jimpass',
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
4373
                              conf, 'http', host='bar.org', path='/dir1/subdir')
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4374
4375
    def test_credentials_for_user(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4376
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4377
[with user]
4378
scheme=http
4379
host=bar.org
4380
user=jim
4381
password=jimpass
4382
"""))
4383
        # Get user
4384
        self._got_user_passwd('jim', 'jimpass',
4385
                              conf, 'http', 'bar.org')
4386
        # Get same user
4387
        self._got_user_passwd('jim', 'jimpass',
4388
                              conf, 'http', 'bar.org', user='jim')
4389
        # Don't get a different user if one is specified
4390
        self._got_user_passwd(None, None,
4391
                              conf, 'http', 'bar.org', user='georges')
4392
3418.4.1 by Vincent Ladeuil
Reproduce bug 199440.
4393
    def test_credentials_for_user_without_password(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4394
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
3418.4.1 by Vincent Ladeuil
Reproduce bug 199440.
4395
[without password]
4396
scheme=http
4397
host=bar.org
4398
user=jim
4399
"""))
4400
        # Get user but no password
4401
        self._got_user_passwd('jim', None,
4402
                              conf, 'http', 'bar.org')
4403
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4404
    def test_verify_certificates(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4405
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4406
[self-signed]
4407
scheme=https
4408
host=bar.org
4409
user=jim
4410
password=jimpass
4411
verify_certificates=False
4412
[normal]
4413
scheme=https
4414
host=foo.net
4415
user=georges
4416
password=bendover
4417
"""))
4418
        credentials = conf.get_credentials('https', 'bar.org')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4419
        self.assertEqual(False, credentials.get('verify_certificates'))
2900.2.3 by Vincent Ladeuil
Credentials matching implementation.
4420
        credentials = conf.get_credentials('https', 'foo.net')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4421
        self.assertEqual(True, credentials.get('verify_certificates'))
2900.2.4 by Vincent Ladeuil
Cosmetic changes.
4422
3777.1.10 by Aaron Bentley
Ensure credentials are stored
4423
4424
class TestAuthenticationStorage(tests.TestCaseInTempDir):
4425
3777.1.8 by Aaron Bentley
Commit work-in-progress
4426
    def test_set_credentials(self):
3777.1.10 by Aaron Bentley
Ensure credentials are stored
4427
        conf = config.AuthenticationConfig()
3777.3.2 by Aaron Bentley
Reverse order of scheme and password
4428
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password',
7143.15.2 by Jelmer Vernooij
Run autopep8.
4429
                             99, path='/foo', verify_certificates=False, realm='realm')
3777.1.8 by Aaron Bentley
Commit work-in-progress
4430
        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
4431
                                           port=99, path='/foo',
4432
                                           realm='realm')
3777.1.10 by Aaron Bentley
Ensure credentials are stored
4433
        CREDENTIALS = {'name': 'name', 'user': 'user', 'password': 'password',
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4434
                       'verify_certificates': False, 'scheme': 'scheme',
4435
                       'host': 'host', 'port': 99, 'path': '/foo',
4107.1.8 by Jean-Francois Roy
Updated test_config to account for the new credentials keys.
4436
                       'realm': 'realm'}
3777.1.10 by Aaron Bentley
Ensure credentials are stored
4437
        self.assertEqual(CREDENTIALS, credentials)
4438
        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
4439
            host='host', scheme='scheme', port=99, path='/foo', realm='realm')
3777.1.10 by Aaron Bentley
Ensure credentials are stored
4440
        self.assertEqual(CREDENTIALS, credentials_from_disk)
3777.1.8 by Aaron Bentley
Commit work-in-progress
4441
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
4442
    def test_reset_credentials_different_name(self):
4443
        conf = config.AuthenticationConfig()
3777.3.2 by Aaron Bentley
Reverse order of scheme and password
4444
        conf.set_credentials('name', 'host', 'user', 'scheme', 'password'),
4445
        conf.set_credentials('name2', 'host', 'user2', 'scheme', 'password'),
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
4446
        self.assertIs(None, conf._get_config().get('name'))
4447
        credentials = conf.get_credentials(host='host', scheme='scheme')
4448
        CREDENTIALS = {'name': 'name2', 'user': 'user2', 'password':
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4449
                       'password', 'verify_certificates': True,
4450
                       'scheme': 'scheme', 'host': 'host', 'port': None,
4107.1.8 by Jean-Francois Roy
Updated test_config to account for the new credentials keys.
4451
                       'path': None, 'realm': None}
3777.1.11 by Aaron Bentley
Ensure changed-name updates clear old values
4452
        self.assertEqual(CREDENTIALS, credentials)
4453
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
4454
6690.1.1 by Jelmer Vernooij
Create authentication.conf in a way that it is only readable to the user.
4455
class TestAuthenticationConfig(tests.TestCaseInTempDir):
2900.2.14 by Vincent Ladeuil
More tests.
4456
    """Test AuthenticationConfig behaviour"""
4457
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
4458
    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.
4459
                                       host=None, port=None, realm=None,
4460
                                       path=None):
2900.2.14 by Vincent Ladeuil
More tests.
4461
        if host is None:
4462
            host = 'bar.org'
4463
        user, password = 'jim', 'precious'
4464
        expected_prompt = expected_prompt_format % {
4465
            'scheme': scheme, 'host': host, 'port': port,
4466
            'user': user, 'realm': realm}
4467
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4468
        ui.ui_factory = tests.TestUIFactory(stdin=password + '\n')
2900.2.14 by Vincent Ladeuil
More tests.
4469
        # We use an empty conf so that the user is always prompted
4470
        conf = config.AuthenticationConfig()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4471
        self.assertEqual(password,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4472
                         conf.get_password(scheme, host, user, port=port,
4473
                                           realm=realm, path=path))
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4474
        self.assertEqual(expected_prompt, ui.ui_factory.stderr.getvalue())
4475
        self.assertEqual('', ui.ui_factory.stdout.getvalue())
2900.2.14 by Vincent Ladeuil
More tests.
4476
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
4477
    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.
4478
                                       host=None, port=None, realm=None,
4479
                                       path=None):
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
4480
        if host is None:
4481
            host = 'bar.org'
4482
        username = 'jim'
4483
        expected_prompt = expected_prompt_format % {
4484
            'scheme': scheme, 'host': host, 'port': port,
4485
            'realm': realm}
7143.15.2 by Jelmer Vernooij
Run autopep8.
4486
        ui.ui_factory = tests.TestUIFactory(stdin=username + '\n')
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
4487
        # We use an empty conf so that the user is always prompted
4488
        conf = config.AuthenticationConfig()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4489
        self.assertEqual(username, conf.get_user(scheme, host, port=port,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4490
                                                 realm=realm, path=path, ask=True))
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4491
        self.assertEqual(expected_prompt, ui.ui_factory.stderr.getvalue())
4492
        self.assertEqual('', ui.ui_factory.stdout.getvalue())
4222.3.2 by Jelmer Vernooij
Prompt for user names if they are not in the configuration.
4493
4494
    def test_username_defaults_prompts(self):
4495
        # 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.
4496
        self._check_default_username_prompt(u'FTP %(host)s username: ', 'ftp')
4497
        self._check_default_username_prompt(
4498
            u'FTP %(host)s:%(port)d username: ', 'ftp', port=10020)
4499
        self._check_default_username_prompt(
4500
            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.
4501
4222.3.11 by Jelmer Vernooij
Add test to make sure the default= parameter works.
4502
    def test_username_default_no_prompt(self):
4503
        conf = config.AuthenticationConfig()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4504
        self.assertEqual(None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4505
                         conf.get_user('ftp', 'example.com'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4506
        self.assertEqual("explicitdefault",
7143.15.2 by Jelmer Vernooij
Run autopep8.
4507
                         conf.get_user('ftp', 'example.com', default="explicitdefault"))
4222.3.11 by Jelmer Vernooij
Add test to make sure the default= parameter works.
4508
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
4509
    def test_password_default_prompts(self):
2900.2.19 by Vincent Ladeuil
Mention proxy and https in the password prompts, with tests.
4510
        # HTTP prompts can't be tested here, see test_http.py
4222.3.1 by Jelmer Vernooij
Mention password when checking default prompt.
4511
        self._check_default_password_prompt(
5923.1.3 by Vincent Ladeuil
Even more unicode prompts fixes revealed by pqm.
4512
            u'FTP %(user)s@%(host)s password: ', 'ftp')
4513
        self._check_default_password_prompt(
4514
            u'FTP %(user)s@%(host)s:%(port)d password: ', 'ftp', port=10020)
4515
        self._check_default_password_prompt(
4516
            u'SSH %(user)s@%(host)s:%(port)d password: ', 'ssh', port=12345)
2900.2.14 by Vincent Ladeuil
More tests.
4517
        # SMTP port handling is a bit special (it's handled if embedded in the
4518
        # host too)
2900.2.22 by Vincent Ladeuil
Polishing.
4519
        # FIXME: should we: forbid that, extend it to other schemes, leave
4520
        # things as they are that's fine thank you ?
5923.1.3 by Vincent Ladeuil
Even more unicode prompts fixes revealed by pqm.
4521
        self._check_default_password_prompt(
4522
            u'SMTP %(user)s@%(host)s password: ', 'smtp')
4523
        self._check_default_password_prompt(
4524
            u'SMTP %(user)s@%(host)s password: ', 'smtp', host='bar.org:10025')
4525
        self._check_default_password_prompt(
4526
            u'SMTP %(user)s@%(host)s:%(port)d password: ', 'smtp', port=10025)
2900.2.14 by Vincent Ladeuil
More tests.
4527
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
4528
    def test_ssh_password_emits_warning(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4529
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
4530
[ssh with password]
4531
scheme=ssh
4532
host=bar.org
4533
user=jim
4534
password=jimpass
4535
"""))
4536
        entered_password = 'typed-by-hand'
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4537
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n')
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
4538
4539
        # Since the password defined in the authentication config is ignored,
4540
        # the user is prompted
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4541
        self.assertEqual(entered_password,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4542
                         conf.get_password('ssh', 'bar.org', user='jim'))
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
4543
        self.assertContainsRe(
4794.1.17 by Robert Collins
Fix from vila for type log_log.
4544
            self.get_log(),
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
4545
            'password ignored in section \\[ssh with password\\]')
3420.1.2 by Vincent Ladeuil
Fix bug #203186 by ignoring passwords for ssh and warning user.
4546
3420.1.3 by Vincent Ladeuil
John's review feedback.
4547
    def test_ssh_without_password_doesnt_emit_warning(self):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4548
        conf = config.AuthenticationConfig(_file=BytesIO(b"""
3420.1.3 by Vincent Ladeuil
John's review feedback.
4549
[ssh with password]
4550
scheme=ssh
4551
host=bar.org
4552
user=jim
4553
"""))
4554
        entered_password = 'typed-by-hand'
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4555
        ui.ui_factory = tests.TestUIFactory(stdin=entered_password + '\n')
3420.1.3 by Vincent Ladeuil
John's review feedback.
4556
4557
        # Since the password defined in the authentication config is ignored,
4558
        # the user is prompted
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4559
        self.assertEqual(entered_password,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4560
                         conf.get_password('ssh', 'bar.org', user='jim'))
3420.1.4 by Vincent Ladeuil
Fix comment.
4561
        # No warning shoud be emitted since there is no password. We are only
4562
        # providing "user".
3420.1.3 by Vincent Ladeuil
John's review feedback.
4563
        self.assertNotContainsRe(
4794.1.15 by Robert Collins
Review feedback.
4564
            self.get_log(),
6798.1.1 by Jelmer Vernooij
Properly escape backslashes.
4565
            'password ignored in section \\[ssh with password\\]')
3420.1.3 by Vincent Ladeuil
John's review feedback.
4566
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
4567
    def test_uses_fallback_stores(self):
4985.1.5 by Vincent Ladeuil
Deploying the new overrideAttr facility further reduces the complexity
4568
        self.overrideAttr(config, 'credential_store_registry',
4569
                          config.CredentialStoreRegistry())
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
4570
        store = StubCredentialStore()
4571
        store.add_credentials("http", "example.com", "joe", "secret")
4572
        config.credential_store_registry.register("stub", store, fallback=True)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
4573
        conf = config.AuthenticationConfig(_file=BytesIO())
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
4574
        creds = conf.get_credentials("http", "example.com")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4575
        self.assertEqual("joe", creds["user"])
4576
        self.assertEqual("secret", creds["password"])
4283.1.3 by Jelmer Vernooij
Add test to make sure AuthenticationConfig queries for fallback credentials.
4577
2900.2.14 by Vincent Ladeuil
More tests.
4578
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4579
class StubCredentialStore(config.CredentialStore):
4580
4581
    def __init__(self):
4582
        self._username = {}
4583
        self._password = {}
4584
4585
    def add_credentials(self, scheme, host, user, password=None):
4586
        self._username[(scheme, host)] = user
4587
        self._password[(scheme, host)] = password
4588
4589
    def get_credentials(self, scheme, host, port=None, user=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4590
                        path=None, realm=None):
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4591
        key = (scheme, host)
7183.3.1 by Martin
Fix E71* lint errors
4592
        if key not in self._username:
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4593
            return None
7143.15.2 by Jelmer Vernooij
Run autopep8.
4594
        return {"scheme": scheme, "host": host, "port": port,
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4595
                "user": self._username[key], "password": self._password[key]}
4596
4597
4598
class CountingCredentialStore(config.CredentialStore):
4599
4600
    def __init__(self):
4601
        self._calls = 0
4602
4603
    def get_credentials(self, scheme, host, port=None, user=None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4604
                        path=None, realm=None):
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4605
        self._calls += 1
4606
        return None
4607
4608
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
4609
class TestCredentialStoreRegistry(tests.TestCase):
4610
4611
    def _get_cs_registry(self):
4612
        return config.credential_store_registry
4613
4614
    def test_default_credential_store(self):
4615
        r = self._get_cs_registry()
4616
        default = r.get_credential_store(None)
4617
        self.assertIsInstance(default, config.PlainTextCredentialStore)
4618
4619
    def test_unknown_credential_store(self):
4620
        r = self._get_cs_registry()
4621
        # It's hard to imagine someone creating a credential store named
4622
        # 'unknown' so we use that as an never registered key.
4623
        self.assertRaises(KeyError, r.get_credential_store, 'unknown')
4624
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4625
    def test_fallback_none_registered(self):
4626
        r = config.CredentialStoreRegistry()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4627
        self.assertEqual(None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4628
                         r.get_fallback_credentials("http", "example.com"))
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4629
4630
    def test_register(self):
4631
        r = config.CredentialStoreRegistry()
4632
        r.register("stub", StubCredentialStore(), fallback=False)
4633
        r.register("another", StubCredentialStore(), fallback=True)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4634
        self.assertEqual(["another", "stub"], r.keys())
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4635
4636
    def test_register_lazy(self):
4637
        r = config.CredentialStoreRegistry()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
4638
        r.register_lazy("stub", "breezy.tests.test_config",
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4639
                        "StubCredentialStore", fallback=False)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4640
        self.assertEqual(["stub"], r.keys())
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4641
        self.assertIsInstance(r.get_credential_store("stub"),
4642
                              StubCredentialStore)
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4643
4644
    def test_is_fallback(self):
4645
        r = config.CredentialStoreRegistry()
4646
        r.register("stub1", None, fallback=False)
4647
        r.register("stub2", None, fallback=True)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4648
        self.assertEqual(False, r.is_fallback("stub1"))
4649
        self.assertEqual(True, r.is_fallback("stub2"))
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4650
4651
    def test_no_fallback(self):
4652
        r = config.CredentialStoreRegistry()
4653
        store = CountingCredentialStore()
4654
        r.register("count", store, fallback=False)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4655
        self.assertEqual(None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4656
                         r.get_fallback_credentials("http", "example.com"))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4657
        self.assertEqual(0, store._calls)
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4658
4659
    def test_fallback_credentials(self):
4660
        r = config.CredentialStoreRegistry()
4661
        store = StubCredentialStore()
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4662
        store.add_credentials("http", "example.com",
4663
                              "somebody", "geheim")
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4664
        r.register("stub", store, fallback=True)
4665
        creds = r.get_fallback_credentials("http", "example.com")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4666
        self.assertEqual("somebody", creds["user"])
4667
        self.assertEqual("geheim", creds["password"])
4283.1.2 by Jelmer Vernooij
Add tests, NEWS item.
4668
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4669
    def test_fallback_first_wins(self):
4670
        r = config.CredentialStoreRegistry()
4671
        stub1 = StubCredentialStore()
4672
        stub1.add_credentials("http", "example.com",
4673
                              "somebody", "stub1")
4674
        r.register("stub1", stub1, fallback=True)
4675
        stub2 = StubCredentialStore()
4676
        stub2.add_credentials("http", "example.com",
4677
                              "somebody", "stub2")
4678
        r.register("stub2", stub1, fallback=True)
4679
        creds = r.get_fallback_credentials("http", "example.com")
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4680
        self.assertEqual("somebody", creds["user"])
4681
        self.assertEqual("stub1", creds["password"])
4283.2.1 by Vincent Ladeuil
Add a test and cleanup some PEP8 issues.
4682
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
4683
4684
class TestPlainTextCredentialStore(tests.TestCase):
4685
4686
    def test_decode_password(self):
4687
        r = config.credential_store_registry
4688
        plain_text = r.get_credential_store()
4689
        decoded = plain_text.decode_password(dict(password='secret'))
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4690
        self.assertEqual('secret', decoded)
3757.3.1 by Vincent Ladeuil
Add credential stores plugging.
4691
5912.5.5 by Florian Dorn
re-added blanks
4692
5912.5.6 by Martin
Revert to implementation in config rather than a plugin
4693
class TestBase64CredentialStore(tests.TestCase):
4694
4695
    def test_decode_password(self):
4696
        r = config.credential_store_registry
4697
        plain_text = r.get_credential_store('base64')
5912.5.7 by Martin
Minor cleanups and note about error case
4698
        decoded = plain_text.decode_password(dict(password='c2VjcmV0'))
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4699
        self.assertEqual(b'secret', decoded)
5912.5.6 by Martin
Revert to implementation in config rather than a plugin
4700
4701
2900.2.14 by Vincent Ladeuil
More tests.
4702
# 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.
4703
# can implement generic tests.
2900.2.15 by Vincent Ladeuil
AuthenticationConfig can be queried for logins too (first step).
4704
# test_user_password_in_url
4705
# test_user_in_url_password_from_config
4706
# test_user_in_url_password_prompted
4707
# test_user_in_config
4708
# test_user_getpass.getuser
4709
# test_user_prompted ?
2900.2.5 by Vincent Ladeuil
ake ftp aware of authentication config.
4710
class TestAuthenticationRing(tests.TestCaseWithTransport):
4711
    pass
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
4712
4713
4714
class TestAutoUserId(tests.TestCase):
4715
    """Test inferring an automatic user name."""
4716
4717
    def test_auto_user_id(self):
4718
        """Automatic inference of user name.
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4719
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
4720
        This is a bit hard to test in an isolated way, because it depends on
4721
        system functions that go direct to /etc or perhaps somewhere else.
4722
        But it's reasonable to say that on Unix, with an /etc/mailname, we ought
4723
        to be able to choose a user name with no configuration.
4724
        """
4725
        if sys.platform == 'win32':
5743.8.17 by Vincent Ladeuil
Add config old_get hook for remote config.
4726
            raise tests.TestSkipped(
4727
                "User name inference not implemented on win32")
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
4728
        realname, address = config._auto_user_id()
4729
        if os.path.exists('/etc/mailname'):
5813.1.1 by Jelmer Vernooij
Allow realname to be empty in tests.
4730
            self.assertIsNot(None, realname)
4731
            self.assertIsNot(None, address)
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
4732
        else:
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4733
            self.assertEqual((None, None), (realname, address))
5050.72.1 by Martin Pool
Set email address from /etc/mailname if possible
4734
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4735
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4736
class TestDefaultMailDomain(tests.TestCaseInTempDir):
4737
    """Test retrieving default domain from mailname file"""
4738
4739
    def test_default_mail_domain_simple(self):
6973.7.5 by Jelmer Vernooij
s/file/open.
4740
        with open('simple', 'w') as f:
6538.4.5 by Haw Loeung (hloeung)
[hloeung] Use try/finally to make sure the tests don't leak any file descriptors if they fail.
4741
            f.write("domainname.com\n")
6538.4.3 by Haw Loeung (hloeung)
[hloeung] Minor cosmetic changes.
4742
        r = config._get_default_mail_domain('simple')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4743
        self.assertEqual('domainname.com', r)
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4744
4745
    def test_default_mail_domain_no_eol(self):
6973.7.5 by Jelmer Vernooij
s/file/open.
4746
        with open('no_eol', 'w') as f:
6538.4.5 by Haw Loeung (hloeung)
[hloeung] Use try/finally to make sure the tests don't leak any file descriptors if they fail.
4747
            f.write("domainname.com")
4748
        r = config._get_default_mail_domain('no_eol')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4749
        self.assertEqual('domainname.com', r)
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4750
4751
    def test_default_mail_domain_multiple_lines(self):
6973.7.5 by Jelmer Vernooij
s/file/open.
4752
        with open('multiple_lines', 'w') as f:
6538.4.5 by Haw Loeung (hloeung)
[hloeung] Use try/finally to make sure the tests don't leak any file descriptors if they fail.
4753
            f.write("domainname.com\nsome other text\n")
6538.4.3 by Haw Loeung (hloeung)
[hloeung] Minor cosmetic changes.
4754
        r = config._get_default_mail_domain('multiple_lines')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4755
        self.assertEqual('domainname.com', r)
6538.4.2 by Haw Loeung (hloeung)
[hloeung] Also added missing unit tests.
4756
4757
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4758
class EmailOptionTests(tests.TestCase):
4759
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4760
    def test_default_email_uses_BRZ_EMAIL(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4761
        conf = config.MemoryStack(b'email=jelmer@debian.org')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4762
        # BRZ_EMAIL takes precedence over EMAIL
4763
        self.overrideEnv('BRZ_EMAIL', 'jelmer@samba.org')
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4764
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4765
        self.assertEqual('jelmer@samba.org', conf.get('email'))
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4766
4767
    def test_default_email_uses_EMAIL(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4768
        conf = config.MemoryStack(b'')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4769
        self.overrideEnv('BRZ_EMAIL', None)
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4770
        self.overrideEnv('EMAIL', 'jelmer@apache.org')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4771
        self.assertEqual('jelmer@apache.org', conf.get('email'))
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4772
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4773
    def test_BRZ_EMAIL_overrides(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4774
        conf = config.MemoryStack(b'email=jelmer@debian.org')
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4775
        self.overrideEnv('BRZ_EMAIL', 'jelmer@apache.org')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4776
        self.assertEqual('jelmer@apache.org', conf.get('email'))
6622.1.28 by Jelmer Vernooij
More renames; commands in output, environment variables.
4777
        self.overrideEnv('BRZ_EMAIL', None)
6374.1.3 by Jelmer Vernooij
Add tests for default_email behaviour.
4778
        self.overrideEnv('EMAIL', 'jelmer@samba.org')
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
4779
        self.assertEqual('jelmer@debian.org', conf.get('email'))
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4780
4781
4782
class MailClientOptionTests(tests.TestCase):
4783
4784
    def test_default(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4785
        conf = config.MemoryStack(b'')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4786
        client = conf.get('mail_client')
4787
        self.assertIs(client, mail_client.DefaultMail)
4788
4789
    def test_evolution(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4790
        conf = config.MemoryStack(b'mail_client=evolution')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4791
        client = conf.get('mail_client')
4792
        self.assertIs(client, mail_client.Evolution)
4793
4794
    def test_kmail(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4795
        conf = config.MemoryStack(b'mail_client=kmail')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4796
        client = conf.get('mail_client')
4797
        self.assertIs(client, mail_client.KMail)
4798
4799
    def test_mutt(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4800
        conf = config.MemoryStack(b'mail_client=mutt')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4801
        client = conf.get('mail_client')
4802
        self.assertIs(client, mail_client.Mutt)
4803
4804
    def test_thunderbird(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4805
        conf = config.MemoryStack(b'mail_client=thunderbird')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4806
        client = conf.get('mail_client')
4807
        self.assertIs(client, mail_client.Thunderbird)
4808
4809
    def test_explicit_default(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4810
        conf = config.MemoryStack(b'mail_client=default')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4811
        client = conf.get('mail_client')
4812
        self.assertIs(client, mail_client.DefaultMail)
4813
4814
    def test_editor(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4815
        conf = config.MemoryStack(b'mail_client=editor')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4816
        client = conf.get('mail_client')
4817
        self.assertIs(client, mail_client.Editor)
4818
4819
    def test_mapi(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4820
        conf = config.MemoryStack(b'mail_client=mapi')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4821
        client = conf.get('mail_client')
4822
        self.assertIs(client, mail_client.MAPIClient)
4823
4824
    def test_xdg_email(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4825
        conf = config.MemoryStack(b'mail_client=xdg-email')
6449.5.6 by Jelmer Vernooij
Port mail client tests to config stacks.
4826
        client = conf.get('mail_client')
4827
        self.assertIs(client, mail_client.XDGEmail)
4828
4829
    def test_unknown(self):
6973.10.4 by Jelmer Vernooij
Update python3.passing.
4830
        conf = config.MemoryStack(b'mail_client=firebird')
6733.1.1 by Jelmer Vernooij
Move config errors from breezy.errors to breezy.config.
4831
        self.assertRaises(config.ConfigOptionValueError, conf.get,
7143.15.2 by Jelmer Vernooij
Run autopep8.
4832
                          'mail_client')