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