/brz/remove-bazaar

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