~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/script.py

  • Committer: Vincent Ladeuil
  • Date: 2009-09-18 12:54:01 UTC
  • mto: (4713.1.1 integration)
  • mto: This revision was merged to the branch mainline in revision 4714.
  • Revision ID: v.ladeuil+lp@free.fr-20090918125401-fb3gl822abfc8omt
Try to relax the test_case/script runner coupling.

* bzrlib/tests/script.py:
(ScriptRunner.__init__): Don't keep the test_case as an attribute,
require the jail_root instead.
(ScriptRunner.run_script, ScriptRunner.run_command,
ScriptRunner._check_output): Add a test_case parameter to be able
to use fail() and assertEqualDiff().
(ScriptRunner.do_bzr): Add a test_case parameter to be able to use
_run_bzr_core().
(ScriptRunner.do_cat, ScriptRunner.do_echo, ScriptRunner,
ScriptRunner.do_mkdir, ScriptRunner.do_rm): Add a test_case
parameter to be able... to be ready for the memory based resources
only implementation :)
(TestCaseWithMemoryTransportAndScript,
TestCaseWithTransportAndScript): Add docstring describing the
intent.

Show diffs side-by-side

added added

removed removed

Lines of Context:
159
159
 
160
160
class ScriptRunner(object):
161
161
 
162
 
    def __init__(self, test_case):
163
 
        self.test_case = test_case
 
162
    def __init__(self, jail_root='/'):
 
163
        self.jail_root = jail_root
164
164
        self.output_checker = doctest.OutputChecker()
165
165
        self.check_options = doctest.ELLIPSIS
166
166
 
167
 
    def run_script(self, text):
 
167
    def run_script(self, text, test_case):
168
168
        for cmd, input, output, error in _script_to_commands(text):
169
 
            self.run_command(cmd, input, output, error)
170
 
 
171
 
    def _check_output(self, expected, actual):
 
169
            self.run_command(cmd, input, output, error, test_case)
 
170
 
 
171
    def run_command(self, cmd, input, output, error, test_case):
 
172
        mname = 'do_' + cmd[0]
 
173
        method = getattr(self, mname, None)
 
174
        if method is None:
 
175
            raise SyntaxError('Command not found "%s"' % (cmd[0],),
 
176
                              None, 1, ' '.join(cmd))
 
177
        if input is None:
 
178
            str_input = ''
 
179
        else:
 
180
            str_input = ''.join(input)
 
181
        args = list(self._pre_process_args(cmd[1:]))
 
182
        retcode, actual_output, actual_error = method(test_case,
 
183
                                                      str_input, args)
 
184
 
 
185
        self._check_output(output, actual_output, test_case)
 
186
        self._check_output(error, actual_error, test_case)
 
187
        if retcode and not error and actual_error:
 
188
            test_case.fail('In \n\t%s\nUnexpected error: %s'
 
189
                           % (' '.join(cmd), actual_error))
 
190
        return retcode, actual_output, actual_error
 
191
 
 
192
    def _check_output(self, expected, actual, test_case):
172
193
        if expected is None:
173
194
            # Specifying None means: any output is accepted
174
195
            return
175
196
        if actual is None:
176
 
            self.test_case.fail('Unexpected: %s' % actual)
 
197
            test_case.fail('Unexpected: %s' % actual)
177
198
        matching = self.output_checker.check_output(
178
199
            expected, actual, self.check_options)
179
200
        if not matching:
183
204
            # 'expected' parameter. So we just fallback to our good old
184
205
            # assertEqualDiff since we know there *are* differences and the
185
206
            # output should be decently readable.
186
 
            self.test_case.assertEqualDiff(expected, actual)
 
207
            test_case.assertEqualDiff(expected, actual)
187
208
 
188
209
    def _pre_process_args(self, args):
189
210
        new_args = []
205
226
                else:
206
227
                    yield arg
207
228
 
208
 
    def run_command(self, cmd, input, output, error):
209
 
        mname = 'do_' + cmd[0]
210
 
        method = getattr(self, mname, None)
211
 
        if method is None:
212
 
            raise SyntaxError('Command not found "%s"' % (cmd[0],),
213
 
                              None, 1, ' '.join(cmd))
214
 
        if input is None:
215
 
            str_input = ''
216
 
        else:
217
 
            str_input = ''.join(input)
218
 
        args = list(self._pre_process_args(cmd[1:]))
219
 
        retcode, actual_output, actual_error = method(str_input, args)
220
 
 
221
 
        self._check_output(output, actual_output)
222
 
        self._check_output(error, actual_error)
223
 
        if retcode and not error and actual_error:
224
 
            self.test_case.fail('In \n\t%s\nUnexpected error: %s'
225
 
                                % (' '.join(cmd), actual_error))
226
 
        return retcode, actual_output, actual_error
227
 
 
228
229
    def _read_input(self, input, in_name):
229
230
        if in_name is not None:
230
231
            infile = open(in_name, 'rb')
245
246
            output = None
246
247
        return output
247
248
 
248
 
    def do_bzr(self, input, args):
249
 
        retcode, out, err = self.test_case._run_bzr_core(
 
249
    def do_bzr(self, test_case, input, args):
 
250
        retcode, out, err = test_case._run_bzr_core(
250
251
            args, retcode=None, encoding=None, stdin=input, working_dir=None)
251
252
        return retcode, out, err
252
253
 
253
 
    def do_cat(self, input, args):
 
254
    def do_cat(self, test_case, input, args):
254
255
        (in_name, out_name, out_mode, args) = _scan_redirection_options(args)
255
256
        if args and in_name is not None:
256
257
            raise SyntaxError('Specify a file OR use redirection')
278
279
                return 1, None, '%s: No such file or directory\n' % (out_name,)
279
280
        return 0, output, None
280
281
 
281
 
    def do_echo(self, input, args):
 
282
    def do_echo(self, test_case, input, args):
282
283
        (in_name, out_name, out_mode, args) = _scan_redirection_options(args)
283
284
        if input and args:
284
285
                raise SyntaxError('Specify parameters OR use redirection')
302
303
        return 0, output, None
303
304
 
304
305
    def _ensure_in_jail(self, path):
305
 
        jail_root = self.test_case.get_jail_root()
306
 
        if not osutils.is_inside(jail_root, osutils.normalizepath(path)):
307
 
            raise ValueError('%s is not inside %s' % (path, jail_root))
 
306
        if not osutils.is_inside(self.jail_root, osutils.normalizepath(path)):
 
307
            raise ValueError('%s is not inside %s' % (path, self.jail_root))
308
308
 
309
 
    def do_cd(self, input, args):
 
309
    def do_cd(self, test_case, input, args):
310
310
        if len(args) > 1:
311
311
            raise SyntaxError('Usage: cd [dir]')
312
312
        if len(args) == 1:
313
313
            d = args[0]
314
314
            self._ensure_in_jail(d)
315
315
        else:
316
 
            d = self.test_case.get_jail_root()
 
316
            d = self.jail_root
317
317
        os.chdir(d)
318
318
        return 0, None, None
319
319
 
320
 
    def do_mkdir(self, input, args):
 
320
    def do_mkdir(self, test_case, input, args):
321
321
        if not args or len(args) != 1:
322
322
            raise SyntaxError('Usage: mkdir dir')
323
323
        d = args[0]
325
325
        os.mkdir(d)
326
326
        return 0, None, None
327
327
 
328
 
    def do_rm(self, input, args):
 
328
    def do_rm(self, test_case, input, args):
329
329
        err = None
330
330
 
331
331
        def error(msg, path):
369
369
 
370
370
 
371
371
class TestCaseWithMemoryTransportAndScript(tests.TestCaseWithMemoryTransport):
 
372
    """Helper class to experiment shell-like test and memory fs.
 
373
 
 
374
    This not intended to be used outside of experiments in implementing memoy
 
375
    based file systems and evolving bzr so that test can use only memory based
 
376
    resources.
 
377
    """
372
378
 
373
379
    def setUp(self):
374
380
        super(TestCaseWithMemoryTransportAndScript, self).setUp()
375
 
        self.script_runner = ScriptRunner(self)
376
 
        # Break the circular dependency
377
 
        def break_dependency():
378
 
            self.script_runner = None
379
 
        self.addCleanup(break_dependency)
380
 
 
381
 
    def get_jail_root(self):
382
 
        raise NotImplementedError(self.get_jail_root)
 
381
        # We don't have a jail_root to provide here. Yet.
 
382
        self.script_runner = ScriptRunner()
383
383
 
384
384
    def run_script(self, script):
385
 
        return self.script_runner.run_script(script)
 
385
        return self.script_runner.run_script(script, self)
386
386
 
387
387
    def run_command(self, cmd, input, output, error):
388
 
        return self.script_runner.run_command(cmd, input, output, error)
 
388
        return self.script_runner.run_command(cmd, input, output, error, self)
389
389
 
390
390
 
391
391
class TestCaseWithTransportAndScript(tests.TestCaseWithTransport):
 
392
    """Helper class to quickly define shell-like tests.
 
393
 
 
394
    Can be used as:
 
395
 
 
396
    from bzrlib.tests import script
 
397
 
 
398
 
 
399
    class TestBug(script.TestCaseWithTransportAndScript):
 
400
 
 
401
        def test_bug_nnnnn(self):
 
402
            self.run_script('''
 
403
            $ bzr init
 
404
            $ bzr do-this
 
405
            # Boom, error
 
406
            ''')
 
407
    """
392
408
 
393
409
    def setUp(self):
394
410
        super(TestCaseWithTransportAndScript, self).setUp()
395
 
        self.script_runner = ScriptRunner(self)
396
 
        # Break the circular dependency
397
 
        def break_dependency():
398
 
            self.script_runner = None
399
 
        self.addCleanup(break_dependency)
400
 
 
401
 
    def get_jail_root(self):
402
 
        return self.test_dir
 
411
        self.script_runner = ScriptRunner(self.test_dir)
403
412
 
404
413
    def run_script(self, script):
405
 
        return self.script_runner.run_script(script)
 
414
        return self.script_runner.run_script(script, self)
406
415
 
407
416
    def run_command(self, cmd, input, output, error):
408
 
        return self.script_runner.run_command(cmd, input, output, error)
 
417
        return self.script_runner.run_command(cmd, input, output, error, self)
 
418