[lit] Implement support of per test timeout in lit.
[oota-llvm.git] / utils / lit / lit / formats / googletest.py
index 06b6a298638408b4e4ccca382612a4f253516960..5b19d4e638f945285a97746b92b90f5457e4d84a 100644 (file)
@@ -5,10 +5,11 @@ import sys
 import lit.Test
 import lit.TestRunner
 import lit.util
+from .base import TestFormat
 
 kIsWindows = sys.platform in ['win32', 'cygwin']
 
-class GoogleTest(object):
+class GoogleTest(TestFormat):
     def __init__(self, test_sub_dir, test_suffix):
         self.test_sub_dir = os.path.normcase(str(test_sub_dir)).split(';')
         self.test_suffix = str(test_suffix)
@@ -30,7 +31,6 @@ class GoogleTest(object):
         try:
             lines = lit.util.capture([path, '--gtest_list_tests'],
                                      env=localConfig.environment)
-            lines = lines.decode('ascii')
             if kIsWindows:
               lines = lines.replace('\r', '')
             lines = lines.split('\n')
@@ -53,6 +53,11 @@ class GoogleTest(object):
             ln = ln[index*2:]
             if ln.endswith('.'):
                 nested_tests.append(ln)
+            elif any([name.startswith('DISABLED_')
+                      for name in nested_tests + [ln]]):
+                # Gtest will internally skip these tests. No need to launch a
+                # child process for it.
+                continue
             else:
                 yield ''.join(nested_tests) + ln
 
@@ -65,7 +70,7 @@ class GoogleTest(object):
         # Discover the tests in this executable.
         for testname in self.getGTestTests(execpath, litConfig, localConfig):
             testPath = path_in_suite + (basename, testname)
-            yield lit.Test.Test(testSuite, testPath, localConfig)
+            yield lit.Test.Test(testSuite, testPath, localConfig, file_path=execpath)
 
     def getTestsInDirectory(self, testSuite, path_in_suite,
                             litConfig, localConfig):
@@ -95,7 +100,7 @@ class GoogleTest(object):
             # Handle GTest parametrized and typed tests, whose name includes
             # some '/'s.
             testPath, namePrefix = os.path.split(testPath)
-            testName = os.path.join(namePrefix, testName)
+            testName = namePrefix + '/' + testName
 
         cmd = [testPath, '--gtest_filter=' + testName]
         if litConfig.useValgrind:
@@ -104,10 +109,24 @@ class GoogleTest(object):
         if litConfig.noExecute:
             return lit.Test.PASS, ''
 
-        out, err, exitCode = lit.TestRunner.executeCommand(
-            cmd, env=test.config.environment)
-
-        if not exitCode:
-            return lit.Test.PASS,''
+        try:
+            out, err, exitCode = lit.util.executeCommand(
+                cmd, env=test.config.environment,
+                timeout=litConfig.maxIndividualTestTime)
+        except lit.util.ExecuteCommandTimeoutException:
+            return (lit.Test.TIMEOUT,
+                    'Reached timeout of {} seconds'.format(
+                        litConfig.maxIndividualTestTime)
+                   )
+
+        if exitCode:
+            return lit.Test.FAIL, out + err
+
+        passing_test_line = '[  PASSED  ] 1 test.'
+        if passing_test_line not in out:
+            msg = ('Unable to find %r in gtest output:\n\n%s%s' %
+                   (passing_test_line, out, err))
+            return lit.Test.UNRESOLVED, msg
+
+        return lit.Test.PASS,''
 
-        return lit.Test.FAIL, out + err