~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/script.py

  • Committer: Jelmer Vernooij
  • Date: 2011-01-11 04:33:12 UTC
  • mto: (5582.12.2 weave-plugin)
  • mto: This revision was merged to the branch mainline in revision 5718.
  • Revision ID: jelmer@samba.org-20110111043312-g4wx6iuf9662f36d
Move weave formats into bzrlib.plugins.weave_fmt.

Show diffs side-by-side

added added

removed removed

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