1b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarfrom __future__ import absolute_import 2be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbarimport os, signal, subprocess, sys 309a28f6973599b3c2e12f19e1d3f91e12de77ff7Daniel Dunbarimport re 458c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbarimport platform 55a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbarimport tempfile 658c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar 7b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.ShUtil as ShUtil 8b35a1733607b07f36c3617932b67debb375a15c5Daniel Dunbarimport lit.Test as Test 9128ce319ec47c46dc7da16aa3a75185899878745Daniel Dunbarimport lit.util 1018d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene 116bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbarclass InternalShellError(Exception): 126bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar def __init__(self, command, message): 136bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar self.command = command 146bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar self.message = message 156bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar 16f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkIsWindows = platform.system() == 'Windows' 17f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar 1858c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar# Don't use close_fds on Windows. 19f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkUseCloseFDs = not kIsWindows 206efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar 216efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar# Use temporary files to replace /dev/null on Windows. 22f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel DunbarkAvoidDevNull = kIsWindows 236efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar 24be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeShCmd(cmd, cfg, cwd, results): 25be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if isinstance(cmd, ShUtil.Seq): 26be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == ';': 27be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 28be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return executeShCmd(cmd.rhs, cfg, cwd, results) 29be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 30be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '&': 31a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar raise InternalShellError(cmd,"unsupported shell operator: '&'") 32be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 33be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '||': 34be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 35be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res != 0: 36be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.rhs, cfg, cwd, results) 37be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 38a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar 39be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.op == '&&': 40be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.lhs, cfg, cwd, results) 41be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res is None: 42be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 43be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 44be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res == 0: 45be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeShCmd(cmd.rhs, cfg, cwd, results) 46be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 47be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 4826e0af54c2eb3efe468715edada97442e469bb19Daniel Dunbar raise ValueError('Unknown shell command: %r' % cmd.op) 49be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 50be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar assert isinstance(cmd, ShUtil.Pipeline) 51be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs = [] 52be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = subprocess.PIPE 535a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderrTempFiles = [] 54c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar opened_files = [] 551befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar named_temp_files = [] 565a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # To avoid deadlock, we use a single stderr stream for piped 575a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # output. This is null until we have seen some output using 585a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # stderr. 595a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar for i,j in enumerate(cmd.commands): 60f1a26cf9df900101b9cbea42b67f7466edc7deedEli Bendersky # Apply the redirections, we use (N,) as a sentinel to indicate stdin, 61a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or 62a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # from a file are represented with a list [file, mode, file-object] 63a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # where file-object is initially None. 64be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects = [(0,), (1,), (2,)] 65be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for r in j.redirects: 66be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r[0] == ('>',2): 67be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[2] = [r[1], 'w', None] 68a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar elif r[0] == ('>>',2): 69a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar redirects[2] = [r[1], 'a', None] 70be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>&',2) and r[1] in '012': 71be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[2] = redirects[int(r[1])] 72be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>&',) or r[0] == ('&>',): 73be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[1] = redirects[2] = [r[1], 'w', None] 74be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('>',): 75be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[1] = [r[1], 'w', None] 76a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar elif r[0] == ('>>',): 77a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar redirects[1] = [r[1], 'a', None] 78be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r[0] == ('<',): 79be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar redirects[0] = [r[1], 'r', None] 80be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 81a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar raise InternalShellError(j,"Unsupported redirect: %r" % (r,)) 82be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 83a3f85d206a4b9f717d4dd9b53cdc280e9105c70fDaniel Dunbar # Map from the final redirections to something subprocess can handle. 84be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar final_redirects = [] 85be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for index,r in enumerate(redirects): 86be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r == (0,): 87be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = input 88be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r == (1,): 89be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if index == 0: 90a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar raise InternalShellError(j,"Unsupported redirect for stdin") 91be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif index == 1: 92be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.PIPE 93be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 94be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.STDOUT 95be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif r == (2,): 96be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if index != 2: 97a80ae9c71c361e0569af66b9885a15c3877c6c2dDaniel Dunbar raise InternalShellError(j,"Unsupported redirect on stdout") 98be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = subprocess.PIPE 99be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 100be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if r[2] is None: 1016efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar if kAvoidDevNull and r[0] == '/dev/null': 1026efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar r[2] = tempfile.TemporaryFile(mode=r[1]) 1036efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar else: 1046efba21342b15d7dc3185462868a606234e064f1Daniel Dunbar r[2] = open(r[0], r[1]) 105474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar # Workaround a Win32 and/or subprocess bug when appending. 106e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar # 107e09ccab0ce2986d1ba6950f2eccc46fd1935ae68Daniel Dunbar # FIXME: Actually, this is probably an instance of PR6753. 108474f0df3ac86691fc2aaa201cacc7b5d0005d236Daniel Dunbar if r[1] == 'a': 109bf477df346b12ae5f6e7af165862575c15905e20Daniel Dunbar r[2].seek(0, 2) 1109fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi opened_files.append(r[2]) 111be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar result = r[2] 112be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar final_redirects.append(result) 113be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 114be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdin, stdout, stderr = final_redirects 115be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 116be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # If stderr wants to come from stdout, but stdout isn't a pipe, then put 117be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # stderr on a pipe and treat it as stdout. 118be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if (stderr == subprocess.STDOUT and stdout != subprocess.PIPE): 119be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderr = subprocess.PIPE 120be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderrIsStdout = True 121be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 122be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderrIsStdout = False 1236bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar 1245a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # Don't allow stderr on a PIPE except for the last 1255a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # process, this could deadlock. 1265a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # 1275a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # FIXME: This is slow, but so is deadlock. 1285a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar if stderr == subprocess.PIPE and j != cmd.commands[-1]: 1295a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderr = tempfile.TemporaryFile(mode='w+b') 1305a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar stderrTempFiles.append((i, stderr)) 1315a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar 1326bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar # Resolve the executable path ourselves. 1336bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar args = list(j.args) 134cb4bfb340941186a0e326e4b00a88a50a86b7ff0Daniel Dunbar executable = lit.util.which(args[0], cfg.environment['PATH']) 135cb4bfb340941186a0e326e4b00a88a50a86b7ff0Daniel Dunbar if not executable: 1366bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar raise InternalShellError(j, '%r: command not found' % j.args[0]) 1376bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar 1381befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar # Replace uses of /dev/null with temporary files. 1391befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar if kAvoidDevNull: 1401befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar for i,arg in enumerate(args): 1411befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar if arg == "/dev/null": 1421befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar f = tempfile.NamedTemporaryFile(delete=False) 1431befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar f.close() 1441befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar named_temp_files.append(f.name) 1451befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar args[i] = f.name 1461befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar 1474b78aa3f56e6dae484f1282cef4ff5237f10f9d8Daniel Dunbar procs.append(subprocess.Popen(args, cwd=cwd, 148cb4bfb340941186a0e326e4b00a88a50a86b7ff0Daniel Dunbar executable = executable, 149be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdin = stdin, 150be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stdout = stdout, 151be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar stderr = stderr, 152be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar env = cfg.environment, 15358c661ced16cd07c796bc867b1db0997c15db69fDaniel Dunbar close_fds = kUseCloseFDs)) 154be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 155be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Immediately close stdin for any process taking stdin from us. 156be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if stdin == subprocess.PIPE: 157be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs[-1].stdin.close() 158be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procs[-1].stdin = None 159be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 160be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Update the current stdin source. 161be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if stdout == subprocess.PIPE: 162be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = procs[-1].stdout 163be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar elif stderrIsStdout: 164be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = procs[-1].stderr 165be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 166be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar input = subprocess.PIPE 167be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 16869c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar # Explicitly close any redirected files. We need to do this now because we 16969c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar # need to release any handles we may have on the temporary files (important 17069c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar # on Win32, for example). Since we have already spawned the subprocess, our 17169c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar # handles have already been transferred so we do not need them anymore. 17269c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar for f in opened_files: 1739fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi f.close() 17469c4cbe9e878e49aa87d322c63afd809588f4cd7Daniel Dunbar 1755a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # FIXME: There is probably still deadlock potential here. Yawn. 176be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData = [None] * len(procs) 177be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData[-1] = procs[-1].communicate() 1785a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar 179be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i in range(len(procs) - 1): 180be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if procs[i].stdout is not None: 181be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = procs[i].stdout.read() 182be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 183be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = '' 184be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if procs[i].stderr is not None: 185be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar err = procs[i].stderr.read() 186be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 187be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar err = '' 188be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar procData[i] = (out,err) 189c3681d334af978e066c4fdbfcadda492585ef338Daniel Dunbar 1905a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar # Read stderr out of the temp files. 1915a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar for i,f in stderrTempFiles: 1925a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar f.seek(0, 0) 1935a461dd513dddaec6fd30196cb8f8680659a6e0dDaniel Dunbar procData[i] = (procData[i][0], f.read()) 194be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 195be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = None 196be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i,(out,err) in enumerate(procData): 197be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = procs[i].wait() 198be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Detect Ctrl-C in subprocess. 199be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if res == -signal.SIGINT: 200be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar raise KeyboardInterrupt 201be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 20280a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar # Ensure the resulting output is always of string type. 20380a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar try: 20480a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar out = str(out.decode('ascii')) 20580a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar except: 20680a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar out = str(out) 20780a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar try: 20880a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar err = str(err.decode('ascii')) 20980a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar except: 21080a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar err = str(err) 21180a06baec266e901f58797c39ac78c9552036b9dDaniel Dunbar 212be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar results.append((cmd.commands[i], out, err, res)) 213be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.pipe_err: 214be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Python treats the exit code as a signed char. 215bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar if exitCode is None: 216bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar exitCode = res 217bd9bb2c515173a2d9fa8f8472e06a753618c0c7aDaniel Dunbar elif res < 0: 218be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = min(exitCode, res) 219be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 220be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = max(exitCode, res) 221be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 222be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = res 223be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 2241befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar # Remove any named temporary files we created. 2251befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar for f in named_temp_files: 2269fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi try: 2279fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi os.remove(f) 2289fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi except OSError: 2299fae6ee6af42b7aca361deb478a212f573a0cd60NAKAMURA Takumi pass 2301befb9b2df7b287872021518cedce4a0aeca3b95Daniel Dunbar 231be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if cmd.negate: 232be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar exitCode = not exitCode 233be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 234be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return exitCode 235be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 236be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScriptInternal(test, litConfig, tmpBase, commands, cwd): 23700fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith cmds = [] 23800fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith for ln in commands: 23900fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith try: 240c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola cmds.append(ShUtil.ShParser(ln, litConfig.isWindows, 241c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola test.config.pipefail).parse()) 24200fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith except: 243501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(Test.FAIL, "shell parser error on: %r" % ln) 24400fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith 24500fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith cmd = cmds[0] 24600fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith for c in cmds[1:]: 24700fb9c429e4400f3daeb87e6fad9498d4c73862aRichard Smith cmd = ShUtil.Seq(cmd, '&&', c) 248be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 249be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar results = [] 2506bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar try: 2516bd2b2e9a27df118951d2fdc88df249d56a4d8feDaniel Dunbar exitCode = executeShCmd(cmd, test.config, cwd, results) 2522e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar except InternalShellError: 2532e60c882bf989207ad3b33685b2353f62ff3ecd4Daniel Dunbar e = sys.exc_info()[1] 254b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar exitCode = 127 255b62fb4ba5cf61070486287da393ada566b4ad4edDaniel Dunbar results.append((e.command, '', e.message, exitCode)) 256be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 257be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out = err = '' 258be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for i,(cmd, cmd_out,cmd_err,res) in enumerate(results): 259be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args)) 260be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Result: %r\n' % (i, res) 261be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Output:\n%s\n\n' % (i, cmd_out) 262be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err) 263be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 264be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return out, err, exitCode 265be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 266be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbardef executeScript(test, litConfig, tmpBase, commands, cwd): 2679869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi bashPath = litConfig.getBashPath(); 2689869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi isWin32CMDEXE = (litConfig.isWindows and not bashPath) 269be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = tmpBase + '.script' 2709869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi if isWin32CMDEXE: 271be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script += '.bat' 272be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 273be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Write script file 2748755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner mode = 'w' 2758755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner if litConfig.isWindows and not isWin32CMDEXE: 2768755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner mode += 'b' # Avoid CRLFs when writing bash scripts. 2778755ae8c69ca522a9931aab4b4951443b2f64d26Reid Kleckner f = open(script, mode) 2789869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi if isWin32CMDEXE: 279be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands)) 280be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 281c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola if test.config.pipefail: 282c1bb2d432501dabdfcb1e78eccfb7377664c4d14Rafael Espindola f.write('set -o pipefail;') 283c15e5b0a0dbdaf8612bdcbba1deedcb77bed1045Richard Smith f.write('{ ' + '; } &&\n{ '.join(commands) + '; }') 284be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.write('\n') 285be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar f.close() 286be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 2879869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi if isWin32CMDEXE: 288be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar command = ['cmd','/c', script] 289be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 2909869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi if bashPath: 2919869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi command = [bashPath, script] 2929869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi else: 2939869c2f71744821d77fca2d0596cd9f27f84c5d2NAKAMURA Takumi command = ['/bin/sh', script] 294be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if litConfig.useValgrind: 295be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # FIXME: Running valgrind on sh is overkill. We probably could just 296be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # run on clang with no real loss. 29732989deb9641cf3878686b5634311a7a125f8f02Jeffrey Yasskin command = litConfig.valgrindArgs + command 298be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 299493e8d4bf503c8f573e0dce95ea146d181c623c6Daniel Dunbar return lit.util.executeCommand(command, cwd=cwd, 300493e8d4bf503c8f573e0dce95ea146d181c623c6Daniel Dunbar env=test.config.environment) 301be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 30235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbardef parseIntegratedTestScriptCommands(source_path): 3035403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar """ 3045403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar parseIntegratedTestScriptCommands(source_path) -> commands 3055403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar 3065403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar Parse the commands in an integrated test script file into a list of 3075403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar (line_number, command_type, line). 3085403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar """ 30935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar 31035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # This code is carefully written to be dual compatible with Python 2.5+ and 31135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Python 3 without requiring input files to always have valid codings. The 31235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # trick we use is to open the file in binary mode and use the regular 31335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # expression library to find the commands, with it scanning strings in 31435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Python2 and bytes in Python3. 31535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # 31635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Once we find a match, we do require each script line to be decodable to 31735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # ascii, so we convert the outputs to ascii before returning. This way the 31835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # remaining code can work with "strings" agnostic of the executing Python 31935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # version. 32035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar 32135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar def to_bytes(str): 32235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Encode to Latin1 to get binary data. 32335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar return str.encode('ISO-8859-1') 32435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar keywords = ('RUN:', 'XFAIL:', 'REQUIRES:', 'END.') 32535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar keywords_re = re.compile( 32635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar to_bytes("(%s)(.*)\n" % ("|".join(k for k in keywords),))) 32735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar 32835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar f = open(source_path, 'rb') 32935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar try: 33035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Read the entire file contents. 33135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar data = f.read() 33235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar 33335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Iterate over the matches. 33435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar line_number = 1 33535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar last_match_position = 0 33635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar for match in keywords_re.finditer(data): 33735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Compute the updated line number by counting the intervening 33835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # newlines. 33935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar match_position = match.start() 34035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar line_number += data.count(to_bytes('\n'), last_match_position, 34135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar match_position) 34235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar last_match_position = match_position 34335d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar 34435d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Convert the keyword and line to ascii strings and yield the 34535d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # command. Note that we take care to return regular strings in 34635d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # Python 2, to avoid other code having to differentiate between the 34735d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar # str and unicode types. 34835d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar keyword,ln = match.groups() 34935d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar yield (line_number, str(keyword[:-1].decode('ascii')), 35035d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar str(ln.decode('ascii'))) 35135d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar finally: 35235d5e9044c580c843eb6e825d87816619e6d7f8fDaniel Dunbar f.close() 3535403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar 3542d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef parseIntegratedTestScript(test, normalize_slashes=False, 3552d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar extra_substitutions=[]): 356be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar """parseIntegratedTestScript - Scan an LLVM/Clang style integrated test 357f793fbc5698263e045661cab3fb06144c66cc1dbDaniel Dunbar script and extract the lines to 'RUN' as well as 'XFAIL' and 'REQUIRES' 358be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar information. The RUN lines also will have variable substitution performed. 359be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar """ 360be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 361be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Get the temporary location, this is always relative to the test suite 362be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # root, not test source root. 363be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # 364be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # FIXME: This should not be here? 365be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar sourcepath = test.getSourcePath() 366f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar sourcedir = os.path.dirname(sourcepath) 367be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar execpath = test.getExecPath() 368be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar execdir,execbase = os.path.split(execpath) 3690f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor tmpDir = os.path.join(execdir, 'Output') 3700f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor tmpBase = os.path.join(tmpDir, execbase) 371be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 372f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar # Normalize slashes, if requested. 373f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar if normalize_slashes: 374f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar sourcepath = sourcepath.replace('\\', '/') 375f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar sourcedir = sourcedir.replace('\\', '/') 376bbbc283d86a911ccf3bdecdc78a7a8f71f31683fNAKAMURA Takumi tmpDir = tmpDir.replace('\\', '/') 377f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar tmpBase = tmpBase.replace('\\', '/') 378f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar 379be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # We use #_MARKER_# to hide %% while we do the other substitutions. 3802d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar substitutions = list(extra_substitutions) 3812d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar substitutions.extend([('%%', '#_MARKER_#')]) 382be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar substitutions.extend(test.config.substitutions) 383be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar substitutions.extend([('%s', sourcepath), 384f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar ('%S', sourcedir), 385f32a41a7e6df8ff5f78c673e3a73303bdba759ffDaniel Dunbar ('%p', sourcedir), 3860191bfcf7a5ae1ccfad7afe8ced59a14ffaca2a6Nico Weber ('%{pathsep}', os.pathsep), 387be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ('%t', tmpBase + '.tmp'), 3880f9d34c71d4f4ea83912c45f99ed286557ea189cDouglas Gregor ('%T', tmpDir), 389be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ('#_MARKER_#', '%')]) 390be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 391e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi # "%/[STpst]" should be normalized. 392e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi substitutions.extend([ 393e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ('%/s', sourcepath.replace('\\', '/')), 394e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ('%/S', sourcedir.replace('\\', '/')), 395e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ('%/p', sourcedir.replace('\\', '/')), 396e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ('%/t', tmpBase.replace('\\', '/') + '.tmp'), 397e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ('%/T', tmpDir.replace('\\', '/')), 398e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi ]) 399e908486f5badf116c8711da76729ea2b3aa933b4NAKAMURA Takumi 400be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Collect the test lines from the script. 401be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script = [] 402b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar requires = [] 4035403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar for line_number, command_type, ln in \ 4045403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar parseIntegratedTestScriptCommands(sourcepath): 4055403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar if command_type == 'RUN': 406be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Trim trailing whitespace. 407be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar ln = ln.rstrip() 408be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 40908639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko # Substitute line number expressions 41008639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko ln = re.sub('%\(line\)', str(line_number), ln) 41108639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko def replace_line_number(match): 41208639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko if match.group(1) == '+': 41308639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko return str(line_number + int(match.group(2))) 41408639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko if match.group(1) == '-': 41508639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko return str(line_number - int(match.group(2))) 41608639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko ln = re.sub('%\(line *([\+-]) *(\d+)\)', replace_line_number, ln) 41708639983ded4250c18614c62450e70ba653aac4cAlexander Kornienko 418be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Collapse lines with trailing '\\'. 419be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if script and script[-1][-1] == '\\': 420be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script[-1] = script[-1][:-1] + ln 421be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 422be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar script.append(ln) 4235403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar elif command_type == 'XFAIL': 424f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar test.xfails.extend([s.strip() for s in ln.split(',')]) 4255403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar elif command_type == 'REQUIRES': 4265403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar requires.extend([s.strip() for s in ln.split(',')]) 4275403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar elif command_type == 'END': 4285403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar # END commands are only honored if the rest of the line is empty. 4295403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar if not ln.strip(): 430be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar break 4315403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar else: 4325403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar raise ValueError("unknown script command type: %r" % ( 4335403214852da123d09b91377ad0fa4543afc816cDaniel Dunbar command_type,)) 434be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 43518d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene # Apply substitutions to the script. Allow full regular 43618d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene # expression syntax. Replace each matching occurrence of regular 43718d49877530c04dd63578e6d9d0a1d3b6955502bDavid Greene # expression pattern a with substitution b in line ln. 438be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar def processLine(ln): 439be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Apply substitutions 440be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar for a,b in substitutions: 441ba69d3f6d448ca0a3a56b71fa65e85712bf76512Francois Pichet if kIsWindows: 4427a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet b = b.replace("\\","\\\\") 4437a0be17c087ad7723e0ec65e63f4eb80ce9b5cefFrancois Pichet ln = re.sub(a, b, ln) 444be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 445be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Strip the trailing newline and any extra whitespace. 446be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return ln.strip() 447a1ba7527ded837e4c98149f7b1fe848a93177e07Daniel Dunbar script = [processLine(ln) 448a1ba7527ded837e4c98149f7b1fe848a93177e07Daniel Dunbar for ln in script] 449be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 450be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Verify the script contains a run line. 451be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if not script: 452501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(Test.UNRESOLVED, "Test has no run line!") 453be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 454b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar # Check for unterminated run lines. 455be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if script[-1][-1] == '\\': 456501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(Test.UNRESOLVED, 457501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar "Test has unterminated run lines (with '\\')") 458be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 459f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick # Check that we have the required features: 460b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar missing_required_features = [f for f in requires 461f2a58425cd2a288b1d9fc3d2484ac774d361a0d7Andrew Trick if f not in test.config.available_features] 462b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar if missing_required_features: 463b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar msg = ', '.join(missing_required_features) 464501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(Test.UNSUPPORTED, 465501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar "Test requires the following features: %s" % msg) 466b937549e517fcb03032bab3441d6ced37fc4db8dDaniel Dunbar 467f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar return script,tmpBase,execdir 468be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 4692d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbardef executeShTest(test, litConfig, useExternalSh, 4702d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar extra_substitutions=[]): 471be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if test.config.unsupported: 472be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return (Test.UNSUPPORTED, 'Test is unsupported') 473be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 4742d4a5bf817ba0d85ddeb34a3c7fc2bc07fda32bdDaniel Dunbar res = parseIntegratedTestScript(test, useExternalSh, extra_substitutions) 475501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar if isinstance(res, lit.Test.Result): 476be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 477501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar if litConfig.noExecute: 478501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(Test.PASS) 479be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 480f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar script, tmpBase, execdir = res 481be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 482be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar # Create the output directory if it does not already exist. 483128ce319ec47c46dc7da16aa3a75185899878745Daniel Dunbar lit.util.mkdir_p(os.path.dirname(tmpBase)) 484be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 485be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar if useExternalSh: 486be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeScript(test, litConfig, tmpBase, script, execdir) 487be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 488be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar res = executeScriptInternal(test, litConfig, tmpBase, script, execdir) 489501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar if isinstance(res, lit.Test.Result): 490be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar return res 491be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 492be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar out,err,exitCode = res 493f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar if exitCode == 0: 494f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar status = Test.PASS 495be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar else: 496f72bc792264941d1cdffe99775ce5e28bcdc51a4Daniel Dunbar status = Test.FAIL 497be7ada718139b8c840a38ba34c4af492b6a05f9fDaniel Dunbar 498501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar # Form the output log. 499501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar output = """Script:\n--\n%s\n--\nExit Code: %d\n\n""" % ( 500501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar '\n'.join(script), exitCode) 501501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar 502501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar # Append the outputs, if present. 503501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar if out: 504501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar output += """Command Output (stdout):\n--\n%s\n--\n""" % (out,) 505501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar if err: 506501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar output += """Command Output (stderr):\n--\n%s\n--\n""" % (err,) 507501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar 508501cba385cf2ae5db1d646ec75e1d4d57e015d80Daniel Dunbar return lit.Test.Result(status, output) 509