~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
3751.1.1 by Martin von Gagern
Handle param_name for ListOption.
321
    def test_list_option_param_name(self):
322
        """Test list options can have their param_name set."""
323
        options = [option.ListOption('hello', type=str, param_name='greeting')]
324
        opts, args = self.parse(
325
            options, ['--hello=world', '--hello=sailor'])
326
        self.assertEqual(['world', 'sailor'], opts.greeting)
327
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
328
329
class TestOptionDefinitions(TestCase):
330
    """Tests for options in the Bazaar codebase."""
331
2598.1.14 by Martin Pool
Revert tightening of options api - breaks too many plugins
332
    def get_builtin_command_options(self):
333
        g = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
334
        for cmd_name in sorted(commands.all_command_names()):
335
            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
336
            for opt_name, opt in sorted(cmd.options().items()):
337
                g.append((cmd_name, opt))
338
        return g
339
2598.1.7 by Martin Pool
Add failing test that global options are all used.
340
    def test_global_options_used(self):
341
        # In the distant memory, options could only be declared globally.  Now
342
        # we prefer to declare them in the command, unless like -r they really
343
        # are used very widely with the exact same meaning.  So this checks
344
        # for any that should be garbage collected.
345
        g = dict(option.Option.OPTIONS.items())
2598.1.9 by Martin Pool
Add failing test that global options are used at least twice
346
        used_globals = {}
2598.1.7 by Martin Pool
Add failing test that global options are all used.
347
        msgs = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
348
        for cmd_name in sorted(commands.all_command_names()):
349
            cmd = commands.get_cmd_object(cmd_name)
350
            for option_or_name in sorted(cmd.takes_options):
2598.1.7 by Martin Pool
Add failing test that global options are all used.
351
                if not isinstance(option_or_name, basestring):
352
                    self.assertIsInstance(option_or_name, option.Option)
353
                elif not option_or_name in g:
354
                    msgs.append("apparent reference to undefined "
355
                        "global option %r from %r"
4119.3.8 by Robert Collins
Get missing command support sorted out.
356
                        % (option_or_name, cmd))
2598.1.7 by Martin Pool
Add failing test that global options are all used.
357
                else:
2598.1.9 by Martin Pool
Add failing test that global options are used at least twice
358
                    used_globals.setdefault(option_or_name, []).append(cmd_name)
359
        unused_globals = set(g.keys()) - set(used_globals.keys())
2598.1.14 by Martin Pool
Revert tightening of options api - breaks too many plugins
360
        # not enforced because there might be plugins that use these globals
361
        ## for option_name in sorted(unused_globals):
362
        ##    msgs.append("unused global option %r" % option_name)
363
        ## for option_name, cmds in sorted(used_globals.items()):
364
        ##     if len(cmds) <= 1:
365
        ##         msgs.append("global option %r is only used by %r"
366
        ##                 % (option_name, cmds))
2598.1.7 by Martin Pool
Add failing test that global options are all used.
367
        if msgs:
368
            self.fail("problems with global option definitions:\n"
369
                    + '\n'.join(msgs))
370
2598.1.1 by Martin Pool
Add test for and documentation of option style, fix up existing options to comply
371
    def test_option_grammar(self):
372
        msgs = []
2598.1.2 by Martin Pool
Also check that option help ends in a period, and fix those that don't
373
        # Option help should be written in sentence form, and have a final
374
        # period and be all on a single line, because the display code will
375
        # wrap it.
376
        option_re = re.compile(r'^[A-Z][^\n]+\.$')
3755.1.1 by Vincent Ladeuil
Fix --verbose leaking into blackbox tests.
377
        for scope, opt in self.get_builtin_command_options():
378
            if not opt.help:
379
                msgs.append('%-16s %-16s %s' %
380
                       ((scope or 'GLOBAL'), opt.name, 'NO HELP'))
381
            elif not option_re.match(opt.help):
382
                msgs.append('%-16s %-16s %s' %
383
                        ((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
384
        if msgs:
385
            self.fail("The following options don't match the style guide:\n"
386
                    + '\n'.join(msgs))
1551.18.12 by Aaron Bentley
Man page doesn't list hidden options (#131667)
387
388
    def test_is_hidden(self):
389
        registry = bzrdir.BzrDirFormatRegistry()
1551.18.13 by Aaron Bentley
Update test from review suggestions
390
        registry.register_metadir('hidden', 'HiddenFormat',
391
            'hidden help text', hidden=True)
392
        registry.register_metadir('visible', 'VisibleFormat',
393
            'visible help text', hidden=False)
1551.18.12 by Aaron Bentley
Man page doesn't list hidden options (#131667)
394
        format = option.RegistryOption('format', '', registry, str)
395
        self.assertTrue(format.is_hidden('hidden'))
396
        self.assertFalse(format.is_hidden('visible'))
2768.1.11 by Ian Clatworthy
Add new option tests for custom help, callbacks and verbose/quiet linkage
397
398
    def test_option_custom_help(self):
399
        the_opt = option.Option.OPTIONS['help']
400
        orig_help = the_opt.help[:]
401
        my_opt = option.custom_help('help', 'suggest lottery numbers')
402
        # Confirm that my_opt has my help and the original is unchanged
403
        self.assertEqual('suggest lottery numbers', my_opt.help)
404
        self.assertEqual(orig_help, the_opt.help)
405
406
407
class TestVerboseQuietLinkage(TestCase):
408
409
    def check(self, parser, level, args):
410
        option._verbosity_level = 0
411
        opts, args = parser.parse_args(args)
412
        self.assertEqual(level, option._verbosity_level)
413
414
    def test_verbose_quiet_linkage(self):
415
        parser = option.get_optparser(option.Option.STD_OPTIONS)
416
        self.check(parser, 0, [])
417
        self.check(parser, 1, ['-v'])
418
        self.check(parser, 2, ['-v', '-v'])
419
        self.check(parser, -1, ['-q'])
420
        self.check(parser, -2, ['-qq'])
421
        self.check(parser, -1, ['-v', '-v', '-q'])
422
        self.check(parser, 2, ['-q', '-v', '-v'])
423
        self.check(parser, 0, ['--no-verbose'])
424
        self.check(parser, 0, ['-v', '-q', '--no-quiet'])