6 # http://pexpect.sourceforge.net/pexpect.html
7 from pexpect
import spawn
, EOF
, TIMEOUT
9 # TODO: do we need to support '\n' too
13 parser
= argparse
.ArgumentParser(
14 description
="Run a test file against a Mal implementation")
15 parser
.add_argument('--rundir',
16 help="change to the directory before running tests")
17 parser
.add_argument('--start-timeout', default
=10, type=int,
18 help="default timeout for initial prompt")
19 parser
.add_argument('--test-timeout', default
=20, type=int,
20 help="default timeout for each individual test action")
21 parser
.add_argument('--pre-eval', default
=None, type=str,
22 help="Mal code to evaluate prior to running the test")
23 parser
.add_argument('--redirect', action
='store_true',
24 help="Run implementation in bash and redirect output to /dev/null")
26 parser
.add_argument('test_file', type=argparse
.FileType('r'),
27 help="a test file formatted as with mal test data")
28 parser
.add_argument('mal_cmd', nargs
="*",
29 help="Mal implementation command line. Use '--' to "
30 "specify a Mal command line with dashed options.")
32 args
= parser
.parse_args(sys
.argv
[1:])
33 test_data
= args
.test_file
.read().split('\n')
35 if args
.rundir
: os
.chdir(args
.rundir
)
38 # Redirect to try and force raw mode (no ASCII codes)
39 p
= spawn('/bin/bash -c "' + " ".join(args
.mal_cmd
) + ' |tee /dev/null"')
41 p
= spawn(args
.mal_cmd
[0], args
.mal_cmd
[1:])
47 form
, output
, ret
= None, "", None
51 if re
.match(r
"^\s*$", line
): # blank line
53 elif line
[0:3] == ";;;": # ignore comment
55 elif line
[0:2] == ";;": # output comment
58 elif line
[0:2] == ";": # unexpected comment
59 print "Test data error at line %d:\n%s" % (test_idx
, line
)
60 return None, None, None, test_idx
61 form
= line
# the line is a form to send
63 # Now find the output and return value
66 if line
[0:3] == ";=>":
67 ret
= line
[3:].replace('\\r', '\r').replace('\\n', '\n')
71 elif line
[0:2] == "; ":
72 output
= output
+ line
[2:] + sep
80 return form
, output
, ret
, test_idx
82 def assert_prompt(timeout
):
83 # Wait for the initial prompt
84 idx
= p
.expect(['user> ', 'mal-user> ', EOF
, TIMEOUT
],
87 print "Did not get 'user> ' or 'mal-user> ' prompt"
88 print " Got : %s" % repr(p
.before
)
92 # Wait for the initial prompt
93 assert_prompt(args
.start_timeout
)
95 # Send the pre-eval code if any
97 sys
.stdout
.write("RUNNING pre-eval: %s" % args
.pre_eval
)
98 p
.sendline(args
.pre_eval
)
99 assert_prompt(args
.test_timeout
)
104 form
, out
, ret
, line_num
= read_test(test_data
)
107 sys
.stdout
.write("TEST: %s -> [%s,%s]" % (form
, repr(out
), repr(ret
)))
109 expected
= "%s%s%s%s" % (form
, sep
, out
, ret
)
113 idx
= p
.expect(['\r\nuser> ', '\nuser> ',
114 '\r\nmal-user> ', '\nmal-user> '],
115 timeout
=args
.test_timeout
)
116 #print "%s,%s,%s" % (idx, repr(p.before), repr(p.after))
117 if ret
== "*" or p
.before
== expected
:
120 print " -> FAIL (line %d):" % line_num
121 print " Expected : %s" % repr(expected
)
122 print " Got : %s" % repr(p
.before
)
128 print "Got TIMEOUT, received: %s" % repr(p
.before
)
132 print "FAILURES: %d" % fail_cnt