160
160
class ScriptRunner(object):
162
def __init__(self, test_case):
163
self.test_case = test_case
161
"""Run a shell-like script from a test.
165
from bzrlib.tests import script
169
def test_bug_nnnnn(self):
170
sr = script.ScriptRunner()
171
sr.run_script(self, '''
164
179
self.output_checker = doctest.OutputChecker()
165
180
self.check_options = doctest.ELLIPSIS
167
def run_script(self, text):
182
def run_script(self, test_case, text):
183
"""Run a shell-like script as a test.
185
:param test_case: A TestCase instance that should provide the fail(),
186
assertEqualDiff and _run_bzr_core() methods as well as a 'test_dir'
187
attribute used as a jail root.
189
:param text: A shell-like script (see _script_to_commands for syntax).
168
191
for cmd, input, output, error in _script_to_commands(text):
169
self.run_command(cmd, input, output, error)
171
def _check_output(self, expected, actual):
192
self.run_command(test_case, cmd, input, output, error)
194
def run_command(self, test_case, cmd, input, output, error):
195
mname = 'do_' + cmd[0]
196
method = getattr(self, mname, None)
198
raise SyntaxError('Command not found "%s"' % (cmd[0],),
199
None, 1, ' '.join(cmd))
203
str_input = ''.join(input)
204
args = list(self._pre_process_args(cmd[1:]))
205
retcode, actual_output, actual_error = method(test_case,
208
self._check_output(output, actual_output, test_case)
209
self._check_output(error, actual_error, test_case)
210
if retcode and not error and actual_error:
211
test_case.fail('In \n\t%s\nUnexpected error: %s'
212
% (' '.join(cmd), actual_error))
213
return retcode, actual_output, actual_error
215
def _check_output(self, expected, actual, test_case):
172
216
if expected is None:
173
217
# Specifying None means: any output is accepted
175
219
if actual is None:
176
self.test_case.fail('Unexpected: %s' % actual)
220
test_case.fail('Unexpected: %s' % actual)
177
221
matching = self.output_checker.check_output(
178
222
expected, actual, self.check_options)
208
def run_command(self, cmd, input, output, error):
209
mname = 'do_' + cmd[0]
210
method = getattr(self, mname, None)
212
raise SyntaxError('Command not found "%s"' % (cmd[0],),
213
None, 1, ' '.join(cmd))
217
str_input = ''.join(input)
218
args = list(self._pre_process_args(cmd[1:]))
219
retcode, actual_output, actual_error = method(str_input, args)
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
228
252
def _read_input(self, input, in_name):
229
253
if in_name is not None:
230
254
infile = open(in_name, 'rb')
248
def do_bzr(self, input, args):
249
retcode, out, err = self.test_case._run_bzr_core(
272
def do_bzr(self, test_case, input, args):
273
retcode, out, err = test_case._run_bzr_core(
250
274
args, retcode=None, encoding=None, stdin=input, working_dir=None)
251
275
return retcode, out, err
253
def do_cat(self, input, args):
277
def do_cat(self, test_case, input, args):
254
278
(in_name, out_name, out_mode, args) = _scan_redirection_options(args)
255
279
if args and in_name is not None:
256
280
raise SyntaxError('Specify a file OR use redirection')
278
302
return 1, None, '%s: No such file or directory\n' % (out_name,)
279
303
return 0, output, None
281
def do_echo(self, input, args):
305
def do_echo(self, test_case, input, args):
282
306
(in_name, out_name, out_mode, args) = _scan_redirection_options(args)
283
307
if input and args:
284
308
raise SyntaxError('Specify parameters OR use redirection')
301
325
return 1, None, '%s: No such file or directory\n' % (out_name,)
302
326
return 0, output, None
304
def _ensure_in_jail(self, path):
305
jail_root = self.test_case.get_jail_root()
328
def _get_jail_root(self, test_case):
329
return test_case.test_dir
331
def _ensure_in_jail(self, test_case, path):
332
jail_root = self._get_jail_root(test_case)
306
333
if not osutils.is_inside(jail_root, osutils.normalizepath(path)):
307
334
raise ValueError('%s is not inside %s' % (path, jail_root))
309
def do_cd(self, input, args):
336
def do_cd(self, test_case, input, args):
310
337
if len(args) > 1:
311
338
raise SyntaxError('Usage: cd [dir]')
312
339
if len(args) == 1:
314
self._ensure_in_jail(d)
341
self._ensure_in_jail(test_case, d)
316
d = self.test_case.get_jail_root()
343
# The test "home" directory is the root of its jail
344
d = self._get_jail_root(test_case)
318
346
return 0, None, None
320
def do_mkdir(self, input, args):
348
def do_mkdir(self, test_case, input, args):
321
349
if not args or len(args) != 1:
322
350
raise SyntaxError('Usage: mkdir dir')
324
self._ensure_in_jail(d)
352
self._ensure_in_jail(test_case, d)
326
354
return 0, None, None
328
def do_rm(self, input, args):
356
def do_rm(self, test_case, input, args):
331
359
def error(msg, path):
373
401
class TestCaseWithMemoryTransportAndScript(tests.TestCaseWithMemoryTransport):
402
"""Helper class to experiment shell-like test and memory fs.
404
This not intended to be used outside of experiments in implementing memoy
405
based file systems and evolving bzr so that test can use only memory based
376
410
super(TestCaseWithMemoryTransportAndScript, self).setUp()
377
self.script_runner = ScriptRunner(self)
378
# Break the circular dependency
379
def break_dependency():
380
self.script_runner = None
381
self.addCleanup(break_dependency)
383
def get_jail_root(self):
384
raise NotImplementedError(self.get_jail_root)
411
self.script_runner = ScriptRunner()
386
413
def run_script(self, script):
387
return self.script_runner.run_script(script)
414
return self.script_runner.run_script(self, script)
389
416
def run_command(self, cmd, input, output, error):
390
return self.script_runner.run_command(cmd, input, output, error)
417
return self.script_runner.run_command(self, cmd, input, output, error)
393
420
class TestCaseWithTransportAndScript(tests.TestCaseWithTransport):
421
"""Helper class to quickly define shell-like tests.
425
from bzrlib.tests import script
428
class TestBug(script.TestCaseWithTransportAndScript):
430
def test_bug_nnnnn(self):
396
439
super(TestCaseWithTransportAndScript, self).setUp()
397
self.script_runner = ScriptRunner(self)
398
# Break the circular dependency
399
def break_dependency():
400
self.script_runner = None
401
self.addCleanup(break_dependency)
403
def get_jail_root(self):
440
self.script_runner = ScriptRunner()
406
442
def run_script(self, script):
407
return self.script_runner.run_script(script)
443
return self.script_runner.run_script(self, script)
409
445
def run_command(self, cmd, input, output, error):
410
return self.script_runner.run_command(cmd, input, output, error)
446
return self.script_runner.run_command(self, cmd, input, output, error)