2020-01-20 17:18:58 -06:00
|
|
|
# 20 january 2020
|
|
|
|
# note: python 3
|
|
|
|
|
2020-02-16 11:55:50 -06:00
|
|
|
import abc
|
2020-01-20 17:18:58 -06:00
|
|
|
import fileinput
|
|
|
|
import re
|
2020-02-16 11:55:50 -06:00
|
|
|
import sys
|
2020-01-20 17:18:58 -06:00
|
|
|
|
2020-02-16 11:55:50 -06:00
|
|
|
def errf(fmt, *args):
|
|
|
|
print(fmt.format(*args), file = sys.stderr)
|
|
|
|
|
|
|
|
class command(metaclass = abc.ABCMeta):
|
|
|
|
@classmethod
|
|
|
|
@abc.abstractmethod
|
|
|
|
def name(cls):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
@abc.abstractmethod
|
|
|
|
def usageString(cls):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
# returns the list of filenames to iterate through
|
|
|
|
# returns None if there was an error parsing arguments
|
|
|
|
@abc.abstractmethod
|
|
|
|
def processArgs(self, args):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
|
|
|
def run(self, casenames):
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
class listCommand:
|
|
|
|
@classmethod
|
|
|
|
def name(cls):
|
|
|
|
return 'list'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def usageString(cls):
|
|
|
|
return 'list [source-files...]'
|
|
|
|
|
|
|
|
def processArgs(self, args):
|
|
|
|
return args
|
|
|
|
|
|
|
|
def run(self, casenames):
|
|
|
|
for x in casenames:
|
|
|
|
print('Test' + x)
|
|
|
|
command.register(listCommand)
|
|
|
|
|
2020-02-16 12:48:20 -06:00
|
|
|
headerHeader = '''// Generated by testlist.py; do not edit
|
|
|
|
struct testingprivCase {
|
|
|
|
const char *name;
|
|
|
|
void (*f)(void);
|
|
|
|
};
|
|
|
|
extern const struct testingprivCase testingprivCases[];
|
|
|
|
extern const size_t testingprivNumCases;'''
|
|
|
|
headerEntryFmt = 'extern void testingprivImplName(Test{})(void);'
|
|
|
|
|
2020-02-16 11:55:50 -06:00
|
|
|
class headerCommand:
|
|
|
|
filename = None
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def name(cls):
|
|
|
|
return 'header'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def usageString(cls):
|
|
|
|
return 'header header-file [source-files...]'
|
|
|
|
|
|
|
|
def processArgs(self, args):
|
|
|
|
if len(args) < 1:
|
|
|
|
errf('error: output filename missing')
|
|
|
|
return None
|
|
|
|
self.filename = args[0]
|
|
|
|
return args[1:]
|
|
|
|
|
|
|
|
def run(self, casenames):
|
2020-02-16 12:48:20 -06:00
|
|
|
with open(self.filename, 'wt') as f:
|
|
|
|
print(headerHeader, file = f)
|
|
|
|
for x in casenames:
|
|
|
|
print(headerEntryFmt.format(x), file = f)
|
2020-02-16 11:55:50 -06:00
|
|
|
command.register(headerCommand)
|
|
|
|
|
2020-02-16 12:48:20 -06:00
|
|
|
sourceHeader = '''// Generated by testlist.py; do not edit
|
|
|
|
#include "test.h"
|
|
|
|
const struct testingprivCase testingprivCases[] = {'''
|
|
|
|
sourceEntryFmt = ' {{ "Test{0}", testingprivImplName(Test{0}) }},'
|
|
|
|
sourceFooter = '''}};
|
|
|
|
const size_t testingprivNumCases = {};'''
|
|
|
|
|
|
|
|
class sourceCommand:
|
|
|
|
filename = None
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def name(cls):
|
|
|
|
return 'source'
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def usageString(cls):
|
|
|
|
return 'source source-file [source-files...]'
|
|
|
|
|
|
|
|
def processArgs(self, args):
|
|
|
|
if len(args) < 1:
|
|
|
|
errf('error: output filename missing')
|
|
|
|
return None
|
|
|
|
self.filename = args[0]
|
|
|
|
return args[1:]
|
|
|
|
|
|
|
|
def run(self, casenames):
|
|
|
|
with open(self.filename, 'wt') as f:
|
|
|
|
print(sourceHeader, file = f)
|
|
|
|
for x in casenames:
|
|
|
|
print(sourceEntryFmt.format(x), file = f)
|
|
|
|
print(sourceFooter.format(len(casenames)), file = f)
|
|
|
|
command.register(sourceCommand)
|
|
|
|
|
2020-02-16 11:55:50 -06:00
|
|
|
commands = [
|
|
|
|
listCommand,
|
|
|
|
headerCommand,
|
2020-02-16 12:48:20 -06:00
|
|
|
sourceCommand,
|
2020-02-16 11:55:50 -06:00
|
|
|
]
|
|
|
|
|
|
|
|
def usage():
|
|
|
|
errf('usage:')
|
|
|
|
errf('{} help', sys.argv[0])
|
|
|
|
for cmd in commands:
|
|
|
|
errf('{} {}', sys.argv[0], cmd.usageString())
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def main():
|
|
|
|
r = re.compile('^(?:Test|TestNoInit)\(([A-Za-z0-9_]+)\)$')
|
|
|
|
|
|
|
|
if len(sys.argv) < 2:
|
|
|
|
usage()
|
|
|
|
cmdname = sys.argv[1]
|
|
|
|
if cmdname == 'help':
|
|
|
|
usage()
|
|
|
|
cmdtype = None
|
|
|
|
for cmd in commands:
|
|
|
|
if cmd.name() == cmdname:
|
|
|
|
cmdtype = cmd
|
|
|
|
break
|
|
|
|
if cmdtype is None:
|
2020-02-16 12:48:20 -06:00
|
|
|
errf('error: unknown command {!r}', cmdname)
|
2020-02-16 11:55:50 -06:00
|
|
|
usage()
|
|
|
|
|
|
|
|
cmd = cmdtype()
|
|
|
|
files = cmd.processArgs(sys.argv[2:])
|
|
|
|
if files is None:
|
|
|
|
usage()
|
|
|
|
|
|
|
|
casenames = []
|
|
|
|
for line in fileinput.input(files = files):
|
|
|
|
match = r.match(line)
|
|
|
|
if match is not None:
|
|
|
|
casenames.append(match.group(1))
|
2020-02-16 12:48:20 -06:00
|
|
|
cmd.run(sorted(casenames))
|
2020-02-16 11:55:50 -06:00
|
|
|
|
|
|
|
main()
|