1from __future__ import absolute_import 2import os 3 4import subprocess 5import sys 6 7import lit.Test 8import lit.TestRunner 9import lit.util 10from lit.formats.base import TestFormat 11 12def getBuildDir(cmd): 13 found = False 14 for arg in cmd: 15 if found: 16 return arg 17 if arg == '--build-dir': 18 found = True 19 return None 20 21def mkdir_p(path): 22 import errno 23 try: 24 os.makedirs(path) 25 except OSError as e: 26 if e.errno != errno.EEXIST: 27 raise 28 if not os.path.isdir(path): 29 raise OSError(errno.ENOTDIR, "%s is not a directory"%path) 30 31class LLDBTest(TestFormat): 32 def __init__(self, dotest_cmd): 33 self.dotest_cmd = dotest_cmd 34 35 def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, 36 localConfig): 37 source_path = testSuite.getSourcePath(path_in_suite) 38 for filename in os.listdir(source_path): 39 # Ignore dot files and excluded tests. 40 if (filename.startswith('.') or filename in localConfig.excludes): 41 continue 42 43 # Ignore files that don't start with 'Test'. 44 if not filename.startswith('Test'): 45 continue 46 47 filepath = os.path.join(source_path, filename) 48 if not os.path.isdir(filepath): 49 base, ext = os.path.splitext(filename) 50 if ext in localConfig.suffixes: 51 yield lit.Test.Test(testSuite, path_in_suite + 52 (filename, ), localConfig) 53 54 def execute(self, test, litConfig): 55 if litConfig.noExecute: 56 return lit.Test.PASS, '' 57 58 if not test.config.lldb_enable_python: 59 return (lit.Test.UNSUPPORTED, 'Python module disabled') 60 61 if test.config.unsupported: 62 return (lit.Test.UNSUPPORTED, 'Test is unsupported') 63 64 testPath, testFile = os.path.split(test.getSourcePath()) 65 # On Windows, the system does not always correctly interpret 66 # shebang lines. To make sure we can execute the tests, add 67 # python exe as the first parameter of the command. 68 cmd = [sys.executable] + self.dotest_cmd + [testPath, '-p', testFile] 69 70 # The macOS system integrity protection (SIP) doesn't allow injecting 71 # libraries into system binaries, but this can be worked around by 72 # copying the binary into a different location. 73 if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \ 74 (sys.executable.startswith('/System/') or \ 75 sys.executable.startswith('/usr/bin/')): 76 builddir = getBuildDir(cmd) 77 mkdir_p(builddir) 78 copied_python = os.path.join(builddir, 'copied-system-python') 79 if not os.path.isfile(copied_python): 80 import shutil, subprocess 81 python = subprocess.check_output([ 82 sys.executable, 83 '-c', 84 'import sys; print(sys.executable)' 85 ]).decode('utf-8').strip() 86 shutil.copy(python, copied_python) 87 cmd[0] = copied_python 88 89 timeoutInfo = None 90 try: 91 out, err, exitCode = lit.util.executeCommand( 92 cmd, 93 env=test.config.environment, 94 timeout=litConfig.maxIndividualTestTime) 95 except lit.util.ExecuteCommandTimeoutException as e: 96 out = e.out 97 err = e.err 98 exitCode = e.exitCode 99 timeoutInfo = 'Reached timeout of {} seconds'.format( 100 litConfig.maxIndividualTestTime) 101 102 output = """Script:\n--\n%s\n--\nExit Code: %d\n""" % ( 103 ' '.join(cmd), exitCode) 104 if timeoutInfo is not None: 105 output += """Timeout: %s\n""" % (timeoutInfo,) 106 output += "\n" 107 108 if out: 109 output += """Command Output (stdout):\n--\n%s\n--\n""" % (out,) 110 if err: 111 output += """Command Output (stderr):\n--\n%s\n--\n""" % (err,) 112 113 if timeoutInfo: 114 return lit.Test.TIMEOUT, output 115 116 if exitCode: 117 # Match FAIL but not XFAIL. 118 for line in out.splitlines() + err.splitlines(): 119 if line.startswith('FAIL:'): 120 return lit.Test.FAIL, output 121 122 if 'XPASS:' in out or 'XPASS:' in err: 123 return lit.Test.XPASS, output 124 125 has_unsupported_tests = 'UNSUPPORTED:' in out or 'UNSUPPORTED:' in err 126 has_passing_tests = 'PASS:' in out or 'PASS:' in err 127 if has_unsupported_tests and not has_passing_tests: 128 return lit.Test.UNSUPPORTED, output 129 130 passing_test_line = 'RESULT: PASSED' 131 if passing_test_line not in out and passing_test_line not in err: 132 return lit.Test.UNRESOLVED, output 133 134 return lit.Test.PASS, output 135