~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_options.py

  • Committer: John Arbash Meinel
  • Date: 2008-08-18 22:34:21 UTC
  • mto: (3606.5.6 1.6)
  • mto: This revision was merged to the branch mainline in revision 3641.
  • Revision ID: john@arbash-meinel.com-20080818223421-todjny24vj4faj4t
Add tests for the fetching behavior.

The proper parameter passed is 'unordered' add an assert for it, and
fix callers that were passing 'unsorted' instead.
Add tests that we make the right get_record_stream call based
on the value of _fetch_uses_deltas.
Fix the fetch request for signatures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006, 2007 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
16
 
 
17
import re
 
18
 
 
19
from bzrlib import (
 
20
    bzrdir,
 
21
    commands,
 
22
    errors,
 
23
    option,
 
24
    )
 
25
from bzrlib.builtins import cmd_commit
 
26
from bzrlib.commands import Command, parse_args
3
27
from bzrlib.tests import TestCase
4
 
from bzrlib.commands import Command, parse_args
5
 
from bzrlib.builtins import cmd_commit, cmd_log, cmd_status
6
 
 
7
 
# TODO: might be nice to just parse them into a structured form and test
8
 
# against that, rather than running the whole command.
 
28
from bzrlib.repofmt import knitrepo
 
29
 
 
30
 
 
31
def parse(options, args):
 
32
    parser = option.get_optparser(dict((o.name, o) for o in options))
 
33
    return parser.parse_args(args)
 
34
 
9
35
 
10
36
class OptionTests(TestCase):
11
37
    """Command-line option tests"""
12
38
 
13
39
    def test_parse_args(self):
14
40
        """Option parser"""
15
 
        eq = self.assertEquals
16
 
        eq(parse_args(cmd_commit(), ['--help']),
17
 
           ([], {'help': True}))
18
 
        eq(parse_args(cmd_status(), ['--all']),
19
 
           ([], {'all': True}))
20
 
        eq(parse_args(cmd_commit(), ['--message=biter']),
21
 
           ([], {'message': 'biter'}))
22
 
        ## eq(parse_args(cmd_log(),  '-r 500'.split()),
23
 
        ##   ([], {'revision': RevisionSpec_int(500)}))
 
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']),
 
45
           ([], {'exclude': [], 'fixes': [], 'help': True}))
 
46
        self.assertEqual(parse_args(cmd_commit(), ['--message=biter']),
 
47
           ([], {'exclude': [], 'fixes': [], 'message': 'biter'}))
24
48
 
25
49
    def test_no_more_opts(self):
26
50
        """Terminated options"""
27
 
        self.assertEquals(parse_args(cmd_commit(), ['--', '-file-with-dashes']),
28
 
                          (['-file-with-dashes'], {}))
 
51
        self.assertEqual(parse_args(cmd_commit(), ['--', '-file-with-dashes']),
 
52
                          (['-file-with-dashes'], {'exclude': [], 'fixes': []}))
29
53
 
30
54
    def test_option_help(self):
31
55
        """Options have help strings."""
32
 
        out, err = self.run_bzr_captured(['commit', '--help'])
33
 
        self.assertContainsRe(out, r'--file.*file containing commit message')
34
 
        self.assertContainsRe(out, r'--help.*-h')
 
56
        out, err = self.run_bzr('commit --help')
 
57
        self.assertContainsRe(out,
 
58
                r'--file(.|\n)*Take commit message from this file\.')
 
59
        self.assertContainsRe(out, r'-h.*--help')
35
60
 
36
61
    def test_option_help_global(self):
37
62
        """Global options have help strings."""
38
 
        out, err = self.run_bzr_captured(['help', 'status'])
39
 
        self.assertContainsRe(out, r'--show-ids.*show internal object')
 
63
        out, err = self.run_bzr('help status')
 
64
        self.assertContainsRe(out, r'--show-ids.*Show internal object.')
40
65
 
41
66
    def test_option_arg_help(self):
42
67
        """Help message shows option arguments."""
43
 
        out, err = self.run_bzr_captured(['help', 'commit'])
44
 
        self.assertEquals(err, '')
 
68
        out, err = self.run_bzr('help commit')
 
69
        self.assertEqual(err, '')
45
70
        self.assertContainsRe(out, r'--file[ =]MSGFILE')
46
71
 
47
72
    def test_unknown_short_opt(self):
48
 
        out, err = self.run_bzr_captured(['help', '-r'], retcode=3)
49
 
        self.assertContainsRe(err, r'unknown short option')
50
 
 
51
 
 
52
 
#     >>> parse_args('log -r 500'.split())
53
 
#     (['log'], {'revision': [<RevisionSpec_int 500>]})
54
 
#     >>> parse_args('log -r500..600'.split())
55
 
#     (['log'], {'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
56
 
#     >>> parse_args('log -vr500..600'.split())
57
 
#     (['log'], {'verbose': True, 'revision': [<RevisionSpec_int 500>, <RevisionSpec_int 600>]})
58
 
#     >>> parse_args('log -rrevno:500..600'.split()) #the r takes an argument
59
 
#     (['log'], {'revision': [<RevisionSpec_revno revno:500>, <RevisionSpec_int 600>]})
 
73
        out, err = self.run_bzr('help -r', retcode=3)
 
74
        self.assertContainsRe(err, r'no such option')
 
75
 
 
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
 
 
81
    def test_allow_dash(self):
 
82
        """Test that we can pass a plain '-' as an argument."""
 
83
        self.assertEqual((['-']), parse_args(cmd_commit(), ['-'])[0])
 
84
 
 
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)
 
88
 
 
89
    def test_conversion(self):
 
90
        options = [option.Option('hello')]
 
91
        opts, args = self.parse(options, ['--no-hello', '--hello'])
 
92
        self.assertEqual(True, opts.hello)
 
93
        opts, args = self.parse(options, [])
 
94
        self.assertFalse(hasattr(opts, 'hello'))
 
95
        opts, args = self.parse(options, ['--hello', '--no-hello'])
 
96
        self.assertEqual(False, opts.hello)
 
97
        options = [option.Option('number', type=int)]
 
98
        opts, args = self.parse(options, ['--number', '6'])
 
99
        self.assertEqual(6, opts.number)
 
100
        self.assertRaises(errors.BzrCommandError, self.parse, options,
 
101
                          ['--number'])
 
102
        self.assertRaises(errors.BzrCommandError, self.parse, options,
 
103
                          ['--no-number'])
 
104
 
 
105
    def test_registry_conversion(self):
 
106
        registry = bzrdir.BzrDirFormatRegistry()
 
107
        registry.register_metadir('one', 'RepositoryFormat7', 'one help')
 
108
        registry.register_metadir('two', 'RepositoryFormatKnit1', 'two help')
 
109
        registry.register_metadir('hidden', 'RepositoryFormatKnit1',
 
110
            'two help', hidden=True)
 
111
        registry.set_default('one')
 
112
        options = [option.RegistryOption('format', '', registry, str)]
 
113
        opts, args = self.parse(options, ['--format', 'one'])
 
114
        self.assertEqual({'format':'one'}, opts)
 
115
        opts, args = self.parse(options, ['--format', 'two'])
 
116
        self.assertEqual({'format':'two'}, opts)
 
117
        self.assertRaises(errors.BadOptionValue, self.parse, options,
 
118
                          ['--format', 'three'])
 
119
        self.assertRaises(errors.BzrCommandError, self.parse, options,
 
120
                          ['--two'])
 
121
        options = [option.RegistryOption('format', '', registry, str,
 
122
                   value_switches=True)]
 
123
        opts, args = self.parse(options, ['--two'])
 
124
        self.assertEqual({'format':'two'}, opts)
 
125
        opts, args = self.parse(options, ['--two', '--one'])
 
126
        self.assertEqual({'format':'one'}, opts)
 
127
        opts, args = self.parse(options, ['--two', '--one',
 
128
                                          '--format', 'two'])
 
129
        self.assertEqual({'format':'two'}, opts)
 
130
        options = [option.RegistryOption('format', '', registry, str,
 
131
                   enum_switch=False)]
 
132
        self.assertRaises(errors.BzrCommandError, self.parse, options,
 
133
                          ['--format', 'two'])
 
134
 
 
135
    def test_override(self):
 
136
        options = [option.Option('hello', type=str),
 
137
                   option.Option('hi', type=str, param_name='hello')]
 
138
        opts, args = self.parse(options, ['--hello', 'a', '--hello', 'b'])
 
139
        self.assertEqual('b', opts.hello)
 
140
        opts, args = self.parse(options, ['--hello', 'b', '--hello', 'a'])
 
141
        self.assertEqual('a', opts.hello)
 
142
        opts, args = self.parse(options, ['--hello', 'a', '--hi', 'b'])
 
143
        self.assertEqual('b', opts.hello)
 
144
        opts, args = self.parse(options, ['--hi', 'b', '--hello', 'a'])
 
145
        self.assertEqual('a', opts.hello)
 
146
 
 
147
    def test_registry_converter(self):
 
148
        options = [option.RegistryOption('format', '',
 
149
                   bzrdir.format_registry, bzrdir.format_registry.make_bzrdir)]
 
150
        opts, args = self.parse(options, ['--format', 'knit'])
 
151
        self.assertIsInstance(opts.format.repository_format,
 
152
                              knitrepo.RepositoryFormatKnit1)
 
153
 
 
154
    def test_from_kwargs(self):
 
155
        my_option = option.RegistryOption.from_kwargs('my-option',
 
156
            help='test option', short='be short', be_long='go long')
 
157
        self.assertEqual(['my-option'],
 
158
            [x[0] for x in my_option.iter_switches()])
 
159
        my_option = option.RegistryOption.from_kwargs('my-option',
 
160
            help='test option', title="My option", short='be short',
 
161
            be_long='go long', value_switches=True)
 
162
        self.assertEqual(['my-option', 'be-long', 'short'],
 
163
            [x[0] for x in my_option.iter_switches()])
 
164
        self.assertEqual('test option', my_option.help)
 
165
 
 
166
    def test_help(self):
 
167
        registry = bzrdir.BzrDirFormatRegistry()
 
168
        registry.register_metadir('one', 'RepositoryFormat7', 'one help')
 
169
        registry.register_metadir('two',
 
170
            'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
171
            'two help',
 
172
            )
 
173
        registry.register_metadir('hidden', 'RepositoryFormat7', 'hidden help',
 
174
            hidden=True)
 
175
        registry.set_default('one')
 
176
        options = [option.RegistryOption('format', 'format help', registry,
 
177
                   str, value_switches=True, title='Formats')]
 
178
        parser = option.get_optparser(dict((o.name, o) for o in options))
 
179
        value = parser.format_option_help()
 
180
        self.assertContainsRe(value, 'format.*format help')
 
181
        self.assertContainsRe(value, 'one.*one help')
 
182
        self.assertContainsRe(value, 'Formats:\n *--format')
 
183
        self.assertNotContainsRe(value, 'hidden help')
 
184
 
 
185
    def test_iter_switches(self):
 
186
        opt = option.Option('hello', help='fg')
 
187
        self.assertEqual(list(opt.iter_switches()),
 
188
                         [('hello', None, None, 'fg')])
 
189
        opt = option.Option('hello', help='fg', type=int)
 
190
        self.assertEqual(list(opt.iter_switches()),
 
191
                         [('hello', None, 'ARG', 'fg')])
 
192
        opt = option.Option('hello', help='fg', type=int, argname='gar')
 
193
        self.assertEqual(list(opt.iter_switches()),
 
194
                         [('hello', None, 'GAR', 'fg')])
 
195
        registry = bzrdir.BzrDirFormatRegistry()
 
196
        registry.register_metadir('one', 'RepositoryFormat7', 'one help')
 
197
        registry.register_metadir('two',
 
198
                'bzrlib.repofmt.knitrepo.RepositoryFormatKnit1',
 
199
                'two help',
 
200
                )
 
201
        registry.set_default('one')
 
202
        opt = option.RegistryOption('format', 'format help', registry,
 
203
                                    value_switches=False)
 
204
        self.assertEqual(list(opt.iter_switches()),
 
205
                         [('format', None, 'ARG', 'format help')])
 
206
        opt = option.RegistryOption('format', 'format help', registry,
 
207
                                    value_switches=True)
 
208
        self.assertEqual(list(opt.iter_switches()),
 
209
                         [('format', None, 'ARG', 'format help'),
 
210
                          ('default', None, None, 'one help'),
 
211
                          ('one', None, None, 'one help'),
 
212
                          ('two', None, None, 'two help'),
 
213
                          ])
 
214
 
 
215
    def test_option_callback_bool(self):
 
216
        "Test booleans get True and False passed correctly to a callback."""
 
217
        cb_calls = []
 
218
        def cb(option, name, value, parser):
 
219
            cb_calls.append((option,name,value,parser))
 
220
        options = [option.Option('hello', custom_callback=cb)]
 
221
        opts, args = self.parse(options, ['--hello', '--no-hello'])
 
222
        self.assertEqual(2, len(cb_calls))
 
223
        opt,name,value,parser = cb_calls[0]
 
224
        self.assertEqual('hello', name)
 
225
        self.assertTrue(value)
 
226
        opt,name,value,parser = cb_calls[1]
 
227
        self.assertEqual('hello', name)
 
228
        self.assertFalse(value)
 
229
 
 
230
    def test_option_callback_str(self):
 
231
        """Test callbacks work for string options both long and short."""
 
232
        cb_calls = []
 
233
        def cb(option, name, value, parser):
 
234
            cb_calls.append((option,name,value,parser))
 
235
        options = [option.Option('hello', type=str, custom_callback=cb,
 
236
            short_name='h')]
 
237
        opts, args = self.parse(options, ['--hello', 'world', '-h', 'mars'])
 
238
        self.assertEqual(2, len(cb_calls))
 
239
        opt,name,value,parser = cb_calls[0]
 
240
        self.assertEqual('hello', name)
 
241
        self.assertEqual('world', value)
 
242
        opt,name,value,parser = cb_calls[1]
 
243
        self.assertEqual('hello', name)
 
244
        self.assertEqual('mars', value)
 
245
 
 
246
 
 
247
class TestListOptions(TestCase):
 
248
    """Tests for ListOption, used to specify lists on the command-line."""
 
249
 
 
250
    def parse(self, options, args):
 
251
        parser = option.get_optparser(dict((o.name, o) for o in options))
 
252
        return parser.parse_args(args)
 
253
 
 
254
    def test_list_option(self):
 
255
        options = [option.ListOption('hello', type=str)]
 
256
        opts, args = self.parse(options, ['--hello=world', '--hello=sailor'])
 
257
        self.assertEqual(['world', 'sailor'], opts.hello)
 
258
 
 
259
    def test_list_option_no_arguments(self):
 
260
        options = [option.ListOption('hello', type=str)]
 
261
        opts, args = self.parse(options, [])
 
262
        self.assertEqual([], opts.hello)
 
263
 
 
264
    def test_list_option_with_int_type(self):
 
265
        options = [option.ListOption('hello', type=int)]
 
266
        opts, args = self.parse(options, ['--hello=2', '--hello=3'])
 
267
        self.assertEqual([2, 3], opts.hello)
 
268
 
 
269
    def test_list_option_with_int_type_can_be_reset(self):
 
270
        options = [option.ListOption('hello', type=int)]
 
271
        opts, args = self.parse(options, ['--hello=2', '--hello=3',
 
272
                                          '--hello=-', '--hello=5'])
 
273
        self.assertEqual([5], opts.hello)
 
274
 
 
275
    def test_list_option_can_be_reset(self):
 
276
        """Passing an option of '-' to a list option should reset the list."""
 
277
        options = [option.ListOption('hello', type=str)]
 
278
        opts, args = self.parse(
 
279
            options, ['--hello=a', '--hello=b', '--hello=-', '--hello=c'])
 
280
        self.assertEqual(['c'], opts.hello)
 
281
 
 
282
    def test_option_callback_list(self):
 
283
        """Test callbacks work for list options."""
 
284
        cb_calls = []
 
285
        def cb(option, name, value, parser):
 
286
            # Note that the value is a reference so copy to keep it
 
287
            cb_calls.append((option,name,value[:],parser))
 
288
        options = [option.ListOption('hello', type=str, custom_callback=cb)]
 
289
        opts, args = self.parse(options, ['--hello=world', '--hello=mars',
 
290
            '--hello=-'])
 
291
        self.assertEqual(3, len(cb_calls))
 
292
        opt,name,value,parser = cb_calls[0]
 
293
        self.assertEqual('hello', name)
 
294
        self.assertEqual(['world'], value)
 
295
        opt,name,value,parser = cb_calls[1]
 
296
        self.assertEqual('hello', name)
 
297
        self.assertEqual(['world', 'mars'], value)
 
298
        opt,name,value,parser = cb_calls[2]
 
299
        self.assertEqual('hello', name)
 
300
        self.assertEqual([], value)
 
301
 
 
302
 
 
303
class TestOptionDefinitions(TestCase):
 
304
    """Tests for options in the Bazaar codebase."""
 
305
 
 
306
    def get_builtin_command_options(self):
 
307
        g = []
 
308
        for cmd_name, cmd_class in sorted(commands.get_all_cmds()):
 
309
            cmd = cmd_class()
 
310
            for opt_name, opt in sorted(cmd.options().items()):
 
311
                g.append((cmd_name, opt))
 
312
        return g
 
313
 
 
314
    def test_global_options_used(self):
 
315
        # In the distant memory, options could only be declared globally.  Now
 
316
        # we prefer to declare them in the command, unless like -r they really
 
317
        # are used very widely with the exact same meaning.  So this checks
 
318
        # for any that should be garbage collected.
 
319
        g = dict(option.Option.OPTIONS.items())
 
320
        used_globals = {}
 
321
        msgs = []
 
322
        for cmd_name, cmd_class in sorted(commands.get_all_cmds()):
 
323
            for option_or_name in sorted(cmd_class.takes_options):
 
324
                if not isinstance(option_or_name, basestring):
 
325
                    self.assertIsInstance(option_or_name, option.Option)
 
326
                elif not option_or_name in g:
 
327
                    msgs.append("apparent reference to undefined "
 
328
                        "global option %r from %r"
 
329
                        % (option_or_name, cmd_class))
 
330
                else:
 
331
                    used_globals.setdefault(option_or_name, []).append(cmd_name)
 
332
        unused_globals = set(g.keys()) - set(used_globals.keys())
 
333
        # not enforced because there might be plugins that use these globals
 
334
        ## for option_name in sorted(unused_globals):
 
335
        ##    msgs.append("unused global option %r" % option_name)
 
336
        ## for option_name, cmds in sorted(used_globals.items()):
 
337
        ##     if len(cmds) <= 1:
 
338
        ##         msgs.append("global option %r is only used by %r"
 
339
        ##                 % (option_name, cmds))
 
340
        if msgs:
 
341
            self.fail("problems with global option definitions:\n"
 
342
                    + '\n'.join(msgs))
 
343
 
 
344
    def test_option_grammar(self):
 
345
        msgs = []
 
346
        # Option help should be written in sentence form, and have a final
 
347
        # period and be all on a single line, because the display code will
 
348
        # wrap it.
 
349
        option_re = re.compile(r'^[A-Z][^\n]+\.$')
 
350
        for scope, option in self.get_builtin_command_options():
 
351
            if not option.help:
 
352
                msgs.append('%-16s %-16s %s' %
 
353
                       ((scope or 'GLOBAL'), option.name, 'NO HELP'))
 
354
            elif not option_re.match(option.help):
 
355
                msgs.append('%-16s %-16s %s' %
 
356
                        ((scope or 'GLOBAL'), option.name, option.help))
 
357
        if msgs:
 
358
            self.fail("The following options don't match the style guide:\n"
 
359
                    + '\n'.join(msgs))
 
360
 
 
361
    def test_is_hidden(self):
 
362
        registry = bzrdir.BzrDirFormatRegistry()
 
363
        registry.register_metadir('hidden', 'HiddenFormat',
 
364
            'hidden help text', hidden=True)
 
365
        registry.register_metadir('visible', 'VisibleFormat',
 
366
            'visible help text', hidden=False)
 
367
        format = option.RegistryOption('format', '', registry, str)
 
368
        self.assertTrue(format.is_hidden('hidden'))
 
369
        self.assertFalse(format.is_hidden('visible'))
 
370
 
 
371
    def test_option_custom_help(self):
 
372
        the_opt = option.Option.OPTIONS['help']
 
373
        orig_help = the_opt.help[:]
 
374
        my_opt = option.custom_help('help', 'suggest lottery numbers')
 
375
        # Confirm that my_opt has my help and the original is unchanged
 
376
        self.assertEqual('suggest lottery numbers', my_opt.help)
 
377
        self.assertEqual(orig_help, the_opt.help)
 
378
 
 
379
 
 
380
class TestVerboseQuietLinkage(TestCase):
 
381
 
 
382
    def check(self, parser, level, args):
 
383
        option._verbosity_level = 0
 
384
        opts, args = parser.parse_args(args)
 
385
        self.assertEqual(level, option._verbosity_level)
 
386
 
 
387
    def test_verbose_quiet_linkage(self):
 
388
        parser = option.get_optparser(option.Option.STD_OPTIONS)
 
389
        self.check(parser, 0, [])
 
390
        self.check(parser, 1, ['-v'])
 
391
        self.check(parser, 2, ['-v', '-v'])
 
392
        self.check(parser, -1, ['-q'])
 
393
        self.check(parser, -2, ['-qq'])
 
394
        self.check(parser, -1, ['-v', '-v', '-q'])
 
395
        self.check(parser, 2, ['-q', '-v', '-v'])
 
396
        self.check(parser, 0, ['--no-verbose'])
 
397
        self.check(parser, 0, ['-v', '-q', '--no-quiet'])