~bzr-pqm/bzr/bzr.dev

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