from __future__ import absolute_import, division, print_function
import argparse
import json
import re
retests = re.compile('(.*?)"""(.*?)(r"""|\s*$)', re.DOTALL)
reinvokes = re.compile('(.+?$)(.+?)\s*(\$|\Z)', re.DOTALL | re.MULTILINE)
p = argparse.ArgumentParser(
description="Outputs src/test/testcases.rs to stdout")
p.add_argument("testcases", metavar="FILE",
help="The testcases.docopt language agnostic test suite.")
args = p.parse_args()
with open(args.testcases) as f:
alltests = f.read()
alltests = re.sub('^r"""', '', alltests)
alltests = re.sub('^\s*#.*$', '', alltests, flags=re.MULTILINE)
tests = [] for m in retests.finditer(alltests):
usage, invokes = m.group(1).strip(), m.group(2).strip()
assert invokes.startswith('$'), 'Bad test: "%s"' % invokes
invokes = re.sub('^\$', '', invokes)
for mi in reinvokes.finditer(invokes):
invoke, expect = mi.group(1).strip(), mi.group(2).strip()
err = expect.startswith('"user-error"')
tests.append({
'usage': usage,
'args': invoke.split()[1:],
'expect': None if err else json.loads(expect),
})
def show_test(i, t):
def show_expect(e):
kvs = []
for k, v in e.iteritems():
kvs.append('("%s", %s)' % (k, show_value(v)))
return ', '.join(kvs)
def show_value(v):
if v is None:
return 'Plain(None)'
elif isinstance(v, basestring):
return 'Plain(Some("%s".to_string()))' % v
elif isinstance(v, bool):
return 'Switch(%s)' % ('true' if v else 'false')
elif isinstance(v, int):
return 'Counted(%d)' % v
elif isinstance(v, list):
elms = ', '.join(['"%s".to_string()' % el for el in v])
return 'List(vec!(%s))' % elms
else:
raise ValueError('Unrecognized value: "%s" (type: %s)'
% (v, type(v)))
args = ', '.join(['"%s"' % arg for arg in t['args']])
if t['expect'] is None:
return 'test_user_error!(test_%d_testcases, "%s", &[%s]);' \
% (i, t['usage'], args)
else:
expect = show_expect(t['expect'])
return 'test_expect!(test_%d_testcases, "%s", &[%s], vec!(%s));' \
% (i, t['usage'], args, expect)
print(
"""// !!! ATTENTION !!!
// This file is automatically generated by `scripts/mk-testcases`.
// Please do not edit this file directly!
use Value::{{Switch, Counted, Plain, List}};
use test::{{get_args, map_from_alist, same_args}};
{tests}
""".format(tests='\n\n'.join([show_test(i, t) for i, t in enumerate(tests)])))