Current state of mal for Clojure West lighting talk.
[jackhill/mal.git] / runtest.py
CommitLineData
31690700
JM
1#!/usr/bin/env python
2
3import os, sys, re
4import argparse
5
6# http://pexpect.sourceforge.net/pexpect.html
7from pexpect import spawn, EOF, TIMEOUT
8
9# TODO: do we need to support '\n' too
10sep = "\r\n"
11rundir = None
12
13parser = argparse.ArgumentParser(
14 description="Run a test file against a Mal implementation")
15parser.add_argument('--rundir',
16 help="change to the directory before running tests")
17parser.add_argument('--start-timeout', default=10, type=int,
18 help="default timeout for initial prompt")
19parser.add_argument('--test-timeout', default=20, type=int,
20 help="default timeout for each individual test action")
21
22parser.add_argument('test_file', type=argparse.FileType('r'),
23 help="a test file formatted as with mal test data")
24parser.add_argument('mal_cmd', nargs="*",
25 help="Mal implementation command line. Use '--' to "
26 "specify a Mal command line with dashed options.")
27
28args = parser.parse_args(sys.argv[1:])
29test_data = args.test_file.read().split('\n')
30
31if args.rundir: os.chdir(args.rundir)
32
33p = spawn(args.mal_cmd[0], args.mal_cmd[1:])
34
35test_idx = 0
36def read_test(data):
37 global test_idx
38 form, output, ret = None, "", None
39 while data:
40 test_idx += 1
41 line = data.pop(0)
42 if re.match(r"^\s*$", line): # blank line
43 continue
44 elif line[0:3] == ";;;": # ignore comment
45 continue
46 elif line[0:2] == ";;": # output comment
47 print line[3:]
48 continue
49 elif line[0:2] == ";": # unexpected comment
50 print "Test data error at line %d:\n%s" % (test_idx, line)
51 return None, None, None, test_idx
52 form = line # the line is a form to send
53
54 # Now find the output and return value
55 while data:
56 line = data[0]
57 if line[0:3] == ";=>":
58 ret = line[3:].replace('\\r', '\r').replace('\\n', '\n')
59 test_idx += 1
60 data.pop(0)
61 break
62 elif line[0:2] == "; ":
63 output = output + line[2:] + sep
64 test_idx += 1
65 data.pop(0)
66 else:
67 ret = "*"
68 break
69 if ret: break
70
71 return form, output, ret, test_idx
72
73
74# Wait for the initial prompt
75idx = p.expect(['user> ', 'mal-user> ', EOF, TIMEOUT],
76 timeout=args.start_timeout)
77if idx not in [0,1]:
78 print "Never got 'user> ' prompt"
79 print " Got : %s" % repr(p.before)
80 sys.exit(1)
81
82fail_cnt = 0
83
84while test_data:
85 form, out, ret, line_num = read_test(test_data)
86 if form == None:
87 break
88 sys.stdout.write("TEST: %s -> [%s,%s]" % (form, repr(out), repr(ret)))
89 sys.stdout.flush()
90 expected = "%s%s%s%s" % (form, sep, out, ret)
91
92 p.sendline(form)
93 try:
94 idx = p.expect(['\r\nuser> ', '\nuser> ',
95 '\r\nmal-user> ', '\nmal-user> '],
96 timeout=args.test_timeout)
97 #print "%s,%s,%s" % (idx, repr(p.before), repr(p.after))
98 if ret == "*" or p.before == expected:
99 print " -> SUCCESS"
100 else:
101 print " -> FAIL (line %d):" % line_num
102 print " Expected : %s" % repr(expected)
103 print " Got : %s" % repr(p.before)
104 fail_cnt += 1
105 except EOF:
106 print "Got EOF"
107 sys.exit(1)
108 except TIMEOUT:
109 print "Got TIMEOUT, received: %s" % repr(p.before)
110 sys.exit(1)
111
112if fail_cnt > 0:
113 print "FAILURES: %d" % fail_cnt
114 sys.exit(2)
115sys.exit(0)