~bzr-pqm/bzr/bzr.dev

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