57
55
Input lines start with '<'.
58
56
Output lines start with nothing.
59
57
Error lines start with '2>'.
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.
81
75
input, output, error = None, None, None
82
text = textwrap.dedent(text)
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] == '':
88
if lines and lines[-1] == '':
76
for line in text.split('\n'):
92
78
# Keep a copy for error reporting
94
80
comment = line.find('#')
97
# NB: this syntax means comments are allowed inside output, which
99
83
line = line[0:comment]
100
84
line = line.rstrip()
103
88
if line.startswith('$'):
104
89
# Time to output the current command
105
90
add_command(cmd_cur, input, output, error)
196
181
self.output_checker = doctest.OutputChecker()
197
182
self.check_options = doctest.ELLIPSIS
199
def run_script(self, test_case, text, null_output_matches_anything=False):
184
def run_script(self, test_case, text):
200
185
"""Run a shell-like script as a test.
202
187
:param test_case: A TestCase instance that should provide the fail(),
204
189
attribute used as a jail root.
206
191
:param text: A shell-like script (see _script_to_commands for syntax).
208
:param null_output_matches_anything: For commands with no specified
209
output, ignore any output that does happen, including output on
212
self.null_output_matches_anything = null_output_matches_anything
213
193
for cmd, input, output, error in _script_to_commands(text):
214
194
self.run_command(test_case, cmd, input, output, error)
218
198
method = getattr(self, mname, None)
219
199
if method is None:
220
200
raise SyntaxError('Command not found "%s"' % (cmd[0],),
221
(None, 1, 1, ' '.join(cmd)))
201
None, 1, ' '.join(cmd))
222
202
if input is None:
227
207
retcode, actual_output, actual_error = method(test_case,
231
self._check_output(output, actual_output, test_case)
232
except AssertionError, e:
233
raise AssertionError(str(e) + " in stdout of command %s" % cmd)
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)
210
self._check_output(output, actual_output, test_case)
211
self._check_output(error, actual_error, test_case)
239
212
if retcode and not error and actual_error:
240
213
test_case.fail('In \n\t%s\nUnexpected error: %s'
241
214
% (' '.join(cmd), actual_error))
242
215
return retcode, actual_output, actual_error
244
217
def _check_output(self, expected, actual, test_case):
248
elif expected == '...\n':
251
test_case.fail('expected output: %r, but found nothing'
254
null_output_matches_anything = getattr(
255
self, 'null_output_matches_anything', False)
256
if null_output_matches_anything and expected is None:
219
# Specifying None means: any output is accepted
259
expected = expected or ''
222
test_case.fail('We expected output: %r, but found None'
260
224
matching = self.output_checker.check_output(
261
225
expected, actual, self.check_options)
266
230
# 'expected' parameter. So we just fallback to our good old
267
231
# assertEqualDiff since we know there *are* differences and the
268
232
# output should be decently readable.
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
274
if expected == actual + '\n':
277
test_case.assertEqualDiff(expected, actual)
233
test_case.assertEqualDiff(expected, actual)
279
235
def _pre_process_args(self, args):
484
440
super(TestCaseWithMemoryTransportAndScript, self).setUp()
485
441
self.script_runner = ScriptRunner()
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)
443
def run_script(self, script):
444
return self.script_runner.run_script(self, script)
491
446
def run_command(self, cmd, input, output, error):
492
447
return self.script_runner.run_command(self, cmd, input, output, error)
514
469
super(TestCaseWithTransportAndScript, self).setUp()
515
470
self.script_runner = ScriptRunner()
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)
472
def run_script(self, script):
473
return self.script_runner.run_script(self, script)
521
475
def run_command(self, cmd, input, output, error):
522
476
return self.script_runner.run_command(self, cmd, input, output, error)
525
def run_script(test_case, script_string, null_output_matches_anything=False):
526
"""Run the given script within a testcase"""
527
return ScriptRunner().run_script(test_case, script_string,
528
null_output_matches_anything=null_output_matches_anything)