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