/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 breezy/tests/script.py

  • Committer: Jelmer Vernooij
  • Date: 2017-06-10 16:40:42 UTC
  • mfrom: (6653.6.7 rename-controldir)
  • mto: This revision was merged to the branch mainline in revision 6690.
  • Revision ID: jelmer@jelmer.uk-20170610164042-zrxqgy2htyduvke2
MergeĀ rename-controldirĀ branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2009, 2010 Canonical Ltd
 
1
# Copyright (C) 2009, 2010, 2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
24
24
import glob
25
25
import os
26
26
import shlex
27
 
from cStringIO import StringIO
 
27
import textwrap
28
28
 
29
 
from bzrlib import (
 
29
from .. import (
30
30
    osutils,
31
31
    tests,
32
32
    )
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)
164
177
    
165
178
    Can be used as:
166
179
 
167
 
    from bzrlib.tests import script
 
180
    from breezy.tests import script
168
181
 
169
182
    ...
170
183
 
171
184
        def test_bug_nnnnn(self):
172
185
            sr = script.ScriptRunner()
173
186
            sr.run_script(self, '''
174
 
            $ bzr init
175
 
            $ bzr do-this
 
187
            $ brz init
 
188
            $ brz do-this
176
189
            # Boom, error
177
190
            ''')
178
191
    """
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 as 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 as 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 = []
272
314
            output = None
273
315
        return output
274
316
 
275
 
    def do_bzr(self, test_case, input, args):
 
317
    def do_brz(self, test_case, input, args):
276
318
        retcode, out, err = test_case._run_bzr_core(
277
319
            args, retcode=None, encoding=None, stdin=input, working_dir=None)
278
320
        return retcode, out, err
291
333
        for in_name in input_names:
292
334
            try:
293
335
                inputs.append(self._read_input(None, in_name))
294
 
            except IOError, e:
 
336
            except IOError as e:
295
337
                # Some filenames are illegal on Windows and generate EINVAL
296
338
                # rather than just saying the filename doesn't exist
297
339
                if e.errno in (errno.ENOENT, errno.EINVAL):
303
345
        # Handle output redirections
304
346
        try:
305
347
            output = self._write_output(output, out_name, out_mode)
306
 
        except IOError, e:
 
348
        except IOError as e:
307
349
            # If out_name cannot be created, we may get 'ENOENT', however if
308
350
            # out_name is something like '', we can get EINVAL
309
351
            if e.errno in (errno.ENOENT, errno.EINVAL):
324
366
        # Handle output redirections
325
367
        try:
326
368
            output = self._write_output(output, out_name, out_mode)
327
 
        except IOError, e:
 
369
        except IOError as e:
328
370
            if e.errno in (errno.ENOENT, errno.EINVAL):
329
371
                return 1, None, '%s: No such file or directory\n' % (out_name,)
330
372
            raise
381
423
            # FIXME: Should we put that in osutils ?
382
424
            try:
383
425
                os.remove(p)
384
 
            except OSError, e:
 
426
            except OSError as e:
385
427
                # Various OSes raises different exceptions (linux: EISDIR,
386
428
                #   win32: EACCES, OSX: EPERM) when invoked on a directory
387
429
                if e.errno in (errno.EISDIR, errno.EPERM, errno.EACCES):
415
457
            if os.path.isdir(dst):
416
458
                real_dst = os.path.join(dst, os.path.basename(src))
417
459
            os.rename(src, real_dst)
418
 
        except OSError, e:
 
460
        except OSError as e:
419
461
            if e.errno == errno.ENOENT:
420
462
                err = error('No such file or directory', src, dst)
421
463
            else:
439
481
    def setUp(self):
440
482
        super(TestCaseWithMemoryTransportAndScript, self).setUp()
441
483
        self.script_runner = ScriptRunner()
 
484
        # FIXME: See shelf_ui.Shelver._char_based. This allow using shelve in
 
485
        # scripts while providing a line-based input (better solution in
 
486
        # progress). -- vila 2011-09-28
 
487
        self.overrideEnv('INSIDE_EMACS', '1')
442
488
 
443
 
    def run_script(self, script):
444
 
        return self.script_runner.run_script(self, script)
 
489
    def run_script(self, script, null_output_matches_anything=False):
 
490
        return self.script_runner.run_script(self, script, 
 
491
                   null_output_matches_anything=null_output_matches_anything)
445
492
 
446
493
    def run_command(self, cmd, input, output, error):
447
494
        return self.script_runner.run_command(self, cmd, input, output, error)
452
499
 
453
500
    Can be used as:
454
501
 
455
 
    from bzrlib.tests import script
 
502
    from breezy.tests import script
456
503
 
457
504
 
458
505
    class TestBug(script.TestCaseWithTransportAndScript):
459
506
 
460
507
        def test_bug_nnnnn(self):
461
508
            self.run_script('''
462
 
            $ bzr init
463
 
            $ bzr do-this
 
509
            $ brz init
 
510
            $ brz do-this
464
511
            # Boom, error
465
512
            ''')
466
513
    """
468
515
    def setUp(self):
469
516
        super(TestCaseWithTransportAndScript, self).setUp()
470
517
        self.script_runner = ScriptRunner()
 
518
        # FIXME: See shelf_ui.Shelver._char_based. This allow using shelve in
 
519
        # scripts while providing a line-based input (better solution in
 
520
        # progress). -- vila 2011-09-28
 
521
        self.overrideEnv('INSIDE_EMACS', '1')
471
522
 
472
 
    def run_script(self, script):
473
 
        return self.script_runner.run_script(self, script)
 
523
    def run_script(self, script, null_output_matches_anything=False):
 
524
        return self.script_runner.run_script(self, script,
 
525
                   null_output_matches_anything=null_output_matches_anything)
474
526
 
475
527
    def run_command(self, cmd, input, output, error):
476
528
        return self.script_runner.run_command(self, cmd, input, output, error)
477
529
 
 
530
 
 
531
def run_script(test_case, script_string, null_output_matches_anything=False):
 
532
    """Run the given script within a testcase"""
 
533
    return ScriptRunner().run_script(test_case, script_string,
 
534
               null_output_matches_anything=null_output_matches_anything)
 
535