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