TestRunner.py revision 44a83f092029fa76bce05ff0c0598afc55215767
1be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport os, signal, subprocess, sys
2be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport StringIO
3be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
4be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport ShUtil
5be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport Test
6be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport Util
7be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
858c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbarimport platform
95a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbarimport tempfile
1058c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar
1118d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greeneimport re
1218d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene
136bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbarclass InternalShellError(Exception):
146bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    def __init__(self, command, message):
156bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.command = command
166bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.message = message
176bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
18f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkIsWindows = platform.system() == 'Windows'
19f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
2058c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar# Don't use close_fds on Windows.
21f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkUseCloseFDs = not kIsWindows
226efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
236efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar# Use temporary files to replace /dev/null on Windows.
24f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkAvoidDevNull = kIsWindows
256efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar
26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeCommand(command, cwd=None, env=None):
27b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    # Close extra file handles on UNIX (on Windows this cannot be done while
28b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    # also redirecting input).
29b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar    close_fds = not kIsWindows
30b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar
31be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    p = subprocess.Popen(command, cwd=cwd,
32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdin=subprocess.PIPE,
33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdout=subprocess.PIPE,
34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stderr=subprocess.PIPE,
35b1a464279623768a3d04ff6726c99dce35d2f360Daniel Dunbar                         env=env, close_fds=close_fds)
36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err = p.communicate()
37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = p.wait()
38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Detect Ctrl-C in subprocess.
40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if exitCode == -signal.SIGINT:
41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise KeyboardInterrupt
42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results):
46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isinstance(cmd, ShUtil.Seq):
47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == ';':
48be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return executeShCmd(cmd.rhs, cfg, cwd, results)
50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&':
52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise NotImplementedError,"unsupported test command: '&'"
53be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
54be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '||':
55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res != 0:
57be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
59be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&&':
60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
61be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res is None:
62be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return res
63be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res == 0:
65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
68be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise ValueError,'Unknown shell command: %r' % cmd.op
69be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    assert isinstance(cmd, ShUtil.Pipeline)
71be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procs = []
72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    input = subprocess.PIPE
735a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    stderrTempFiles = []
74c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar    opened_files = []
751befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    named_temp_files = []
765a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # To avoid deadlock, we use a single stderr stream for piped
775a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # output. This is null until we have seen some output using
785a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # stderr.
795a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,j in enumerate(cmd.commands):
80a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Apply the redirections, we use (N,) as a sentinal to indicate stdin,
81a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
82a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # from a file are represented with a list [file, mode, file-object]
83a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # where file-object is initially None.
84be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        redirects = [(0,), (1,), (2,)]
85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for r in j.redirects:
86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r[0] == ('>',2):
87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = [r[1], 'w', None]
88a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',2):
89a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[2] = [r[1], 'a', None]
90be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',2) and r[1] in '012':
91be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = redirects[int(r[1])]
92be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',) or r[0] == ('&>',):
93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = redirects[2] = [r[1], 'w', None]
94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>',):
95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = [r[1], 'w', None]
96a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',):
97a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[1] = [r[1], 'a', None]
98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('<',):
99be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[0] = [r[1], 'r', None]
100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
101be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                raise NotImplementedError,"Unsupported redirect: %r" % (r,)
102be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
103a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Map from the final redirections to something subprocess can handle.
104be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        final_redirects = []
105be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for index,r in enumerate(redirects):
106be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r == (0,):
107be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = input
108be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (1,):
109be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index == 0:
110be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect for stdin"
111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                elif index == 1:
112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.PIPE
113be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                else:
114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.STDOUT
115be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (2,):
116be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index != 2:
117be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect on stdout"
118be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = subprocess.PIPE
119be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
120be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if r[2] is None:
1216efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    if kAvoidDevNull and r[0] == '/dev/null':
1226efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = tempfile.TemporaryFile(mode=r[1])
1236efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    else:
1246efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = open(r[0], r[1])
125474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    # Workaround a Win32 and/or subprocess bug when appending.
126e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    #
127e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    # FIXME: Actually, this is probably an instance of PR6753.
128474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    if r[1] == 'a':
129bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar                        r[2].seek(0, 2)
1309fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi                    opened_files.append(r[2])
131be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = r[2]
132be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            final_redirects.append(result)
133be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
134be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        stdin, stdout, stderr = final_redirects
135be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
136be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # If stderr wants to come from stdout, but stdout isn't a pipe, then put
137be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # stderr on a pipe and treat it as stdout.
138be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
139be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderr = subprocess.PIPE
140be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = True
141be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
142be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = False
1436bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1445a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # Don't allow stderr on a PIPE except for the last
1455a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # process, this could deadlock.
1465a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            #
1475a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # FIXME: This is slow, but so is deadlock.
1485a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            if stderr == subprocess.PIPE and j != cmd.commands[-1]:
1495a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderr = tempfile.TemporaryFile(mode='w+b')
1505a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderrTempFiles.append((i, stderr))
1515a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1526bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        # Resolve the executable path ourselves.
1536bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args = list(j.args)
1546bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args[0] = Util.which(args[0], cfg.environment['PATH'])
1556bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        if not args[0]:
1566bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            raise InternalShellError(j, '%r: command not found' % j.args[0])
1576bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1581befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        # Replace uses of /dev/null with temporary files.
1591befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        if kAvoidDevNull:
1601befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            for i,arg in enumerate(args):
1611befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                if arg == "/dev/null":
1621befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f = tempfile.NamedTemporaryFile(delete=False)
1631befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f.close()
1641befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    named_temp_files.append(f.name)
1651befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    args[i] = f.name
1661befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
1674b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar        procs.append(subprocess.Popen(args, cwd=cwd,
168be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdin = stdin,
169be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdout = stdout,
170be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stderr = stderr,
171be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      env = cfg.environment,
17258c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar                                      close_fds = kUseCloseFDs))
173be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
174be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Immediately close stdin for any process taking stdin from us.
175be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdin == subprocess.PIPE:
176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin.close()
177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin = None
178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Update the current stdin source.
180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdout == subprocess.PIPE:
181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stdout
182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif stderrIsStdout:
183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stderr
184be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = subprocess.PIPE
186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
18769c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # Explicitly close any redirected files. We need to do this now because we
18869c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # need to release any handles we may have on the temporary files (important
18969c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # on Win32, for example). Since we have already spawned the subprocess, our
19069c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # handles have already been transferred so we do not need them anymore.
19169c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    for f in opened_files:
1929fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        f.close()
19369c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar
1945a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # FIXME: There is probably still deadlock potential here. Yawn.
195be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData = [None] * len(procs)
196be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData[-1] = procs[-1].communicate()
1975a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
198be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i in range(len(procs) - 1):
199be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stdout is not None:
200be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = procs[i].stdout.read()
201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = ''
203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stderr is not None:
204be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = procs[i].stderr.read()
205be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
206be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = ''
207be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        procData[i] = (out,err)
208c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar
2095a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # Read stderr out of the temp files.
2105a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,f in stderrTempFiles:
2115a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        f.seek(0, 0)
2125a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        procData[i] = (procData[i][0], f.read())
213be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
214be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = None
215be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(out,err) in enumerate(procData):
216be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = procs[i].wait()
217be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Detect Ctrl-C in subprocess.
218be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if res == -signal.SIGINT:
219be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise KeyboardInterrupt
220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results.append((cmd.commands[i], out, err, res))
222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.pipe_err:
223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Python treats the exit code as a signed char.
224be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res < 0:
225be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = min(exitCode, res)
226be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
227be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = max(exitCode, res)
228be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
229be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = res
230be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2311befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    # Remove any named temporary files we created.
2321befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    for f in named_temp_files:
2339fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        try:
2349fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            os.remove(f)
2359fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi        except OSError:
2369fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi            pass
2371befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
238be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if cmd.negate:
239be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = not exitCode
240be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
241be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return exitCode
242be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
243be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
244be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    ln = ' &&\n'.join(commands)
245be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    try:
246be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.ShParser(ln, litConfig.isWindows).parse()
247be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    except:
248be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.FAIL, "shell parser error on: %r" % ln)
249be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
250be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    results = []
2516bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    try:
2526bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = executeShCmd(cmd, test.config, cwd, results)
2536bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    except InternalShellError,e:
2546bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        out = ''
2556bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        err = e.message
2566bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = 255
257be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
263be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
264be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
265be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
267be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd):
268be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    import TclUtil
269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmds = []
270be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in commands:
271be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Given the unfortunate way LLVM's test are written, the line gets
272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # backslash substitution done twice.
273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True)
274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
276be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            tokens = list(TclUtil.TclLexer(ln).lex())
277be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
278be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return (Test.FAIL, "Tcl lexer error on: %r" % ln)
279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
280be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Validate there are no control tokens.
281be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for t in tokens:
282be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if not isinstance(t, str):
283be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return (Test.FAIL,
284be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                        "Invalid test line: %r containing %r" % (ln, t))
285be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
286be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
287be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline())
288be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
2892c0a49c8cba8b7a6624d9c0b96f7d94231e10d22Daniel Dunbar            return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln)
290be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
291b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin    if litConfig.useValgrind:
292b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin        for pipeline in cmds:
293b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin            if pipeline.commands:
294b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                # Only valgrind the first command in each pipeline, to avoid
295b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                # valgrinding things like grep, not, and FileCheck.
296b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                cmd = pipeline.commands[0]
29732989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin                cmd.args = litConfig.valgrindArgs + cmd.args
298b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin
299be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmd = cmds[0]
300be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for c in cmds[1:]:
301be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.Seq(cmd, '&&', c)
302be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
3037723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    # FIXME: This is lame, we shouldn't need bash. See PR5240.
3047723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    bashPath = litConfig.getBashPath()
3057723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    if litConfig.useTclAsSh and bashPath:
306be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script = tmpBase + '.script'
307be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
308be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Write script file
309be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f = open(script,'w')
310be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        print >>f, 'set -o pipefail'
311be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd.toShell(f, pipefail = True)
312be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.close()
313be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
314be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 0:
315be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, cmd
316be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, open(script).read()
317be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout
318be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return '', '', 0
319be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
3207723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar        command = [litConfig.getBashPath(), script]
321be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out,err,exitCode = executeCommand(command, cwd=cwd,
322be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                          env=test.config.environment)
323be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
324be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return out,err,exitCode
325be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
326be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results = []
3276bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        try:
3286bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = executeShCmd(cmd, test.config, cwd, results)
3296bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        except InternalShellError,e:
3306bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            results.append((e.command, '', e.message + '\n', 255))
3316bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = 255
332be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
333be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
334be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
335be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out, cmd_err, res) in enumerate(results):
336be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
337be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
338be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
339be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
340be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
341be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
342be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
343be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd):
3449869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    bashPath = litConfig.getBashPath();
3459869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    isWin32CMDEXE = (litConfig.isWindows and not bashPath)
346be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = tmpBase + '.script'
3479869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
348be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script += '.bat'
349be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
350be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Write script file
351be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f = open(script,'w')
3529869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
353be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
354be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
355be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write(' &&\n'.join(commands))
356be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.write('\n')
357be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.close()
358be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
3599869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
360be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['cmd','/c', script]
361be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
3629869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        if bashPath:
3639869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = [bashPath, script]
3649869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        else:
3659869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = ['/bin/sh', script]
366be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if litConfig.useValgrind:
367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # FIXME: Running valgrind on sh is overkill. We probably could just
368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # run on clang with no real loss.
36932989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin            command = litConfig.valgrindArgs + command
370be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
371be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return executeCommand(command, cwd=cwd, env=test.config.environment)
372be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
37344a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbardef isExpectedFail(test, xfails, xtargets):
37444a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar    # If the xfail matches an available feature, it always fails.
37542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xfails:
37644a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar        if item in test.config.available_features:
37744a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar            return True
37844a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar
37944a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar    # Otherwise, check if any xfail matches this target.
38044a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar    for item in xfails:
38144a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar        if item == '*' or item in test.suite.config.target_triple:
38242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar            break
38342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    else:
38442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        return False
38542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
38642543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    # If so, see if it is expected to pass on this target.
38742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    #
38842543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    # FIXME: Rename XTARGET to something that makes sense, like XPASS.
38942543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xtargets:
39044a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar        if item == '*' or item in test.suite.config.target_triple:
39142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar            return False
39242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
39342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return True
39442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
3952d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef parseIntegratedTestScript(test, normalize_slashes=False,
3962d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                              extra_substitutions=[]):
397be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
398be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
399be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    information. The RUN lines also will have variable substitution performed.
400be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """
401be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
402be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Get the temporary location, this is always relative to the test suite
403be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # root, not test source root.
404be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    #
405be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # FIXME: This should not be here?
406be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    sourcepath = test.getSourcePath()
407f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    sourcedir = os.path.dirname(sourcepath)
408be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execpath = test.getExecPath()
409be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execdir,execbase = os.path.split(execpath)
4100f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpDir = os.path.join(execdir, 'Output')
4110f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpBase = os.path.join(tmpDir, execbase)
41240c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar    if test.index is not None:
41340c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar        tmpBase += '_%d' % test.index
414be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
415f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Normalize slashes, if requested.
416f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    if normalize_slashes:
417f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcepath = sourcepath.replace('\\', '/')
418f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcedir = sourcedir.replace('\\', '/')
419bbbc283d86a911ccf3bdecdc78a7a8f71f31683fNAKAMURA Takumi        tmpDir = tmpDir.replace('\\', '/')
420f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        tmpBase = tmpBase.replace('\\', '/')
421f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # We use #_MARKER_# to hide %% while we do the other substitutions.
4232d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions = list(extra_substitutions)
4242d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    substitutions.extend([('%%', '#_MARKER_#')])
425be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend(test.config.substitutions)
426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend([('%s', sourcepath),
427f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%S', sourcedir),
428f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%p', sourcedir),
4290191bfcf7a5ae1ccfad7afe8ced59a14ffaca2a6Nico Weber                          ('%{pathsep}', os.pathsep),
430be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%t', tmpBase + '.tmp'),
4310f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor                          ('%T', tmpDir),
4325110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          # FIXME: Remove this once we kill DejaGNU.
4335110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          ('%abs_tmp', tmpBase + '.tmp'),
434be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('#_MARKER_#', '%')])
435be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
436be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Collect the test lines from the script.
437be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = []
438be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xfails = []
439be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xtargets = []
440b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    requires = []
441be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in open(sourcepath):
442be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 'RUN:' in ln:
443be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Isolate the command to run.
444be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            index = ln.index('RUN:')
445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln[index+4:]
446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
447be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Trim trailing whitespace.
448be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.rstrip()
449be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
450be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Collapse lines with trailing '\\'.
451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if script and script[-1][-1] == '\\':
452be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script[-1] = script[-1][:-1] + ln
453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
454be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script.append(ln)
45542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        elif 'XFAIL:' in ln:
456be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XFAIL:') + 6:].split(',')
457be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xfails.extend([s.strip() for s in items])
458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'XTARGET:' in ln:
459be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XTARGET:') + 8:].split(',')
460be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xtargets.extend([s.strip() for s in items])
461b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        elif 'REQUIRES:' in ln:
462b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            items = ln[ln.index('REQUIRES:') + 9:].split(',')
463b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            requires.extend([s.strip() for s in items])
464be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'END.' in ln:
465be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Check for END. lines.
466be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if ln[ln.index('END.'):].strip() == 'END.':
467be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
468be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
46918d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # Apply substitutions to the script.  Allow full regular
47018d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression syntax.  Replace each matching occurrence of regular
47118d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression pattern a with substitution b in line ln.
472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    def processLine(ln):
473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Apply substitutions
474be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for a,b in substitutions:
475ba69d3f6d448ca0a3a56b71fa65e85712bf76512Francois Pichet            if kIsWindows:
4767a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet                b = b.replace("\\","\\\\")
4777a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet            ln = re.sub(a, b, ln)
478be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
479be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Strip the trailing newline and any extra whitespace.
480be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return ln.strip()
481be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = map(processLine, script)
482be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
483be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Verify the script contains a run line.
484be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if not script:
485be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has no run line!")
486be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
487b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    # Check for unterminated run lines.
488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if script[-1][-1] == '\\':
489be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
490be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
491f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick    # Check that we have the required features:
492b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    missing_required_features = [f for f in requires
493f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick                                 if f not in test.config.available_features]
494b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    if missing_required_features:
495b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        msg = ', '.join(missing_required_features)
496b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        return (Test.UNSUPPORTED,
497b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar                "Test requires the following features: %s" % msg)
498b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar
49944a83f092029fa76bce05ff0c0598afc55215767Daniel Dunbar    isXFail = isExpectedFail(test, xfails, xtargets)
50042543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return script,isXFail,tmpBase,execdir
501be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
50234f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohmandef formatTestOutput(status, out, err, exitCode, failDueToStderr, script):
503be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    output = StringIO.StringIO()
504be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Script:"
505be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
506be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, '\n'.join(script)
507be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
50834f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    print >>output, "Exit Code: %r" % exitCode,
50934f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    if failDueToStderr:
51034f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman        print >>output, "(but there was output on stderr)"
51134f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    else:
51234f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman        print >>output
5138a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if out:
5148a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "Command Output (stdout):"
5158a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5168a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        output.write(out)
5178a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5188a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if err:
5198a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "Command Output (stderr):"
5208a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5218a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        output.write(err)
5228a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
523be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return (status, output.getvalue())
524be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
525be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclTest(test, litConfig):
526be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
527be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
528be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
529f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Parse the test script, normalizing slashes in substitutions on Windows
530f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # (since otherwise Tcl style lexing will treat them as escapes).
531f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows)
532be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
533be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
534be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
53542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
536be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
537be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
538be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
539be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
540be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
541be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
542be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
543be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir)
544be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
545be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
546be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
54734f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Test for failure. In addition to the exit code, Tcl commands are
54834f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # considered to fail if there is any standard error output.
549be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
550be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isXFail:
5517c12837916e647a9225fe2433f826588f2f28726Andrew Trick        ok = exitCode != 0 or err and not litConfig.ignoreStdErr
552bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
553bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
554bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
555bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
556be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
5577c12837916e647a9225fe2433f826588f2f28726Andrew Trick        ok = exitCode == 0 and (not err or litConfig.ignoreStdErr)
558bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
559bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
560bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
561bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
562be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
563be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
564be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
565be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
56634f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Set a flag for formatTestOutput so it can explain why the test was
56734f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # considered to have failed, despite having an exit code of 0.
5687c12837916e647a9225fe2433f826588f2f28726Andrew Trick    failDueToStderr = exitCode == 0 and err and not litConfig.ignoreStdErr
56934f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman
57034f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
571be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5722d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef executeShTest(test, litConfig, useExternalSh,
5732d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar                  extra_substitutions=[]):
574be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
575be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
576be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5772d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar    res = parseIntegratedTestScript(test, useExternalSh, extra_substitutions)
578be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
579be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
580be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
58142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
582be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
583be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
584be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
585be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
586be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
587be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
588be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
589be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if useExternalSh:
590be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScript(test, litConfig, tmpBase, script, execdir)
591be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
592be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
593be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
594be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
595be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
596be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
59742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    if isXFail:
598be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
599bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
600bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
601bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
602bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
603be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
604be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
605bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
606bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
607bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
608bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
609be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
610be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
611be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
612be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
61334f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Sh tests are not considered to fail just from stderr output.
61434f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    failDueToStderr = False
61534f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman
61634f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
617