/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
1
# Copyright (C) 2005-2012, 2016 Canonical Ltd
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
2
#
1185.12.59 by Aaron Bentley
Added command-quieting test
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
7
#
1185.12.59 by Aaron Bentley
Added command-quieting test
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.
1887.1.1 by Adeodato Simó
Do not separate paragraphs in the copyright statement with blank lines,
12
#
1185.12.59 by Aaron Bentley
Added command-quieting test
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.12.59 by Aaron Bentley
Added command-quieting test
16
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
17
import errno
5264.1.2 by Robert Collins
Final fix for 'no help for command' issue. We now show a clean message
18
import inspect
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
19
import sys
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
20
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
21
from .. import (
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
22
    builtins,
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
23
    commands,
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
24
    config,
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
25
    errors,
4251.1.1 by Aaron Bentley
Support hidden options.
26
    option,
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
27
    tests,
6240.5.3 by Brian de Alwis
Addressed points from review:
28
    trace,
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
29
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
30
from ..commands import display_command
31
from . import TestSkipped
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
32
33
34
class TestCommands(tests.TestCase):
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
35
5264.1.2 by Robert Collins
Final fix for 'no help for command' issue. We now show a clean message
36
    def test_all_commands_have_help(self):
37
        commands._register_builtin_commands()
38
        commands_without_help = set()
39
        base_doc = inspect.getdoc(commands.Command)
40
        for cmd_name in commands.all_command_names():
41
            cmd = commands.get_cmd_object(cmd_name)
42
            cmd_help = cmd.help()
43
            if not cmd_help or cmd_help == base_doc:
44
                commands_without_help.append(cmd_name)
45
        self.assertLength(0, commands_without_help)
46
1185.12.59 by Aaron Bentley
Added command-quieting test
47
    def test_display_command(self):
1185.33.18 by Martin Pool
[patch] handle bad IOError subclass raised by urlopen
48
        """EPIPE message is selectively suppressed"""
1185.12.59 by Aaron Bentley
Added command-quieting test
49
        def pipe_thrower():
50
            raise IOError(errno.EPIPE, "Bogus pipe error")
51
        self.assertRaises(IOError, pipe_thrower)
7143.15.2 by Jelmer Vernooij
Run autopep8.
52
1185.12.59 by Aaron Bentley
Added command-quieting test
53
        @display_command
54
        def non_thrower():
55
            pipe_thrower()
56
        non_thrower()
7143.15.2 by Jelmer Vernooij
Run autopep8.
57
1185.12.59 by Aaron Bentley
Added command-quieting test
58
        @display_command
59
        def other_thrower():
60
            raise IOError(errno.ESPIPE, "Bogus pipe error")
61
        self.assertRaises(IOError, other_thrower)
62
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
63
    def test_unicode_command(self):
1948.1.8 by John Arbash Meinel
Don't raise UnicodeCommand on request, instead just let it fall out when we get to NoSuchCommand
64
        # This error is thrown when we can't find the command in the
65
        # list of available commands
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
66
        self.assertRaises(errors.CommandError,
1948.1.1 by John Arbash Meinel
Raise a reasonable error when a command is non-ascii
67
                          commands.run_bzr, [u'cmd\xb5'])
1948.1.8 by John Arbash Meinel
Don't raise UnicodeCommand on request, instead just let it fall out when we get to NoSuchCommand
68
69
    def test_unicode_option(self):
70
        # This error is actually thrown by optparse, when it
71
        # can't find the given option
1913.2.4 by Martin Pool
python2.5 apparently has trouble with unicode options
72
        import optparse
73
        if optparse.__version__ == "1.5.3":
74
            raise TestSkipped("optparse 1.5.3 can't handle unicode options")
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
75
        self.assertRaises(errors.CommandError,
1948.1.8 by John Arbash Meinel
Don't raise UnicodeCommand on request, instead just let it fall out when we get to NoSuchCommand
76
                          commands.run_bzr, ['log', u'--option\xb5'])
77
4251.1.1 by Aaron Bentley
Support hidden options.
78
    @staticmethod
79
    def get_command(options):
4251.1.7 by Aaron Bentley
Use generated subclass instead of patching Command instance
80
        class cmd_foo(commands.Command):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
81
            __doc__ = 'Bar'
4251.1.7 by Aaron Bentley
Use generated subclass instead of patching Command instance
82
83
            takes_options = options
84
85
        return cmd_foo()
4251.1.1 by Aaron Bentley
Support hidden options.
86
87
    def test_help_hidden(self):
88
        c = self.get_command([option.Option('foo', hidden=True)])
89
        self.assertNotContainsRe(c.get_help_text(), '--foo')
90
91
    def test_help_not_hidden(self):
92
        c = self.get_command([option.Option('foo', hidden=False)])
93
        self.assertContainsRe(c.get_help_text(), '--foo')
94
5255.5.1 by Ian Clatworthy
Ensure builtin_command_names() is initialized correctly
95
6161.1.5 by Vincent Ladeuil
Get rid of the --override-config long name, ensures the overrides are resest when the command has run.
96
class TestInsideCommand(tests.TestCaseInTempDir):
97
98
    def test_command_see_config_overrides(self):
99
        def run(cmd):
100
            # We override the run() command method so we can observe the
101
            # overrides from inside.
102
            c = config.GlobalStack()
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
103
            self.assertEqual('12', c.get('xx'))
104
            self.assertEqual('foo', c.get('yy'))
6161.1.5 by Vincent Ladeuil
Get rid of the --override-config long name, ensures the overrides are resest when the command has run.
105
        self.overrideAttr(builtins.cmd_rocks, 'run', run)
106
        self.run_bzr(['rocks', '-Oxx=12', '-Oyy=foo'])
107
        c = config.GlobalStack()
108
        # Ensure that we don't leak outside of the command
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
109
        self.assertEqual(None, c.get('xx'))
110
        self.assertEqual(None, c.get('yy'))
6161.1.5 by Vincent Ladeuil
Get rid of the --override-config long name, ensures the overrides are resest when the command has run.
111
112
5741.3.1 by Martin Pool
Add Command.invoked_as
113
class TestInvokedAs(tests.TestCase):
114
115
    def test_invoked_as(self):
116
        """The command object knows the actual name used to invoke it."""
5741.3.8 by Martin Pool
Fix slightly broken test
117
        commands.install_bzr_command_hooks()
118
        commands._register_builtin_commands()
5741.3.1 by Martin Pool
Add Command.invoked_as
119
        # get one from the real get_cmd_object.
120
        c = commands.get_cmd_object('ci')
121
        self.assertIsInstance(c, builtins.cmd_commit)
6614.1.3 by Vincent Ladeuil
Fix assertEquals being deprecated by using assertEqual.
122
        self.assertEqual(c.invoked_as, 'ci')
5741.3.1 by Martin Pool
Add Command.invoked_as
123
124
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
125
class TestGetAlias(tests.TestCase):
2155.2.3 by Marius Kruger
* commands.py
126
127
    def _get_config(self, config_text):
5345.2.9 by Vincent Ladeuil
Rename IniBaseConfig.from_bytes to from_string.
128
        my_config = config.GlobalConfig.from_string(config_text)
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
129
        return my_config
130
131
    def test_simple(self):
2155.2.3 by Marius Kruger
* commands.py
132
        my_config = self._get_config("[ALIASES]\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
133
                                     "diff=diff -r -2..-1\n")
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
134
        self.assertEqual([u'diff', u'-r', u'-2..-1'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
135
                         commands.get_alias("diff", config=my_config))
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
136
137
    def test_single_quotes(self):
2155.2.3 by Marius Kruger
* commands.py
138
        my_config = self._get_config("[ALIASES]\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
139
                                     "diff=diff -r -2..-1 --diff-options "
140
                                     "'--strip-trailing-cr -wp'\n")
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
141
        self.assertEqual([u'diff', u'-r', u'-2..-1', u'--diff-options',
142
                          u'--strip-trailing-cr -wp'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
143
                         commands.get_alias("diff", config=my_config))
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
144
145
    def test_double_quotes(self):
2155.2.3 by Marius Kruger
* commands.py
146
        my_config = self._get_config("[ALIASES]\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
147
                                     "diff=diff -r -2..-1 --diff-options "
148
                                     "\"--strip-trailing-cr -wp\"\n")
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
149
        self.assertEqual([u'diff', u'-r', u'-2..-1', u'--diff-options',
150
                          u'--strip-trailing-cr -wp'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
151
                         commands.get_alias("diff", config=my_config))
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
152
153
    def test_unicode(self):
2155.2.3 by Marius Kruger
* commands.py
154
        my_config = self._get_config("[ALIASES]\n"
7143.15.2 by Jelmer Vernooij
Run autopep8.
155
                                     u'iam=whoami "Erik B\u00e5gfors <erik@bagfors.nu>"\n')
2155.2.1 by Marius Kruger
* Get command aliases to respect quoted arguments.
156
        self.assertEqual([u'whoami', u'Erik B\u00e5gfors <erik@bagfors.nu>'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
157
                         commands.get_alias("iam", config=my_config))
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
158
159
160
class TestSeeAlso(tests.TestCase):
161
    """Tests for the see also functional of Command."""
162
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
163
    @staticmethod
164
    def _get_command_with_see_also(see_also):
165
        class ACommand(commands.Command):
166
            __doc__ = """A sample command."""
167
            _see_also = see_also
168
        return ACommand()
169
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
170
    def test_default_subclass_no_see_also(self):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
171
        command = self._get_command_with_see_also([])
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
172
        self.assertEqual([], command.get_see_also())
173
174
    def test__see_also(self):
175
        """When _see_also is defined, it sets the result of get_see_also()."""
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
176
        command = self._get_command_with_see_also(['bar', 'foo'])
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
177
        self.assertEqual(['bar', 'foo'], command.get_see_also())
178
179
    def test_deduplication(self):
180
        """Duplicates in _see_also are stripped out."""
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
181
        command = self._get_command_with_see_also(['foo', 'foo'])
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
182
        self.assertEqual(['foo'], command.get_see_also())
183
184
    def test_sorted(self):
185
        """_see_also is sorted by get_see_also."""
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
186
        command = self._get_command_with_see_also(['foo', 'bar'])
2425.2.1 by Robert Collins
Command objects can now declare related help topics by having _see_also
187
        self.assertEqual(['bar', 'foo'], command.get_see_also())
2432.1.21 by Robert Collins
Teach Command.get_help_text to show additional help cross references when supplied.
188
189
    def test_additional_terms(self):
190
        """Additional terms can be supplied and are deduped and sorted."""
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
191
        command = self._get_command_with_see_also(['foo', 'bar'])
2432.1.21 by Robert Collins
Teach Command.get_help_text to show additional help cross references when supplied.
192
        self.assertEqual(['bar', 'foo', 'gam'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
193
                         command.get_see_also(['gam', 'bar', 'gam']))
2432.1.21 by Robert Collins
Teach Command.get_help_text to show additional help cross references when supplied.
194
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
195
196
class TestRegisterLazy(tests.TestCase):
197
198
    def setUp(self):
6552.1.3 by Vincent Ladeuil
Use super() instead of calling <base>.setup(self), as the original fix illustrated a too-easy-to-fall-into trap.
199
        super(TestRegisterLazy, self).setUp()
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
200
        import breezy.tests.fake_command
201
        del sys.modules['breezy.tests.fake_command']
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
202
        global lazy_command_imported
203
        lazy_command_imported = False
4119.3.8 by Robert Collins
Get missing command support sorted out.
204
        commands.install_bzr_command_hooks()
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
205
206
    @staticmethod
207
    def remove_fake():
208
        commands.plugin_cmds.remove('fake')
209
210
    def assertIsFakeCommand(self, cmd_obj):
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
211
        from breezy.tests.fake_command import cmd_fake
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
212
        self.assertIsInstance(cmd_obj, cmd_fake)
213
214
    def test_register_lazy(self):
215
        """Ensure lazy registration works"""
216
        commands.plugin_cmds.register_lazy('cmd_fake', [],
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
217
                                           'breezy.tests.fake_command')
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
218
        self.addCleanup(self.remove_fake)
219
        self.assertFalse(lazy_command_imported)
220
        fake_instance = commands.get_cmd_object('fake')
221
        self.assertTrue(lazy_command_imported)
222
        self.assertIsFakeCommand(fake_instance)
223
224
    def test_get_unrelated_does_not_import(self):
225
        commands.plugin_cmds.register_lazy('cmd_fake', [],
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
226
                                           'breezy.tests.fake_command')
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
227
        self.addCleanup(self.remove_fake)
228
        commands.get_cmd_object('status')
229
        self.assertFalse(lazy_command_imported)
230
231
    def test_aliases(self):
232
        commands.plugin_cmds.register_lazy('cmd_fake', ['fake_alias'],
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
233
                                           'breezy.tests.fake_command')
3785.1.4 by Aaron Bentley
Enable lazy-loading of commands
234
        self.addCleanup(self.remove_fake)
235
        fake_instance = commands.get_cmd_object('fake_alias')
236
        self.assertIsFakeCommand(fake_instance)
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
237
238
239
class TestExtendCommandHook(tests.TestCase):
240
241
    def test_fires_on_get_cmd_object(self):
242
        # The extend_command(cmd) hook fires when commands are delivered to the
243
        # ui, not simply at registration (because lazy registered plugin
244
        # commands are registered).
245
        # when they are simply created.
246
        hook_calls = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
247
        commands.install_bzr_command_hooks()
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
248
        commands.Command.hooks.install_named_hook(
249
            "extend_command", hook_calls.append, None)
250
        # create a command, should not fire
7143.15.2 by Jelmer Vernooij
Run autopep8.
251
5018.1.12 by Martin Pool
Tests for commands must now properly register them, not just poke them into bzrlib.builtins
252
        class cmd_test_extend_command_hook(commands.Command):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
253
            __doc__ = """A sample command."""
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
254
        self.assertEqual([], hook_calls)
255
        # -- as a builtin
256
        # register the command class, should not fire
257
        try:
7143.15.2 by Jelmer Vernooij
Run autopep8.
258
            commands.builtin_command_registry.register(
259
                cmd_test_extend_command_hook)
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
260
            self.assertEqual([], hook_calls)
261
            # and ask for the object, should fire
262
            cmd = commands.get_cmd_object('test-extend-command-hook')
263
            # For resilience - to ensure all code paths hit it - we
264
            # fire on everything returned in the 'cmd_dict', which is currently
265
            # all known commands, so assert that cmd is in hook_calls
266
            self.assertSubset([cmd], hook_calls)
267
            del hook_calls[:]
268
        finally:
7143.15.2 by Jelmer Vernooij
Run autopep8.
269
            commands.builtin_command_registry.remove(
270
                'test-extend-command-hook')
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
271
        # -- as a plugin lazy registration
272
        try:
273
            # register the command class, should not fire
274
            commands.plugin_cmds.register_lazy('cmd_fake', [],
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
275
                                               'breezy.tests.fake_command')
4000.1.1 by Robert Collins
Add a new hook Commands['extend_command'] for plugins that want to alter commands without overriding the entire command.
276
            self.assertEqual([], hook_calls)
277
            # and ask for the object, should fire
278
            cmd = commands.get_cmd_object('fake')
279
            self.assertEqual([cmd], hook_calls)
280
        finally:
281
            commands.plugin_cmds.remove('fake')
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
282
283
284
class TestGetCommandHook(tests.TestCase):
285
286
    def test_fires_on_get_cmd_object(self):
287
        # The get_command(cmd) hook fires when commands are delivered to the
288
        # ui.
4119.3.8 by Robert Collins
Get missing command support sorted out.
289
        commands.install_bzr_command_hooks()
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
290
        hook_calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
291
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
292
        class ACommand(commands.Command):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
293
            __doc__ = """A sample command."""
7143.15.2 by Jelmer Vernooij
Run autopep8.
294
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
295
        def get_cmd(cmd_or_None, cmd_name):
296
            hook_calls.append(('called', cmd_or_None, cmd_name))
297
            if cmd_name in ('foo', 'info'):
298
                return ACommand()
299
        commands.Command.hooks.install_named_hook(
300
            "get_command", get_cmd, None)
301
        # create a command directly, should not fire
302
        cmd = ACommand()
303
        self.assertEqual([], hook_calls)
304
        # ask by name, should fire and give us our command
305
        cmd = commands.get_cmd_object('foo')
306
        self.assertEqual([('called', None, 'foo')], hook_calls)
307
        self.assertIsInstance(cmd, ACommand)
308
        del hook_calls[:]
309
        # ask by a name that is supplied by a builtin - the hook should still
310
        # fire and we still get our object, but we should see the builtin
311
        # passed to the hook.
312
        cmd = commands.get_cmd_object('info')
313
        self.assertIsInstance(cmd, ACommand)
314
        self.assertEqual(1, len(hook_calls))
315
        self.assertEqual('info', hook_calls[0][2])
316
        self.assertIsInstance(hook_calls[0][1], builtins.cmd_info)
317
318
6690.5.2 by Jelmer Vernooij
Add tests for guess_command.
319
class TestCommandNotFound(tests.TestCase):
320
321
    def setUp(self):
322
        super(TestCommandNotFound, self).setUp()
323
        commands._register_builtin_commands()
324
        commands.install_bzr_command_hooks()
325
326
    def test_not_found_no_suggestion(self):
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
327
        e = self.assertRaises(errors.CommandError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
328
                              commands.get_cmd_object, 'idontexistand')
6690.5.2 by Jelmer Vernooij
Add tests for guess_command.
329
        self.assertEqual('unknown command "idontexistand"', str(e))
330
331
    def test_not_found_with_suggestion(self):
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
332
        e = self.assertRaises(errors.CommandError,
7143.15.2 by Jelmer Vernooij
Run autopep8.
333
                              commands.get_cmd_object, 'statue')
6690.5.2 by Jelmer Vernooij
Add tests for guess_command.
334
        self.assertEqual('unknown command "statue". Perhaps you meant "status"',
7143.15.2 by Jelmer Vernooij
Run autopep8.
335
                         str(e))
6690.5.2 by Jelmer Vernooij
Add tests for guess_command.
336
337
4119.3.8 by Robert Collins
Get missing command support sorted out.
338
class TestGetMissingCommandHook(tests.TestCase):
339
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
340
    def hook_missing(self):
341
        """Hook get_missing_command for testing."""
342
        self.hook_calls = []
7143.15.2 by Jelmer Vernooij
Run autopep8.
343
4119.3.8 by Robert Collins
Get missing command support sorted out.
344
        class ACommand(commands.Command):
5131.2.6 by Martin
Fix more tests which were failing under -OO that had been missed earlier
345
            __doc__ = """A sample command."""
7143.15.2 by Jelmer Vernooij
Run autopep8.
346
4119.3.8 by Robert Collins
Get missing command support sorted out.
347
        def get_missing_cmd(cmd_name):
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
348
            self.hook_calls.append(('called', cmd_name))
4119.3.8 by Robert Collins
Get missing command support sorted out.
349
            if cmd_name in ('foo', 'info'):
350
                return ACommand()
351
        commands.Command.hooks.install_named_hook(
352
            "get_missing_command", get_missing_cmd, None)
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
353
        self.ACommand = ACommand
354
355
    def test_fires_on_get_cmd_object(self):
356
        # The get_missing_command(cmd) hook fires when commands are delivered to the
357
        # ui.
358
        self.hook_missing()
4119.3.8 by Robert Collins
Get missing command support sorted out.
359
        # create a command directly, should not fire
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
360
        self.cmd = self.ACommand()
361
        self.assertEqual([], self.hook_calls)
4119.3.8 by Robert Collins
Get missing command support sorted out.
362
        # ask by name, should fire and give us our command
363
        cmd = commands.get_cmd_object('foo')
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
364
        self.assertEqual([('called', 'foo')], self.hook_calls)
365
        self.assertIsInstance(cmd, self.ACommand)
366
        del self.hook_calls[:]
4119.3.8 by Robert Collins
Get missing command support sorted out.
367
        # ask by a name that is supplied by a builtin - the hook should not
368
        # fire and we still get our object.
369
        commands.install_bzr_command_hooks()
370
        cmd = commands.get_cmd_object('info')
371
        self.assertNotEqual(None, cmd)
5058.2.1 by Robert Collins
* ``bzr help`` will no longer trigger the get_missing_command hook when
372
        self.assertEqual(0, len(self.hook_calls))
373
374
    def test_skipped_on_HelpCommandIndex_get_topics(self):
375
        # The get_missing_command(cmd_name) hook is not fired when
376
        # looking up help topics.
377
        self.hook_missing()
378
        topic = commands.HelpCommandIndex()
379
        topics = topic.get_topics('foo')
380
        self.assertEqual([], self.hook_calls)
4119.3.8 by Robert Collins
Get missing command support sorted out.
381
382
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
383
class TestListCommandHook(tests.TestCase):
384
385
    def test_fires_on_all_command_names(self):
386
        # The list_commands() hook fires when all_command_names() is invoked.
387
        hook_calls = []
4119.3.8 by Robert Collins
Get missing command support sorted out.
388
        commands.install_bzr_command_hooks()
7143.15.2 by Jelmer Vernooij
Run autopep8.
389
4119.3.4 by Robert Collins
Add Command lookup hooks: list_commands and get_command.
390
        def list_my_commands(cmd_names):
391
            hook_calls.append('called')
392
            cmd_names.update(['foo', 'bar'])
393
            return cmd_names
394
        commands.Command.hooks.install_named_hook(
395
            "list_commands", list_my_commands, None)
396
        # Get a command, which should not trigger the hook.
397
        cmd = commands.get_cmd_object('info')
398
        self.assertEqual([], hook_calls)
399
        # Get all command classes (for docs and shell completion).
400
        cmds = list(commands.all_command_names())
401
        self.assertEqual(['called'], hook_calls)
402
        self.assertSubset(['foo', 'bar'], cmds)
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
403
7143.15.2 by Jelmer Vernooij
Run autopep8.
404
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
405
class TestPreAndPostCommandHooks(tests.TestCase):
6619.3.9 by Jelmer Vernooij
Run 2to3 standarderror fixer.
406
    class TestError(Exception):
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
407
        __doc__ = """A test exception."""
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
408
409
    def test_pre_and_post_hooks(self):
410
        hook_calls = []
411
412
        def pre_command(cmd):
413
            self.assertEqual([], hook_calls)
414
            hook_calls.append('pre')
415
6240.5.7 by Jelmer Vernooij
Drop exception suppression support.
416
        def post_command(cmd):
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
417
            self.assertEqual(['pre', 'run'], hook_calls)
418
            hook_calls.append('post')
419
420
        def run(cmd):
421
            self.assertEqual(['pre'], hook_calls)
422
            hook_calls.append('run')
423
424
        self.overrideAttr(builtins.cmd_rocks, 'run', run)
425
        commands.install_bzr_command_hooks()
426
        commands.Command.hooks.install_named_hook(
427
            "pre_command", pre_command, None)
428
        commands.Command.hooks.install_named_hook(
429
            "post_command", post_command, None)
430
431
        self.assertEqual([], hook_calls)
432
        self.run_bzr(['rocks', '-Oxx=12', '-Oyy=foo'])
433
        self.assertEqual(['pre', 'run', 'post'], hook_calls)
434
435
    def test_post_hook_provided_exception(self):
436
        hook_calls = []
437
6240.5.7 by Jelmer Vernooij
Drop exception suppression support.
438
        def post_command(cmd):
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
439
            hook_calls.append('post')
440
441
        def run(cmd):
442
            hook_calls.append('run')
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
443
            raise self.TestError()
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
444
445
        self.overrideAttr(builtins.cmd_rocks, 'run', run)
446
        commands.install_bzr_command_hooks()
447
        commands.Command.hooks.install_named_hook(
448
            "post_command", post_command, None)
449
450
        self.assertEqual([], hook_calls)
6240.5.7 by Jelmer Vernooij
Drop exception suppression support.
451
        self.assertRaises(self.TestError, commands.run_bzr, [u'rocks'])
6240.5.1 by Brian de Alwis
Introduce two new command hooks, 'pre_command' and 'post_command',
452
        self.assertEqual(['run', 'post'], hook_calls)
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
453
454
    def test_pre_command_error(self):
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
455
        """Ensure an CommandError in pre_command aborts the command"""
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
456
457
        hook_calls = []
458
459
        def pre_command(cmd):
460
            hook_calls.append('pre')
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
461
            # verify that all subclasses of CommandError caught too
6731.1.5 by Jelmer Vernooij
Fix import errors.
462
            raise commands.BzrOptionError()
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
463
464
        def post_command(cmd, e):
465
            self.fail('post_command should not be called')
466
467
        def run(cmd):
468
            self.fail('command should not be called')
469
470
        self.overrideAttr(builtins.cmd_rocks, 'run', run)
471
        commands.install_bzr_command_hooks()
472
        commands.Command.hooks.install_named_hook(
473
            "pre_command", pre_command, None)
474
        commands.Command.hooks.install_named_hook(
475
            "post_command", post_command, None)
476
477
        self.assertEqual([], hook_calls)
7490.61.1 by Jelmer Vernooij
Rename BzrCommandError to CommandError.
478
        self.assertRaises(errors.CommandError,
6240.5.4 by Brian de Alwis
Modified proposal as described on Dec 12:
479
                          commands.run_bzr, [u'rocks'])
480
        self.assertEqual(['pre'], hook_calls)
481
6690.5.2 by Jelmer Vernooij
Add tests for guess_command.
482
483
class GuessCommandTests(tests.TestCase):
484
485
    def setUp(self):
486
        super(GuessCommandTests, self).setUp()
487
        commands._register_builtin_commands()
488
        commands.install_bzr_command_hooks()
489
490
    def test_guess_override(self):
491
        self.assertEqual('ci', commands.guess_command('ic'))
492
493
    def test_guess(self):
494
        commands.get_cmd_object('status')
495
        self.assertEqual('status', commands.guess_command('statue'))
496
497
    def test_none(self):
498
        self.assertIs(None, commands.guess_command('nothingisevenclose'))