~bzr-pqm/bzr/bzr.dev

5557.1.15 by John Arbash Meinel
Merge bzr.dev 5597 to resolve NEWS, aka bzr-2.3.txt
1
# Copyright (C) 2005-2011 Canonical Ltd
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
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
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
16
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
17
import re
18
2221.4.1 by Aaron Bentley
Get registry options working
19
from bzrlib import (
20
    bzrdir,
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
21
    commands,
5363.2.9 by Jelmer Vernooij
Fix some tests.
22
    controldir,
2221.4.1 by Aaron Bentley
Get registry options working
23
    errors,
24
    option,
5945.1.1 by Martin von Gagern
Allow -s as shorthand for --log-format=short.
25
    registry,
2221.4.1 by Aaron Bentley
Get registry options working
26
    )
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
27
from bzrlib.builtins import cmd_commit
5579.3.1 by Jelmer Vernooij
Remove unused imports.
28
from bzrlib.commands import parse_args
1185.31.25 by John Arbash Meinel
Renamed all of the tests from selftest/foo.py to tests/test_foo.py
29
from bzrlib.tests import TestCase
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
30
from bzrlib.repofmt import knitrepo
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
31
2376.4.22 by Jonathan Lange
Variety of whitespace cleanups, tightening of tests and docstring changes in
32
2227.1.4 by mbp at sourcefrog
add test that legacy SHORT_OPTIONS really works, and set_short_name
33
def parse(options, args):
34
    parser = option.get_optparser(dict((o.name, o) for o in options))
35
    return parser.parse_args(args)
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
36
2376.4.22 by Jonathan Lange
Variety of whitespace cleanups, tightening of tests and docstring changes in
37
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
38
class OptionTests(TestCase):
39
    """Command-line option tests"""
40
41
    def test_parse_args(self):
42
        """Option parser"""
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
43
        # XXX: Using cmd_commit makes these tests overly sensitive to changes
44
        # to cmd_commit, when they are meant to be about option parsing in
45
        # general.
46
        self.assertEqual(parse_args(cmd_commit(), ['--help']),
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
47
           ([], {'author': [], 'exclude': [], 'fixes': [], 'help': True}))
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
48
        self.assertEqual(parse_args(cmd_commit(), ['--message=biter']),
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
49
           ([], {'author': [], 'exclude': [], 'fixes': [], 'message': 'biter'}))
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
50
1185.16.49 by mbp at sourcefrog
- more refactoring and tests of commandline
51
    def test_no_more_opts(self):
52
        """Terminated options"""
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
53
        self.assertEqual(parse_args(cmd_commit(), ['--', '-file-with-dashes']),
4056.2.1 by James Westby
Allow specifying multiple authors for a revision.
54
                          (['-file-with-dashes'], {'author': [], 'exclude': [], 'fixes': []}))
1185.16.49 by mbp at sourcefrog
- more refactoring and tests of commandline
55
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
56
    def test_option_help(self):
57
        """Options have help strings."""
2552.2.2 by Vincent Ladeuil
Enforce run_bzr(string) where possible.
58
        out, err = self.run_bzr('commit --help')
2598.1.4 by Martin Pool
Fix up tests for option help cleanups
59
        self.assertContainsRe(out,
60
                r'--file(.|\n)*Take commit message from this file\.')
1857.1.12 by Aaron Bentley
Fix a bunch of test cases that assumed --merge-type or log-format
61
        self.assertContainsRe(out, r'-h.*--help')
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
62
63
    def test_option_help_global(self):
64
        """Global options have help strings."""
2552.2.2 by Vincent Ladeuil
Enforce run_bzr(string) where possible.
65
        out, err = self.run_bzr('help status')
2598.1.4 by Martin Pool
Fix up tests for option help cleanups
66
        self.assertContainsRe(out, r'--show-ids.*Show internal object.')
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
67
68
    def test_option_arg_help(self):
69
        """Help message shows option arguments."""
2552.2.2 by Vincent Ladeuil
Enforce run_bzr(string) where possible.
70
        out, err = self.run_bzr('help commit')
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
71
        self.assertEqual(err, '')
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
72
        self.assertContainsRe(out, r'--file[ =]MSGFILE')
73
1185.35.24 by Aaron Bentley
Fixed handling of short options not accepted by the command
74
    def test_unknown_short_opt(self):
2552.2.2 by Vincent Ladeuil
Enforce run_bzr(string) where possible.
75
        out, err = self.run_bzr('help -r', retcode=3)
1857.1.1 by Aaron Bentley
Use optparse for parsing options
76
        self.assertContainsRe(err, r'no such option')
1185.35.24 by Aaron Bentley
Fixed handling of short options not accepted by the command
77
2227.1.4 by mbp at sourcefrog
add test that legacy SHORT_OPTIONS really works, and set_short_name
78
    def test_set_short_name(self):
79
        o = option.Option('wiggle')
80
        o.set_short_name('w')
81
        self.assertEqual(o.short_name(), 'w')
82
1852.1.1 by John Arbash Meinel
Allow a plain '-' to be supplied as an argument. bug #50984
83
    def test_allow_dash(self):
84
        """Test that we can pass a plain '-' as an argument."""
3602.1.5 by Robert Collins
Fixups for test_options due to the changes to cmd_commit - insta-review by spiv.
85
        self.assertEqual((['-']), parse_args(cmd_commit(), ['-'])[0])
1852.1.1 by John Arbash Meinel
Allow a plain '-' to be supplied as an argument. bug #50984
86
2221.4.1 by Aaron Bentley
Get registry options working
87
    def parse(self, options, args):
88
        parser = option.get_optparser(dict((o.name, o) for o in options))
89
        return parser.parse_args(args)
2221.4.9 by Aaron Bentley
Zap trailing whitespace
90
1857.1.15 by Aaron Bentley
Add tests for generating an option parser
91
    def test_conversion(self):
92
        options = [option.Option('hello')]
2221.4.1 by Aaron Bentley
Get registry options working
93
        opts, args = self.parse(options, ['--no-hello', '--hello'])
1857.1.16 by Aaron Bentley
Add tests for iter_switches
94
        self.assertEqual(True, opts.hello)
2221.4.1 by Aaron Bentley
Get registry options working
95
        opts, args = self.parse(options, [])
2768.1.6 by Ian Clatworthy
Fix existing option and help tests
96
        self.assertFalse(hasattr(opts, 'hello'))
2221.4.1 by Aaron Bentley
Get registry options working
97
        opts, args = self.parse(options, ['--hello', '--no-hello'])
1857.1.22 by Aaron Bentley
Negations set value to False, instead of Optparser.DEFAULT_VALUE
98
        self.assertEqual(False, opts.hello)
1857.1.15 by Aaron Bentley
Add tests for generating an option parser
99
        options = [option.Option('number', type=int)]
2221.4.1 by Aaron Bentley
Get registry options working
100
        opts, args = self.parse(options, ['--number', '6'])
1857.1.16 by Aaron Bentley
Add tests for iter_switches
101
        self.assertEqual(6, opts.number)
2221.4.9 by Aaron Bentley
Zap trailing whitespace
102
        self.assertRaises(errors.BzrCommandError, self.parse, options,
2221.4.1 by Aaron Bentley
Get registry options working
103
                          ['--number'])
2221.4.9 by Aaron Bentley
Zap trailing whitespace
104
        self.assertRaises(errors.BzrCommandError, self.parse, options,
1857.1.15 by Aaron Bentley
Add tests for generating an option parser
105
                          ['--no-number'])
1185.16.48 by mbp at sourcefrog
- more refactoring of and tests for option parsing
106
4251.1.1 by Aaron Bentley
Support hidden options.
107
    def test_is_hidden(self):
108
        self.assertTrue(option.Option('foo', hidden=True).is_hidden('foo'))
109
        self.assertFalse(option.Option('foo', hidden=False).is_hidden('foo'))
110
2221.4.1 by Aaron Bentley
Get registry options working
111
    def test_registry_conversion(self):
5363.2.9 by Jelmer Vernooij
Fix some tests.
112
        registry = controldir.ControlDirFormatRegistry()
113
        bzrdir.register_metadir(registry, 'one', 'RepositoryFormat7', 'one help')
114
        bzrdir.register_metadir(registry, 'two', 'RepositoryFormatKnit1', 'two help')
115
        bzrdir.register_metadir(registry, 'hidden', 'RepositoryFormatKnit1',
1551.13.2 by Aaron Bentley
Hide dirstate-with-subtree format
116
            'two help', hidden=True)
2221.4.1 by Aaron Bentley
Get registry options working
117
        registry.set_default('one')
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
118
        options = [option.RegistryOption('format', '', registry, str)]
2221.4.1 by Aaron Bentley
Get registry options working
119
        opts, args = self.parse(options, ['--format', 'one'])
120
        self.assertEqual({'format':'one'}, opts)
121
        opts, args = self.parse(options, ['--format', 'two'])
122
        self.assertEqual({'format':'two'}, opts)
2221.4.9 by Aaron Bentley
Zap trailing whitespace
123
        self.assertRaises(errors.BadOptionValue, self.parse, options,
2221.4.1 by Aaron Bentley
Get registry options working
124
                          ['--format', 'three'])
2221.4.9 by Aaron Bentley
Zap trailing whitespace
125
        self.assertRaises(errors.BzrCommandError, self.parse, options,
2221.4.1 by Aaron Bentley
Get registry options working
126
                          ['--two'])
2221.4.9 by Aaron Bentley
Zap trailing whitespace
127
        options = [option.RegistryOption('format', '', registry, str,
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
128
                   value_switches=True)]
2221.4.1 by Aaron Bentley
Get registry options working
129
        opts, args = self.parse(options, ['--two'])
130
        self.assertEqual({'format':'two'}, opts)
131
        opts, args = self.parse(options, ['--two', '--one'])
132
        self.assertEqual({'format':'one'}, opts)
2221.4.9 by Aaron Bentley
Zap trailing whitespace
133
        opts, args = self.parse(options, ['--two', '--one',
2221.4.1 by Aaron Bentley
Get registry options working
134
                                          '--format', 'two'])
135
        self.assertEqual({'format':'two'}, opts)
1551.12.18 by Aaron Bentley
Allow RegistryOption to omit the value-taking option
136
        options = [option.RegistryOption('format', '', registry, str,
137
                   enum_switch=False)]
138
        self.assertRaises(errors.BzrCommandError, self.parse, options,
139
                          ['--format', 'two'])
2221.4.1 by Aaron Bentley
Get registry options working
140
2745.4.2 by Lukáš Lalinsky
Allow options to be stored in attributes that differ from their 'name' and use this to let '--change' and '--revision' to override each other.
141
    def test_override(self):
142
        options = [option.Option('hello', type=str),
143
                   option.Option('hi', type=str, param_name='hello')]
144
        opts, args = self.parse(options, ['--hello', 'a', '--hello', 'b'])
145
        self.assertEqual('b', opts.hello)
146
        opts, args = self.parse(options, ['--hello', 'b', '--hello', 'a'])
147
        self.assertEqual('a', opts.hello)
148
        opts, args = self.parse(options, ['--hello', 'a', '--hi', 'b'])
149
        self.assertEqual('b', opts.hello)
150
        opts, args = self.parse(options, ['--hi', 'b', '--hello', 'a'])
151
        self.assertEqual('a', opts.hello)
152
2221.4.1 by Aaron Bentley
Get registry options working
153
    def test_registry_converter(self):
2221.4.9 by Aaron Bentley
Zap trailing whitespace
154
        options = [option.RegistryOption('format', '',
2204.5.5 by Aaron Bentley
Remove RepositoryFormat.set_default_format, deprecate get_format_type
155
                   bzrdir.format_registry, bzrdir.format_registry.make_bzrdir)]
2221.4.1 by Aaron Bentley
Get registry options working
156
        opts, args = self.parse(options, ['--format', 'knit'])
157
        self.assertIsInstance(opts.format.repository_format,
2241.1.6 by Martin Pool
Move Knit repositories into the submodule bzrlib.repofmt.knitrepo and
158
                              knitrepo.RepositoryFormatKnit1)
2221.4.1 by Aaron Bentley
Get registry options working
159
3224.5.34 by Andrew Bennetts
Polish lazy_registry feature a little.
160
    def test_lazy_registry(self):
161
        options = [option.RegistryOption('format', '',
162
                   lazy_registry=('bzrlib.bzrdir','format_registry'),
163
                   converter=str)]
164
        opts, args = self.parse(options, ['--format', 'knit'])
165
        self.assertEqual({'format': 'knit'}, opts)
166
        self.assertRaises(
167
            errors.BadOptionValue, self.parse, options, ['--format', 'BAD'])
168
1551.12.24 by Aaron Bentley
Add RegistryOption.from_swargs to simplify simple registry options
169
    def test_from_kwargs(self):
170
        my_option = option.RegistryOption.from_kwargs('my-option',
171
            help='test option', short='be short', be_long='go long')
172
        self.assertEqual(['my-option'],
173
            [x[0] for x in my_option.iter_switches()])
174
        my_option = option.RegistryOption.from_kwargs('my-option',
175
            help='test option', title="My option", short='be short',
176
            be_long='go long', value_switches=True)
177
        self.assertEqual(['my-option', 'be-long', 'short'],
178
            [x[0] for x in my_option.iter_switches()])
2681.1.5 by Aaron Bentley
Display correct help message in from_kwargs
179
        self.assertEqual('test option', my_option.help)
1551.12.24 by Aaron Bentley
Add RegistryOption.from_swargs to simplify simple registry options
180
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
181
    def test_help(self):
5363.2.9 by Jelmer Vernooij
Fix some tests.
182
        registry = controldir.ControlDirFormatRegistry()
183
        bzrdir.register_metadir(registry, 'one', 'RepositoryFormat7', 'one help')
184
        bzrdir.register_metadir(registry, 'two',
2241.1.21 by Martin Pool
Change register_metadir to take fully-qualified repository class name.
185
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
186
            'two help',
187
            )
5363.2.9 by Jelmer Vernooij
Fix some tests.
188
        bzrdir.register_metadir(registry, 'hidden', 'RepositoryFormat7', 'hidden help',
1551.13.2 by Aaron Bentley
Hide dirstate-with-subtree format
189
            hidden=True)
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
190
        registry.set_default('one')
191
        options = [option.RegistryOption('format', 'format help', registry,
2221.4.12 by Aaron Bentley
Add option grouping to RegistryOption and clean up format options
192
                   str, value_switches=True, title='Formats')]
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
193
        parser = option.get_optparser(dict((o.name, o) for o in options))
194
        value = parser.format_option_help()
195
        self.assertContainsRe(value, 'format.*format help')
196
        self.assertContainsRe(value, 'one.*one help')
2221.4.12 by Aaron Bentley
Add option grouping to RegistryOption and clean up format options
197
        self.assertContainsRe(value, 'Formats:\n *--format')
1551.13.2 by Aaron Bentley
Hide dirstate-with-subtree format
198
        self.assertNotContainsRe(value, 'hidden help')
2221.4.2 by Aaron Bentley
Implement RegistryOption on init
199
1857.1.16 by Aaron Bentley
Add tests for iter_switches
200
    def test_iter_switches(self):
201
        opt = option.Option('hello', help='fg')
202
        self.assertEqual(list(opt.iter_switches()),
203
                         [('hello', None, None, 'fg')])
204
        opt = option.Option('hello', help='fg', type=int)
205
        self.assertEqual(list(opt.iter_switches()),
206
                         [('hello', None, 'ARG', 'fg')])
207
        opt = option.Option('hello', help='fg', type=int, argname='gar')
208
        self.assertEqual(list(opt.iter_switches()),
209
                         [('hello', None, 'GAR', 'fg')])
5363.2.9 by Jelmer Vernooij
Fix some tests.
210
        registry = controldir.ControlDirFormatRegistry()
211
        bzrdir.register_metadir(registry, 'one', 'RepositoryFormat7', 'one help')
212
        bzrdir.register_metadir(registry, 'two',
2241.1.21 by Martin Pool
Change register_metadir to take fully-qualified repository class name.
213
                'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
214
                'two help',
215
                )
2221.4.4 by Aaron Bentley
Fix iter_switches behavior when value_switches is true
216
        registry.set_default('one')
217
        opt = option.RegistryOption('format', 'format help', registry,
218
                                    value_switches=False)
219
        self.assertEqual(list(opt.iter_switches()),
220
                         [('format', None, 'ARG', 'format help')])
221
        opt = option.RegistryOption('format', 'format help', registry,
222
                                    value_switches=True)
223
        self.assertEqual(list(opt.iter_switches()),
224
                         [('format', None, 'ARG', 'format help'),
2221.4.9 by Aaron Bentley
Zap trailing whitespace
225
                          ('default', None, None, 'one help'),
226
                          ('one', None, None, 'one help'),
227
                          ('two', None, None, 'two help'),
2221.4.4 by Aaron Bentley
Fix iter_switches behavior when value_switches is true
228
                          ])
1857.1.16 by Aaron Bentley
Add tests for iter_switches
229
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
230
    def test_option_callback_bool(self):
231
        "Test booleans get True and False passed correctly to a callback."""
232
        cb_calls = []
233
        def cb(option, name, value, parser):
234
            cb_calls.append((option,name,value,parser))
235
        options = [option.Option('hello', custom_callback=cb)]
236
        opts, args = self.parse(options, ['--hello', '--no-hello'])
237
        self.assertEqual(2, len(cb_calls))
238
        opt,name,value,parser = cb_calls[0]
239
        self.assertEqual('hello', name)
240
        self.assertTrue(value)
241
        opt,name,value,parser = cb_calls[1]
242
        self.assertEqual('hello', name)
243
        self.assertFalse(value)
244
245
    def test_option_callback_str(self):
246
        """Test callbacks work for string options both long and short."""
247
        cb_calls = []
248
        def cb(option, name, value, parser):
249
            cb_calls.append((option,name,value,parser))
250
        options = [option.Option('hello', type=str, custom_callback=cb,
251
            short_name='h')]
252
        opts, args = self.parse(options, ['--hello', 'world', '-h', 'mars'])
253
        self.assertEqual(2, len(cb_calls))
254
        opt,name,value,parser = cb_calls[0]
255
        self.assertEqual('hello', name)
256
        self.assertEqual('world', value)
257
        opt,name,value,parser = cb_calls[1]
258
        self.assertEqual('hello', name)
259
        self.assertEqual('mars', value)
260
2376.4.1 by jml at canonical
Blackbox-driven --fixes option to commit.
261
2376.4.11 by Jonathan Lange
Provide a way of resetting list options (specifying '-' as the argument)
262
class TestListOptions(TestCase):
263
    """Tests for ListOption, used to specify lists on the command-line."""
264
2376.4.1 by jml at canonical
Blackbox-driven --fixes option to commit.
265
    def parse(self, options, args):
266
        parser = option.get_optparser(dict((o.name, o) for o in options))
267
        return parser.parse_args(args)
268
269
    def test_list_option(self):
270
        options = [option.ListOption('hello', type=str)]
271
        opts, args = self.parse(options, ['--hello=world', '--hello=sailor'])
272
        self.assertEqual(['world', 'sailor'], opts.hello)
273
3668.2.1 by Vincent Ladeuil
Fix bug #263249 by setting valid default _param_name.
274
    def test_list_option_with_dash(self):
275
        options = [option.ListOption('with-dash', type=str)]
276
        opts, args = self.parse(options, ['--with-dash=world',
277
                                          '--with-dash=sailor'])
278
        self.assertEqual(['world', 'sailor'], opts.with_dash)
279
2376.4.1 by jml at canonical
Blackbox-driven --fixes option to commit.
280
    def test_list_option_no_arguments(self):
281
        options = [option.ListOption('hello', type=str)]
282
        opts, args = self.parse(options, [])
283
        self.assertEqual([], opts.hello)
2376.4.11 by Jonathan Lange
Provide a way of resetting list options (specifying '-' as the argument)
284
2376.4.22 by Jonathan Lange
Variety of whitespace cleanups, tightening of tests and docstring changes in
285
    def test_list_option_with_int_type(self):
286
        options = [option.ListOption('hello', type=int)]
287
        opts, args = self.parse(options, ['--hello=2', '--hello=3'])
288
        self.assertEqual([2, 3], opts.hello)
289
290
    def test_list_option_with_int_type_can_be_reset(self):
291
        options = [option.ListOption('hello', type=int)]
292
        opts, args = self.parse(options, ['--hello=2', '--hello=3',
293
                                          '--hello=-', '--hello=5'])
294
        self.assertEqual([5], opts.hello)
295
2376.4.11 by Jonathan Lange
Provide a way of resetting list options (specifying '-' as the argument)
296
    def test_list_option_can_be_reset(self):
297
        """Passing an option of '-' to a list option should reset the list."""
298
        options = [option.ListOption('hello', type=str)]
299
        opts, args = self.parse(
300
            options, ['--hello=a', '--hello=b', '--hello=-', '--hello=c'])
301
        self.assertEqual(['c'], opts.hello)
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
302
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
303
    def test_option_callback_list(self):
304
        """Test callbacks work for list options."""
305
        cb_calls = []
306
        def cb(option, name, value, parser):
307
            # Note that the value is a reference so copy to keep it
308
            cb_calls.append((option,name,value[:],parser))
309
        options = [option.ListOption('hello', type=str, custom_callback=cb)]
310
        opts, args = self.parse(options, ['--hello=world', '--hello=mars',
311
            '--hello=-'])
312
        self.assertEqual(3, len(cb_calls))
313
        opt,name,value,parser = cb_calls[0]
314
        self.assertEqual('hello', name)
315
        self.assertEqual(['world'], value)
316
        opt,name,value,parser = cb_calls[1]
317
        self.assertEqual('hello', name)
318
        self.assertEqual(['world', 'mars'], value)
319
        opt,name,value,parser = cb_calls[2]
320
        self.assertEqual('hello', name)
321
        self.assertEqual([], value)
322
3751.1.1 by Martin von Gagern
Handle param_name for ListOption.
323
    def test_list_option_param_name(self):
324
        """Test list options can have their param_name set."""
325
        options = [option.ListOption('hello', type=str, param_name='greeting')]
326
        opts, args = self.parse(
327
            options, ['--hello=world', '--hello=sailor'])
328
        self.assertEqual(['world', 'sailor'], opts.greeting)
329
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
330
331
class TestOptionDefinitions(TestCase):
332
    """Tests for options in the Bazaar codebase."""
333
2598.1.14 by Martin Pool
Revert tightening of options api - breaks too many plugins
334
    def get_builtin_command_options(self):
335
        g = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
336
        for cmd_name in sorted(commands.all_command_names()):
337
            cmd = commands.get_cmd_object(cmd_name)
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
338
            for opt_name, opt in sorted(cmd.options().items()):
339
                g.append((cmd_name, opt))
340
        return g
341
2598.1.7 by Martin Pool
Add failing test that global options are all used.
342
    def test_global_options_used(self):
343
        # In the distant memory, options could only be declared globally.  Now
344
        # we prefer to declare them in the command, unless like -r they really
345
        # are used very widely with the exact same meaning.  So this checks
346
        # for any that should be garbage collected.
347
        g = dict(option.Option.OPTIONS.items())
2598.1.9 by Martin Pool
Add failing test that global options are used at least twice
348
        used_globals = {}
2598.1.7 by Martin Pool
Add failing test that global options are all used.
349
        msgs = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
350
        for cmd_name in sorted(commands.all_command_names()):
351
            cmd = commands.get_cmd_object(cmd_name)
352
            for option_or_name in sorted(cmd.takes_options):
2598.1.7 by Martin Pool
Add failing test that global options are all used.
353
                if not isinstance(option_or_name, basestring):
354
                    self.assertIsInstance(option_or_name, option.Option)
355
                elif not option_or_name in g:
356
                    msgs.append("apparent reference to undefined "
357
                        "global option %r from %r"
4119.3.8 by Robert Collins
Get missing command support sorted out.
358
                        % (option_or_name, cmd))
2598.1.7 by Martin Pool
Add failing test that global options are all used.
359
                else:
2598.1.9 by Martin Pool
Add failing test that global options are used at least twice
360
                    used_globals.setdefault(option_or_name, []).append(cmd_name)
361
        unused_globals = set(g.keys()) - set(used_globals.keys())
2598.1.14 by Martin Pool
Revert tightening of options api - breaks too many plugins
362
        # not enforced because there might be plugins that use these globals
363
        ## for option_name in sorted(unused_globals):
364
        ##    msgs.append("unused global option %r" % option_name)
365
        ## for option_name, cmds in sorted(used_globals.items()):
366
        ##     if len(cmds) <= 1:
367
        ##         msgs.append("global option %r is only used by %r"
368
        ##                 % (option_name, cmds))
2598.1.7 by Martin Pool
Add failing test that global options are all used.
369
        if msgs:
370
            self.fail("problems with global option definitions:\n"
371
                    + '\n'.join(msgs))
372
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
373
    def test_option_grammar(self):
374
        msgs = []
2598.1.2 by Martin Pool
Also check that option help ends in a period, and fix those that don't
375
        # Option help should be written in sentence form, and have a final
376
        # period and be all on a single line, because the display code will
377
        # wrap it.
378
        option_re = re.compile(r'^[A-Z][^\n]+\.$')
3755.1.1 by Vincent Ladeuil
Fix --verbose leaking into blackbox tests.
379
        for scope, opt in self.get_builtin_command_options():
380
            if not opt.help:
381
                msgs.append('%-16s %-16s %s' %
382
                       ((scope or 'GLOBAL'), opt.name, 'NO HELP'))
383
            elif not option_re.match(opt.help):
384
                msgs.append('%-16s %-16s %s' %
385
                        ((scope or 'GLOBAL'), opt.name, opt.help))
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
386
        if msgs:
387
            self.fail("The following options don't match the style guide:\n"
388
                    + '\n'.join(msgs))
1551.18.12 by Aaron Bentley
Man page doesn't list hidden options (#131667)
389
390
    def test_is_hidden(self):
5363.2.9 by Jelmer Vernooij
Fix some tests.
391
        registry = controldir.ControlDirFormatRegistry()
392
        bzrdir.register_metadir(registry, 'hidden', 'HiddenFormat',
1551.18.13 by Aaron Bentley
Update test from review suggestions
393
            'hidden help text', hidden=True)
5363.2.9 by Jelmer Vernooij
Fix some tests.
394
        bzrdir.register_metadir(registry, 'visible', 'VisibleFormat',
1551.18.13 by Aaron Bentley
Update test from review suggestions
395
            'visible help text', hidden=False)
1551.18.12 by Aaron Bentley
Man page doesn't list hidden options (#131667)
396
        format = option.RegistryOption('format', '', registry, str)
397
        self.assertTrue(format.is_hidden('hidden'))
398
        self.assertFalse(format.is_hidden('visible'))
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
399
5574.9.3 by Jelmer Vernooij
Add -F as alias for 'bzr diff -F format'
400
    def test_short_name(self):
401
        registry = controldir.ControlDirFormatRegistry()
402
        opt = option.RegistryOption('format', help='', registry=registry)
403
        self.assertEquals(None, opt.short_name())
404
        opt = option.RegistryOption('format', short_name='F', help='',
405
            registry=registry)
406
        self.assertEquals('F', opt.short_name())
407
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
408
    def test_option_custom_help(self):
409
        the_opt = option.Option.OPTIONS['help']
410
        orig_help = the_opt.help[:]
411
        my_opt = option.custom_help('help', 'suggest lottery numbers')
412
        # Confirm that my_opt has my help and the original is unchanged
413
        self.assertEqual('suggest lottery numbers', my_opt.help)
414
        self.assertEqual(orig_help, the_opt.help)
415
5945.1.1 by Martin von Gagern
Allow -s as shorthand for --log-format=short.
416
    def test_short_value_switches(self):
417
        reg = registry.Registry()
418
        reg.register('short', 'ShortChoice')
419
        reg.register('long', 'LongChoice')
420
        ropt = option.RegistryOption('choice', '', reg, value_switches=True,
421
            short_value_switches={'short': 's'})
422
        opts, args = parse([ropt], ['--short'])
423
        self.assertEqual('ShortChoice', opts.choice)
424
        opts, args = parse([ropt], ['-s'])
425
        self.assertEqual('ShortChoice', opts.choice)
426
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
427
428
class TestVerboseQuietLinkage(TestCase):
429
430
    def check(self, parser, level, args):
431
        option._verbosity_level = 0
432
        opts, args = parser.parse_args(args)
433
        self.assertEqual(level, option._verbosity_level)
434
435
    def test_verbose_quiet_linkage(self):
436
        parser = option.get_optparser(option.Option.STD_OPTIONS)
437
        self.check(parser, 0, [])
438
        self.check(parser, 1, ['-v'])
439
        self.check(parser, 2, ['-v', '-v'])
440
        self.check(parser, -1, ['-q'])
441
        self.check(parser, -2, ['-qq'])
442
        self.check(parser, -1, ['-v', '-v', '-q'])
443
        self.check(parser, 2, ['-q', '-v', '-v'])
444
        self.check(parser, 0, ['--no-verbose'])
445
        self.check(parser, 0, ['-v', '-q', '--no-quiet'])