Index: tools/testrunner/local/statusfile.py |
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py |
index 8464ef22414448e72e59da586a5162485ba8f987..877652923d0a80ba06ff0739f87f57d6c00be133 100644 |
--- a/tools/testrunner/local/statusfile.py |
+++ b/tools/testrunner/local/statusfile.py |
@@ -26,6 +26,10 @@ |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
import os |
+import re |
+ |
+from variants import ALL_VARIANTS |
+from utils import Freeze |
# These outcomes can occur in a TestCase's outcomes list: |
SKIP = "SKIP" |
@@ -63,6 +67,10 @@ for var in ["debug", "release", "big", "little", |
"windows", "linux", "aix"]: |
VARIABLES[var] = var |
+# Allow using variants as keywords. |
+for var in ALL_VARIANTS: |
+ VARIABLES[var] = var |
+ |
def DoSkip(outcomes): |
return SKIP in outcomes |
@@ -116,6 +124,34 @@ def _JoinsPassAndFail(outcomes1, outcomes2): |
FAIL in outcomes2 |
) |
+VARIANT_EXPRESSION = object() |
+ |
+def _EvalExpression(exp, variables): |
+ try: |
+ return eval(exp, variables) |
+ except NameError as e: |
+ identifier = re.match("name '(.*)' is not defined", e.message).group(1) |
+ assert identifier == "variant", "Unknown identifier: %s" % identifier |
+ return VARIANT_EXPRESSION |
+ |
+ |
+def _EvalVariantExpression(section, rules, wildcards, variant, variables): |
+ variables_with_variant = {} |
+ variables_with_variant.update(variables) |
+ variables_with_variant["variant"] = variant |
+ result = _EvalExpression(section[0], variables_with_variant) |
+ assert result != VARIANT_EXPRESSION |
+ if result is True: |
+ _ReadSection( |
+ section[1], |
+ rules[variant], |
+ wildcards[variant], |
+ variables_with_variant, |
+ ) |
+ else: |
+ assert result is False, "Make sure expressions evaluate to boolean values" |
+ |
+ |
def _ParseOutcomeList(rule, outcomes, target_dict, variables): |
result = set([]) |
if type(outcomes) == str: |
@@ -124,7 +160,16 @@ def _ParseOutcomeList(rule, outcomes, target_dict, variables): |
if type(item) == str: |
_AddOutcome(result, item) |
elif type(item) == list: |
- if not eval(item[0], variables): continue |
+ exp = _EvalExpression(item[0], variables) |
+ assert exp != VARIANT_EXPRESSION, ( |
+ "Nested variant expressions are not supported") |
+ if exp is False: |
+ continue |
+ |
+ # Ensure nobody uses an identifier by mistake, like "default", |
+ # which would evaluate to true here otherwise. |
+ assert exp is True, "Make sure expressions evaluate to boolean values" |
+ |
for outcome in item[1:]: |
assert type(outcome) == str |
_AddOutcome(result, outcome) |
@@ -146,35 +191,57 @@ def _ParseOutcomeList(rule, outcomes, target_dict, variables): |
target_dict[rule] = result |
-def ReadContent(path): |
- with open(path) as f: |
- global KEYWORDS |
- return eval(f.read(), KEYWORDS) |
+def ReadContent(content): |
+ global KEYWORDS |
+ return eval(content, KEYWORDS) |
-def ReadStatusFile(path, variables): |
- contents = ReadContent(path) |
+def ReadStatusFile(content, variables): |
+ # Empty defaults for rules and wildcards. Variant-independent |
+ # rules are mapped by "", others by the variant name. |
+ rules = {variant: {} for variant in ALL_VARIANTS} |
+ rules[""] = {} |
+ wildcards = {variant: {} for variant in ALL_VARIANTS} |
+ wildcards[""] = {} |
- rules = {} |
- wildcards = {} |
variables.update(VARIABLES) |
- for section in contents: |
+ for section in ReadContent(content): |
assert type(section) == list |
assert len(section) == 2 |
- if not eval(section[0], variables): continue |
- section = section[1] |
- assert type(section) == dict |
- for rule in section: |
- assert type(rule) == str |
- if rule[-1] == '*': |
- _ParseOutcomeList(rule, section[rule], wildcards, variables) |
- else: |
- _ParseOutcomeList(rule, section[rule], rules, variables) |
- return rules, wildcards |
+ exp = _EvalExpression(section[0], variables) |
+ if exp is False: |
+ # The expression is variant-independent and evaluates to False. |
+ continue |
+ elif exp == VARIANT_EXPRESSION: |
+ # If the expression contains one or more "variant" keywords, we evaluate |
+ # it for all possible variants and create rules for those that apply. |
+ for variant in ALL_VARIANTS: |
+ _EvalVariantExpression(section, rules, wildcards, variant, variables) |
+ else: |
+ # The expression is variant-independent and evaluates to True. |
+ assert exp is True, "Make sure expressions evaluate to boolean values" |
+ _ReadSection( |
+ section[1], |
+ rules[""], |
+ wildcards[""], |
+ variables, |
+ ) |
+ return Freeze(rules), Freeze(wildcards) |
+ |
+ |
+def _ReadSection(section, rules, wildcards, variables): |
+ assert type(section) == dict |
+ for rule in section: |
+ assert type(rule) == str |
+ if rule[-1] == '*': |
+ _ParseOutcomeList(rule, section[rule], wildcards, variables) |
+ else: |
+ _ParseOutcomeList(rule, section[rule], rules, variables) |
def PresubmitCheck(path): |
- contents = ReadContent(path) |
+ with open(path) as f: |
+ contents = ReadContent(f.read()) |
root_prefix = os.path.basename(os.path.dirname(path)) + "/" |
status = {"success": True} |
def _assert(check, message): # Like "assert", but doesn't throw. |