raise ValueError("expected: %s\nhave: %s" %
(self.quote(t), self.quote(self.token)))
- def isIdentifier(self, t):
- if (t is BooleanExpression.END or t == '&&' or t == '||' or
- t == '!' or t == '(' or t == ')'):
+ @staticmethod
+ def isIdentifier(token):
+ if (token is BooleanExpression.END or token == '&&' or token == '||' or
+ token == '!' or token == '(' or token == ')'):
return False
return True
elif self.accept('('):
self.parseOR()
self.expect(')')
- elif not self.isIdentifier(self.token):
+ elif not BooleanExpression.isIdentifier(self.token):
raise ValueError("expected: '!' or '(' or identifier\nhave: %s" %
self.quote(self.token))
else:
"actual error was:\n%s\n" +
"expected error was:\n%s\n") % (expr, e, error))
except BaseException as e:
- self.fail(("expression %r caused the wrong exception; actual " +
+ self.fail(("expression %r caused the wrong exception; actual " +
"exception was: \n%r") % (expr, e))
def test_errors(self):
+import itertools
import os
from xml.sax.saxutils import quoteattr
from json import JSONEncoder
addMicroResult(microResult)
Attach a micro-test result to the test result, with the given name and
- result. It is an error to attempt to attach a micro-test with the
+ result. It is an error to attempt to attach a micro-test with the
same name multiple times.
Each micro-test result must be an instance of the Result class.
except ValueError as e:
raise ValueError('Error in UNSUPPORTED list:\n%s' % str(e))
+ def getUsedFeatures(self):
+ """
+ getUsedFeatures() -> list of strings
+
+ Returns a list of all features appearing in XFAIL, UNSUPPORTED and
+ REQUIRES annotations for this test.
+ """
+ import lit.TestRunner
+ parsed = lit.TestRunner._parseKeywords(self.getSourcePath(), require_script=False)
+ feature_keywords = ('UNSUPPORTED:', 'REQUIRES:', 'XFAIL:')
+ boolean_expressions = itertools.chain.from_iterable(
+ parsed[k] or [] for k in feature_keywords
+ )
+ tokens = itertools.chain.from_iterable(
+ BooleanExpression.tokenize(expr) for expr in
+ boolean_expressions if expr != '*'
+ )
+ identifiers = set(filter(BooleanExpression.isIdentifier, tokens))
+ return identifiers
+
def isEarlyTest(self):
"""
isEarlyTest() -> bool
BooleanExpression.evaluate(s, [])
return output
-def parseIntegratedTestScript(test, additional_parsers=[],
- require_script=True):
- """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
- script and extract the lines to 'RUN' as well as 'XFAIL', 'REQUIRES',
- 'UNSUPPORTED' and 'ALLOW_RETRIES' information.
- If additional parsers are specified then the test is also scanned for the
- keywords they specify and all matches are passed to the custom parser.
+def _parseKeywords(sourcepath, additional_parsers=[],
+ require_script=True):
+ """_parseKeywords
- If 'require_script' is False an empty script
- may be returned. This can be used for test formats where the actual script
- is optional or ignored.
- """
+ Scan an LLVM/Clang style integrated test script and extract all the lines
+ pertaining to a special parser. This includes 'RUN', 'XFAIL', 'REQUIRES',
+ 'UNSUPPORTED' and 'ALLOW_RETRIES', as well as other specified custom
+ parsers.
+ Returns a dictionary mapping each custom parser to its value after
+ parsing the test.
+ """
# Install the built-in keyword parsers.
script = []
builtin_parsers = [
- IntegratedTestKeywordParser('RUN:', ParserKind.COMMAND,
- initial_value=script),
- IntegratedTestKeywordParser('XFAIL:', ParserKind.BOOLEAN_EXPR,
- initial_value=test.xfails),
- IntegratedTestKeywordParser('REQUIRES:', ParserKind.BOOLEAN_EXPR,
- initial_value=test.requires),
- IntegratedTestKeywordParser('UNSUPPORTED:', ParserKind.BOOLEAN_EXPR,
- initial_value=test.unsupported),
+ IntegratedTestKeywordParser('RUN:', ParserKind.COMMAND, initial_value=script),
+ IntegratedTestKeywordParser('XFAIL:', ParserKind.BOOLEAN_EXPR),
+ IntegratedTestKeywordParser('REQUIRES:', ParserKind.BOOLEAN_EXPR),
+ IntegratedTestKeywordParser('UNSUPPORTED:', ParserKind.BOOLEAN_EXPR),
IntegratedTestKeywordParser('ALLOW_RETRIES:', ParserKind.INTEGER),
IntegratedTestKeywordParser('END.', ParserKind.TAG)
]
keyword_parsers[parser.keyword] = parser
# Collect the test lines from the script.
- sourcepath = test.getSourcePath()
for line_number, command_type, ln in \
parseIntegratedTestScriptCommands(sourcepath,
keyword_parsers.keys()):
if value and value[-1][-1] == '\\':
raise ValueError("Test has unterminated %s lines (with '\\')" % key)
+ # Make sure there's at most one ALLOW_RETRIES: line
+ allowed_retries = keyword_parsers['ALLOW_RETRIES:'].getValue()
+ if allowed_retries and len(allowed_retries) > 1:
+ return lit.Test.Result(Test.UNRESOLVED,
+ "Test has more than one ALLOW_RETRIES lines")
+
+ return {p.keyword: p.getValue() for p in keyword_parsers.values()}
+
+
+def parseIntegratedTestScript(test, additional_parsers=[],
+ require_script=True):
+ """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
+ script and extract the lines to 'RUN' as well as 'XFAIL', 'REQUIRES',
+ 'UNSUPPORTED' and 'ALLOW_RETRIES' information into the given test.
+
+ If additional parsers are specified then the test is also scanned for the
+ keywords they specify and all matches are passed to the custom parser.
+
+ If 'require_script' is False an empty script
+ may be returned. This can be used for test formats where the actual script
+ is optional or ignored.
+ """
+ # Parse the test sources and extract test properties
+ parsed = _parseKeywords(test.getSourcePath(), additional_parsers, require_script)
+ script = parsed['RUN:'] or []
+ test.xfails = parsed['XFAIL:'] or []
+ test.requires = parsed['REQUIRES:'] or []
+ test.unsupported = parsed['UNSUPPORTED:'] or []
+ if parsed['ALLOW_RETRIES:']:
+ test.allowed_retries = parsed['ALLOW_RETRIES:'][0]
+
# Enforce REQUIRES:
missing_required_features = test.getMissingRequiredFeatures()
if missing_required_features:
"Test does not support the following features "
"and/or targets: %s" % msg)
- # Handle ALLOW_RETRIES:
- allowed_retries = keyword_parsers['ALLOW_RETRIES:'].getValue()
- if allowed_retries:
- if len(allowed_retries) > 1:
- return lit.Test.Result(Test.UNRESOLVED,
- "Test has more than one ALLOW_RETRIES lines")
- test.allowed_retries = allowed_retries[0]
-
# Enforce limit_to_features.
if not test.isWithinFeatureLimits():
msg = ', '.join(test.config.limit_to_features)