TestRunner.py revision 7c12837916e647a9225fe2433f826588f2f28726
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):
27be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    p = subprocess.Popen(command, cwd=cwd,
28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdin=subprocess.PIPE,
29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdout=subprocess.PIPE,
30be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stderr=subprocess.PIPE,
31be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         env=env)
32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err = p.communicate()
33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = p.wait()
34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Detect Ctrl-C in subprocess.
36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if exitCode == -signal.SIGINT:
37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise KeyboardInterrupt
38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results):
42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isinstance(cmd, ShUtil.Seq):
43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == ';':
44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return executeShCmd(cmd.rhs, cfg, cwd, results)
46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&':
48be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise NotImplementedError,"unsupported test command: '&'"
49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '||':
51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res != 0:
53be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
54be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&&':
56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
57be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res is None:
58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return res
59be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res == 0:
61be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
62be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
63be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise ValueError,'Unknown shell command: %r' % cmd.op
65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    assert isinstance(cmd, ShUtil.Pipeline)
67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procs = []
68be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    input = subprocess.PIPE
695a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    stderrTempFiles = []
70c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar    opened_files = []
711befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    named_temp_files = []
725a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # To avoid deadlock, we use a single stderr stream for piped
735a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # output. This is null until we have seen some output using
745a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # stderr.
755a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,j in enumerate(cmd.commands):
76a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Apply the redirections, we use (N,) as a sentinal to indicate stdin,
77a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or
78a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # from a file are represented with a list [file, mode, file-object]
79a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # where file-object is initially None.
80be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        redirects = [(0,), (1,), (2,)]
81be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for r in j.redirects:
82be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r[0] == ('>',2):
83be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = [r[1], 'w', None]
84a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',2):
85a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[2] = [r[1], 'a', None]
86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',2) and r[1] in '012':
87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = redirects[int(r[1])]
88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',) or r[0] == ('&>',):
89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = redirects[2] = [r[1], 'w', None]
90be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>',):
91be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = [r[1], 'w', None]
92a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar            elif r[0] == ('>>',):
93a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar                redirects[1] = [r[1], 'a', None]
94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('<',):
95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[0] = [r[1], 'r', None]
96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
97be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                raise NotImplementedError,"Unsupported redirect: %r" % (r,)
98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
99a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar        # Map from the final redirections to something subprocess can handle.
100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        final_redirects = []
101be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for index,r in enumerate(redirects):
102be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r == (0,):
103be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = input
104be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (1,):
105be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index == 0:
106be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect for stdin"
107be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                elif index == 1:
108be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.PIPE
109be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                else:
110be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.STDOUT
111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (2,):
112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index != 2:
113be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect on stdout"
114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = subprocess.PIPE
115be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
116be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if r[2] is None:
1176efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    if kAvoidDevNull and r[0] == '/dev/null':
1186efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = tempfile.TemporaryFile(mode=r[1])
1196efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                    else:
1206efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar                        r[2] = open(r[0], r[1])
121474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    # Workaround a Win32 and/or subprocess bug when appending.
122e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    #
123e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar                    # FIXME: Actually, this is probably an instance of PR6753.
124474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar                    if r[1] == 'a':
125bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar                        r[2].seek(0, 2)
126c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar                    opened_files.append(r[2])
127be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = r[2]
128be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            final_redirects.append(result)
129be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
130be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        stdin, stdout, stderr = final_redirects
131be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
132be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # If stderr wants to come from stdout, but stdout isn't a pipe, then put
133be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # stderr on a pipe and treat it as stdout.
134be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
135be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderr = subprocess.PIPE
136be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = True
137be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
138be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = False
1396bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1405a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # Don't allow stderr on a PIPE except for the last
1415a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # process, this could deadlock.
1425a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            #
1435a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # FIXME: This is slow, but so is deadlock.
1445a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            if stderr == subprocess.PIPE and j != cmd.commands[-1]:
1455a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderr = tempfile.TemporaryFile(mode='w+b')
1465a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderrTempFiles.append((i, stderr))
1475a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1486bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        # Resolve the executable path ourselves.
1496bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args = list(j.args)
1506bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args[0] = Util.which(args[0], cfg.environment['PATH'])
1516bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        if not args[0]:
1526bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            raise InternalShellError(j, '%r: command not found' % j.args[0])
1536bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1541befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        # Replace uses of /dev/null with temporary files.
1551befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        if kAvoidDevNull:
1561befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            for i,arg in enumerate(args):
1571befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                if arg == "/dev/null":
1581befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f = tempfile.NamedTemporaryFile(delete=False)
1591befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    f.close()
1601befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    named_temp_files.append(f.name)
1611befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar                    args[i] = f.name
1621befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
1634b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar        procs.append(subprocess.Popen(args, cwd=cwd,
164be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdin = stdin,
165be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdout = stdout,
166be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stderr = stderr,
167be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      env = cfg.environment,
16858c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar                                      close_fds = kUseCloseFDs))
169be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
170be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Immediately close stdin for any process taking stdin from us.
171be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdin == subprocess.PIPE:
172be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin.close()
173be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin = None
174be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
175be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Update the current stdin source.
176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdout == subprocess.PIPE:
177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stdout
178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif stderrIsStdout:
179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stderr
180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = subprocess.PIPE
182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
18369c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # Explicitly close any redirected files. We need to do this now because we
18469c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # need to release any handles we may have on the temporary files (important
18569c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # on Win32, for example). Since we have already spawned the subprocess, our
18669c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    # handles have already been transferred so we do not need them anymore.
18769c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar    for f in opened_files:
18869c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar        f.close()
18969c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar
1905a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # FIXME: There is probably still deadlock potential here. Yawn.
191be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData = [None] * len(procs)
192be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData[-1] = procs[-1].communicate()
1935a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
194be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i in range(len(procs) - 1):
195be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stdout is not None:
196be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = procs[i].stdout.read()
197be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
198be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = ''
199be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stderr is not None:
200be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = procs[i].stderr.read()
201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = ''
203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        procData[i] = (out,err)
204c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar
2055a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # Read stderr out of the temp files.
2065a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,f in stderrTempFiles:
2075a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        f.seek(0, 0)
2085a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        procData[i] = (procData[i][0], f.read())
209be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
210be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = None
211be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(out,err) in enumerate(procData):
212be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = procs[i].wait()
213be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Detect Ctrl-C in subprocess.
214be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if res == -signal.SIGINT:
215be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise KeyboardInterrupt
216be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
217be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results.append((cmd.commands[i], out, err, res))
218be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.pipe_err:
219be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Python treats the exit code as a signed char.
220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res < 0:
221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = min(exitCode, res)
222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = max(exitCode, res)
224be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
225be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = res
226be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2271befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    # Remove any named temporary files we created.
2281befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar    for f in named_temp_files:
2291befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        try:
2301befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            os.remove(f)
2311befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar        except OSError:
2321befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar            pass
2331befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar
234be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if cmd.negate:
235be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = not exitCode
236be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
237be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return exitCode
238be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
239be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
240be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    ln = ' &&\n'.join(commands)
241be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    try:
242be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.ShParser(ln, litConfig.isWindows).parse()
243be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    except:
244be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.FAIL, "shell parser error on: %r" % ln)
245be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
246be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    results = []
2476bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    try:
2486bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = executeShCmd(cmd, test.config, cwd, results)
2496bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    except InternalShellError,e:
2506bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        out = ''
2516bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        err = e.message
2526bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = 255
253be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
254be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
255be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
256be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
257be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
263be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd):
264be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    import TclUtil
265be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmds = []
266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in commands:
267be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Given the unfortunate way LLVM's test are written, the line gets
268be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # backslash substitution done twice.
269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True)
270be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
271be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            tokens = list(TclUtil.TclLexer(ln).lex())
273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return (Test.FAIL, "Tcl lexer error on: %r" % ln)
275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
276be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Validate there are no control tokens.
277be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for t in tokens:
278be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if not isinstance(t, str):
279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return (Test.FAIL,
280be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                        "Invalid test line: %r containing %r" % (ln, t))
281be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
282be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
283be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline())
284be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
2852c0a49c8cba8b7a6624d9c0b96f7d94231e10d22Daniel Dunbar            return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln)
286be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
287b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin    if litConfig.useValgrind:
288b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin        for pipeline in cmds:
289b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin            if pipeline.commands:
290b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                # Only valgrind the first command in each pipeline, to avoid
291b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                # valgrinding things like grep, not, and FileCheck.
292b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin                cmd = pipeline.commands[0]
29332989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin                cmd.args = litConfig.valgrindArgs + cmd.args
294b5e9770aef7176668cb1a1d97c085c061798cfd3Jeffrey Yasskin
295be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmd = cmds[0]
296be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for c in cmds[1:]:
297be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.Seq(cmd, '&&', c)
298be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
2997723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    # FIXME: This is lame, we shouldn't need bash. See PR5240.
3007723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    bashPath = litConfig.getBashPath()
3017723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar    if litConfig.useTclAsSh and bashPath:
302be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script = tmpBase + '.script'
303be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
304be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Write script file
305be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f = open(script,'w')
306be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        print >>f, 'set -o pipefail'
307be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd.toShell(f, pipefail = True)
308be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.close()
309be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
310be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 0:
311be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, cmd
312be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, open(script).read()
313be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout
314be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return '', '', 0
315be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
3167723d45153c5610349486121e2b50b5ba60b2f5cDaniel Dunbar        command = [litConfig.getBashPath(), script]
317be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out,err,exitCode = executeCommand(command, cwd=cwd,
318be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                          env=test.config.environment)
319be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
320be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return out,err,exitCode
321be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
322be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results = []
3236bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        try:
3246bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = executeShCmd(cmd, test.config, cwd, results)
3256bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        except InternalShellError,e:
3266bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            results.append((e.command, '', e.message + '\n', 255))
3276bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = 255
328be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
329be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
330be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
331be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out, cmd_err, res) in enumerate(results):
332be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
333be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
334be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
335be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
336be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
337be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
338be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
339be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd):
3409869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    bashPath = litConfig.getBashPath();
3419869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    isWin32CMDEXE = (litConfig.isWindows and not bashPath)
342be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = tmpBase + '.script'
3439869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
344be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script += '.bat'
345be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
346be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Write script file
347be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f = open(script,'w')
3489869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
349be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
350be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
351be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write(' &&\n'.join(commands))
352be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.write('\n')
353be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.close()
354be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
3559869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    if isWin32CMDEXE:
356be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['cmd','/c', script]
357be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
3589869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        if bashPath:
3599869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = [bashPath, script]
3609869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi        else:
3619869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi            command = ['/bin/sh', script]
362be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if litConfig.useValgrind:
363be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # FIXME: Running valgrind on sh is overkill. We probably could just
364be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # run on clang with no real loss.
36532989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin            command = litConfig.valgrindArgs + command
366be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return executeCommand(command, cwd=cwd, env=test.config.environment)
368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
36942543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbardef isExpectedFail(xfails, xtargets, target_triple):
37042543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    # Check if any xfail matches this target.
37142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xfails:
37242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        if item == '*' or item in target_triple:
37342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar            break
37442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    else:
37542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        return False
37642543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
37742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    # If so, see if it is expected to pass on this target.
37842543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    #
37942543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    # FIXME: Rename XTARGET to something that makes sense, like XPASS.
38042543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    for item in xtargets:
38142543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        if item == '*' or item in target_triple:
38242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar            return False
38342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
38442543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return True
38542543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar
386771d90ff4316d3557bfb1d6d500529d290b808d0Daniel Dunbardef parseIntegratedTestScript(test, normalize_slashes=False):
387be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
388be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
389be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    information. The RUN lines also will have variable substitution performed.
390be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """
391be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
392be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Get the temporary location, this is always relative to the test suite
393be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # root, not test source root.
394be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    #
395be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # FIXME: This should not be here?
396be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    sourcepath = test.getSourcePath()
397f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    sourcedir = os.path.dirname(sourcepath)
398be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execpath = test.getExecPath()
399be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execdir,execbase = os.path.split(execpath)
4000f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpDir = os.path.join(execdir, 'Output')
4010f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor    tmpBase = os.path.join(tmpDir, execbase)
40240c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar    if test.index is not None:
40340c67b5832877935a555fc63bfaa735332c79700Daniel Dunbar        tmpBase += '_%d' % test.index
404be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
405f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Normalize slashes, if requested.
406f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    if normalize_slashes:
407f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcepath = sourcepath.replace('\\', '/')
408f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        sourcedir = sourcedir.replace('\\', '/')
409f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar        tmpBase = tmpBase.replace('\\', '/')
410f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar
411be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # We use #_MARKER_# to hide %% while we do the other substitutions.
412be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions = [('%%', '#_MARKER_#')]
413be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend(test.config.substitutions)
414be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend([('%s', sourcepath),
415f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%S', sourcedir),
416f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar                          ('%p', sourcedir),
417be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%t', tmpBase + '.tmp'),
4180f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor                          ('%T', tmpDir),
4195110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          # FIXME: Remove this once we kill DejaGNU.
4205110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          ('%abs_tmp', tmpBase + '.tmp'),
421be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('#_MARKER_#', '%')])
422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
423be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Collect the test lines from the script.
424be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = []
425be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xfails = []
426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xtargets = []
427b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    requires = []
428be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in open(sourcepath):
429be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 'RUN:' in ln:
430be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Isolate the command to run.
431be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            index = ln.index('RUN:')
432be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln[index+4:]
433be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
434be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Trim trailing whitespace.
435be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.rstrip()
436be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
437be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Collapse lines with trailing '\\'.
438be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if script and script[-1][-1] == '\\':
439be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script[-1] = script[-1][:-1] + ln
440be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
441be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script.append(ln)
44242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar        elif 'XFAIL:' in ln:
443be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XFAIL:') + 6:].split(',')
444be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xfails.extend([s.strip() for s in items])
445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'XTARGET:' in ln:
446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XTARGET:') + 8:].split(',')
447be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xtargets.extend([s.strip() for s in items])
448b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        elif 'REQUIRES:' in ln:
449b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            items = ln[ln.index('REQUIRES:') + 9:].split(',')
450b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar            requires.extend([s.strip() for s in items])
451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'END.' in ln:
452be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Check for END. lines.
453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if ln[ln.index('END.'):].strip() == 'END.':
454be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
455be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
45618d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # Apply substitutions to the script.  Allow full regular
45718d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression syntax.  Replace each matching occurrence of regular
45818d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene    # expression pattern a with substitution b in line ln.
459be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    def processLine(ln):
460be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Apply substitutions
461be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for a,b in substitutions:
462ba69d3f6d448ca0a3a56b71fa65e85712bf76512Francois Pichet            if kIsWindows:
4637a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet                b = b.replace("\\","\\\\")
4647a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet            ln = re.sub(a, b, ln)
465be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
466be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Strip the trailing newline and any extra whitespace.
467be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return ln.strip()
468be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = map(processLine, script)
469be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
470be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Verify the script contains a run line.
471be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if not script:
472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has no run line!")
473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
474b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    # Check for unterminated run lines.
475be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if script[-1][-1] == '\\':
476be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
477be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
478f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick    # Check that we have the required features:
479b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    missing_required_features = [f for f in requires
480f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick                                 if f not in test.config.available_features]
481b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar    if missing_required_features:
482b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        msg = ', '.join(missing_required_features)
483b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar        return (Test.UNSUPPORTED,
484b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar                "Test requires the following features: %s" % msg)
485b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar
48642543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    isXFail = isExpectedFail(xfails, xtargets, test.suite.config.target_triple)
48742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    return script,isXFail,tmpBase,execdir
488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
48934f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohmandef formatTestOutput(status, out, err, exitCode, failDueToStderr, script):
490be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    output = StringIO.StringIO()
491be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Script:"
492be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
493be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, '\n'.join(script)
494be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
49534f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    print >>output, "Exit Code: %r" % exitCode,
49634f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    if failDueToStderr:
49734f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman        print >>output, "(but there was output on stderr)"
49834f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    else:
49934f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman        print >>output
5008a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if out:
5018a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "Command Output (stdout):"
5028a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5038a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        output.write(out)
5048a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5058a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman    if err:
5068a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "Command Output (stderr):"
5078a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
5088a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        output.write(err)
5098a7ffe651f706a6819e94e6a99bbb2c1bb1d4391Dan Gohman        print >>output, "--"
510be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return (status, output.getvalue())
511be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
512be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclTest(test, litConfig):
513be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
514be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
515be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
516f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # Parse the test script, normalizing slashes in substitutions on Windows
517f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    # (since otherwise Tcl style lexing will treat them as escapes).
518f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar    res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows)
519be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
520be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
521be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
52242543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
523be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
524be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
525be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
526be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
527be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
528be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
529be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
530be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir)
531be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
532be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
533be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
53434f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Test for failure. In addition to the exit code, Tcl commands are
53534f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # considered to fail if there is any standard error output.
536be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
537be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isXFail:
5387c12837916e647a9225fe2433f826588f2f28726Andrew Trick        ok = exitCode != 0 or err and not litConfig.ignoreStdErr
539bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
540bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
541bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
542bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
543be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
5447c12837916e647a9225fe2433f826588f2f28726Andrew Trick        ok = exitCode == 0 and (not err or litConfig.ignoreStdErr)
545bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
546bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
547bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
548bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
549be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
550be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
551be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
552be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
55334f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Set a flag for formatTestOutput so it can explain why the test was
55434f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # considered to have failed, despite having an exit code of 0.
5557c12837916e647a9225fe2433f826588f2f28726Andrew Trick    failDueToStderr = exitCode == 0 and err and not litConfig.ignoreStdErr
55634f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman
55734f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
558be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
559ee504b8cd78f5d54e4ae6ed2cfff88a9e8226771Daniel Dunbardef executeShTest(test, litConfig, useExternalSh):
560be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
561be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
562be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
5639869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi    res = parseIntegratedTestScript(test, useExternalSh)
564be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
565be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
566be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
56742543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    script, isXFail, tmpBase, execdir = res
568be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
569be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
570be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
571be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
572be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
573be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
574be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
575be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if useExternalSh:
576be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScript(test, litConfig, tmpBase, script, execdir)
577be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
578be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
579be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
580be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
581be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
582be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
58342543b7b736c9304b4877148943ff8a5fee3c22bDaniel Dunbar    if isXFail:
584be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
585bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
586bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XFAIL
587bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
588bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.XPASS
589be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
590be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
591bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        if ok:
592bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.PASS
593bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman        else:
594bd2499a0b128ca15e97d8d67e72f8c9024d3310bDan Gohman            status = Test.FAIL
595be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
596be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
597be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
598be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
59934f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    # Sh tests are not considered to fail just from stderr output.
60034f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    failDueToStderr = False
60134f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman
60234f68fc040a920b32ee11c5a8f63ba8a75240f26Dan Gohman    return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
603