~bzr-pqm/bzr/bzr.dev

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