TestRunner.py revision 35d5e9044c580c843eb6e825d87816619e6d7f8f
1b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarfrom __future__ import absolute_import
2be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport os, signal, subprocess, sys
309a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbarimport re
458c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbarimport platform
55a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbarimport tempfile
658c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar
7b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.ShUtil as ShUtil
8b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.Test as Test
9128ce319ec47c46dc7da16aa3a75185899878745Daniel Dunbarimport lit.util
1018d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene
116bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbarclass InternalShellError(Exception):
126bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    def __init__(self, command, message):
136bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.command = command
146bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.message = message
156bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
16f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkIsWindows = platform.system() == 'Windows'
17f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
1858c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar# Don't use close_fds on Windows.
19f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkUseCloseFDs = not kIsWindows
206efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
216efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar# Use temporary files to replace /dev/null on Windows.
22f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkAvoidDevNull = kIsWindows
236efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
24be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results):
25be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isinstance(cmd, ShUtil.Seq):
26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == ';':
27be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return executeShCmd(cmd.rhs, cfg, cwd, results)
29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
30be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&':
31a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar            raise InternalShellError(cmd,"unsupported shell operator: '&'")
32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '||':
34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res != 0:
36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
38a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar
39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&&':
40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res is None:
42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return res
43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res == 0:
45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
4826e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar        raise ValueError('Unknown shell command: %r' % cmd.op)
49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    assert isinstance(cmd, ShUtil.Pipeline)
51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procs = []
52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    input = subprocess.PIPE
535a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    stderrTempFiles = []
54c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar    opened_files = []
551befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    named_temp_files = []
565a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # To avoid deadlock, we use a single stderr stream for piped
575a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # output. This is null until we have seen some output using
585a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # stderr.
595a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,j in enumerate(cmd.commands):
60f1a26cf9df900101b9cbea42b67f7466edc7deedEli Bendersky        # Apply the redirections, we use (N,) as a sentinel to indicate stdin,
61a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
62a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # from a file are represented with a list [file, mode, file-object]
63a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # where file-object is initially None.
64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        redirects = [(0,), (1,), (2,)]
65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for r in j.redirects:
66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r[0] == ('>',2):
67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = [r[1], 'w', None]
68a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',2):
69a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[2] = [r[1], 'a', None]
70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',2) and r[1] in '012':
71be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = redirects[int(r[1])]
72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',) or r[0] == ('&>',):
73be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = redirects[2] = [r[1], 'w', None]
74be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>',):
75be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = [r[1], 'w', None]
76a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',):
77a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[1] = [r[1], 'a', None]
78be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('<',):
79be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[0] = [r[1], 'r', None]
80be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
81a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                raise InternalShellError(j,"Unsupported redirect: %r" % (r,))
82be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
83a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Map from the final redirections to something subprocess can handle.
84be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        final_redirects = []
85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for index,r in enumerate(redirects):
86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r == (0,):
87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = input
88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (1,):
89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index == 0:
90a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                    raise InternalShellError(j,"Unsupported redirect for stdin")
91be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                elif index == 1:
92be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.PIPE
93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                else:
94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.STDOUT
95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (2,):
96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index != 2:
97a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar                    raise InternalShellError(j,"Unsupported redirect on stdout")
98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = subprocess.PIPE
99be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if r[2] is None:
1016efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    if kAvoidDevNull and r[0] == '/dev/null':
1026efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = tempfile.TemporaryFile(mode=r[1])
1036efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    else:
1046efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = open(r[0], r[1])
105474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    # Workaround a Win32 and/or subprocess bug when appending.
106e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    #
107e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    # FIXME: Actually, this is probably an instance of PR6753.
108474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    if r[1] == 'a':
109bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar                        r[2].seek(0, 2)
1109fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi                    opened_files.append(r[2])
111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = r[2]
112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            final_redirects.append(result)
113be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        stdin, stdout, stderr = final_redirects
115be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
116be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # If stderr wants to come from stdout, but stdout isn't a pipe, then put
117be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # stderr on a pipe and treat it as stdout.
118be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
119be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderr = subprocess.PIPE
120be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = True
121be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
122be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = False
1236bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1245a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # Don't allow stderr on a PIPE except for the last
1255a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # process, this could deadlock.
1265a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            #
1275a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # FIXME: This is slow, but so is deadlock.
1285a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            if stderr == subprocess.PIPE and j != cmd.commands[-1]:
1295a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderr = tempfile.TemporaryFile(mode='w+b')
1305a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderrTempFiles.append((i, stderr))
1315a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1326bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        # Resolve the executable path ourselves.
1336bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args = list(j.args)
134128ce319ec47c46dc7da16aa3a75185899878745Daniel Dunbar        args[0] = lit.util.which(args[0], cfg.environment['PATH'])
1356bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        if not args[0]:
1366bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            raise InternalShellError(j, '%r: command not found' % j.args[0])
1376bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1381befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        # Replace uses of /dev/null with temporary files.
1391befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        if kAvoidDevNull:
1401befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            for i,arg in enumerate(args):
1411befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                if arg == "/dev/null":
1421befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f = tempfile.NamedTemporaryFile(delete=False)
1431befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f.close()
1441befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    named_temp_files.append(f.name)
1451befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    args[i] = f.name
1461befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
1474b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar        procs.append(subprocess.Popen(args, cwd=cwd,
148be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdin = stdin,
149be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdout = stdout,
150be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stderr = stderr,
151be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      env = cfg.environment,
15258c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar                                      close_fds = kUseCloseFDs))
153be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
154be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Immediately close stdin for any process taking stdin from us.
155be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdin == subprocess.PIPE:
156be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin.close()
157be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin = None
158be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
159be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Update the current stdin source.
160be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdout == subprocess.PIPE:
161be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stdout
162be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif stderrIsStdout:
163be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stderr
164be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
165be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = subprocess.PIPE
166be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
16769c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # Explicitly close any redirected files. We need to do this now because we
16869c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # need to release any handles we may have on the temporary files (important
16969c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # on Win32, for example). Since we have already spawned the subprocess, our
17069c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # handles have already been transferred so we do not need them anymore.
17169c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    for f in opened_files:
1729fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        f.close()
17369c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar
1745a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # FIXME: There is probably still deadlock potential here. Yawn.
175be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData = [None] * len(procs)
176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData[-1] = procs[-1].communicate()
1775a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i in range(len(procs) - 1):
179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stdout is not None:
180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = procs[i].stdout.read()
181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = ''
183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stderr is not None:
184be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = procs[i].stderr.read()
185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = ''
187be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        procData[i] = (out,err)
188c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar
1895a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # Read stderr out of the temp files.
1905a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,f in stderrTempFiles:
1915a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        f.seek(0, 0)
1925a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        procData[i] = (procData[i][0], f.read())
193be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
194be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = None
195be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(out,err) in enumerate(procData):
196be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = procs[i].wait()
197be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Detect Ctrl-C in subprocess.
198be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if res == -signal.SIGINT:
199be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise KeyboardInterrupt
200be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results.append((cmd.commands[i], out, err, res))
202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.pipe_err:
203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Python treats the exit code as a signed char.
204bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar            if exitCode is None:
205bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar                exitCode = res
206bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar            elif res < 0:
207be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = min(exitCode, res)
208be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
209be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = max(exitCode, res)
210be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
211be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = res
212be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2131befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    # Remove any named temporary files we created.
2141befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    for f in named_temp_files:
2159fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        try:
2169fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            os.remove(f)
2179fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        except OSError:
2189fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            pass
2191befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if cmd.negate:
221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = not exitCode
222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return exitCode
224be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
225be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
22600fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    cmds = []
22700fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    for ln in commands:
22800fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        try:
229c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola            cmds.append(ShUtil.ShParser(ln, litConfig.isWindows,
230c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola                                        test.config.pipefail).parse())
23100fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        except:
23200fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith            return (Test.FAIL, "shell parser error on: %r" % ln)
23300fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith
23400fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    cmd = cmds[0]
23500fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith    for c in cmds[1:]:
23600fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith        cmd = ShUtil.Seq(cmd, '&&', c)
237be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
238be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    results = []
2396bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    try:
2406bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = executeShCmd(cmd, test.config, cwd, results)
2412e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar    except InternalShellError:
2422e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar        e = sys.exc_info()[1]
243b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar        exitCode = 127
244b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar        results.append((e.command, '', e.message, exitCode))
245be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
246be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
247be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
248be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
249be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
250be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
251be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
252be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
253be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
254be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
255be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd):
2569869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    bashPath = litConfig.getBashPath();
2579869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    isWin32CMDEXE = (litConfig.isWindows and not bashPath)
258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = tmpBase + '.script'
2599869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script += '.bat'
261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Write script file
2638755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    mode = 'w'
2648755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    if litConfig.isWindows and not isWin32CMDEXE:
2658755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner      mode += 'b'  # Avoid CRLFs when writing bash scripts.
2668755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner    f = open(script, mode)
2679869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
268be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
270c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola        if test.config.pipefail:
271c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola            f.write('set -o pipefail;')
272c15e5b0a0dbdaf8612bdcbba1deedcb77bed1045Richard Smith        f.write('{ ' + '; } &&\n{ '.join(commands) + '; }')
273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.write('\n')
274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.close()
275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2769869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
277be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['cmd','/c', script]
278be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
2799869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        if bashPath:
2809869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = [bashPath, script]
2819869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        else:
2829869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = ['/bin/sh', script]
283be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if litConfig.useValgrind:
284be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # FIXME: Running valgrind on sh is overkill. We probably could just
285be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # run on clang with no real loss.
28632989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin            command = litConfig.valgrindArgs + command
287be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
288493e8d4bf503c8f573e0dce95ea146d181c623c6Daniel Dunbar    return lit.util.executeCommand(command, cwd=cwd,
289493e8d4bf503c8f573e0dce95ea146d181c623c6Daniel Dunbar                                   env=test.config.environment)
290be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
291f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbardef isExpectedFail(test, xfails):
292f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    # Check if any of the xfails match an available feature or the target.
29342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xfails:
294f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is the wildcard, it always fails.
295f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item == '*':
29644a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar            return True
29744a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar
298f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is an exact match for one of the features, it fails.
299f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item in test.config.available_features:
300f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar            return True
30142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
302f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        # If this is a part of the target triple, it fails.
303f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar        if item in test.suite.config.target_triple:
304f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar            return True
30542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
306f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    return False
30742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
30835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbardef parseIntegratedTestScriptCommands(source_path):
3095403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    """
3105403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    parseIntegratedTestScriptCommands(source_path) -> commands
3115403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar
3125403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    Parse the commands in an integrated test script file into a list of
3135403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    (line_number, command_type, line).
3145403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    """
31535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar
31635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # This code is carefully written to be dual compatible with Python 2.5+ and
31735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # Python 3 without requiring input files to always have valid codings. The
31835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # trick we use is to open the file in binary mode and use the regular
31935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # expression library to find the commands, with it scanning strings in
32035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # Python2 and bytes in Python3.
32135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    #
32235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # Once we find a match, we do require each script line to be decodable to
32335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # ascii, so we convert the outputs to ascii before returning. This way the
32435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # remaining code can work with "strings" agnostic of the executing Python
32535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    # version.
32635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar
32735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    def to_bytes(str):
32835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        # Encode to Latin1 to get binary data.
32935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        return str.encode('ISO-8859-1')
33035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    keywords = ('RUN:', 'XFAIL:', 'REQUIRES:', 'END.')
33135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    keywords_re = re.compile(
33235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        to_bytes("(%s)(.*)\n" % ("|".join(k for k in keywords),)))
33335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar
33435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    f = open(source_path, 'rb')
33535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    try:
33635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        # Read the entire file contents.
33735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        data = f.read()
33835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar
33935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        # Iterate over the matches.
34035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        line_number = 1
34135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        last_match_position = 0
34235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        for match in keywords_re.finditer(data):
34335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # Compute the updated line number by counting the intervening
34435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # newlines.
34535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            match_position = match.start()
34635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            line_number += data.count(to_bytes('\n'), last_match_position,
34735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar                                      match_position)
34835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            last_match_position = match_position
34935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar
35035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # Convert the keyword and line to ascii strings and yield the
35135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # command. Note that we take care to return regular strings in
35235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # Python 2, to avoid other code having to differentiate between the
35335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            # str and unicode types.
35435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            keyword,ln = match.groups()
35535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar            yield (line_number, str(keyword[:-1].decode('ascii')),
35635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar                   str(ln.decode('ascii')))
35735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar    finally:
35835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar        f.close()
3595403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar
3602d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef parseIntegratedTestScript(test, normalize_slashes=False,
3612d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                              extra_substitutions=[]):
362be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
363f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    script and extract the lines to 'RUN' as well as 'XFAIL' and 'REQUIRES'
364be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    information. The RUN lines also will have variable substitution performed.
365be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """
366be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Get the temporary location, this is always relative to the test suite
368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # root, not test source root.
369be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    #
370be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # FIXME: This should not be here?
371be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    sourcepath = test.getSourcePath()
372f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    sourcedir = os.path.dirname(sourcepath)
373be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execpath = test.getExecPath()
374be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execdir,execbase = os.path.split(execpath)
3750f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpDir = os.path.join(execdir, 'Output')
3760f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpBase = os.path.join(tmpDir, execbase)
377be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
378f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Normalize slashes, if requested.
379f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    if normalize_slashes:
380f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcepath = sourcepath.replace('\\', '/')
381f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcedir = sourcedir.replace('\\', '/')
382bbbc283d86a911ccf3bdecdc78a7a8f71f31683fNAKAMURA Takumi        tmpDir = tmpDir.replace('\\', '/')
383f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        tmpBase = tmpBase.replace('\\', '/')
384f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
385be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # We use #_MARKER_# to hide %% while we do the other substitutions.
3862d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions = list(extra_substitutions)
3872d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions.extend([('%%', '#_MARKER_#')])
388be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend(test.config.substitutions)
389be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend([('%s', sourcepath),
390f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%S', sourcedir),
391f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%p', sourcedir),
3920191bfcf7a5ae1ccfad7afe8ced59a14ffaca2a6Nico Weber                          ('%{pathsep}', os.pathsep),
393be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%t', tmpBase + '.tmp'),
3940f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor                          ('%T', tmpDir),
395be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('#_MARKER_#', '%')])
396be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
397e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi    # "%/[STpst]" should be normalized.
398e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi    substitutions.extend([
399e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ('%/s', sourcepath.replace('\\', '/')),
400e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ('%/S', sourcedir.replace('\\', '/')),
401e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ('%/p', sourcedir.replace('\\', '/')),
402e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ('%/t', tmpBase.replace('\\', '/') + '.tmp'),
403e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ('%/T', tmpDir.replace('\\', '/')),
404e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi            ])
405e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi
406be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Collect the test lines from the script.
407be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = []
408be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xfails = []
409b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    requires = []
4105403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar    for line_number, command_type, ln in \
4115403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            parseIntegratedTestScriptCommands(sourcepath):
4125403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar        if command_type == 'RUN':
413be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Trim trailing whitespace.
414be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.rstrip()
415be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
41608639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            # Substitute line number expressions
41708639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            ln = re.sub('%\(line\)', str(line_number), ln)
41808639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            def replace_line_number(match):
41908639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                if match.group(1) == '+':
42008639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                    return str(line_number + int(match.group(2)))
42108639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                if match.group(1) == '-':
42208639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko                    return str(line_number - int(match.group(2)))
42308639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko            ln = re.sub('%\(line *([\+-]) *(\d+)\)', replace_line_number, ln)
42408639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko
425be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Collapse lines with trailing '\\'.
426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if script and script[-1][-1] == '\\':
427be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script[-1] = script[-1][:-1] + ln
428be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
429be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script.append(ln)
4305403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar        elif command_type == 'XFAIL':
4315403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            xfails.extend([s.strip() for s in ln.split(',')])
4325403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar        elif command_type == 'REQUIRES':
4335403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            requires.extend([s.strip() for s in ln.split(',')])
4345403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar        elif command_type == 'END':
4355403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            # END commands are only honored if the rest of the line is empty.
4365403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            if not ln.strip():
437be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
4385403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar        else:
4395403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar            raise ValueError("unknown script command type: %r" % (
4405403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar                    command_type,))
441be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
44218d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # Apply substitutions to the script.  Allow full regular
44318d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression syntax.  Replace each matching occurrence of regular
44418d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression pattern a with substitution b in line ln.
445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    def processLine(ln):
446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Apply substitutions
447be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for a,b in substitutions:
448ba69d3f6d448ca0a3a56b71fa65e85712bf76512Francois Pichet            if kIsWindows:
4497a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet                b = b.replace("\\","\\\\")
4507a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet            ln = re.sub(a, b, ln)
451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
452be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Strip the trailing newline and any extra whitespace.
453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return ln.strip()
454a1ba7527ded837e4c98149f7b1fe848a93177e07Daniel Dunbar    script = [processLine(ln)
455a1ba7527ded837e4c98149f7b1fe848a93177e07Daniel Dunbar              for ln in script]
456be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
457be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Verify the script contains a run line.
458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if not script:
459be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has no run line!")
460be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
461b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    # Check for unterminated run lines.
462be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if script[-1][-1] == '\\':
463be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
464be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
465f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick    # Check that we have the required features:
466b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    missing_required_features = [f for f in requires
467f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick                                 if f not in test.config.available_features]
468b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    if missing_required_features:
469b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        msg = ', '.join(missing_required_features)
470b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        return (Test.UNSUPPORTED,
471b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar                "Test requires the following features: %s" % msg)
472b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar
473f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar    isXFail = isExpectedFail(test, xfails)
47442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return script,isXFail,tmpBase,execdir
475be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
476213a789a711724c864defdc2c3e1208d6c5b7fd4Daniel Dunbardef formatTestOutput(status, out, err, exitCode, script):
477213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar    output = """\
478213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel DunbarScript:
479213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
480213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar%s
481213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
482213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel DunbarExit Code: %d
483213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar
484213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar""" % ('\n'.join(script), exitCode)
485213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar
486213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar    # Append the stdout, if present.
4878a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if out:
488213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar        output += """\
489213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel DunbarCommand Output (stdout):
490213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
491213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar%s
492213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
493213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar""" % (out,)
494213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar
495213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar    # Append the stderr, if present.
4968a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if err:
497213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar        output += """\
498213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel DunbarCommand Output (stderr):
499213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
500213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar%s
501213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar--
502213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar""" % (err,)
503213ab86ee6d51a27ec87ed8320c6b8407dd25595Daniel Dunbar    return (status, output)
504be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5052d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef executeShTest(test, litConfig, useExternalSh,
5062d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                  extra_substitutions=[]):
507be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
508be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
509be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5102d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    res = parseIntegratedTestScript(test, useExternalSh, extra_substitutions)
511be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
512be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
513be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
51442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
515be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5168f4aab8c2fe095ce1286fc1bd0bdd9157ed00398NAKAMURA Takumi    if litConfig.noExecute:
5178f4aab8c2fe095ce1286fc1bd0bdd9157ed00398NAKAMURA Takumi        return (Test.PASS, '')
5188f4aab8c2fe095ce1286fc1bd0bdd9157ed00398NAKAMURA Takumi
519be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
520128ce319ec47c46dc7da16aa3a75185899878745Daniel Dunbar    lit.util.mkdir_p(os.path.dirname(tmpBase))
521be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
522be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if useExternalSh:
523be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScript(test, litConfig, tmpBase, script, execdir)
524be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
525be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
526be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
527be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
528be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
529be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
53042543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    if isXFail:
531be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
532bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
533bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
534bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
535bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
536be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
537be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
538bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
539bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
540bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
541bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
542be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
543be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
544be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
545be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
546213a789a711724c864defdc2c3e1208d6c5b7fd4Daniel Dunbar    return formatTestOutput(status, out, err, exitCode, script)
547