Teach lit to honor conditional directives. The syntax is:
authorJohn McCall <rjmccall@apple.com>
Thu, 4 Mar 2010 09:36:50 +0000 (09:36 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 4 Mar 2010 09:36:50 +0000 (09:36 +0000)
  IF(condition(value)):
If the value satisfies the condition, the line is processed by lit;  otherwise
it is skipped.  A test with no unignored directives is resolved as Unsupported.

The test suite is responsible for defining conditions;  conditions are unary
functions over strings.  I've defined two conditions in the LLVM test suite,
TARGET (with values like those in TARGETS_TO_BUILD) and BINDING (with values
like those in llvm_bindings).  So for example you can write:
  IF(BINDING(ocaml)): RUN: %blah %s -o -
and the RUN line will only execute if LLVM was configured with the ocaml
bindings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97726 91177308-0d34-0410-b5e6-96231b3b80d8

test/lit.cfg
utils/lit/lit/TestRunner.py
utils/lit/lit/TestingConfig.py

index 929871a1d225d53395a3584959d965e65e2c7143..b4aec5a50ab145b9d51bcddc9330992096c5c64d 100644 (file)
@@ -144,6 +144,9 @@ bindings = set(site_exp['llvm_bindings'].split(','))
 def llvm_supports_binding(name):
     return name in bindings
 
+config.conditions["TARGET"] = llvm_supports_target
+config.conditions["BINDING"] = llvm_supports_binding
+
 # Provide on_clone hook for reading 'dg.exp'.
 import os
 simpleLibData = re.compile(r"""load_lib llvm.exp
index 20fbc6c13a9f24f4b0754abbbcd1991089346064..148beba0ca7bcb7d533ddb03d7f5895212810ea4 100644 (file)
@@ -385,7 +385,30 @@ def parseIntegratedTestScript(test):
     script = []
     xfails = []
     xtargets = []
+    ignoredAny = False
     for ln in open(sourcepath):
+        if 'IF(' in ln:
+            # Required syntax here is IF(condition(value)):
+            index = ln.index('IF(')
+            ln = ln[index+3:]
+            index = ln.index('(')
+            if index is -1:
+                return (Test.UNRESOLVED, "ill-formed IF at '"+ln[:10]+"'")
+            condition = ln[:index]
+            ln = ln[index+1:]
+            index = ln.index(')')
+            if index is -1 or ln[index:index+3] != ')):':
+                return (Test.UNRESOLVED, "ill-formed IF at '"+ln[:10]+"'")
+            value = ln[:index]
+            ln = ln[index+3:]
+
+            # Actually test the condition.
+            if condition not in test.config.conditions:
+                return (Test.UNRESOLVED, "unknown condition '"+condition+"'")
+            if not test.config.conditions[condition](value):
+                ignoredAny = True
+                continue
+
         if 'RUN:' in ln:
             # Isolate the command to run.
             index = ln.index('RUN:')
@@ -422,6 +445,8 @@ def parseIntegratedTestScript(test):
 
     # Verify the script contains a run line.
     if not script:
+        if ignoredAny:
+            return (Test.UNSUPPORTED, "Test has only ignored run lines")
         return (Test.UNRESOLVED, "Test has no run line!")
 
     if script[-1][-1] == '\\':
index 1f5067c8e50294f85434e143f80e256b4db67175..b1302ffc5fde8c9bad932d21d898997f7d5a8d78 100644 (file)
@@ -27,7 +27,8 @@ class TestingConfig:
                                    on_clone = None,
                                    test_exec_root = None,
                                    test_source_root = None,
-                                   excludes = [])
+                                   excludes = [],
+                                   conditions = {})
 
         if os.path.exists(path):
             # FIXME: Improve detection and error reporting of errors in the
@@ -53,7 +54,7 @@ class TestingConfig:
 
     def __init__(self, parent, name, suffixes, test_format,
                  environment, substitutions, unsupported, on_clone,
-                 test_exec_root, test_source_root, excludes):
+                 test_exec_root, test_source_root, excludes, conditions):
         self.parent = parent
         self.name = str(name)
         self.suffixes = set(suffixes)
@@ -65,6 +66,7 @@ class TestingConfig:
         self.test_exec_root = test_exec_root
         self.test_source_root = test_source_root
         self.excludes = set(excludes)
+        self.conditions = dict(conditions)
 
     def clone(self, path):
         # FIXME: Chain implementations?
@@ -74,7 +76,7 @@ class TestingConfig:
                             self.environment, self.substitutions,
                             self.unsupported, self.on_clone,
                             self.test_exec_root, self.test_source_root,
-                            self.excludes)
+                            self.excludes, self.conditions)
         if cfg.on_clone:
             cfg.on_clone(self, cfg, path)
         return cfg