/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

  • Committer: John Arbash Meinel
  • Date: 2011-01-11 18:48:11 UTC
  • mto: This revision was merged to the branch mainline in revision 5596.
  • Revision ID: john@arbash-meinel.com-20110111184811-igkdbe9d0io7hfgh
don't import pdb in live code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
import glob
25
25
import os
26
26
import shlex
27
 
from cStringIO import StringIO
 
27
import textwrap
28
28
 
29
29
from bzrlib import (
30
30
    osutils,
55
55
    Input lines start with '<'.
56
56
    Output lines start with nothing.
57
57
    Error lines start with '2>'.
 
58
 
 
59
    :return: A sequence of ([args], input, output, errors), where the args are
 
60
        split in to words, and the input, output, and errors are just strings,
 
61
        typically containing newlines.
58
62
    """
59
63
 
60
64
    commands = []
73
77
    cmd_line = 1
74
78
    lineno = 0
75
79
    input, output, error = None, None, None
76
 
    for line in text.split('\n'):
 
80
    text = textwrap.dedent(text)
 
81
    lines = text.split('\n')
 
82
    # to make use of triple-quoted strings easier, we ignore a blank line
 
83
    # right at the start and right at the end; the rest are meaningful
 
84
    if lines and lines[0] == '':
 
85
        del lines[0]
 
86
    if lines and lines[-1] == '':
 
87
        del lines[-1]
 
88
    for line in lines:
77
89
        lineno += 1
78
90
        # Keep a copy for error reporting
79
91
        orig = line
80
92
        comment =  line.find('#')
81
93
        if comment >= 0:
82
94
            # Delete comments
 
95
            # NB: this syntax means comments are allowed inside output, which
 
96
            # may be confusing...
83
97
            line = line[0:comment]
84
98
            line = line.rstrip()
85
 
        if line == '':
86
 
            # Ignore empty lines
87
 
            continue
 
99
            if line == '':
 
100
                continue
88
101
        if line.startswith('$'):
89
102
            # Time to output the current command
90
103
            add_command(cmd_cur, input, output, error)
181
194
        self.output_checker = doctest.OutputChecker()
182
195
        self.check_options = doctest.ELLIPSIS
183
196
 
184
 
    def run_script(self, test_case, text):
 
197
    def run_script(self, test_case, text, null_output_matches_anything=False):
185
198
        """Run a shell-like script as a test.
186
199
 
187
200
        :param test_case: A TestCase instance that should provide the fail(),
189
202
            attribute used as a jail root.
190
203
 
191
204
        :param text: A shell-like script (see _script_to_commands for syntax).
 
205
 
 
206
        :param null_output_matches_anything: For commands with no specified
 
207
            output, ignore any output that does happen, including output on
 
208
            standard error.
192
209
        """
 
210
        self.null_output_matches_anything = null_output_matches_anything
193
211
        for cmd, input, output, error in _script_to_commands(text):
194
212
            self.run_command(test_case, cmd, input, output, error)
195
213
 
198
216
        method = getattr(self, mname, None)
199
217
        if method is None:
200
218
            raise SyntaxError('Command not found "%s"' % (cmd[0],),
201
 
                              None, 1, ' '.join(cmd))
 
219
                              (None, 1, 1, ' '.join(cmd)))
202
220
        if input is None:
203
221
            str_input = ''
204
222
        else:
207
225
        retcode, actual_output, actual_error = method(test_case,
208
226
                                                      str_input, args)
209
227
 
210
 
        self._check_output(output, actual_output, test_case)
211
 
        self._check_output(error, actual_error, test_case)
 
228
        try:
 
229
            self._check_output(output, actual_output, test_case)
 
230
        except AssertionError, e:
 
231
            raise AssertionError(str(e) + " in stdout of command %s" % cmd)
 
232
        try:
 
233
            self._check_output(error, actual_error, test_case)
 
234
        except AssertionError, e:
 
235
            raise AssertionError(str(e) +
 
236
                " in stderr of running command %s" % cmd)
212
237
        if retcode and not error and actual_error:
213
238
            test_case.fail('In \n\t%s\nUnexpected error: %s'
214
239
                           % (' '.join(cmd), actual_error))
215
240
        return retcode, actual_output, actual_error
216
241
 
217
242
    def _check_output(self, expected, actual, test_case):
218
 
        if expected is None:
219
 
            # Specifying None means: any output is accepted
 
243
        if not actual:
 
244
            if expected is None:
 
245
                return
 
246
            elif expected == '...\n':
 
247
                return
 
248
            else:
 
249
                test_case.fail('expected output: %r, but found nothing'
 
250
                            % (expected,))
 
251
 
 
252
        null_output_matches_anything = getattr(
 
253
            self, 'null_output_matches_anything', False)
 
254
        if null_output_matches_anything and expected is None:
220
255
            return
221
 
        if actual is None:
222
 
            test_case.fail('We expected output: %r, but found None'
223
 
                           % (expected,))
 
256
 
 
257
        expected = expected or ''
224
258
        matching = self.output_checker.check_output(
225
259
            expected, actual, self.check_options)
226
260
        if not matching:
230
264
            # 'expected' parameter. So we just fallback to our good old
231
265
            # assertEqualDiff since we know there *are* differences and the
232
266
            # output should be decently readable.
233
 
            test_case.assertEqualDiff(expected, actual)
 
267
            #
 
268
            # As a special case, we allow output that's missing a final
 
269
            # newline to match an expected string that does have one, so that
 
270
            # we can match a prompt printed on one line, then input given on
 
271
            # the next line.
 
272
            if expected == actual + '\n':
 
273
                pass
 
274
            else:
 
275
                test_case.assertEqualDiff(expected, actual)
234
276
 
235
277
    def _pre_process_args(self, args):
236
278
        new_args = []
440
482
        super(TestCaseWithMemoryTransportAndScript, self).setUp()
441
483
        self.script_runner = ScriptRunner()
442
484
 
443
 
    def run_script(self, script):
444
 
        return self.script_runner.run_script(self, script)
 
485
    def run_script(self, script, null_output_matches_anything=False):
 
486
        return self.script_runner.run_script(self, script, 
 
487
                   null_output_matches_anything=null_output_matches_anything)
445
488
 
446
489
    def run_command(self, cmd, input, output, error):
447
490
        return self.script_runner.run_command(self, cmd, input, output, error)
469
512
        super(TestCaseWithTransportAndScript, self).setUp()
470
513
        self.script_runner = ScriptRunner()
471
514
 
472
 
    def run_script(self, script):
473
 
        return self.script_runner.run_script(self, script)
 
515
    def run_script(self, script, null_output_matches_anything=False):
 
516
        return self.script_runner.run_script(self, script,
 
517
                   null_output_matches_anything=null_output_matches_anything)
474
518
 
475
519
    def run_command(self, cmd, input, output, error):
476
520
        return self.script_runner.run_command(self, cmd, input, output, error)
477
521
 
 
522
 
 
523
def run_script(test_case, script_string, null_output_matches_anything=False):
 
524
    """Run the given script within a testcase"""
 
525
    return ScriptRunner().run_script(test_case, script_string,
 
526
               null_output_matches_anything=null_output_matches_anything)
 
527