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