1from __future__ import absolute_import 2import os 3import sys 4 5import lit.Test 6import lit.TestRunner 7import lit.util 8from .base import TestFormat 9 10kIsWindows = sys.platform in ['win32', 'cygwin'] 11 12class GoogleTest(TestFormat): 13 def __init__(self, test_sub_dir, test_suffix): 14 self.test_sub_dir = os.path.normcase(str(test_sub_dir)).split(';') 15 self.test_suffix = str(test_suffix) 16 17 # On Windows, assume tests will also end in '.exe'. 18 if kIsWindows: 19 self.test_suffix += '.exe' 20 21 def getGTestTests(self, path, litConfig, localConfig): 22 """getGTestTests(path) - [name] 23 24 Return the tests available in gtest executable. 25 26 Args: 27 path: String path to a gtest executable 28 litConfig: LitConfig instance 29 localConfig: TestingConfig instance""" 30 31 try: 32 lines = lit.util.capture([path, '--gtest_list_tests'], 33 env=localConfig.environment) 34 if kIsWindows: 35 lines = lines.replace('\r', '') 36 lines = lines.split('\n') 37 except: 38 litConfig.error("unable to discover google-tests in %r" % path) 39 raise StopIteration 40 41 nested_tests = [] 42 for ln in lines: 43 if not ln.strip(): 44 continue 45 46 if 'Running main() from gtest_main.cc' in ln: 47 # Upstream googletest prints this to stdout prior to running 48 # tests. LLVM removed that print statement in r61540, but we 49 # handle it here in case upstream googletest is being used. 50 continue 51 52 prefix = '' 53 index = 0 54 while ln[index*2:index*2+2] == ' ': 55 index += 1 56 while len(nested_tests) > index: 57 nested_tests.pop() 58 59 ln = ln[index*2:] 60 if ln.endswith('.'): 61 nested_tests.append(ln) 62 elif any([name.startswith('DISABLED_') 63 for name in nested_tests + [ln]]): 64 # Gtest will internally skip these tests. No need to launch a 65 # child process for it. 66 continue 67 else: 68 yield ''.join(nested_tests) + ln 69 70 # Note: path_in_suite should not include the executable name. 71 def getTestsInExecutable(self, testSuite, path_in_suite, execpath, 72 litConfig, localConfig): 73 if not execpath.endswith(self.test_suffix): 74 return 75 (dirname, basename) = os.path.split(execpath) 76 # Discover the tests in this executable. 77 for testname in self.getGTestTests(execpath, litConfig, localConfig): 78 testPath = path_in_suite + (basename, testname) 79 yield lit.Test.Test(testSuite, testPath, localConfig, file_path=execpath) 80 81 def getTestsInDirectory(self, testSuite, path_in_suite, 82 litConfig, localConfig): 83 source_path = testSuite.getSourcePath(path_in_suite) 84 for filename in os.listdir(source_path): 85 filepath = os.path.join(source_path, filename) 86 if os.path.isdir(filepath): 87 # Iterate over executables in a directory. 88 if not os.path.normcase(filename) in self.test_sub_dir: 89 continue 90 dirpath_in_suite = path_in_suite + (filename, ) 91 for subfilename in os.listdir(filepath): 92 execpath = os.path.join(filepath, subfilename) 93 for test in self.getTestsInExecutable( 94 testSuite, dirpath_in_suite, execpath, 95 litConfig, localConfig): 96 yield test 97 elif ('.' in self.test_sub_dir): 98 for test in self.getTestsInExecutable( 99 testSuite, path_in_suite, filepath, 100 litConfig, localConfig): 101 yield test 102 103 def execute(self, test, litConfig): 104 testPath,testName = os.path.split(test.getSourcePath()) 105 while not os.path.exists(testPath): 106 # Handle GTest parametrized and typed tests, whose name includes 107 # some '/'s. 108 testPath, namePrefix = os.path.split(testPath) 109 testName = namePrefix + '/' + testName 110 111 cmd = [testPath, '--gtest_filter=' + testName] 112 if litConfig.useValgrind: 113 cmd = litConfig.valgrindArgs + cmd 114 115 if litConfig.noExecute: 116 return lit.Test.PASS, '' 117 118 try: 119 out, err, exitCode = lit.util.executeCommand( 120 cmd, env=test.config.environment, 121 timeout=litConfig.maxIndividualTestTime) 122 except lit.util.ExecuteCommandTimeoutException: 123 return (lit.Test.TIMEOUT, 124 'Reached timeout of {} seconds'.format( 125 litConfig.maxIndividualTestTime) 126 ) 127 128 if exitCode: 129 return lit.Test.FAIL, out + err 130 131 passing_test_line = '[ PASSED ] 1 test.' 132 if passing_test_line not in out: 133 msg = ('Unable to find %r in gtest output:\n\n%s%s' % 134 (passing_test_line, out, err)) 135 return lit.Test.UNRESOLVED, msg 136 137 return lit.Test.PASS,'' 138 139