'''Usage: %s [OPTIONS] <input file(s)>
Generate test source file for CxxTest.
-v, --version Write CxxTest version
-o, --output=NAME Write output to file NAME
--runner=CLASS Create a main() function that runs CxxTest::CLASS
--gui=CLASS Like --runner, with GUI component
--error-printer Same as --runner=ErrorPrinter
--abort-on-fail Abort tests on failed asserts (like xUnit)
--have-std Use standard library (even if not found in tests)
--no-std Don\'t use standard library (even if found in tests)
--have-eh Use exception handling (even if not found in tests)
--no-eh Don\'t use exception handling (even if found in tests)
--longlong=[TYPE] Use TYPE (default: long long) as long long
--template=TEMPLATE Use TEMPLATE file to generate the test runner
--include=HEADER Include HEADER in test runner before other headers
--root Write CxxTest globals
--part Don\'t write CxxTest globals
--no-static-init Don\'t rely on static initialization
'''
import re
import sys
import getopt
import glob
import string
# Global variables
suites = []
suite = None
outputFileName = None
runner = None
gui = None
root = None
part = None
noStaticInit = None
templateFileName = None
headers = []
def main():
'''The main program'''
'''Print usage info and exit'''
if problem is None:
print usageString()
else:
def usageString():
'''Construct program usage string'''
'''Print error message and exit'''
def parseCommandline():
'''Analyze command line arguments'''
try:
['version', 'output=', 'runner=', 'gui=',
'error-printer', 'abort-on-fail', 'have-std', 'no-std',
'have-eh', 'no-eh', 'template=', 'include=',
'root', 'part', 'no-static-init', 'factor', 'longlong='] )
'''Set options specified on command line'''
for o, a in options:
if o in ('-v', '--version'):
elif o in ('-o', '--output'):
outputFileName = a
elif o == '--template':
templateFileName = a
elif o == '--runner':
runner = a
elif o == '--gui':
gui = a
elif o == '--include':
a = ('"%s"' % a)
elif o == '--error-printer':
runner = 'ErrorPrinter'
elif o == '--abort-on-fail':
abortOnFail = 1
elif o == '--have-std':
elif o == '--no-std':
elif o == '--have-eh':
elif o == '--no-eh':
elif o == '--root':
root = 1
elif o == '--part':
part = 1
elif o == '--no-static-init':
noStaticInit = 1
elif o == '--factor':
factor = 1
elif o == '--longlong':
if a:
longlong = a
else:
longlong = 'long long'
abort( '--no-static-init cannot be used with --root/--part' )
runner = 'StdioPrinter'
def printVersion():
'''Print CxxTest version and exit'''
'''Set input files specified on command line'''
usage( "No input files found" )
return files
'''Expand all wildcards in an array (glob)'''
fileNames = []
for fileName in patternFiles:
return fileNames
'''Convert backslashes to slashes in file name'''
'''Scan all input files for test suites'''
global suites
abort( 'No tests defined' )
'''Scan single input file for test suites'''
lineNo = 0
while 1:
if not line:
break
'''Scan single input line for interesting stuff'''
global suite
if suite:
'''Analyze line which is part of a suite'''
global inBlock
'''Returns whether current line is part of the current suite.
This can be false when we are in a generated suite outside of CXXTEST_CODE() blocks
If the suite is generated, adds the line to the list of lines'''
if not suite['generated']:
return 1
global inBlock
if not inBlock:
if inBlock:
return inBlock
std_re = re.compile( r"\b(std\s*::|CXXTEST_STD|using\s+namespace\s+std\b|^\s*\#\s*include\s+<[a-z0-9]+>)" )
'''Check if current line uses standard library'''
global haveStandardLibrary, noStandardLibrary
if not noStandardLibrary:
'''Check if current line uses exception handling'''
if not noExceptionHandling:
'''Check if current line starts a new test suite'''
if m:
if m:
'''Start scanning a new suite'''
global suite
'file' : file,
'line' : line,
'generated' : generated,
'tests' : [],
'lines' : [] }
'''Check if current line starts a new CXXTEST_CODE() block'''
'''Check if current line starts a test'''
if m:
'''Add a test function to the current suite'''
'suite' : suite,
'line' : line,
}
'''Append the line to the current CXXTEST_CODE() block'''
if e:
return e is None
line, 0 )
'''Check if current line defines a createSuite() function'''
'''Check if current line defines a destroySuite() function'''
'''Convert a string to its C representation'''
'''Add createSuite()/destroySuite() to current suite'''
def closeSuite():
'''Close current suite and add it to the list if valid'''
global suite
if suite is not None:
suite = None
'''Verify current suite is legal'''
abort( '%s:%s: Suite %s has createSuite() but no destroySuite()' %
abort( '%s:%s: Suite %s has destroySuite() but no createSuite()' %
'''Add current suite to list'''
global suites
def writeOutput():
'''Create output file'''
if templateFileName:
else:
def writeSimpleOutput():
'''Create output not based on template'''
writeWorld( output )
def writeTemplateOutput():
'''Create output based on template file'''
while 1:
if not line:
break;
writeWorld( output )
else:
def startOutputFile():
'''Create output file and write header'''
if outputFileName is not None:
else:
return output
'''Write the CxxTest header (#includes and #defines)'''
if wrotePreamble: return
if abortOnFail:
if longlong:
if factor:
if runner:
if gui:
wrotePreamble = 1
'''Write the main() function for the test runner'''
if gui:
if noStaticInit:
output.write( ' return CxxTest::GuiTuiRunner<CxxTest::%s, CxxTest::%s>( argc, argv ).run();\n' % (gui, runner) )
elif runner:
if noStaticInit:
'''Write the world definitions'''
global wroteWorld, part
if wroteWorld: return
if noStaticInit:
wroteWorld = 1
'''Write all TestDescriptions and SuiteDescriptions'''
if isGenerated(suite):
else:
'''Checks whether a suite class should be created'''
return suite['generated']
'''Checks whether a suite is dynamic'''
'''Add #include "file" statement'''
global lastIncluded
if file == lastIncluded: return
'''Write a suite declared with CXXTEST_SUITE()'''
'''Create static suite pointer object for dynamic suites'''
if noStaticInit:
else:
'''Create static suite object for non-dynamic suites'''
'''Write the head of the test linked list for a suite'''
if noStaticInit:
else:
'''Write all test descriptions for a suite'''
'''Write test description object'''
if not noStaticInit:
'''Body of TestDescription::run()'''
'''Body of TestDescription::run() for test in a dynamic suite'''
'''Body of TestDescription::run() for test in a non-dynamic suite'''
'''Write SuiteDescription object'''
else:
'''Write SuiteDescription for a dynamic suite'''
if not noStaticInit:
'''Write SuiteDescription for a static suite'''
if not noStaticInit:
'''Write static members of CxxTest classes'''
'''Write CxxTest::initialize(), which replaces static initialization'''
else:
main()