~greatmay12/+junk/test1

« back to all changes in this revision

Viewing changes to bzrlib/plugins/bash_completion/tests/test_bashcomp.py

  • Committer: thitipong at ndrsolution
  • Date: 2011-11-14 06:31:02 UTC
  • Revision ID: thitipong@ndrsolution.com-20111114063102-9obte3yfi2azku7d
ndr redirect version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2010 by 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
import bzrlib
 
18
from bzrlib import commands, tests
 
19
from bzrlib.tests import features
 
20
from bzrlib.plugins.bash_completion.bashcomp import *
 
21
 
 
22
import os
 
23
import subprocess
 
24
 
 
25
 
 
26
class BashCompletionMixin(object):
 
27
    """Component for testing execution of a bash completion script."""
 
28
 
 
29
    _test_needs_features = [features.bash_feature]
 
30
 
 
31
    def complete(self, words, cword=-1):
 
32
        """Perform a bash completion.
 
33
 
 
34
        :param words: a list of words representing the current command.
 
35
        :param cword: the current word to complete, defaults to the last one.
 
36
        """
 
37
        if self.script is None:
 
38
            self.script = self.get_script()
 
39
        proc = subprocess.Popen([features.bash_feature.path,
 
40
                                 '--noprofile'],
 
41
                                stdin=subprocess.PIPE,
 
42
                                stdout=subprocess.PIPE,
 
43
                                stderr=subprocess.PIPE)
 
44
        if cword < 0:
 
45
            cword = len(words) + cword
 
46
        input = '%s\n' % self.script
 
47
        input += ('COMP_WORDS=( %s )\n' %
 
48
                  ' '.join(["'"+w.replace("'", "'\\''")+"'" for w in words]))
 
49
        input += 'COMP_CWORD=%d\n' % cword
 
50
        input += '%s\n' % getattr(self, 'script_name', '_bzr')
 
51
        input += 'echo ${#COMPREPLY[*]}\n'
 
52
        input += "IFS=$'\\n'\n"
 
53
        input += 'echo "${COMPREPLY[*]}"\n'
 
54
        (out, err) = proc.communicate(input)
 
55
        if '' != err:
 
56
            raise AssertionError('Unexpected error message:\n%s' % err)
 
57
        self.assertEqual('', err, 'No messages to standard error')
 
58
        #import sys
 
59
        #print >>sys.stdout, '---\n%s\n---\n%s\n---\n' % (input, out)
 
60
        lines = out.split('\n')
 
61
        nlines = int(lines[0])
 
62
        del lines[0]
 
63
        self.assertEqual('', lines[-1], 'Newline at end')
 
64
        del lines[-1]
 
65
        if nlines == 0 and len(lines) == 1 and lines[0] == '':
 
66
            del lines[0]
 
67
        self.assertEqual(nlines, len(lines), 'No newlines in generated words')
 
68
        self.completion_result = set(lines)
 
69
        return self.completion_result
 
70
 
 
71
    def assertCompletionEquals(self, *words):
 
72
        self.assertEqual(set(words), self.completion_result)
 
73
 
 
74
    def assertCompletionContains(self, *words):
 
75
        missing = set(words) - self.completion_result
 
76
        if missing:
 
77
            raise AssertionError('Completion should contain %r but it has %r'
 
78
                                 % (missing, self.completion_result))
 
79
 
 
80
    def assertCompletionOmits(self, *words):
 
81
        surplus = set(words) & self.completion_result
 
82
        if surplus:
 
83
            raise AssertionError('Completion should omit %r but it has %r'
 
84
                                 % (surplus, res, self.completion_result))
 
85
 
 
86
    def get_script(self):
 
87
        commands.install_bzr_command_hooks()
 
88
        dc = DataCollector()
 
89
        data = dc.collect()
 
90
        cg = BashCodeGen(data)
 
91
        res = cg.function()
 
92
        return res
 
93
 
 
94
 
 
95
class TestBashCompletion(tests.TestCase, BashCompletionMixin):
 
96
    """Test bash completions that don't execute bzr."""
 
97
 
 
98
    def __init__(self, methodName='testMethod'):
 
99
        super(TestBashCompletion, self).__init__(methodName)
 
100
        self.script = None
 
101
 
 
102
    def test_simple_scipt(self):
 
103
        """Ensure that the test harness works as expected"""
 
104
        self.script = """
 
105
_bzr() {
 
106
    COMPREPLY=()
 
107
    # add all words in reverse order, with some markup around them
 
108
    for ((i = ${#COMP_WORDS[@]}; i > 0; --i)); do
 
109
        COMPREPLY+=( "-${COMP_WORDS[i-1]}+" )
 
110
    done
 
111
    # and append the current word
 
112
    COMPREPLY+=( "+${COMP_WORDS[COMP_CWORD]}-" )
 
113
}
 
114
"""
 
115
        self.complete(['foo', '"bar', "'baz"], cword=1)
 
116
        self.assertCompletionEquals("-'baz+", '-"bar+', '-foo+', '+"bar-')
 
117
 
 
118
    def test_cmd_ini(self):
 
119
        self.complete(['bzr', 'ini'])
 
120
        self.assertCompletionContains('init', 'init-repo', 'init-repository')
 
121
        self.assertCompletionOmits('commit')
 
122
 
 
123
    def test_init_opts(self):
 
124
        self.complete(['bzr', 'init', '-'])
 
125
        self.assertCompletionContains('-h', '--2a', '--format=2a')
 
126
 
 
127
    def test_global_opts(self):
 
128
        self.complete(['bzr', '-', 'init'], cword=1)
 
129
        self.assertCompletionContains('--no-plugins', '--builtin')
 
130
 
 
131
    def test_commit_dashm(self):
 
132
        self.complete(['bzr', 'commit', '-m'])
 
133
        self.assertCompletionEquals('-m')
 
134
 
 
135
    def test_status_negated(self):
 
136
        self.complete(['bzr', 'status', '--n'])
 
137
        self.assertCompletionContains('--no-versioned', '--no-verbose')
 
138
 
 
139
    def test_init_format_any(self):
 
140
        self.complete(['bzr', 'init', '--format', '=', 'directory'], cword=3)
 
141
        self.assertCompletionContains('1.9', '2a')
 
142
 
 
143
    def test_init_format_2(self):
 
144
        self.complete(['bzr', 'init', '--format', '=', '2', 'directory'],
 
145
                      cword=4)
 
146
        self.assertCompletionContains('2a')
 
147
        self.assertCompletionOmits('1.9')
 
148
 
 
149
 
 
150
class TestBashCompletionInvoking(tests.TestCaseWithTransport,
 
151
                                 BashCompletionMixin):
 
152
    """Test bash completions that might execute bzr.
 
153
 
 
154
    Only the syntax ``$(bzr ...`` is supported so far. The bzr command
 
155
    will be replaced by the bzr instance running this selftest.
 
156
    """
 
157
 
 
158
    def __init__(self, methodName='testMethod'):
 
159
        super(TestBashCompletionInvoking, self).__init__(methodName)
 
160
        self.script = None
 
161
 
 
162
    def get_script(self):
 
163
        s = super(TestBashCompletionInvoking, self).get_script()
 
164
        return s.replace("$(bzr ", "$('%s' " % self.get_bzr_path())
 
165
 
 
166
    def test_revspec_tag_all(self):
 
167
        self.requireFeature(features.sed_feature)
 
168
        wt = self.make_branch_and_tree('.', format='dirstate-tags')
 
169
        wt.branch.tags.set_tag('tag1', 'null:')
 
170
        wt.branch.tags.set_tag('tag2', 'null:')
 
171
        wt.branch.tags.set_tag('3tag', 'null:')
 
172
        self.complete(['bzr', 'log', '-r', 'tag', ':'])
 
173
        self.assertCompletionEquals('tag1', 'tag2', '3tag')
 
174
 
 
175
    def test_revspec_tag_prefix(self):
 
176
        self.requireFeature(features.sed_feature)
 
177
        wt = self.make_branch_and_tree('.', format='dirstate-tags')
 
178
        wt.branch.tags.set_tag('tag1', 'null:')
 
179
        wt.branch.tags.set_tag('tag2', 'null:')
 
180
        wt.branch.tags.set_tag('3tag', 'null:')
 
181
        self.complete(['bzr', 'log', '-r', 'tag', ':', 't'])
 
182
        self.assertCompletionEquals('tag1', 'tag2')
 
183
 
 
184
    def test_revspec_tag_spaces(self):
 
185
        self.requireFeature(features.sed_feature)
 
186
        wt = self.make_branch_and_tree('.', format='dirstate-tags')
 
187
        wt.branch.tags.set_tag('tag with spaces', 'null:')
 
188
        self.complete(['bzr', 'log', '-r', 'tag', ':', 't'])
 
189
        self.assertCompletionEquals(r'tag\ with\ spaces')
 
190
        self.complete(['bzr', 'log', '-r', '"tag:t'])
 
191
        self.assertCompletionEquals('tag:tag with spaces')
 
192
        self.complete(['bzr', 'log', '-r', "'tag:t"])
 
193
        self.assertCompletionEquals('tag:tag with spaces')
 
194
 
 
195
    def test_revspec_tag_endrange(self):
 
196
        self.requireFeature(features.sed_feature)
 
197
        wt = self.make_branch_and_tree('.', format='dirstate-tags')
 
198
        wt.branch.tags.set_tag('tag1', 'null:')
 
199
        wt.branch.tags.set_tag('tag2', 'null:')
 
200
        self.complete(['bzr', 'log', '-r', '3..tag', ':', 't'])
 
201
        self.assertCompletionEquals('tag1', 'tag2')
 
202
        self.complete(['bzr', 'log', '-r', '"3..tag:t'])
 
203
        self.assertCompletionEquals('3..tag:tag1', '3..tag:tag2')
 
204
        self.complete(['bzr', 'log', '-r', "'3..tag:t"])
 
205
        self.assertCompletionEquals('3..tag:tag1', '3..tag:tag2')
 
206
 
 
207
 
 
208
class TestBashCodeGen(tests.TestCase):
 
209
 
 
210
    def test_command_names(self):
 
211
        data = CompletionData()
 
212
        bar = CommandData('bar')
 
213
        bar.aliases.append('baz')
 
214
        data.commands.append(bar)
 
215
        data.commands.append(CommandData('foo'))
 
216
        cg = BashCodeGen(data)
 
217
        self.assertEqual('bar baz foo', cg.command_names())
 
218
 
 
219
    def test_debug_output(self):
 
220
        data = CompletionData()
 
221
        self.assertEqual('', BashCodeGen(data, debug=False).debug_output())
 
222
        self.assertTrue(BashCodeGen(data, debug=True).debug_output())
 
223
 
 
224
    def test_bzr_version(self):
 
225
        data = CompletionData()
 
226
        cg = BashCodeGen(data)
 
227
        self.assertEqual('%s.' % bzrlib.version_string, cg.bzr_version())
 
228
        data.plugins['foo'] = PluginData('foo', '1.0')
 
229
        data.plugins['bar'] = PluginData('bar', '2.0')
 
230
        cg = BashCodeGen(data)
 
231
        self.assertEqual('''\
 
232
%s and the following plugins:
 
233
# bar 2.0
 
234
# foo 1.0''' % bzrlib.version_string, cg.bzr_version())
 
235
 
 
236
    def test_global_options(self):
 
237
        data = CompletionData()
 
238
        data.global_options.add('--foo')
 
239
        data.global_options.add('--bar')
 
240
        cg = BashCodeGen(data)
 
241
        self.assertEqual('--bar --foo', cg.global_options())
 
242
 
 
243
    def test_command_cases(self):
 
244
        data = CompletionData()
 
245
        bar = CommandData('bar')
 
246
        bar.aliases.append('baz')
 
247
        bar.options.append(OptionData('--opt'))
 
248
        data.commands.append(bar)
 
249
        data.commands.append(CommandData('foo'))
 
250
        cg = BashCodeGen(data)
 
251
        self.assertEqualDiff('''\
 
252
\tbar|baz)
 
253
\t\tcmdOpts=( --opt )
 
254
\t\t;;
 
255
\tfoo)
 
256
\t\tcmdOpts=(  )
 
257
\t\t;;
 
258
''', cg.command_cases())
 
259
 
 
260
    def test_command_case(self):
 
261
        cmd = CommandData('cmd')
 
262
        cmd.plugin = PluginData('plugger', '1.0')
 
263
        bar = OptionData('--bar')
 
264
        bar.registry_keys = ['that', 'this']
 
265
        bar.error_messages.append('Some error message')
 
266
        cmd.options.append(bar)
 
267
        cmd.options.append(OptionData('--foo'))
 
268
        data = CompletionData()
 
269
        data.commands.append(cmd)
 
270
        cg = BashCodeGen(data)
 
271
        self.assertEqualDiff('''\
 
272
\tcmd)
 
273
\t\t# plugin "plugger 1.0"
 
274
\t\t# Some error message
 
275
\t\tcmdOpts=( --bar=that --bar=this --foo )
 
276
\t\tcase $curOpt in
 
277
\t\t\t--bar) optEnums=( that this ) ;;
 
278
\t\tesac
 
279
\t\t;;
 
280
''', cg.command_case(cmd))
 
281
 
 
282
 
 
283
class TestDataCollector(tests.TestCase):
 
284
 
 
285
    def setUp(self):
 
286
        super(TestDataCollector, self).setUp()
 
287
        commands.install_bzr_command_hooks()
 
288
 
 
289
    def test_global_options(self):
 
290
        dc = DataCollector()
 
291
        dc.global_options()
 
292
        self.assertSubset(['--no-plugins', '--builtin'],
 
293
                           dc.data.global_options)
 
294
 
 
295
    def test_commands(self):
 
296
        dc = DataCollector()
 
297
        dc.commands()
 
298
        self.assertSubset(['init', 'init-repo', 'init-repository'],
 
299
                           dc.data.all_command_aliases())
 
300
 
 
301
    def test_commands_from_plugins(self):
 
302
        dc = DataCollector()
 
303
        dc.commands()
 
304
        self.assertSubset(['bash-completion'],
 
305
                           dc.data.all_command_aliases())
 
306
 
 
307
    def test_commit_dashm(self):
 
308
        dc = DataCollector()
 
309
        cmd = dc.command('commit')
 
310
        self.assertSubset(['-m'],
 
311
                           [str(o) for o in cmd.options])
 
312
 
 
313
    def test_status_negated(self):
 
314
        dc = DataCollector()
 
315
        cmd = dc.command('status')
 
316
        self.assertSubset(['--no-versioned', '--no-verbose'],
 
317
                           [str(o) for o in cmd.options])
 
318
 
 
319
    def test_init_format(self):
 
320
        dc = DataCollector()
 
321
        cmd = dc.command('init')
 
322
        for opt in cmd.options:
 
323
            if opt.name == '--format':
 
324
                self.assertSubset(['2a'], opt.registry_keys)
 
325
                return
 
326
        raise AssertionError('Option --format not found')