160
160
class ScriptRunner(object):
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
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)
171
def _check_output(self, expected, actual):
169
self.run_command(cmd, input, output, error, test_case)
171
def run_command(self, cmd, input, output, error, test_case):
172
mname = 'do_' + cmd[0]
173
method = getattr(self, mname, None)
175
raise SyntaxError('Command not found "%s"' % (cmd[0],),
176
None, 1, ' '.join(cmd))
180
str_input = ''.join(input)
181
args = list(self._pre_process_args(cmd[1:]))
182
retcode, actual_output, actual_error = method(test_case,
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
192
def _check_output(self, expected, actual, test_case):
172
193
if expected is None:
173
194
# Specifying None means: any output is accepted
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)
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)
188
209
def _pre_process_args(self, args):
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
229
def _read_input(self, input, in_name):
229
230
if in_name is not None:
230
231
infile = open(in_name, 'rb')
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
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
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
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))
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:
314
314
self._ensure_in_jail(d)
316
d = self.test_case.get_jail_root()
318
318
return 0, None, None
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')
371
371
class TestCaseWithMemoryTransportAndScript(tests.TestCaseWithMemoryTransport):
372
"""Helper class to experiment shell-like test and memory fs.
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
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)
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()
384
384
def run_script(self, script):
385
return self.script_runner.run_script(script)
385
return self.script_runner.run_script(script, self)
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)
391
391
class TestCaseWithTransportAndScript(tests.TestCaseWithTransport):
392
"""Helper class to quickly define shell-like tests.
396
from bzrlib.tests import script
399
class TestBug(script.TestCaseWithTransportAndScript):
401
def test_bug_nnnnn(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)
401
def get_jail_root(self):
411
self.script_runner = ScriptRunner(self.test_dir)
404
413
def run_script(self, script):
405
return self.script_runner.run_script(script)
414
return self.script_runner.run_script(script, self)
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)