1from __future__ import absolute_import 2import os 3import tempfile 4import subprocess 5import sys 6import platform 7 8import lit.Test 9import lit.TestRunner 10import lit.util 11from lit.formats.base import TestFormat 12 13 14class LLDBTest(TestFormat): 15 def __init__(self, dotest_cmd): 16 self.dotest_cmd = dotest_cmd 17 18 def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, 19 localConfig): 20 source_path = testSuite.getSourcePath(path_in_suite) 21 for filename in os.listdir(source_path): 22 # Ignore dot files and excluded tests. 23 if (filename.startswith('.') or filename in localConfig.excludes): 24 continue 25 26 # Ignore files that don't start with 'Test'. 27 if not filename.startswith('Test'): 28 continue 29 30 filepath = os.path.join(source_path, filename) 31 if not os.path.isdir(filepath): 32 base, ext = os.path.splitext(filename) 33 if ext in localConfig.suffixes: 34 yield lit.Test.Test(testSuite, path_in_suite + 35 (filename, ), localConfig) 36 37 def execute(self, test, litConfig): 38 if litConfig.noExecute: 39 return lit.Test.PASS, '' 40 41 if not getattr(test.config, 'lldb_enable_python', False): 42 return (lit.Test.UNSUPPORTED, 'Python module disabled') 43 44 if test.config.unsupported: 45 return (lit.Test.UNSUPPORTED, 'Test is unsupported') 46 47 testPath, testFile = os.path.split(test.getSourcePath()) 48 49 # The Python used to run lit can be different from the Python LLDB was 50 # build with. 51 executable = test.config.python_executable 52 53 # On Windows, the system does not always correctly interpret 54 # shebang lines. To make sure we can execute the tests, add 55 # python exe as the first parameter of the command. 56 cmd = [executable] + self.dotest_cmd + [testPath, '-p', testFile] 57 58 if 'lldb-repro-capture' in test.config.available_features or \ 59 'lldb-repro-replay' in test.config.available_features: 60 reproducer_path = os.path.join( 61 test.config.lldb_reproducer_directory, testFile) 62 if 'lldb-repro-capture' in test.config.available_features: 63 cmd.extend(['--capture-path', reproducer_path]) 64 else: 65 cmd.extend(['--replay-path', reproducer_path]) 66 67 timeoutInfo = None 68 try: 69 out, err, exitCode = lit.util.executeCommand( 70 cmd, 71 env=test.config.environment, 72 timeout=litConfig.maxIndividualTestTime) 73 except lit.util.ExecuteCommandTimeoutException as e: 74 out = e.out 75 err = e.err 76 exitCode = e.exitCode 77 timeoutInfo = 'Reached timeout of {} seconds'.format( 78 litConfig.maxIndividualTestTime) 79 80 if sys.version_info.major == 2: 81 # In Python 2, string objects can contain Unicode characters. Use 82 # the non-strict 'replace' decoding mode. We cannot use the strict 83 # mode right now because lldb's StringPrinter facility and the 84 # Python utf8 decoder have different interpretations of which 85 # characters are "printable". This leads to Python utf8 decoding 86 # exceptions even though lldb is behaving as expected. 87 out = out.decode('utf-8', 'replace') 88 err = err.decode('utf-8', 'replace') 89 90 output = """Script:\n--\n%s\n--\nExit Code: %d\n""" % ( 91 ' '.join(cmd), exitCode) 92 if timeoutInfo is not None: 93 output += """Timeout: %s\n""" % (timeoutInfo,) 94 output += "\n" 95 96 if out: 97 output += """Command Output (stdout):\n--\n%s\n--\n""" % (out,) 98 if err: 99 output += """Command Output (stderr):\n--\n%s\n--\n""" % (err,) 100 101 if timeoutInfo: 102 return lit.Test.TIMEOUT, output 103 104 if exitCode: 105 if 'XPASS:' in out or 'XPASS:' in err: 106 return lit.Test.XPASS, output 107 108 # Otherwise this is just a failure. 109 return lit.Test.FAIL, output 110 111 has_unsupported_tests = 'UNSUPPORTED:' in out or 'UNSUPPORTED:' in err 112 has_passing_tests = 'PASS:' in out or 'PASS:' in err 113 if has_unsupported_tests and not has_passing_tests: 114 return lit.Test.UNSUPPORTED, output 115 116 passing_test_line = 'RESULT: PASSED' 117 if passing_test_line not in out and passing_test_line not in err: 118 return lit.Test.UNRESOLVED, output 119 120 return lit.Test.PASS, output 121