[lldb/Test] Fix ASan/TSan workaround for Xcode Python 3
[lldb.git] / lldb / test / API / lldbtest.py
1 from __future__ import absolute_import
2 import os
3 import tempfile
4 import subprocess
5 import sys
6 import platform
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
41         if not test.config.lldb_enable_python:
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