TestRunner.py revision 5a461dd513dddaec6fd30196cb8f8680659a6e0d
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
116bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbarclass InternalShellError(Exception):
126bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    def __init__(self, command, message):
136bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.command = command
146bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        self.message = message
156bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1658c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar# Don't use close_fds on Windows.
1758c661ced16cd07c796bc867b1db0997c15db69fDaniel DunbarkUseCloseFDs = platform.system() != 'Windows'
18be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeCommand(command, cwd=None, env=None):
19be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    p = subprocess.Popen(command, cwd=cwd,
20be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdin=subprocess.PIPE,
21be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stdout=subprocess.PIPE,
22be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         stderr=subprocess.PIPE,
23be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         env=env)
24be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err = p.communicate()
25be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = p.wait()
26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
27be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Detect Ctrl-C in subprocess.
28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if exitCode == -signal.SIGINT:
29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise KeyboardInterrupt
30be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
31be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results):
34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isinstance(cmd, ShUtil.Seq):
35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == ';':
36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return executeShCmd(cmd.rhs, cfg, cwd, results)
38be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&':
40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise NotImplementedError,"unsupported test command: '&'"
41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '||':
43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res != 0:
45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.op == '&&':
48be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            res = executeShCmd(cmd.lhs, cfg, cwd, results)
49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res is None:
50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return res
51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res == 0:
53be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                res = executeShCmd(cmd.rhs, cfg, cwd, results)
54be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return res
55be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
56be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        raise ValueError,'Unknown shell command: %r' % cmd.op
57be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
58be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    assert isinstance(cmd, ShUtil.Pipeline)
59be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procs = []
60be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    input = subprocess.PIPE
615a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    stderrTempFiles = []
625a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # To avoid deadlock, we use a single stderr stream for piped
635a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # output. This is null until we have seen some output using
645a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # stderr.
655a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,j in enumerate(cmd.commands):
66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        redirects = [(0,), (1,), (2,)]
67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for r in j.redirects:
68be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r[0] == ('>',2):
69be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = [r[1], 'w', None]
70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',2) and r[1] in '012':
71be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[2] = redirects[int(r[1])]
72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>&',) or r[0] == ('&>',):
73be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = redirects[2] = [r[1], 'w', None]
74be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('>',):
75be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[1] = [r[1], 'w', None]
76be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r[0] == ('<',):
77be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                redirects[0] = [r[1], 'r', None]
78be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
79be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                raise NotImplementedError,"Unsupported redirect: %r" % (r,)
80be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
81be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        final_redirects = []
82be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for index,r in enumerate(redirects):
83be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if r == (0,):
84be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = input
85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (1,):
86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index == 0:
87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect for stdin"
88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                elif index == 1:
89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.PIPE
90be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                else:
91be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    result = subprocess.STDOUT
92be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            elif r == (2,):
93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if index != 2:
94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    raise NotImplementedError,"Unsupported redirect on stdout"
95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = subprocess.PIPE
96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
97be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                if r[2] is None:
98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                    r[2] = open(r[0], r[1])
99be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                result = r[2]
100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            final_redirects.append(result)
101be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
102be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        stdin, stdout, stderr = final_redirects
103be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
104be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # If stderr wants to come from stdout, but stdout isn't a pipe, then put
105be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # stderr on a pipe and treat it as stdout.
106be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE):
107be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderr = subprocess.PIPE
108be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = True
109be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
110be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            stderrIsStdout = False
1116bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1125a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # Don't allow stderr on a PIPE except for the last
1135a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # process, this could deadlock.
1145a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            #
1155a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            # FIXME: This is slow, but so is deadlock.
1165a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar            if stderr == subprocess.PIPE and j != cmd.commands[-1]:
1175a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderr = tempfile.TemporaryFile(mode='w+b')
1185a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar                stderrTempFiles.append((i, stderr))
1195a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1206bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        # Resolve the executable path ourselves.
1216bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args = list(j.args)
1226bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        args[0] = Util.which(args[0], cfg.environment['PATH'])
1236bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        if not args[0]:
1246bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            raise InternalShellError(j, '%r: command not found' % j.args[0])
1256bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar
1264b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar        procs.append(subprocess.Popen(args, cwd=cwd,
127be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdin = stdin,
128be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stdout = stdout,
129be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      stderr = stderr,
130be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                      env = cfg.environment,
13158c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar                                      close_fds = kUseCloseFDs))
132be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
133be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Immediately close stdin for any process taking stdin from us.
134be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdin == subprocess.PIPE:
135be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin.close()
136be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            procs[-1].stdin = None
137be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
138be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Update the current stdin source.
139be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if stdout == subprocess.PIPE:
140be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stdout
141be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif stderrIsStdout:
142be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = procs[-1].stderr
143be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
144be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            input = subprocess.PIPE
145be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
1465a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # FIXME: There is probably still deadlock potential here. Yawn.
147be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData = [None] * len(procs)
148be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    procData[-1] = procs[-1].communicate()
1495a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
150be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i in range(len(procs) - 1):
151be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stdout is not None:
152be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = procs[i].stdout.read()
153be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
154be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = ''
155be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if procs[i].stderr is not None:
156be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = procs[i].stderr.read()
157be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
158be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            err = ''
159be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        procData[i] = (out,err)
1605a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar
1615a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    # Read stderr out of the temp files.
1625a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar    for i,f in stderrTempFiles:
1635a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        f.seek(0, 0)
1645a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar        procData[i] = (procData[i][0], f.read())
165be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
166be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    exitCode = None
167be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(out,err) in enumerate(procData):
168be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = procs[i].wait()
169be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Detect Ctrl-C in subprocess.
170be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if res == -signal.SIGINT:
171be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            raise KeyboardInterrupt
172be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
173be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results.append((cmd.commands[i], out, err, res))
174be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if cmd.pipe_err:
175be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Python treats the exit code as a signed char.
176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if res < 0:
177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = min(exitCode, res)
178be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                exitCode = max(exitCode, res)
180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        else:
181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = res
182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if cmd.negate:
184be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = not exitCode
185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return exitCode
187be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
188be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd):
189be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    ln = ' &&\n'.join(commands)
190be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    try:
191be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.ShParser(ln, litConfig.isWindows).parse()
192be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    except:
193be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.FAIL, "shell parser error on: %r" % ln)
194be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
195be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    results = []
1966bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    try:
1976bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = executeShCmd(cmd, test.config, cwd, results)
1986bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar    except InternalShellError,e:
1996bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        out = ''
2006bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        err = e.message
2016bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        exitCode = 255
202be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
203be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
204be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out,cmd_err,res) in enumerate(results):
205be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
206be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
207be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
208be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
209be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
210be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
211be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
212be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd):
213be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    import TclUtil
214be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmds = []
215be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in commands:
216be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Given the unfortunate way LLVM's test are written, the line gets
217be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # backslash substitution done twice.
218be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True)
219be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            tokens = list(TclUtil.TclLexer(ln).lex())
222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return (Test.FAIL, "Tcl lexer error on: %r" % ln)
224be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
225be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Validate there are no control tokens.
226be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for t in tokens:
227be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if not isinstance(t, str):
228be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return (Test.FAIL,
229be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                        "Invalid test line: %r containing %r" % (ln, t))
230be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
231be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        try:
232be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline())
233be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        except:
2342c0a49c8cba8b7a6624d9c0b96f7d94231e10d22Daniel Dunbar            return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln)
235be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
236be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    cmd = cmds[0]
237be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for c in cmds[1:]:
238be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd = ShUtil.Seq(cmd, '&&', c)
239be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
240be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.useTclAsSh:
241be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script = tmpBase + '.script'
242be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
243be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Write script file
244be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f = open(script,'w')
245be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        print >>f, 'set -o pipefail'
246be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        cmd.toShell(f, pipefail = True)
247be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.close()
248be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
249be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 0:
250be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, cmd
251be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout, open(script).read()
252be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            print >>sys.stdout
253be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            return '', '', 0
254be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
255f072432e2613d06da2d839eee062f5f116fb8191Daniel Dunbar        command = ['/bin/bash', script]
256be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out,err,exitCode = executeCommand(command, cwd=cwd,
257be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                                          env=test.config.environment)
258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Tcl commands fail on standard error output.
260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if err:
261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            exitCode = 1
262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            out = 'Command has output on stderr!\n\n' + out
263be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
264be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return out,err,exitCode
265be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        results = []
2676bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        try:
2686bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = executeShCmd(cmd, test.config, cwd, results)
2696bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar        except InternalShellError,e:
2706bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            results.append((e.command, '', e.message + '\n', 255))
2716bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar            exitCode = 255
272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out = err = ''
274be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
275be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Tcl commands fail on standard error output.
276be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if [True for _,_,err,res in results if err]:
277be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        exitCode = 1
278be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command has output on stderr!\n\n'
279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
280be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for i,(cmd, cmd_out, cmd_err, res) in enumerate(results):
281be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args))
282be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Result: %r\n' % (i, res)
283be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Output:\n%s\n\n' % (i, cmd_out)
284be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err)
285be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
286be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return out, err, exitCode
287be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
288be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd):
289be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = tmpBase + '.script'
290be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.isWindows:
291be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        script += '.bat'
292be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
293be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Write script file
294be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f = open(script,'w')
295be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.isWindows:
296be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
297be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
298be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        f.write(' &&\n'.join(commands))
299be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.write('\n')
300be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    f.close()
301be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
302be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.isWindows:
303be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['cmd','/c', script]
304be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
305be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        command = ['/bin/sh', script]
306be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if litConfig.useValgrind:
307be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # FIXME: Running valgrind on sh is overkill. We probably could just
308be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # run on clang with no real loss.
309be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            valgrindArgs = ['valgrind', '-q',
310be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                            '--tool=memcheck', '--trace-children=yes',
311be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                            '--error-exitcode=123']
312be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            valgrindArgs.extend(litConfig.valgrindArgs)
313be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
314be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            command = valgrindArgs + command
315be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
316be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return executeCommand(command, cwd=cwd, env=test.config.environment)
317be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
318be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef parseIntegratedTestScript(test, xfailHasColon, requireAndAnd):
319be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test
320be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script and extract the lines to 'RUN' as well as 'XFAIL' and 'XTARGET'
321be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    information. The RUN lines also will have variable substitution performed.
322be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    """
323be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
324be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Get the temporary location, this is always relative to the test suite
325be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # root, not test source root.
326be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    #
327be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # FIXME: This should not be here?
328be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    sourcepath = test.getSourcePath()
329be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execpath = test.getExecPath()
330be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    execdir,execbase = os.path.split(execpath)
331be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    tmpBase = os.path.join(execdir, 'Output', execbase)
332be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
333be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # We use #_MARKER_# to hide %% while we do the other substitutions.
334be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions = [('%%', '#_MARKER_#')]
335be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend(test.config.substitutions)
336be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    substitutions.extend([('%s', sourcepath),
337be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%S', os.path.dirname(sourcepath)),
338be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%p', os.path.dirname(sourcepath)),
339be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('%t', tmpBase + '.tmp'),
3405110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          # FIXME: Remove this once we kill DejaGNU.
3415110609ceb901f20e1d8b38530e09f9e9017386cDaniel Dunbar                          ('%abs_tmp', tmpBase + '.tmp'),
342be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                          ('#_MARKER_#', '%')])
343be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
344be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Collect the test lines from the script.
345be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = []
346be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xfails = []
347be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    xtargets = []
348be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for ln in open(sourcepath):
349be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if 'RUN:' in ln:
350be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Isolate the command to run.
351be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            index = ln.index('RUN:')
352be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln[index+4:]
353be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
354be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Trim trailing whitespace.
355be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.rstrip()
356be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
357be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Collapse lines with trailing '\\'.
358be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if script and script[-1][-1] == '\\':
359be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script[-1] = script[-1][:-1] + ln
360be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            else:
361be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                script.append(ln)
362be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif xfailHasColon and 'XFAIL:' in ln:
363be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XFAIL:') + 6:].split(',')
364be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xfails.extend([s.strip() for s in items])
365be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif not xfailHasColon and 'XFAIL' in ln:
366be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XFAIL') + 5:].split(',')
367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xfails.extend([s.strip() for s in items])
368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'XTARGET:' in ln:
369be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            items = ln[ln.index('XTARGET:') + 8:].split(',')
370be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            xtargets.extend([s.strip() for s in items])
371be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        elif 'END.' in ln:
372be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Check for END. lines.
373be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if ln[ln.index('END.'):].strip() == 'END.':
374be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
375be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
376be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Apply substitutions to the script.
377be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    def processLine(ln):
378be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Apply substitutions
379be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for a,b in substitutions:
380be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = ln.replace(a,b)
381be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
382be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        # Strip the trailing newline and any extra whitespace.
383be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return ln.strip()
384be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script = map(processLine, script)
385be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
386be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Verify the script contains a run line.
387be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if not script:
388be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has no run line!")
389be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
390be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if script[-1][-1] == '\\':
391be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNRESOLVED, "Test has unterminated run lines (with '\\')")
392be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
393be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Validate interior lines for '&&', a lovely historical artifact.
394be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if requireAndAnd:
395be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for i in range(len(script) - 1):
396be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            ln = script[i]
397be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
398be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if not ln.endswith('&&'):
399be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                return (Test.FAIL,
400be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                        ("MISSING \'&&\': %s\n"  +
401be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                         "FOLLOWED BY   : %s\n") % (ln, script[i + 1]))
402be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
403be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            # Strip off '&&'
404be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            script[i] = ln[:-2]
405be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
406be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return script,xfails,xtargets,tmpBase,execdir
407be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
408be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef formatTestOutput(status, out, err, exitCode, script):
409be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    output = StringIO.StringIO()
410be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Script:"
411be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
412be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, '\n'.join(script)
413be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
414be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Exit Code: %r" % exitCode
415be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Command Output (stdout):"
416be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
417be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    output.write(out)
418be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
419be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "Command Output (stderr):"
420be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
421be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    output.write(err)
422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    print >>output, "--"
423be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return (status, output.getvalue())
424be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
425be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeTclTest(test, litConfig):
426be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
427be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
428be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
429be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    res = parseIntegratedTestScript(test, True, False)
430be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
431be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
432be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
433be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script, xfails, xtargets, tmpBase, execdir = res
434be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
435be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
436be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
437be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
438be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
439be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
440be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
441be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir)
442be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
443be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
444be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    isXFail = False
446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    for item in xfails:
447be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        if item == '*' or item in test.suite.config.target_triple:
448be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            isXFail = True
449be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            break
450be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # If this is XFAIL, see if it is expected to pass on this target.
452be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isXFail:
453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        for item in xtargets:
454be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar            if item == '*' or item in test.suite.config.target_triple:
455be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                isXFail = False
456be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar                break
457be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
459be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if isXFail:
460be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
461be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        status = (Test.XPASS, Test.XFAIL)[ok]
462be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
463be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
464be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        status = (Test.FAIL, Test.PASS)[ok]
465be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
466be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
467be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
468be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
469be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return formatTestOutput(status, out, err, exitCode, script)
470be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
471be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShTest(test, litConfig, useExternalSh, requireAndAnd):
472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if test.config.unsupported:
473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.UNSUPPORTED, 'Test is unsupported')
474be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
475be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    res = parseIntegratedTestScript(test, False, requireAndAnd)
476be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
477be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
478be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
479be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    script, xfails, xtargets, tmpBase, execdir = res
480be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
481be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if litConfig.noExecute:
482be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (Test.PASS, '')
483be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
484be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    # Create the output directory if it does not already exist.
485be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    Util.mkdir_p(os.path.dirname(tmpBase))
486be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
487be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if useExternalSh:
488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScript(test, litConfig, tmpBase, script, execdir)
489be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
490be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        res = executeScriptInternal(test, litConfig, tmpBase, script, execdir)
491be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if len(res) == 2:
492be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return res
493be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
494be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    out,err,exitCode = res
495be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if xfails:
496be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode != 0
497be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        status = (Test.XPASS, Test.XFAIL)[ok]
498be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    else:
499be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        ok = exitCode == 0
500be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        status = (Test.FAIL, Test.PASS)[ok]
501be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
502be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    if ok:
503be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar        return (status,'')
504be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar
505be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar    return formatTestOutput(status, out, err, exitCode, script)
506