1from __future__ import absolute_import 2import os 3import sys 4 5import lit.Test 6import lit.TestRunner 7import lit.Util 8 9kIsWindows = sys.platform in ['win32', 'cygwin'] 10 11class GoogleTest(object): 12 def __init__(self, test_sub_dir, test_suffix): 13 self.test_sub_dir = os.path.normcase(str(test_sub_dir)).split(';') 14 self.test_suffix = str(test_suffix) 15 16 # On Windows, assume tests will also end in '.exe'. 17 if kIsWindows: 18 self.test_suffix += '.exe' 19 20 def getGTestTests(self, path, litConfig, localConfig): 21 """getGTestTests(path) - [name] 22 23 Return the tests available in gtest executable. 24 25 Args: 26 path: String path to a gtest executable 27 litConfig: LitConfig instance 28 localConfig: TestingConfig instance""" 29 30 try: 31 lines = lit.Util.capture([path, '--gtest_list_tests'], 32 env=localConfig.environment) 33 if kIsWindows: 34 lines = lines.replace('\r', '') 35 lines = lines.split('\n') 36 except: 37 litConfig.error("unable to discover google-tests in %r" % path) 38 raise StopIteration 39 40 nested_tests = [] 41 for ln in lines: 42 if not ln.strip(): 43 continue 44 45 prefix = '' 46 index = 0 47 while ln[index*2:index*2+2] == ' ': 48 index += 1 49 while len(nested_tests) > index: 50 nested_tests.pop() 51 52 ln = ln[index*2:] 53 if ln.endswith('.'): 54 nested_tests.append(ln) 55 else: 56 yield ''.join(nested_tests) + ln 57 58 # Note: path_in_suite should not include the executable name. 59 def getTestsInExecutable(self, testSuite, path_in_suite, execpath, 60 litConfig, localConfig): 61 if not execpath.endswith(self.test_suffix): 62 return 63 (dirname, basename) = os.path.split(execpath) 64 # Discover the tests in this executable. 65 for testname in self.getGTestTests(execpath, litConfig, localConfig): 66 testPath = path_in_suite + (basename, testname) 67 yield lit.Test.Test(testSuite, testPath, localConfig) 68 69 def getTestsInDirectory(self, testSuite, path_in_suite, 70 litConfig, localConfig): 71 source_path = testSuite.getSourcePath(path_in_suite) 72 for filename in os.listdir(source_path): 73 filepath = os.path.join(source_path, filename) 74 if os.path.isdir(filepath): 75 # Iterate over executables in a directory. 76 if not os.path.normcase(filename) in self.test_sub_dir: 77 continue 78 dirpath_in_suite = path_in_suite + (filename, ) 79 for subfilename in os.listdir(filepath): 80 execpath = os.path.join(filepath, subfilename) 81 for test in self.getTestsInExecutable( 82 testSuite, dirpath_in_suite, execpath, 83 litConfig, localConfig): 84 yield test 85 elif ('.' in self.test_sub_dir): 86 for test in self.getTestsInExecutable( 87 testSuite, path_in_suite, filepath, 88 litConfig, localConfig): 89 yield test 90 91 def execute(self, test, litConfig): 92 testPath,testName = os.path.split(test.getSourcePath()) 93 while not os.path.exists(testPath): 94 # Handle GTest parametrized and typed tests, whose name includes 95 # some '/'s. 96 testPath, namePrefix = os.path.split(testPath) 97 testName = os.path.join(namePrefix, testName) 98 99 cmd = [testPath, '--gtest_filter=' + testName] 100 if litConfig.useValgrind: 101 cmd = litConfig.valgrindArgs + cmd 102 103 if litConfig.noExecute: 104 return lit.Test.PASS, '' 105 106 out, err, exitCode = lit.TestRunner.executeCommand( 107 cmd, env=test.config.environment) 108 109 if not exitCode: 110 return lit.Test.PASS,'' 111 112 return lit.Test.FAIL, out + err 113 114### 115 116class FileBasedTest(object): 117 def getTestsInDirectory(self, testSuite, path_in_suite, 118 litConfig, localConfig): 119 source_path = testSuite.getSourcePath(path_in_suite) 120 for filename in os.listdir(source_path): 121 # Ignore dot files and excluded tests. 122 if (filename.startswith('.') or 123 filename in localConfig.excludes): 124 continue 125 126 filepath = os.path.join(source_path, filename) 127 if not os.path.isdir(filepath): 128 base,ext = os.path.splitext(filename) 129 if ext in localConfig.suffixes: 130 yield lit.Test.Test(testSuite, path_in_suite + (filename,), 131 localConfig) 132 133class ShTest(FileBasedTest): 134 def __init__(self, execute_external = False): 135 self.execute_external = execute_external 136 137 def execute(self, test, litConfig): 138 return lit.TestRunner.executeShTest(test, litConfig, 139 self.execute_external) 140 141### 142 143import re 144import tempfile 145 146class OneCommandPerFileTest: 147 # FIXME: Refactor into generic test for running some command on a directory 148 # of inputs. 149 150 def __init__(self, command, dir, recursive=False, 151 pattern=".*", useTempInput=False): 152 if isinstance(command, str): 153 self.command = [command] 154 else: 155 self.command = list(command) 156 if dir is not None: 157 dir = str(dir) 158 self.dir = dir 159 self.recursive = bool(recursive) 160 self.pattern = re.compile(pattern) 161 self.useTempInput = useTempInput 162 163 def getTestsInDirectory(self, testSuite, path_in_suite, 164 litConfig, localConfig): 165 dir = self.dir 166 if dir is None: 167 dir = testSuite.getSourcePath(path_in_suite) 168 169 for dirname,subdirs,filenames in os.walk(dir): 170 if not self.recursive: 171 subdirs[:] = [] 172 173 subdirs[:] = [d for d in subdirs 174 if (d != '.svn' and 175 d not in localConfig.excludes)] 176 177 for filename in filenames: 178 if (filename.startswith('.') or 179 not self.pattern.match(filename) or 180 filename in localConfig.excludes): 181 continue 182 183 path = os.path.join(dirname,filename) 184 suffix = path[len(dir):] 185 if suffix.startswith(os.sep): 186 suffix = suffix[1:] 187 test = lit.Test.Test( 188 testSuite, path_in_suite + tuple(suffix.split(os.sep)), 189 localConfig) 190 # FIXME: Hack? 191 test.source_path = path 192 yield test 193 194 def createTempInput(self, tmp, test): 195 abstract 196 197 def execute(self, test, litConfig): 198 if test.config.unsupported: 199 return (lit.Test.UNSUPPORTED, 'Test is unsupported') 200 201 cmd = list(self.command) 202 203 # If using temp input, create a temporary file and hand it to the 204 # subclass. 205 if self.useTempInput: 206 tmp = tempfile.NamedTemporaryFile(suffix='.cpp') 207 self.createTempInput(tmp, test) 208 tmp.flush() 209 cmd.append(tmp.name) 210 elif hasattr(test, 'source_path'): 211 cmd.append(test.source_path) 212 else: 213 cmd.append(test.getSourcePath()) 214 215 out, err, exitCode = lit.TestRunner.executeCommand(cmd) 216 217 diags = out + err 218 if not exitCode and not diags.strip(): 219 return lit.Test.PASS,'' 220 221 # Try to include some useful information. 222 report = """Command: %s\n""" % ' '.join(["'%s'" % a 223 for a in cmd]) 224 if self.useTempInput: 225 report += """Temporary File: %s\n""" % tmp.name 226 report += "--\n%s--\n""" % open(tmp.name).read() 227 report += """Output:\n--\n%s--""" % diags 228 229 return lit.Test.FAIL, report 230