/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/script.py

Merge updates in shell-like tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 
 
17
 
from cStringIO import StringIO
 
16
"""Shell-like test scripts.
 
17
 
 
18
This allows users to write tests in a syntax very close to a shell session,
 
19
using a restricted and limited set of commands that should be enough to mimic
 
20
most of the behaviours.
 
21
 
 
22
A script is a set of commands, each command is composed of:
 
23
- one mandatory command line,
 
24
- one optional set of input lines to feed the command,
 
25
- one optional set of output expected lines,
 
26
- one optional set of error expected lines.
 
27
 
 
28
The optional lines starts with a special string (mnemonic: shell redirection):
 
29
- '<' for input,
 
30
- '>' for output,
 
31
- '2>' for errors,
 
32
 
 
33
The execution stops as soon as an expected output or an expected error is not
 
34
matched. 
 
35
 
 
36
When no output is specified, any ouput from the command is accepted
 
37
and let the execution continue. 
 
38
 
 
39
If an error occurs and no expected error is specified, the execution stops.
 
40
 
 
41
The matching is done on a full string comparison basis unless '...' is used, in
 
42
which case expected output/errors can be lees precise.
 
43
 
 
44
Examples:
 
45
 
 
46
The following will succeeds only if 'bzr add' outputs 'adding file'.
 
47
 
 
48
  bzr add file
 
49
  >adding file
 
50
 
 
51
If you want the command to succeed for any output, just use:
 
52
 
 
53
  bzr add file
 
54
 
 
55
The following will stop with an error:
 
56
 
 
57
  bzr not-a-command
 
58
 
 
59
If you want it to succeed, use:
 
60
 
 
61
  bzr not-a-command
 
62
  2> bzr: ERROR: unknown command "not-a-command"
 
63
 
 
64
You can use ellipsis (...) to replace any piece of text you don't want to be
 
65
matched exactly:
 
66
 
 
67
  bzr branch not-a-branch
 
68
  2>bzr: ERROR: Not a branch...not-a-branch/".
 
69
 
 
70
 
 
71
This can be used to ignore entire lines too:
 
72
 
 
73
cat
 
74
<first line
 
75
<second line
 
76
<third line
 
77
<fourth line
 
78
<last line
 
79
>first line
 
80
>...
 
81
>last line
 
82
 
 
83
You can check the content of a file with cat:
 
84
 
 
85
  cat <file
 
86
  >expected content
 
87
 
 
88
You can also check the existence of a file with cat, the following will fail if
 
89
the file doesn't exist:
 
90
 
 
91
  cat file
 
92
 
 
93
"""
 
94
 
 
95
import doctest
18
96
import os
19
97
import shlex
 
98
from cStringIO import StringIO
20
99
 
21
100
from bzrlib import (
22
101
    osutils,
144
223
    return in_name, out_name, out_mode, remaining
145
224
 
146
225
 
147
 
class TestCaseWithScript(tests.TestCaseWithTransport):
 
226
class ScriptRunner(object):
148
227
 
149
 
    def setUp(self):
150
 
        super(TestCaseWithScript, self).setUp()
151
 
        self._vars = {}
 
228
    def __init__(self, test_case):
 
229
        self.test_case = test_case
 
230
        self.output_checker = doctest.OutputChecker()
 
231
        self.check_options = doctest.ELLIPSIS
152
232
 
153
233
    def run_script(self, text):
154
234
        for cmd, input, output, error in _script_to_commands(text):
155
 
            self.run_command(cmd, input, output, error)
 
235
            out, err = self.run_command(cmd, input, output, error)
156
236
 
157
237
    def _check_output(self, expected, actual):
158
238
        if expected is None:
159
239
            # Specifying None means: any output is accepted
160
240
            return
161
 
        self.assertEquals(expected, actual)
 
241
        if actual is None:
 
242
            self.test_case.fail('Unexpected: %s' % actual)
 
243
        matching = self.output_checker.check_output(
 
244
            expected, actual, self.check_options)
 
245
        if not matching:
 
246
            # Note that we can't use output_checker.output_difference() here
 
247
            # because... the API is boken (expected must be a doctest specific
 
248
            # object of whicha 'want' attribute will be our 'expected'
 
249
            # parameter. So we just fallbacl to our good old assertEqualDiff
 
250
            # since we know there are differences and the output should be
 
251
            # decently readable.
 
252
            self.test_case.assertEqualDiff(expected, actual)
162
253
 
163
254
    def run_command(self, cmd, input, output, error):
164
255
        mname = 'do_' + cmd[0]
174
265
 
175
266
        self._check_output(output, actual_output)
176
267
        self._check_output(error, actual_error)
 
268
        if not error and actual_error:
 
269
            self.test_case.fail('Unexpected error: %s' % actual_error)
177
270
        return actual_output, actual_error
178
271
 
179
272
    def _read_input(self, input, in_name):
197
290
        return output
198
291
 
199
292
    def do_bzr(self, input, args):
200
 
        out, err = self._run_bzr_core(args, retcode=None, encoding=None,
201
 
                                      stdin=input, working_dir=None)
 
293
        out, err = self.test_case._run_bzr_core(
 
294
            args, retcode=None, encoding=None, stdin=input, working_dir=None)
202
295
        return out, err
203
296
 
204
297
    def do_cat(self, input, args):
232
325
        return output, None
233
326
 
234
327
    def _ensure_in_jail(self, path):
235
 
        if not osutils.is_inside(self.test_dir, osutils.normalizepath(path)):
236
 
                raise ValueError('%s is not inside %s' % (path, self.test_dir))
 
328
        jail_root = self.test_case.get_jail_root()
 
329
        if not osutils.is_inside(jail_root, osutils.normalizepath(path)):
 
330
            raise ValueError('%s is not inside %s' % (path, jail_root))
237
331
 
238
332
    def do_cd(self, input, args):
239
333
        if len(args) > 1:
242
336
            d = args[0]
243
337
            self._ensure_in_jail(d)
244
338
        else:
245
 
            d = self.test_dir
 
339
            d = self.test_case.get_jail_root()
246
340
        os.chdir(d)
247
341
        return None, None
248
342
 
254
348
        os.mkdir(d)
255
349
        return None, None
256
350
 
 
351
 
 
352
class TestCaseWithMemoryTransportAndScript(tests.TestCaseWithMemoryTransport):
 
353
 
 
354
    def setUp(self):
 
355
        super(TestCaseWithMemoryTransportAndScript, self).setUp()
 
356
        self.script_runner = ScriptRunner(self)
 
357
        # Break the circular dependency
 
358
        def break_dependency():
 
359
            self.script_runner = None
 
360
        self.addCleanup(break_dependency)
 
361
 
 
362
    def get_jail_root(self):
 
363
        raise NotImplementedError(self.get_jail_root)
 
364
 
 
365
    def run_script(self, script):
 
366
        return self.script_runner.run_script(script)
 
367
 
 
368
    def run_command(self, cmd, input, output, error):
 
369
        return self.script_runner.run_command(cmd, input, output, error)
 
370
 
 
371
 
 
372
class TestCaseWithTransportAndScript(tests.TestCaseWithTransport):
 
373
 
 
374
    def setUp(self):
 
375
        super(TestCaseWithTransportAndScript, self).setUp()
 
376
        self.script_runner = ScriptRunner(self)
 
377
        # Break the circular dependency
 
378
        def break_dependency():
 
379
            self.script_runner = None
 
380
        self.addCleanup(break_dependency)
 
381
 
 
382
    def get_jail_root(self):
 
383
        return self.test_dir
 
384
 
 
385
    def run_script(self, script):
 
386
        return self.script_runner.run_script(script)
 
387
 
 
388
    def run_command(self, cmd, input, output, error):
 
389
        return self.script_runner.run_command(cmd, input, output, error)