TestRunner.py revision 09a28f6973599b3c2e12f19e1d3f91e12de77ff7
1b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarfrom __future__ import absolute_import
2be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport os, signal, subprocess, sys
309a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbarimport re
458c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbarimport platform
55a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbarimport tempfile
609a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbartry:
709a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    from io import StringIO
809a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbarexcept ImportError:
909a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    from StringIO import StringIO
1058c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar
11b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.ShUtil as ShUtil
12b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.Test as Test
13b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.Util as Util
1418d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene
156bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbarclass InternalShellError(Exception):
166bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    def __init__(self, command, message):
176bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.command = command
186bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.message = message
196bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
20f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkIsWindows = platform.system() == 'Windows'
21f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
2258c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar# Don't use close_fds on Windows.
23f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkUseCloseFDs = not kIsWindows
246efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
256efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar# Use temporary files to replace /dev/null on Windows.
26f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkAvoidDevNull = kIsWindows
276efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeCommand(command, cwd=None, env=None):
29b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    # Close extra file handles on UNIX (on Windows this cannot be done while
30b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    # also redirecting input).
31b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    close_fds = not kIsWindows
32b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar
33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    p = subprocess.Popen(command, cwd=cwd,
34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdin=subprocess.PIPE,
35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdout=subprocess.PIPE,
36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stderr=subprocess.PIPE,
37b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar                         env=env, close_fds=close_fds)
38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err = p.communicate()
39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = p.wait()
40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Detect Ctrl-C in subprocess.
42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if exitCode == -signal.SIGINT:
43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise KeyboardInterrupt
44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results):
48be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isinstance(cmd, ShUtil.Seq):
49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == ';':
50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return executeShCmd(cmd.rhs, cfg, cwd, results)
52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
53be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&':
54a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar            raise InternalShellError(cmd,"unsupported shell operator: '&'")
55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '||':
57be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res != 0:
59be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
61a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar
62be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&&':
63be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res is None:
65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return res
66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res == 0:
68be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
69be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
7126e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar        raise ValueError('Unknown shell command: %r' % cmd.op)
72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
73be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    assert isinstance(cmd, ShUtil.Pipeline)
74be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procs = []
75be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    input = subprocess.PIPE
765a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    stderrTempFiles = []
77c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar    opened_files = []
781befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    named_temp_files = []
795a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # To avoid deadlock, we use a single stderr stream for piped
805a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # output. This is null until we have seen some output using
815a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # stderr.
825a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,j in enumerate(cmd.commands):
83f1a26cf9df900101b9cbea42b67f7466edc7deedEli Bendersky        # Apply the redirections, we use (N,) as a sentinel to indicate stdin,
84a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
85a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # from a file are represented with a list [file, mode, file-object]
86a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # where file-object is initially None.
87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        redirects = [(0,), (1,), (2,)]
88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for r in j.redirects:
89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r[0] == ('>',2):
90be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = [r[1], 'w', None]
91a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',2):
92a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[2] = [r[1], 'a', None]
93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',2) and r[1] in '012':
94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = redirects[int(r[1])]
95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',) or r[0] == ('&>',):
96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = redirects[2] = [r[1], 'w', None]
97be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>',):
98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = [r[1], 'w', None]
99a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',):
100a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[1] = [r[1], 'a', None]
101be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('<',):
102be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[0] = [r[1], 'r', None]
103be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
104a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                raise InternalShellError(j,"Unsupported redirect: %r" % (r,))
105be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
106a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Map from the final redirections to something subprocess can handle.
107be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        final_redirects = []
108be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for index,r in enumerate(redirects):
109be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r == (0,):
110be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = input
111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (1,):
112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index == 0:
113a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                    raise InternalShellError(j,"Unsupported redirect for stdin")
114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                elif index == 1:
115be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.PIPE
116be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                else:
117be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.STDOUT
118be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (2,):
119be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index != 2:
120a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                    raise InternalShellError(j,"Unsupported redirect on stdout")
121be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = subprocess.PIPE
122be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
123be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if r[2] is None:
1246efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    if kAvoidDevNull and r[0] == '/dev/null':
1256efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = tempfile.TemporaryFile(mode=r[1])
1266efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    else:
1276efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = open(r[0], r[1])
128474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    # Workaround a Win32 and/or subprocess bug when appending.
129e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    #
130e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    # FIXME: Actually, this is probably an instance of PR6753.
131474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    if r[1] == 'a':
132bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar                        r[2].seek(0, 2)
1339fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi                    opened_files.append(r[2])
134be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = r[2]
135be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            final_redirects.append(result)
136be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
137be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        stdin, stdout, stderr = final_redirects
138be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
139be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # If stderr wants to come from stdout, but stdout isn't a pipe, then put
140be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # stderr on a pipe and treat it as stdout.
141be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
142be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderr = subprocess.PIPE
143be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = True
144be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
145be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = False
1466bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1475a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # Don't allow stderr on a PIPE except for the last
1485a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # process, this could deadlock.
1495a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            #
1505a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # FIXME: This is slow, but so is deadlock.
1515a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            if stderr == subprocess.PIPE and j != cmd.commands[-1]:
1525a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderr = tempfile.TemporaryFile(mode='w+b')
1535a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderrTempFiles.append((i, stderr))
1545a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1556bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        # Resolve the executable path ourselves.
1566bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args = list(j.args)
1576bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args[0] = Util.which(args[0], cfg.environment['PATH'])
1586bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        if not args[0]:
1596bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            raise InternalShellError(j, '%r: command not found' % j.args[0])
1606bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1611befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        # Replace uses of /dev/null with temporary files.
1621befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        if kAvoidDevNull:
1631befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            for i,arg in enumerate(args):
1641befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                if arg == "/dev/null":
1651befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f = tempfile.NamedTemporaryFile(delete=False)
1661befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f.close()
1671befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    named_temp_files.append(f.name)
1681befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    args[i] = f.name
1691befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
1704b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar        procs.append(subprocess.Popen(args, cwd=cwd,
171be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdin = stdin,
172be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdout = stdout,
173be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stderr = stderr,
174be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      env = cfg.environment,
17558c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar                                      close_fds = kUseCloseFDs))
176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Immediately close stdin for any process taking stdin from us.
178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdin == subprocess.PIPE:
179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin.close()
180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin = None
181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Update the current stdin source.
183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdout == subprocess.PIPE:
184be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stdout
185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif stderrIsStdout:
186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stderr
187be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
188be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = subprocess.PIPE
189be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
19069c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # Explicitly close any redirected files. We need to do this now because we
19169c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # need to release any handles we may have on the temporary files (important
19269c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # on Win32, for example). Since we have already spawned the subprocess, our
19369c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # handles have already been transferred so we do not need them anymore.
19469c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    for f in opened_files:
1959fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        f.close()
19669c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar
1975a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # FIXME: There is probably still deadlock potential here. Yawn.
198be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData = [None] * len(procs)
199be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData[-1] = procs[-1].communicate()
2005a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i in range(len(procs) - 1):
202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stdout is not None:
203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = procs[i].stdout.read()
204be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
205be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = ''
206be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stderr is not None:
207be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = procs[i].stderr.read()
208be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
209be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = ''
210be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        procData[i] = (out,err)
211c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar
2125a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # Read stderr out of the temp files.
2135a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,f in stderrTempFiles:
2145a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        f.seek(0, 0)
2155a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        procData[i] = (procData[i][0], f.read())
216be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
217be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = None
218be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(out,err) in enumerate(procData):
219be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = procs[i].wait()
220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Detect Ctrl-C in subprocess.
221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if res == -signal.SIGINT:
222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise KeyboardInterrupt
223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
224be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results.append((cmd.commands[i], out, err, res))
225be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.pipe_err:
226be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Python treats the exit code as a signed char.
227be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res < 0:
228be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = min(exitCode, res)
229be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
230be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = max(exitCode, res)
231be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
232be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = res
233be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2341befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    # Remove any named temporary files we created.
2351befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    for f in named_temp_files:
2369fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        try:
2379fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            os.remove(f)
2389fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        except OSError:
2399fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            pass
2401befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
241be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if cmd.negate:
242be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = not exitCode
243be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
244be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return exitCode
245be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
246be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
24700fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    cmds = []
24800fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    for ln in commands:
24900fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        try:
250c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola            cmds.append(ShUtil.ShParser(ln, litConfig.isWindows,
251c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola                                        test.config.pipefail).parse())
25200fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        except:
25300fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith            return (Test.FAIL, "shell parser error on: %r" % ln)
25400fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith
25500fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    cmd = cmds[0]
25600fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    for c in cmds[1:]:
25700fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        cmd = ShUtil.Seq(cmd, '&&', c)
258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    results = []
2606bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    try:
2616bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = executeShCmd(cmd, test.config, cwd, results)
2622e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar    except InternalShellError:
2632e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar        e = sys.exc_info()[1]
264b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar        exitCode = 127
265b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar        results.append((e.command, '', e.message, exitCode))
266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
267be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
268be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
270be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
271be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
276be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd):
2779869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    bashPath = litConfig.getBashPath();
2789869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    isWin32CMDEXE = (litConfig.isWindows and not bashPath)
279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = tmpBase + '.script'
2809869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
281be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script += '.bat'
282be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
283be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Write script file
2848755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    mode = 'w'
2858755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    if litConfig.isWindows and not isWin32CMDEXE:
2868755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner      mode += 'b'  # Avoid CRLFs when writing bash scripts.
2878755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    f = open(script, mode)
2889869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
289be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
290be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
291c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola        if test.config.pipefail:
292c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola            f.write('set -o pipefail;')
293c15e5b0a0dbdaf8612bdcbba1deedcb77bed1045Richard Smith        f.write('{ ' + '; } &&\n{ '.join(commands) + '; }')
294be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.write('\n')
295be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.close()
296be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2979869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
298be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['cmd','/c', script]
299be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
3009869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        if bashPath:
3019869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = [bashPath, script]
3029869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        else:
3039869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = ['/bin/sh', script]
304be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if litConfig.useValgrind:
305be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # FIXME: Running valgrind on sh is overkill. We probably could just
306be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # run on clang with no real loss.
30732989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin            command = litConfig.valgrindArgs + command
308be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
309be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return executeCommand(command, cwd=cwd, env=test.config.environment)
310be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
311f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbardef isExpectedFail(test, xfails):
312f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    # Check if any of the xfails match an available feature or the target.
31342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xfails:
314f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is the wildcard, it always fails.
315f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item == '*':
31644a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar            return True
31744a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar
318f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is an exact match for one of the features, it fails.
319f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item in test.config.available_features:
320f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar            return True
32142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
322f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is a part of the target triple, it fails.
323f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item in test.suite.config.target_triple:
324f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar            return True
32542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
326f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    return False
32742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
3282d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef parseIntegratedTestScript(test, normalize_slashes=False,
3292d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                              extra_substitutions=[]):
330be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
331f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    script and extract the lines to 'RUN' as well as 'XFAIL' and 'REQUIRES'
332be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    information. The RUN lines also will have variable substitution performed.
333be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """
334be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
335be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Get the temporary location, this is always relative to the test suite
336be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # root, not test source root.
337be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    #
338be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # FIXME: This should not be here?
339be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    sourcepath = test.getSourcePath()
340f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    sourcedir = os.path.dirname(sourcepath)
341be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execpath = test.getExecPath()
342be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execdir,execbase = os.path.split(execpath)
3430f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpDir = os.path.join(execdir, 'Output')
3440f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpBase = os.path.join(tmpDir, execbase)
34540c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar    if test.index is not None:
34640c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar        tmpBase += '_%d' % test.index
347be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
348f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Normalize slashes, if requested.
349f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    if normalize_slashes:
350f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcepath = sourcepath.replace('\\', '/')
351f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcedir = sourcedir.replace('\\', '/')
352bbbc283d86a911ccf3bdecdc78a7a8f71f31683fNAKAMURA Takumi        tmpDir = tmpDir.replace('\\', '/')
353f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        tmpBase = tmpBase.replace('\\', '/')
354f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
355be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # We use #_MARKER_# to hide %% while we do the other substitutions.
3562d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions = list(extra_substitutions)
3572d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions.extend([('%%', '#_MARKER_#')])
358be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend(test.config.substitutions)
359be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend([('%s', sourcepath),
360f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%S', sourcedir),
361f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%p', sourcedir),
3620191bfcf7a5ae1ccfad7afe8ced59a14ffaca2a6Nico Weber                          ('%{pathsep}', os.pathsep),
363be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%t', tmpBase + '.tmp'),
3640f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor                          ('%T', tmpDir),
365be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('#_MARKER_#', '%')])
366be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Collect the test lines from the script.
368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = []
369be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xfails = []
370b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    requires = []
37108639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko    line_number = 0
372be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in open(sourcepath):
37308639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko        line_number += 1
374be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 'RUN:' in ln:
375be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Isolate the command to run.
376be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            index = ln.index('RUN:')
377be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln[index+4:]
378be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
379be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Trim trailing whitespace.
380be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.rstrip()
381be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
38208639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            # Substitute line number expressions
38308639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            ln = re.sub('%\(line\)', str(line_number), ln)
38408639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            def replace_line_number(match):
38508639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                if match.group(1) == '+':
38608639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                    return str(line_number + int(match.group(2)))
38708639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                if match.group(1) == '-':
38808639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                    return str(line_number - int(match.group(2)))
38908639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            ln = re.sub('%\(line *([\+-]) *(\d+)\)', replace_line_number, ln)
39008639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko
391be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Collapse lines with trailing '\\'.
392be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if script and script[-1][-1] == '\\':
393be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script[-1] = script[-1][:-1] + ln
394be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
395be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script.append(ln)
39642543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        elif 'XFAIL:' in ln:
397be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XFAIL:') + 6:].split(',')
398be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xfails.extend([s.strip() for s in items])
399b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        elif 'REQUIRES:' in ln:
400b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            items = ln[ln.index('REQUIRES:') + 9:].split(',')
401b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            requires.extend([s.strip() for s in items])
402be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'END.' in ln:
403be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Check for END. lines.
404be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if ln[ln.index('END.'):].strip() == 'END.':
405be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
406be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
40718d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # Apply substitutions to the script.  Allow full regular
40818d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression syntax.  Replace each matching occurrence of regular
40918d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression pattern a with substitution b in line ln.
410be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    def processLine(ln):
411be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Apply substitutions
412be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for a,b in substitutions:
413ba69d3f6d448ca0a3a56b71fa65e85712bf76512Francois Pichet            if kIsWindows:
4147a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet                b = b.replace("\\","\\\\")
4157a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet            ln = re.sub(a, b, ln)
416be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
417be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Strip the trailing newline and any extra whitespace.
418be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return ln.strip()
419be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = map(processLine, script)
420be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
421be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Verify the script contains a run line.
422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if not script:
423be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has no run line!")
424be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
425b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    # Check for unterminated run lines.
426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if script[-1][-1] == '\\':
427be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
428be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
429f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick    # Check that we have the required features:
430b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    missing_required_features = [f for f in requires
431f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick                                 if f not in test.config.available_features]
432b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    if missing_required_features:
433b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        msg = ', '.join(missing_required_features)
434b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        return (Test.UNSUPPORTED,
435b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar                "Test requires the following features: %s" % msg)
436b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar
437f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    isXFail = isExpectedFail(test, xfails)
43842543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return script,isXFail,tmpBase,execdir
439be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
440213a789a711724c864defdc2c3e1208d6c5b7fd4Daniel Dunbardef formatTestOutput(status, out, err, exitCode, script):
44109a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output = StringIO()
44209a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output.write(u"Script:\n")
44309a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output.write(u"--\n")
44409a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output.write(u'\n'.join(script))
44509a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output.write(u"\n--\n")
44609a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar    output.write(u"Exit Code: %r\n\n" % exitCode)
4478a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if out:
44809a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"Command Output (stdout):\n")
44909a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"--\n")
45009a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(unicode(out))
45109a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"--\n")
4528a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if err:
45309a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"Command Output (stderr):\n")
45409a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"--\n")
45509a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(unicode(err))
45609a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbar        output.write(u"--\n")
457be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return (status, output.getvalue())
458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
4592d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef executeShTest(test, litConfig, useExternalSh,
4602d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                  extra_substitutions=[]):
461be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
462be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
463be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
4642d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    res = parseIntegratedTestScript(test, useExternalSh, extra_substitutions)
465be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
466be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
467be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
46842543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
469be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
470be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
471be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if useExternalSh:
474be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScript(test, litConfig, tmpBase, script, execdir)
475be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
476be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
477be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
478be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
479be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
480be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
48142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    if isXFail:
482be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
483bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
484bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
485bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
486bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
487be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
489bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
490bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
491bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
492bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
493be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
494be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
495be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
496be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
497213a789a711724c864defdc2c3e1208d6c5b7fd4Daniel Dunbar    return formatTestOutput(status, out, err, exitCode, script)
498