150
|
1 from __future__ import absolute_import
|
|
2 import os
|
173
|
3 import tempfile
|
150
|
4 import subprocess
|
|
5 import sys
|
173
|
6 import platform
|
150
|
7
|
|
8 import lit.Test
|
|
9 import lit.TestRunner
|
|
10 import lit.util
|
|
11 from lit.formats.base import TestFormat
|
|
12
|
|
13
|
|
14 class 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
|
207
|
41 if not getattr(test.config, 'lldb_enable_python', False):
|
150
|
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())
|
173
|
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
|
150
|
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.
|
173
|
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:
|
207
|
60 reproducer_path = os.path.join(
|
|
61 test.config.lldb_reproducer_directory, testFile)
|
173
|
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
|
150
|
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
|
173
|
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
|
150
|
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
|
173
|
108 # Otherwise this is just a failure.
|
|
109 return lit.Test.FAIL, output
|
|
110
|
150
|
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
|